xref: /freebsd/usr.sbin/ppp/chat.c (revision 1dff3fc5656924dd70e1fe4420295230b6a0753c)
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