1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Most of codes are derived from chat.c by Karl Fox (karl@MorningStar.Com). 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Chat -- a program for automatic session establishment (i.e. dial 9af57ed9fSAtsushi Murai * the phone and log in). 10af57ed9fSAtsushi Murai * 11af57ed9fSAtsushi Murai * This software is in the public domain. 12af57ed9fSAtsushi Murai * 13af57ed9fSAtsushi Murai * Please send all bug reports, requests for information, etc. to: 14af57ed9fSAtsushi Murai * 15af57ed9fSAtsushi Murai * Karl Fox <karl@MorningStar.Com> 16af57ed9fSAtsushi Murai * Morning Star Technologies, Inc. 17af57ed9fSAtsushi Murai * 1760 Zollinger Road 18af57ed9fSAtsushi Murai * Columbus, OH 43221 19af57ed9fSAtsushi Murai * (614)451-1883 20af57ed9fSAtsushi Murai * 211dff3fc5SAndrey A. Chernov * $Id: chat.c,v 1.5 1995/09/02 17:20:50 amurai Exp $ 22af57ed9fSAtsushi Murai * 23af57ed9fSAtsushi Murai * TODO: 24af57ed9fSAtsushi Murai * o Support more UUCP compatible control sequences. 25af57ed9fSAtsushi Murai * o Dialing shoud not block monitor process. 2684b8a6ebSAtsushi Murai * o Reading modem by select should be unified into main.c 27af57ed9fSAtsushi Murai */ 28af57ed9fSAtsushi Murai #include "defs.h" 29af57ed9fSAtsushi Murai #include <ctype.h> 30af57ed9fSAtsushi Murai #include <sys/uio.h> 31af57ed9fSAtsushi Murai #ifndef isblank 32af57ed9fSAtsushi Murai #define isblank(c) ((c) == '\t' || (c) == ' ') 33af57ed9fSAtsushi Murai #endif 34af57ed9fSAtsushi Murai #include <sys/time.h> 35af57ed9fSAtsushi Murai #include <fcntl.h> 3653c9f6c0SAtsushi Murai #include <errno.h> 3753c9f6c0SAtsushi Murai #include <signal.h> 3853c9f6c0SAtsushi Murai #include <sys/wait.h> 39af57ed9fSAtsushi Murai #include "timeout.h" 40af57ed9fSAtsushi Murai #include "vars.h" 41af57ed9fSAtsushi Murai 4253c9f6c0SAtsushi Murai #define IBSIZE 200 4353c9f6c0SAtsushi Murai 44af57ed9fSAtsushi Murai static int TimeoutSec; 45af57ed9fSAtsushi Murai static int abort_next, timeout_next; 46af57ed9fSAtsushi Murai static int numaborts; 47af57ed9fSAtsushi Murai char *AbortStrings[50]; 4853c9f6c0SAtsushi Murai char inbuff[IBSIZE]; 49af57ed9fSAtsushi Murai 50af57ed9fSAtsushi Murai extern int ChangeParity(char *); 51af57ed9fSAtsushi Murai 52af57ed9fSAtsushi Murai #define MATCH 1 53af57ed9fSAtsushi Murai #define NOMATCH 0 54af57ed9fSAtsushi Murai #define ABORT -1 55af57ed9fSAtsushi Murai 56af57ed9fSAtsushi Murai static char * 57af57ed9fSAtsushi Murai findblank(p, instring) 58af57ed9fSAtsushi Murai char *p; 59af57ed9fSAtsushi Murai int instring; 60af57ed9fSAtsushi Murai { 61af57ed9fSAtsushi Murai if (instring) { 62af57ed9fSAtsushi Murai while (*p) { 63af57ed9fSAtsushi Murai if (*p == '\\') { 64af57ed9fSAtsushi Murai strcpy(p, p + 1); 65af57ed9fSAtsushi Murai if (!*p) 66af57ed9fSAtsushi Murai break; 67af57ed9fSAtsushi Murai } else if (*p == '"') 68af57ed9fSAtsushi Murai return(p); 69af57ed9fSAtsushi Murai p++; 70af57ed9fSAtsushi Murai } 71af57ed9fSAtsushi Murai } else { 72af57ed9fSAtsushi Murai while (*p) { 73af57ed9fSAtsushi Murai if (isblank(*p)) 74af57ed9fSAtsushi Murai return(p); 75af57ed9fSAtsushi Murai p++; 76af57ed9fSAtsushi Murai } 77af57ed9fSAtsushi Murai } 78af57ed9fSAtsushi Murai return p; 79af57ed9fSAtsushi Murai } 80af57ed9fSAtsushi Murai 81af57ed9fSAtsushi Murai int 82af57ed9fSAtsushi Murai MakeArgs(script, pvect) 83af57ed9fSAtsushi Murai char *script; 84af57ed9fSAtsushi Murai char **pvect; 85af57ed9fSAtsushi Murai { 86af57ed9fSAtsushi Murai int nargs, nb; 87af57ed9fSAtsushi Murai int instring; 88af57ed9fSAtsushi Murai 89af57ed9fSAtsushi Murai nargs = 0; 90af57ed9fSAtsushi Murai while (*script) { 91af57ed9fSAtsushi Murai nb = strspn(script, " \t"); 92af57ed9fSAtsushi Murai script += nb; 93af57ed9fSAtsushi Murai if (*script) { 94af57ed9fSAtsushi Murai if (*script == '"') { 95af57ed9fSAtsushi Murai instring = 1; 96af57ed9fSAtsushi Murai script++; 97af57ed9fSAtsushi Murai if (*script == '\0') 98af57ed9fSAtsushi Murai return(nargs); 99af57ed9fSAtsushi Murai } else 100af57ed9fSAtsushi Murai instring = 0; 101af57ed9fSAtsushi Murai *pvect++ = script; 102af57ed9fSAtsushi Murai nargs++; 103af57ed9fSAtsushi Murai script = findblank(script, instring); 104af57ed9fSAtsushi Murai if (*script) 105af57ed9fSAtsushi Murai *script++ = '\0'; 106af57ed9fSAtsushi Murai } 107af57ed9fSAtsushi Murai } 108af57ed9fSAtsushi Murai *pvect = NULL; 109af57ed9fSAtsushi Murai return nargs; 110af57ed9fSAtsushi Murai } 111af57ed9fSAtsushi Murai 112af57ed9fSAtsushi Murai /* 113af57ed9fSAtsushi Murai * \r Carrige return character 114af57ed9fSAtsushi Murai * \s Space character 115af57ed9fSAtsushi Murai * \n Line feed character 1161dff3fc5SAndrey A. Chernov * \T Telephone number(s) (defined via `set phone') 117af57ed9fSAtsushi Murai * \t Tab character 118af57ed9fSAtsushi Murai */ 119af57ed9fSAtsushi Murai char * 120af57ed9fSAtsushi Murai ExpandString(str, result, sendmode) 121af57ed9fSAtsushi Murai char *str; 122af57ed9fSAtsushi Murai char *result; 123af57ed9fSAtsushi Murai int sendmode; 124af57ed9fSAtsushi Murai { 125af57ed9fSAtsushi Murai int addcr = 0; 1261dff3fc5SAndrey A. Chernov char *phone; 127af57ed9fSAtsushi Murai 128af57ed9fSAtsushi Murai if (sendmode) 129af57ed9fSAtsushi Murai addcr = 1; 130af57ed9fSAtsushi Murai while (*str) { 131af57ed9fSAtsushi Murai switch (*str) { 132af57ed9fSAtsushi Murai case '\\': 133af57ed9fSAtsushi Murai str++; 134af57ed9fSAtsushi Murai switch (*str) { 135af57ed9fSAtsushi Murai case 'c': 136af57ed9fSAtsushi Murai if (sendmode) 137af57ed9fSAtsushi Murai addcr = 0; 138af57ed9fSAtsushi Murai break; 139af57ed9fSAtsushi Murai case 'd': /* Delay 2 seconds */ 140af57ed9fSAtsushi Murai sleep(2); break; 141af57ed9fSAtsushi Murai case 'p': 142af57ed9fSAtsushi Murai usleep(250000); break; /* Pause 0.25 sec */ 143af57ed9fSAtsushi Murai case 'n': 144af57ed9fSAtsushi Murai *result++ = '\n'; break; 145af57ed9fSAtsushi Murai case 'r': 146af57ed9fSAtsushi Murai *result++ = '\r'; break; 147af57ed9fSAtsushi Murai case 's': 148af57ed9fSAtsushi Murai *result++ = ' '; break; 149af57ed9fSAtsushi Murai case 't': 150af57ed9fSAtsushi Murai *result++ = '\t'; break; 151af57ed9fSAtsushi Murai case 'P': 152af57ed9fSAtsushi Murai bcopy(VarAuthKey, result, strlen(VarAuthKey)); 153af57ed9fSAtsushi Murai result += strlen(VarAuthKey); 154af57ed9fSAtsushi Murai break; 155af57ed9fSAtsushi Murai case 'T': 1561dff3fc5SAndrey A. Chernov if (VarNextPhone == NULL) 1571dff3fc5SAndrey A. Chernov VarNextPhone = VarPhoneList; 1581dff3fc5SAndrey A. Chernov phone = strsep(&VarNextPhone, ":"); 1591dff3fc5SAndrey A. Chernov bcopy(phone, result, strlen(phone)); 1601dff3fc5SAndrey A. Chernov result += strlen(phone); 1611dff3fc5SAndrey A. Chernov if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER) 1621dff3fc5SAndrey A. Chernov fprintf(stderr, "Phone: %s\n", phone); 163af57ed9fSAtsushi Murai break; 164af57ed9fSAtsushi Murai case 'U': 165af57ed9fSAtsushi Murai bcopy(VarAuthName, result, strlen(VarAuthName)); 166af57ed9fSAtsushi Murai result += strlen(VarAuthName); 167af57ed9fSAtsushi Murai break; 168af57ed9fSAtsushi Murai default: 169af57ed9fSAtsushi Murai *result++ = *str; break; 170af57ed9fSAtsushi Murai } 171af57ed9fSAtsushi Murai if (*str) str++; 172af57ed9fSAtsushi Murai break; 173af57ed9fSAtsushi Murai case '^': 174af57ed9fSAtsushi Murai str++; 175af57ed9fSAtsushi Murai if (*str) 176af57ed9fSAtsushi Murai *result++ = *str++ & 0x1f; 177af57ed9fSAtsushi Murai break; 178af57ed9fSAtsushi Murai default: 179af57ed9fSAtsushi Murai *result++ = *str++; 180af57ed9fSAtsushi Murai break; 181af57ed9fSAtsushi Murai } 182af57ed9fSAtsushi Murai } 183af57ed9fSAtsushi Murai if (addcr) 184af57ed9fSAtsushi Murai *result++ = '\r'; 185af57ed9fSAtsushi Murai *result++ = '\0'; 186af57ed9fSAtsushi Murai return(result); 187af57ed9fSAtsushi Murai } 188af57ed9fSAtsushi Murai 189af57ed9fSAtsushi Murai int 190af57ed9fSAtsushi Murai WaitforString(estr) 191af57ed9fSAtsushi Murai char *estr; 192af57ed9fSAtsushi Murai { 193af57ed9fSAtsushi Murai struct timeval timeout; 194af57ed9fSAtsushi Murai char *s, *str, ch; 195af57ed9fSAtsushi Murai char *inp; 196af57ed9fSAtsushi Murai fd_set rfds; 19753c9f6c0SAtsushi Murai int i, nfds, nb; 198af57ed9fSAtsushi Murai char buff[200]; 199af57ed9fSAtsushi Murai 20053c9f6c0SAtsushi Murai #ifdef SIGALRM 20153c9f6c0SAtsushi Murai int omask; 20253c9f6c0SAtsushi Murai omask = sigblock(sigmask(SIGALRM)); 20353c9f6c0SAtsushi Murai #endif 204af57ed9fSAtsushi Murai (void) ExpandString(estr, buff, 0); 205af57ed9fSAtsushi Murai LogPrintf(LOG_CHAT, "Wait for (%d): %s --> %s\n", TimeoutSec, estr, buff); 206af57ed9fSAtsushi Murai str = buff; 207af57ed9fSAtsushi Murai inp = inbuff; 208af57ed9fSAtsushi Murai 209af57ed9fSAtsushi Murai nfds = modem + 1; 210af57ed9fSAtsushi Murai s = str; 211af57ed9fSAtsushi Murai for (;;) { 212af57ed9fSAtsushi Murai FD_ZERO(&rfds); 213af57ed9fSAtsushi Murai FD_SET(modem, &rfds); 214af57ed9fSAtsushi Murai /* 215af57ed9fSAtsushi Murai * Because it is not clear whether select() modifies timeout value, 216af57ed9fSAtsushi Murai * it is better to initialize timeout values everytime. 217af57ed9fSAtsushi Murai */ 218af57ed9fSAtsushi Murai timeout.tv_sec = TimeoutSec; 219af57ed9fSAtsushi Murai timeout.tv_usec = 0; 220af57ed9fSAtsushi Murai i = select(nfds, &rfds, NULL, NULL, &timeout); 221af57ed9fSAtsushi Murai #ifdef notdef 222af57ed9fSAtsushi Murai TimerService(); 223af57ed9fSAtsushi Murai #endif 224af57ed9fSAtsushi Murai if (i < 0) { 22553c9f6c0SAtsushi Murai #ifdef SIGALRM 22653c9f6c0SAtsushi Murai if (errno == EINTR) 22753c9f6c0SAtsushi Murai continue; 22853c9f6c0SAtsushi Murai sigsetmask(omask); 22953c9f6c0SAtsushi Murai #endif 230af57ed9fSAtsushi Murai perror("select"); 23153c9f6c0SAtsushi Murai *inp = 0; 232af57ed9fSAtsushi Murai return(NOMATCH); 233af57ed9fSAtsushi Murai } else if (i == 0) { /* Timeout reached! */ 23453c9f6c0SAtsushi Murai *inp = 0; 23553c9f6c0SAtsushi Murai if (inp != inbuff) 23653c9f6c0SAtsushi Murai LogPrintf(LOG_CHAT, "got: %s\n", inbuff); 237af57ed9fSAtsushi Murai LogPrintf(LOG_CHAT, "can't get (%d).\n", timeout.tv_sec); 23853c9f6c0SAtsushi Murai #ifdef SIGALRM 23953c9f6c0SAtsushi Murai sigsetmask(omask); 24053c9f6c0SAtsushi Murai #endif 241af57ed9fSAtsushi Murai return(NOMATCH); 242af57ed9fSAtsushi Murai } 243af57ed9fSAtsushi Murai if (FD_ISSET(modem, &rfds)) { /* got something */ 24453c9f6c0SAtsushi Murai if (DEV_IS_SYNC) { 24553c9f6c0SAtsushi Murai nb = read(modem, inbuff, IBSIZE-1); 24653c9f6c0SAtsushi Murai inbuff[nb] = 0; 24753c9f6c0SAtsushi Murai if (strstr(inbuff, str)) { 24853c9f6c0SAtsushi Murai #ifdef SIGALRM 24953c9f6c0SAtsushi Murai sigsetmask(omask); 25053c9f6c0SAtsushi Murai #endif 25153c9f6c0SAtsushi Murai return(MATCH); 25253c9f6c0SAtsushi Murai } 25353c9f6c0SAtsushi Murai for (i = 0; i < numaborts; i++) { 25453c9f6c0SAtsushi Murai if (strstr(inbuff, AbortStrings[i])) { 25553c9f6c0SAtsushi Murai LogPrintf(LOG_CHAT, "Abort: %s\n", AbortStrings[i]); 25653c9f6c0SAtsushi Murai #ifdef SIGALRM 25753c9f6c0SAtsushi Murai sigsetmask(omask); 25853c9f6c0SAtsushi Murai #endif 25953c9f6c0SAtsushi Murai return(ABORT); 26053c9f6c0SAtsushi Murai } 26153c9f6c0SAtsushi Murai } 26253c9f6c0SAtsushi Murai } else { 263af57ed9fSAtsushi Murai read(modem, &ch, 1); 264af57ed9fSAtsushi Murai *inp++ = ch; 265af57ed9fSAtsushi Murai if (ch == *s) { 266af57ed9fSAtsushi Murai s++; 267af57ed9fSAtsushi Murai if (*s == '\0') { 26853c9f6c0SAtsushi Murai #ifdef SIGALRM 26953c9f6c0SAtsushi Murai sigsetmask(omask); 27053c9f6c0SAtsushi Murai #endif 27153c9f6c0SAtsushi Murai *inp = 0; 272af57ed9fSAtsushi Murai return(MATCH); 273af57ed9fSAtsushi Murai } 274af57ed9fSAtsushi Murai } else { 275af57ed9fSAtsushi Murai s = str; 276af57ed9fSAtsushi Murai if (inp == inbuff+ IBSIZE) { 277af57ed9fSAtsushi Murai bcopy(inp - 100, inbuff, 100); 278af57ed9fSAtsushi Murai inp = inbuff + 100; 279af57ed9fSAtsushi Murai } 280af57ed9fSAtsushi Murai for (i = 0; i < numaborts; i++) { /* Look for Abort strings */ 281af57ed9fSAtsushi Murai int len; 282af57ed9fSAtsushi Murai char *s1; 283af57ed9fSAtsushi Murai 284af57ed9fSAtsushi Murai s1 = AbortStrings[i]; 285af57ed9fSAtsushi Murai len = strlen(s1); 286af57ed9fSAtsushi Murai if ((len <= inp - inbuff) && (strncmp(inp - len, s1, len) == 0)) { 287af57ed9fSAtsushi Murai LogPrintf(LOG_CHAT, "Abort: %s\n", s1); 28853c9f6c0SAtsushi Murai *inp = 0; 28953c9f6c0SAtsushi Murai #ifdef SIGALRM 29053c9f6c0SAtsushi Murai sigsetmask(omask); 29153c9f6c0SAtsushi Murai #endif 292af57ed9fSAtsushi Murai return(ABORT); 293af57ed9fSAtsushi Murai } 294af57ed9fSAtsushi Murai } 295af57ed9fSAtsushi Murai } 296af57ed9fSAtsushi Murai } 297af57ed9fSAtsushi Murai } 298af57ed9fSAtsushi Murai } 29953c9f6c0SAtsushi Murai #ifdef SIGALRM 30053c9f6c0SAtsushi Murai sigsetmask(omask); 30153c9f6c0SAtsushi Murai #endif 30253c9f6c0SAtsushi Murai } 30353c9f6c0SAtsushi Murai 30453c9f6c0SAtsushi Murai void 30553c9f6c0SAtsushi Murai ExecStr(command, out) 30653c9f6c0SAtsushi Murai char *command, *out; 30753c9f6c0SAtsushi Murai { 30853c9f6c0SAtsushi Murai int pid; 30953c9f6c0SAtsushi Murai int fids[2]; 31053c9f6c0SAtsushi Murai char *vector[20]; 31153c9f6c0SAtsushi Murai int stat, nb; 31253c9f6c0SAtsushi Murai char *cp; 31353c9f6c0SAtsushi Murai char tmp[300]; 31453c9f6c0SAtsushi Murai extern int errno; 31553c9f6c0SAtsushi Murai 31653c9f6c0SAtsushi Murai cp = inbuff + strlen(inbuff) - 1; 31753c9f6c0SAtsushi Murai while (cp > inbuff) { 31853c9f6c0SAtsushi Murai if (*cp < ' ' && *cp != '\t') { 31953c9f6c0SAtsushi Murai cp++; 32053c9f6c0SAtsushi Murai break; 32153c9f6c0SAtsushi Murai } 32253c9f6c0SAtsushi Murai cp--; 32353c9f6c0SAtsushi Murai } 32453c9f6c0SAtsushi Murai sprintf(tmp, "%s %s", command, cp); 32553c9f6c0SAtsushi Murai (void) MakeArgs(tmp, &vector); 32653c9f6c0SAtsushi Murai 32753c9f6c0SAtsushi Murai pipe(fids); 32853c9f6c0SAtsushi Murai pid = fork(); 32953c9f6c0SAtsushi Murai if (pid == 0) { 33053c9f6c0SAtsushi Murai signal(SIGINT, SIG_DFL); 33153c9f6c0SAtsushi Murai signal(SIGQUIT, SIG_DFL); 33253c9f6c0SAtsushi Murai signal(SIGTERM, SIG_DFL); 33353c9f6c0SAtsushi Murai signal(SIGHUP, SIG_DFL); 33453c9f6c0SAtsushi Murai close(fids[0]); 33553c9f6c0SAtsushi Murai dup2(fids[1], 1); 33653c9f6c0SAtsushi Murai close(fids[1]); 33753c9f6c0SAtsushi Murai nb = open("/dev/tty", O_RDWR); 33853c9f6c0SAtsushi Murai dup2(nb, 0); 33953c9f6c0SAtsushi Murai LogPrintf(LOG_CHAT, "exec: %s\n", command); 34053c9f6c0SAtsushi Murai pid = execvp(command, vector); 34153c9f6c0SAtsushi Murai LogPrintf(LOG_CHAT, "execvp failed for (%d/%d): %s\n", pid, errno, command); 34253c9f6c0SAtsushi Murai exit(127); 34353c9f6c0SAtsushi Murai } else { 34453c9f6c0SAtsushi Murai close(fids[1]); 34553c9f6c0SAtsushi Murai for (;;) { 34653c9f6c0SAtsushi Murai nb = read(fids[0], out, 1); 34753c9f6c0SAtsushi Murai if (nb <= 0) 34853c9f6c0SAtsushi Murai break; 34953c9f6c0SAtsushi Murai out++; 35053c9f6c0SAtsushi Murai } 35153c9f6c0SAtsushi Murai *out = '\0'; 35253c9f6c0SAtsushi Murai close(fids[0]); 35353c9f6c0SAtsushi Murai close(fids[1]); 35453c9f6c0SAtsushi Murai waitpid(pid, &stat, WNOHANG); 35553c9f6c0SAtsushi Murai } 35653c9f6c0SAtsushi Murai } 357af57ed9fSAtsushi Murai 358af57ed9fSAtsushi Murai void 359af57ed9fSAtsushi Murai SendString(str) 360af57ed9fSAtsushi Murai char *str; 361af57ed9fSAtsushi Murai { 36253c9f6c0SAtsushi Murai char *cp; 36353c9f6c0SAtsushi Murai int nb, on; 364af57ed9fSAtsushi Murai char buff[200]; 365af57ed9fSAtsushi Murai 366af57ed9fSAtsushi Murai if (abort_next) { 367af57ed9fSAtsushi Murai abort_next = 0; 368af57ed9fSAtsushi Murai ExpandString(str, buff, 0); 369af57ed9fSAtsushi Murai AbortStrings[numaborts++] = strdup(buff); 370af57ed9fSAtsushi Murai } else if (timeout_next) { 371af57ed9fSAtsushi Murai timeout_next = 0; 372af57ed9fSAtsushi Murai TimeoutSec = atoi(str); 373af57ed9fSAtsushi Murai if (TimeoutSec <= 0) 374af57ed9fSAtsushi Murai TimeoutSec = 30; 375af57ed9fSAtsushi Murai } else { 37653c9f6c0SAtsushi Murai if (*str == '!') { 37753c9f6c0SAtsushi Murai (void) ExpandString(str+1, buff+2, 0); 37853c9f6c0SAtsushi Murai ExecStr(buff + 2, buff + 2); 37953c9f6c0SAtsushi Murai } else { 38053c9f6c0SAtsushi Murai (void) ExpandString(str, buff+2, 1); 38153c9f6c0SAtsushi Murai } 382c3899f8dSAtsushi Murai if (strstr(str, "\\P")) { /* Do not log the password itself. */ 383c3899f8dSAtsushi Murai LogPrintf(LOG_CHAT, "sending: %s\n", str); 384c3899f8dSAtsushi Murai } else { 38553c9f6c0SAtsushi Murai LogPrintf(LOG_CHAT, "sending: %s\n", buff+2); 386c3899f8dSAtsushi Murai } 38753c9f6c0SAtsushi Murai cp = buff; 38853c9f6c0SAtsushi Murai if (DEV_IS_SYNC) 38953c9f6c0SAtsushi Murai bcopy("\377\003", buff, 2); /* Prepend HDLC header */ 39053c9f6c0SAtsushi Murai else 39153c9f6c0SAtsushi Murai cp += 2; 39253c9f6c0SAtsushi Murai on = strlen(cp); 39353c9f6c0SAtsushi Murai nb = write(modem, cp, on); 394af57ed9fSAtsushi Murai } 395af57ed9fSAtsushi Murai } 396af57ed9fSAtsushi Murai 397af57ed9fSAtsushi Murai int 398af57ed9fSAtsushi Murai ExpectString(str) 399af57ed9fSAtsushi Murai char *str; 400af57ed9fSAtsushi Murai { 401af57ed9fSAtsushi Murai char *minus; 402af57ed9fSAtsushi Murai int state; 403af57ed9fSAtsushi Murai 404af57ed9fSAtsushi Murai if (strcmp(str, "ABORT") == 0) { 405af57ed9fSAtsushi Murai ++abort_next; 406af57ed9fSAtsushi Murai return(MATCH); 407af57ed9fSAtsushi Murai } 408af57ed9fSAtsushi Murai if (strcmp(str, "TIMEOUT") == 0) { 409af57ed9fSAtsushi Murai ++timeout_next; 410af57ed9fSAtsushi Murai return(MATCH); 411af57ed9fSAtsushi Murai } 412af57ed9fSAtsushi Murai LogPrintf(LOG_CHAT, "Expecting %s\n", str); 413af57ed9fSAtsushi Murai while (*str) { 414af57ed9fSAtsushi Murai /* 415af57ed9fSAtsushi Murai * Check whether if string contains sub-send-expect. 416af57ed9fSAtsushi Murai */ 417af57ed9fSAtsushi Murai for (minus = str; *minus; minus++) { 418af57ed9fSAtsushi Murai if (*minus == '-') { 419af57ed9fSAtsushi Murai if (minus == str || minus[-1] != '\\') 420af57ed9fSAtsushi Murai break; 421af57ed9fSAtsushi Murai } 422af57ed9fSAtsushi Murai } 423af57ed9fSAtsushi Murai if (*minus == '-') { /* We have sub-send-expect. */ 424af57ed9fSAtsushi Murai *minus++ = '\0'; 425af57ed9fSAtsushi Murai state = WaitforString(str); 426af57ed9fSAtsushi Murai if (state != NOMATCH) 427af57ed9fSAtsushi Murai return(state); 428af57ed9fSAtsushi Murai /* 429af57ed9fSAtsushi Murai * Can't get expect string. Sendout send part. 430af57ed9fSAtsushi Murai */ 431af57ed9fSAtsushi Murai str = minus; 432af57ed9fSAtsushi Murai for (minus = str; *minus; minus++) { 433af57ed9fSAtsushi Murai if (*minus == '-') { 434af57ed9fSAtsushi Murai if (minus == str || minus[-1] != '\\') 435af57ed9fSAtsushi Murai break; 436af57ed9fSAtsushi Murai } 437af57ed9fSAtsushi Murai } 438af57ed9fSAtsushi Murai if (*minus == '-') { 439af57ed9fSAtsushi Murai *minus++ = '\0'; 440af57ed9fSAtsushi Murai SendString(str); 441af57ed9fSAtsushi Murai str = minus; 442af57ed9fSAtsushi Murai } else { 443af57ed9fSAtsushi Murai SendString(str); 444af57ed9fSAtsushi Murai return(MATCH); 445af57ed9fSAtsushi Murai } 446af57ed9fSAtsushi Murai } else { 447af57ed9fSAtsushi Murai /* 448af57ed9fSAtsushi Murai * Simple case. Wait for string. 449af57ed9fSAtsushi Murai */ 450af57ed9fSAtsushi Murai return(WaitforString(str)); 451af57ed9fSAtsushi Murai } 452af57ed9fSAtsushi Murai } 453af57ed9fSAtsushi Murai return(MATCH); 454af57ed9fSAtsushi Murai } 455af57ed9fSAtsushi Murai 456af57ed9fSAtsushi Murai int 457af57ed9fSAtsushi Murai DoChat(script) 458af57ed9fSAtsushi Murai char *script; 459af57ed9fSAtsushi Murai { 460af57ed9fSAtsushi Murai char *vector[20]; 461af57ed9fSAtsushi Murai char **argv; 462af57ed9fSAtsushi Murai int argc, n, state; 463af57ed9fSAtsushi Murai #ifdef DEBUG 464af57ed9fSAtsushi Murai int i; 465af57ed9fSAtsushi Murai #endif 466af57ed9fSAtsushi Murai 467af57ed9fSAtsushi Murai timeout_next = abort_next = 0; 468af57ed9fSAtsushi Murai for (n = 0; AbortStrings[n]; n++) { 469af57ed9fSAtsushi Murai free(AbortStrings[n]); 470af57ed9fSAtsushi Murai AbortStrings[n] = NULL; 471af57ed9fSAtsushi Murai } 472af57ed9fSAtsushi Murai numaborts = 0; 473af57ed9fSAtsushi Murai 474af57ed9fSAtsushi Murai bzero(vector, sizeof(vector)); 475af57ed9fSAtsushi Murai n = MakeArgs(script, &vector); 476af57ed9fSAtsushi Murai #ifdef DEBUG 477af57ed9fSAtsushi Murai logprintf("n = %d\n", n); 478af57ed9fSAtsushi Murai for (i = 0; i < n; i++) 479af57ed9fSAtsushi Murai logprintf(" %s\n", vector[i]); 480af57ed9fSAtsushi Murai #endif 481af57ed9fSAtsushi Murai argc = n; 482af57ed9fSAtsushi Murai argv = vector; 483af57ed9fSAtsushi Murai TimeoutSec = 30; 484af57ed9fSAtsushi Murai while (*argv) { 485af57ed9fSAtsushi Murai if (strcmp(*argv, "P_ZERO") == 0 || 486af57ed9fSAtsushi Murai strcmp(*argv, "P_ODD") == 0 || strcmp(*argv, "P_EVEN") == 0) { 487af57ed9fSAtsushi Murai ChangeParity(*argv++); 488af57ed9fSAtsushi Murai continue; 489af57ed9fSAtsushi Murai } 490af57ed9fSAtsushi Murai state = ExpectString(*argv++); 491af57ed9fSAtsushi Murai switch (state) { 492af57ed9fSAtsushi Murai case MATCH: 493af57ed9fSAtsushi Murai if (*argv) 494af57ed9fSAtsushi Murai SendString(*argv++); 495af57ed9fSAtsushi Murai break; 496af57ed9fSAtsushi Murai case ABORT: 497af57ed9fSAtsushi Murai #ifdef notdef 498af57ed9fSAtsushi Murai HangupModem(); 499af57ed9fSAtsushi Murai #endif 500af57ed9fSAtsushi Murai case NOMATCH: 501af57ed9fSAtsushi Murai return(NOMATCH); 502af57ed9fSAtsushi Murai } 503af57ed9fSAtsushi Murai } 504af57ed9fSAtsushi Murai return(MATCH); 505af57ed9fSAtsushi Murai } 506