1/* chatc.c 2 Subroutines to handle chat script commands. 3 4 Copyright (C) 1992, 2002 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP uuconf library. 7 8 This library is free software; you can redistribute it and/or 9 modify it under the terms of the GNU Library General Public License 10 as published by the Free Software Foundation; either version 2 of 11 the License, or (at your option) any later version. 12 13 This library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 Library General Public License for more details. 17 18 You should have received a copy of the GNU Library General Public 19 License along with this library; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucnfi.h" 26 27#if USE_RCS_ID 28const char _uuconf_chatc_rcsid[] = "$Id: chatc.c,v 1.10 2002/03/05 19:10:42 ian Rel $"; 29#endif 30 31#include <ctype.h> 32#include <errno.h> 33 34static int icchat P((pointer pglobal, int argc, char **argv, 35 pointer pvar, pointer pinfo)); 36static int icchat_fail P((pointer pglobal, int argc, char **argv, 37 pointer pvar, pointer pinfo)); 38static int icunknown P((pointer pglobal, int argc, char **argv, 39 pointer pvar, pointer pinfo)); 40 41/* The chat script commands. */ 42 43static const struct cmdtab_offset asChat_cmds[] = 44{ 45 { "chat", UUCONF_CMDTABTYPE_FN, 46 offsetof (struct uuconf_chat, uuconf_pzchat), icchat }, 47 { "chat-program", UUCONF_CMDTABTYPE_FULLSTRING, 48 offsetof (struct uuconf_chat, uuconf_pzprogram), NULL }, 49 { "chat-timeout", UUCONF_CMDTABTYPE_INT, 50 offsetof (struct uuconf_chat, uuconf_ctimeout), NULL }, 51 { "chat-fail", UUCONF_CMDTABTYPE_FN | 2, 52 offsetof (struct uuconf_chat, uuconf_pzfail), icchat_fail }, 53 { "chat-seven-bit", UUCONF_CMDTABTYPE_BOOLEAN, 54 offsetof (struct uuconf_chat, uuconf_fstrip), NULL }, 55 { NULL, 0, 0, NULL } 56}; 57 58#define CCHAT_CMDS (sizeof asChat_cmds / sizeof asChat_cmds[0]) 59 60/* Handle a chat script command. The chat script commands are entered 61 as UUCONF_CMDTABTYPE_PREFIX, and the commands are routed to this 62 function. We copy the command table onto the stack and repoint it 63 at qchat in order to make the function reentrant. The return value 64 can include UUCONF_CMDTABRET_KEEP, but should not include 65 UUCONF_CMDTABRET_EXIT. */ 66 67int 68_uuconf_ichat_cmd (qglobal, argc, argv, qchat, pblock) 69 struct sglobal *qglobal; 70 int argc; 71 char **argv; 72 struct uuconf_chat *qchat; 73 pointer pblock; 74{ 75 char *zchat; 76 struct uuconf_cmdtab as[CCHAT_CMDS]; 77 int iret; 78 79 /* This is only invoked when argv[0] will contain the string "chat"; 80 the specific chat script command comes after that point. */ 81 for (zchat = argv[0]; *zchat != '\0'; zchat++) 82 if ((*zchat == 'c' || *zchat == 'C') 83 && strncasecmp (zchat, "chat", sizeof "chat" - 1) == 0) 84 break; 85 if (*zchat == '\0') 86 return UUCONF_SYNTAX_ERROR; 87 argv[0] = zchat; 88 89 _uuconf_ucmdtab_base (asChat_cmds, CCHAT_CMDS, (char *) qchat, as); 90 91 iret = uuconf_cmd_args ((pointer) qglobal, argc, argv, as, pblock, 92 icunknown, 0, pblock); 93 94 /* If chat-program was specified with no arguments, treat that as no 95 chat-program. This may be used to override an earlier 96 chat-program. There is a space leak here. */ 97 if (qchat->uuconf_pzprogram != NULL && qchat->uuconf_pzprogram[0] == NULL) 98 qchat->uuconf_pzprogram = NULL; 99 100 return iret &~ UUCONF_CMDTABRET_EXIT; 101} 102 103/* Handle the "chat" command. This breaks up substrings in expect 104 strings, and sticks the arguments into a NULL terminated array. */ 105 106static int 107icchat (pglobal, argc, argv, pvar, pinfo) 108 pointer pglobal; 109 int argc; 110 char **argv; 111 pointer pvar; 112 pointer pinfo; 113{ 114 struct sglobal *qglobal = (struct sglobal *) pglobal; 115 char ***ppz = (char ***) pvar; 116 pointer pblock = pinfo; 117 int i; 118 119 *ppz = NULL; 120 121 for (i = 1; i < argc; i += 2) 122 { 123 char *z, *zdash; 124 int iret; 125 126 /* Break the expect string into substrings. */ 127 z = argv[i]; 128 zdash = strchr (z, '-'); 129 while (zdash != NULL) 130 { 131 *zdash = '\0'; 132 iret = _uuconf_iadd_string (qglobal, z, TRUE, FALSE, ppz, 133 pblock); 134 if (iret != UUCONF_SUCCESS) 135 return iret; 136 *zdash = '-'; 137 z = zdash; 138 zdash = strchr (z + 1, '-'); 139 } 140 141 iret = _uuconf_iadd_string (qglobal, z, FALSE, FALSE, ppz, pblock); 142 if (iret != UUCONF_SUCCESS) 143 return iret; 144 145 /* Add the send string without breaking it up. If it starts 146 with a dash we must replace it with an escape sequence, to 147 prevent it from being interpreted as a subsend. */ 148 149 if (i + 1 < argc) 150 { 151 if (argv[i + 1][0] != '-') 152 iret = _uuconf_iadd_string (qglobal, argv[i + 1], FALSE, 153 FALSE, ppz, pblock); 154 else 155 { 156 size_t clen; 157 158 clen = strlen (argv[i + 1]); 159 z = uuconf_malloc (pblock, clen + 2); 160 if (z == NULL) 161 { 162 qglobal->ierrno = errno; 163 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; 164 } 165 z[0] = '\\'; 166 memcpy ((pointer) (z + 1), (pointer) argv[i + 1], clen + 1); 167 iret = _uuconf_iadd_string (qglobal, z, FALSE, FALSE, ppz, 168 pblock); 169 } 170 if (iret != UUCONF_SUCCESS) 171 return iret; 172 } 173 } 174 175 return UUCONF_CMDTABRET_KEEP; 176} 177 178/* Add a new chat failure string. */ 179 180/*ARGSUSED*/ 181static int 182icchat_fail (pglobal, argc, argv, pvar, pinfo) 183 pointer pglobal; 184 int argc ATTRIBUTE_UNUSED; 185 char **argv; 186 pointer pvar; 187 pointer pinfo; 188{ 189 struct sglobal *qglobal = (struct sglobal *) pglobal; 190 char ***ppz = (char ***) pvar; 191 pointer pblock = pinfo; 192 193 return _uuconf_iadd_string (qglobal, argv[1], TRUE, FALSE, ppz, pblock); 194} 195 196/* Return a syntax error for an unknown command. */ 197 198/*ARGSUSED*/ 199static int 200icunknown (pglobal, argc, argv, pvar, pinfo) 201 pointer pglobal ATTRIBUTE_UNUSED; 202 int argc ATTRIBUTE_UNUSED; 203 char **argv ATTRIBUTE_UNUSED; 204 pointer pvar ATTRIBUTE_UNUSED; 205 pointer pinfo ATTRIBUTE_UNUSED; 206{ 207 return UUCONF_SYNTAX_ERROR; 208} 209