Deleted Added
full compact
chat.c (23585) chat.c (23840)
1/*
2 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
3 *
4 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
5 *
6 * Most of codes are derived from chat.c by Karl Fox (karl@MorningStar.Com).
7 *
8 * Chat -- a program for automatic session establishment (i.e. dial
9 * the phone and log in).
10 *
11 * This software is in the public domain.
12 *
13 * Please send all bug reports, requests for information, etc. to:
14 *
15 * Karl Fox <karl@MorningStar.Com>
16 * Morning Star Technologies, Inc.
17 * 1760 Zollinger Road
18 * Columbus, OH 43221
19 * (614)451-1883
20 *
1/*
2 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
3 *
4 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
5 *
6 * Most of codes are derived from chat.c by Karl Fox (karl@MorningStar.Com).
7 *
8 * Chat -- a program for automatic session establishment (i.e. dial
9 * the phone and log in).
10 *
11 * This software is in the public domain.
12 *
13 * Please send all bug reports, requests for information, etc. to:
14 *
15 * Karl Fox <karl@MorningStar.Com>
16 * Morning Star Technologies, Inc.
17 * 1760 Zollinger Road
18 * Columbus, OH 43221
19 * (614)451-1883
20 *
21 * $Id: chat.c,v 1.20 1997/03/09 20:03:34 ache Exp $
21 * $Id: chat.c,v 1.21 1997/03/09 20:09:14 ache Exp $
22 *
23 * TODO:
24 * o Support more UUCP compatible control sequences.
25 * o Dialing shoud not block monitor process.
26 * o Reading modem by select should be unified into main.c
27 */
28#include "defs.h"
29#include <ctype.h>
30#include <sys/uio.h>
31#ifndef isblank
32#define isblank(c) ((c) == '\t' || (c) == ' ')
33#endif
34#include <sys/time.h>
35#include <fcntl.h>
36#include <errno.h>
37#include <signal.h>
38#include <sys/wait.h>
39#include "timeout.h"
40#include "vars.h"
22 *
23 * TODO:
24 * o Support more UUCP compatible control sequences.
25 * o Dialing shoud not block monitor process.
26 * o Reading modem by select should be unified into main.c
27 */
28#include "defs.h"
29#include <ctype.h>
30#include <sys/uio.h>
31#ifndef isblank
32#define isblank(c) ((c) == '\t' || (c) == ' ')
33#endif
34#include <sys/time.h>
35#include <fcntl.h>
36#include <errno.h>
37#include <signal.h>
38#include <sys/wait.h>
39#include "timeout.h"
40#include "vars.h"
41#include "sig.h"
41
42#define IBSIZE 200
43
44static int TimeoutSec;
45static int abort_next, timeout_next;
46static int numaborts;
47char *AbortStrings[50];
48char inbuff[IBSIZE*2+1];
49
50extern int ChangeParity(char *);
51
52#define MATCH 1
53#define NOMATCH 0
54#define ABORT -1
55
56static char *
57findblank(p, instring)
58char *p;
59int instring;
60{
61 if (instring) {
62 while (*p) {
63 if (*p == '\\') {
64 strcpy(p, p + 1);
65 if (!*p)
66 break;
67 } else if (*p == '"')
68 return(p);
69 p++;
70 }
71 } else {
72 while (*p) {
73 if (isblank(*p))
74 return(p);
75 p++;
76 }
77 }
78 return p;
79}
80
81int
82MakeArgs(script, pvect)
83char *script;
84char **pvect;
85{
86 int nargs, nb;
87 int instring;
88
89 nargs = 0;
90 while (*script) {
91 nb = strspn(script, " \t");
92 script += nb;
93 if (*script) {
94 if (*script == '"') {
95 instring = 1;
96 script++;
97 if (*script == '\0')
98 return(nargs);
99 } else
100 instring = 0;
101 *pvect++ = script;
102 nargs++;
103 script = findblank(script, instring);
104 if (*script)
105 *script++ = '\0';
106 }
107 }
108 *pvect = NULL;
109 return nargs;
110}
111
112/*
113 * \c don't add a cr
114 * \d Sleep a little (delay 2 seconds
115 * \n Line feed character
116 * \P Auth Key password
117 * \p pause 0.25 sec
118 * \r Carrige return character
119 * \s Space character
120 * \T Telephone number(s) (defined via `set phone')
121 * \t Tab character
122 * \U Auth User
123 */
124char *
125ExpandString(str, result, reslen, sendmode)
126char *str;
127char *result;
128int reslen;
129int sendmode;
130{
131 int addcr = 0;
132 char *phone;
133
134 result[--reslen] = '\0';
135 if (sendmode)
136 addcr = 1;
137 while (*str && reslen > 0) {
138 switch (*str) {
139 case '\\':
140 str++;
141 switch (*str) {
142 case 'c':
143 if (sendmode)
144 addcr = 0;
145 break;
146 case 'd': /* Delay 2 seconds */
147 sleep(2); break;
148 case 'p':
149 usleep(250000); break; /* Pause 0.25 sec */
150 case 'n':
151 *result++ = '\n'; reslen--; break;
152 case 'r':
153 *result++ = '\r'; reslen--; break;
154 case 's':
155 *result++ = ' '; reslen--; break;
156 case 't':
157 *result++ = '\t'; reslen--; break;
158 case 'P':
159 strncpy(result, VarAuthKey, reslen);
160 reslen -= strlen(result);
161 result += strlen(result);
162 break;
163 case 'T':
164 if (VarNextPhone == NULL) {
165 strcpy(VarPhoneCopy, VarPhoneList);
166 VarNextPhone = VarPhoneCopy;
167 }
168 phone = strsep(&VarNextPhone, ":");
169 strncpy(result, phone, reslen);
170 reslen -= strlen(result);
171 result += strlen(result);
172 if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER)
173 fprintf(stderr, "Phone: %s\n", phone);
174 LogPrintf(LOG_PHASE_BIT, "Phone: %s\n", phone);
175 break;
176 case 'U':
177 strncpy(result, VarAuthName, reslen);
178 reslen -= strlen(result);
179 result += strlen(result);
180 break;
181 default:
182 reslen--;
183 *result++ = *str;
184 break;
185 }
186 if (*str)
187 str++;
188 break;
189 case '^':
190 str++;
191 if (*str) {
192 *result++ = *str++ & 0x1f;
193 reslen--;
194 }
195 break;
196 default:
197 *result++ = *str++;
198 reslen--;
199 break;
200 }
201 }
202 if (--reslen > 0) {
203 if (addcr)
204 *result++ = '\r';
205 }
206 if (--reslen > 0)
207 *result++ = '\0';
208 return(result);
209}
210
211#define MAXLOGBUFF 200
212static char logbuff[MAXLOGBUFF];
213static int loglen = 0;
214
215static void clear_log() {
216 memset(logbuff,0,MAXLOGBUFF);
217 loglen = 0;
218}
219
220static void flush_log() {
221 if ((loglevel & LOG_CONNECT_BIT)
222 || ((loglevel & LOG_CARRIER_BIT)
223 && strstr(logbuff,"CARRIER"))) {
224 LogPrintf(LOG_CONNECT_BIT|LOG_CARRIER_BIT,"Chat: %s\n",logbuff);
225 }
226 clear_log();
227}
228
229static void connect_log(char *str, int single_p) {
230 int space = MAXLOGBUFF - loglen - 1;
231
232 while (space--) {
233 if (*str == '\n') {
234 flush_log();
235 } else {
236 logbuff[loglen++] = *str;
237 }
238 if (single_p || !*++str) break;
239 }
240 if (!space) flush_log();
241}
242
243
244
245int
246WaitforString(estr)
247char *estr;
248{
249 struct timeval timeout;
250 char *s, *str, ch;
251 char *inp;
252 fd_set rfds;
253 int i, nfds, nb, msg;
254 char buff[200];
255
256
257#ifdef SIGALRM
258 int omask;
259 omask = sigblock(sigmask(SIGALRM));
260#endif
261 clear_log();
262 (void) ExpandString(estr, buff, sizeof(buff), 0);
263 LogPrintf(LOG_CHAT_BIT, "Wait for (%d): %s --> %s\n", TimeoutSec, estr, buff);
264 str = buff;
265 inp = inbuff;
266
267 if (strlen(str)>=IBSIZE){
268 str[IBSIZE]=0;
269 LogPrintf(LOG_CHAT_BIT, "Truncating String to %d character: %s\n", IBSIZE, str);
270 }
271
272 nfds = modem + 1;
273 s = str;
274 msg = FALSE;
275 for (;;) {
276 FD_ZERO(&rfds);
277 FD_SET(modem, &rfds);
278 /*
279 * Because it is not clear whether select() modifies timeout value,
280 * it is better to initialize timeout values everytime.
281 */
282 timeout.tv_sec = TimeoutSec;
283 timeout.tv_usec = 0;
284 i = select(nfds, &rfds, NULL, NULL, &timeout);
285#ifdef notdef
286 TimerService();
287#endif
288 if (i < 0) {
289#ifdef SIGALRM
290 if (errno == EINTR)
291 continue;
292 sigsetmask(omask);
293#endif
294 perror("select");
295 *inp = 0;
296 return(NOMATCH);
297 } else if (i == 0) { /* Timeout reached! */
298 *inp = 0;
299 if (inp != inbuff)
300 LogPrintf(LOG_CHAT_BIT, "got: %s\n", inbuff);
301 LogPrintf(LOG_CHAT_BIT, "can't get (%d).\n", timeout.tv_sec);
302#ifdef SIGALRM
303 sigsetmask(omask);
304#endif
305 return(NOMATCH);
306 }
307 if (FD_ISSET(modem, &rfds)) { /* got something */
308 if (DEV_IS_SYNC) {
309 int length;
310 if ((length=strlen(inbuff))>IBSIZE){
311 bcopy(&(inbuff[IBSIZE]),inbuff,IBSIZE+1); /* shuffle down next part*/
312 length=strlen(inbuff);
313 }
314 nb = read(modem, &(inbuff[length]), IBSIZE);
315 inbuff[nb + length] = 0;
316 connect_log(inbuff,0);
317 if (strstr(inbuff, str)) {
318#ifdef SIGALRM
319 sigsetmask(omask);
320#endif
321 flush_log();
322 return(MATCH);
323 }
324 for (i = 0; i < numaborts; i++) {
325 if (strstr(inbuff, AbortStrings[i])) {
326 LogPrintf(LOG_CHAT_BIT, "Abort: %s\n", AbortStrings[i]);
327#ifdef SIGALRM
328 sigsetmask(omask);
329#endif
330 flush_log();
331 return(ABORT);
332 }
333 }
334 } else {
335 read(modem, &ch, 1);
336 connect_log(&ch,1);
337 *inp++ = ch;
338 if (ch == *s) {
339 s++;
340 if (*s == '\0') {
341#ifdef SIGALRM
342 sigsetmask(omask);
343#endif
344 *inp = 0;
345 flush_log();
346 return(MATCH);
347 }
348 } else {
349 s = str;
350 if (inp == inbuff+ IBSIZE) {
351 bcopy(inp - 100, inbuff, 100);
352 inp = inbuff + 100;
353 }
354 for (i = 0; i < numaborts; i++) { /* Look for Abort strings */
355 int len;
356 char *s1;
357
358 s1 = AbortStrings[i];
359 len = strlen(s1);
360 if ((len <= inp - inbuff) && (strncmp(inp - len, s1, len) == 0)) {
361 LogPrintf(LOG_CHAT_BIT, "Abort: %s\n", s1);
362 *inp = 0;
363#ifdef SIGALRM
364 sigsetmask(omask);
365#endif
366 flush_log();
367 return(ABORT);
368 }
369 }
370 }
371 }
372 }
373 }
374#ifdef SIGALRM
375 sigsetmask(omask);
376#endif
377}
378
379void
380ExecStr(command, out)
381char *command, *out;
382{
383 int pid;
384 int fids[2];
385 char *vector[20];
386 int stat, nb;
387 char *cp;
388 char tmp[300];
389 extern int errno;
390
391 cp = inbuff + strlen(inbuff) - 1;
392 while (cp > inbuff) {
393 if (*cp < ' ' && *cp != '\t') {
394 cp++;
395 break;
396 }
397 cp--;
398 }
399 snprintf(tmp, sizeof tmp, "%s %s", command, cp);
400 (void) MakeArgs(tmp, &vector);
401
402 pipe(fids);
403 pid = fork();
404 if (pid == 0) {
42
43#define IBSIZE 200
44
45static int TimeoutSec;
46static int abort_next, timeout_next;
47static int numaborts;
48char *AbortStrings[50];
49char inbuff[IBSIZE*2+1];
50
51extern int ChangeParity(char *);
52
53#define MATCH 1
54#define NOMATCH 0
55#define ABORT -1
56
57static char *
58findblank(p, instring)
59char *p;
60int instring;
61{
62 if (instring) {
63 while (*p) {
64 if (*p == '\\') {
65 strcpy(p, p + 1);
66 if (!*p)
67 break;
68 } else if (*p == '"')
69 return(p);
70 p++;
71 }
72 } else {
73 while (*p) {
74 if (isblank(*p))
75 return(p);
76 p++;
77 }
78 }
79 return p;
80}
81
82int
83MakeArgs(script, pvect)
84char *script;
85char **pvect;
86{
87 int nargs, nb;
88 int instring;
89
90 nargs = 0;
91 while (*script) {
92 nb = strspn(script, " \t");
93 script += nb;
94 if (*script) {
95 if (*script == '"') {
96 instring = 1;
97 script++;
98 if (*script == '\0')
99 return(nargs);
100 } else
101 instring = 0;
102 *pvect++ = script;
103 nargs++;
104 script = findblank(script, instring);
105 if (*script)
106 *script++ = '\0';
107 }
108 }
109 *pvect = NULL;
110 return nargs;
111}
112
113/*
114 * \c don't add a cr
115 * \d Sleep a little (delay 2 seconds
116 * \n Line feed character
117 * \P Auth Key password
118 * \p pause 0.25 sec
119 * \r Carrige return character
120 * \s Space character
121 * \T Telephone number(s) (defined via `set phone')
122 * \t Tab character
123 * \U Auth User
124 */
125char *
126ExpandString(str, result, reslen, sendmode)
127char *str;
128char *result;
129int reslen;
130int sendmode;
131{
132 int addcr = 0;
133 char *phone;
134
135 result[--reslen] = '\0';
136 if (sendmode)
137 addcr = 1;
138 while (*str && reslen > 0) {
139 switch (*str) {
140 case '\\':
141 str++;
142 switch (*str) {
143 case 'c':
144 if (sendmode)
145 addcr = 0;
146 break;
147 case 'd': /* Delay 2 seconds */
148 sleep(2); break;
149 case 'p':
150 usleep(250000); break; /* Pause 0.25 sec */
151 case 'n':
152 *result++ = '\n'; reslen--; break;
153 case 'r':
154 *result++ = '\r'; reslen--; break;
155 case 's':
156 *result++ = ' '; reslen--; break;
157 case 't':
158 *result++ = '\t'; reslen--; break;
159 case 'P':
160 strncpy(result, VarAuthKey, reslen);
161 reslen -= strlen(result);
162 result += strlen(result);
163 break;
164 case 'T':
165 if (VarNextPhone == NULL) {
166 strcpy(VarPhoneCopy, VarPhoneList);
167 VarNextPhone = VarPhoneCopy;
168 }
169 phone = strsep(&VarNextPhone, ":");
170 strncpy(result, phone, reslen);
171 reslen -= strlen(result);
172 result += strlen(result);
173 if ((mode & (MODE_INTER|MODE_AUTO)) == MODE_INTER)
174 fprintf(stderr, "Phone: %s\n", phone);
175 LogPrintf(LOG_PHASE_BIT, "Phone: %s\n", phone);
176 break;
177 case 'U':
178 strncpy(result, VarAuthName, reslen);
179 reslen -= strlen(result);
180 result += strlen(result);
181 break;
182 default:
183 reslen--;
184 *result++ = *str;
185 break;
186 }
187 if (*str)
188 str++;
189 break;
190 case '^':
191 str++;
192 if (*str) {
193 *result++ = *str++ & 0x1f;
194 reslen--;
195 }
196 break;
197 default:
198 *result++ = *str++;
199 reslen--;
200 break;
201 }
202 }
203 if (--reslen > 0) {
204 if (addcr)
205 *result++ = '\r';
206 }
207 if (--reslen > 0)
208 *result++ = '\0';
209 return(result);
210}
211
212#define MAXLOGBUFF 200
213static char logbuff[MAXLOGBUFF];
214static int loglen = 0;
215
216static void clear_log() {
217 memset(logbuff,0,MAXLOGBUFF);
218 loglen = 0;
219}
220
221static void flush_log() {
222 if ((loglevel & LOG_CONNECT_BIT)
223 || ((loglevel & LOG_CARRIER_BIT)
224 && strstr(logbuff,"CARRIER"))) {
225 LogPrintf(LOG_CONNECT_BIT|LOG_CARRIER_BIT,"Chat: %s\n",logbuff);
226 }
227 clear_log();
228}
229
230static void connect_log(char *str, int single_p) {
231 int space = MAXLOGBUFF - loglen - 1;
232
233 while (space--) {
234 if (*str == '\n') {
235 flush_log();
236 } else {
237 logbuff[loglen++] = *str;
238 }
239 if (single_p || !*++str) break;
240 }
241 if (!space) flush_log();
242}
243
244
245
246int
247WaitforString(estr)
248char *estr;
249{
250 struct timeval timeout;
251 char *s, *str, ch;
252 char *inp;
253 fd_set rfds;
254 int i, nfds, nb, msg;
255 char buff[200];
256
257
258#ifdef SIGALRM
259 int omask;
260 omask = sigblock(sigmask(SIGALRM));
261#endif
262 clear_log();
263 (void) ExpandString(estr, buff, sizeof(buff), 0);
264 LogPrintf(LOG_CHAT_BIT, "Wait for (%d): %s --> %s\n", TimeoutSec, estr, buff);
265 str = buff;
266 inp = inbuff;
267
268 if (strlen(str)>=IBSIZE){
269 str[IBSIZE]=0;
270 LogPrintf(LOG_CHAT_BIT, "Truncating String to %d character: %s\n", IBSIZE, str);
271 }
272
273 nfds = modem + 1;
274 s = str;
275 msg = FALSE;
276 for (;;) {
277 FD_ZERO(&rfds);
278 FD_SET(modem, &rfds);
279 /*
280 * Because it is not clear whether select() modifies timeout value,
281 * it is better to initialize timeout values everytime.
282 */
283 timeout.tv_sec = TimeoutSec;
284 timeout.tv_usec = 0;
285 i = select(nfds, &rfds, NULL, NULL, &timeout);
286#ifdef notdef
287 TimerService();
288#endif
289 if (i < 0) {
290#ifdef SIGALRM
291 if (errno == EINTR)
292 continue;
293 sigsetmask(omask);
294#endif
295 perror("select");
296 *inp = 0;
297 return(NOMATCH);
298 } else if (i == 0) { /* Timeout reached! */
299 *inp = 0;
300 if (inp != inbuff)
301 LogPrintf(LOG_CHAT_BIT, "got: %s\n", inbuff);
302 LogPrintf(LOG_CHAT_BIT, "can't get (%d).\n", timeout.tv_sec);
303#ifdef SIGALRM
304 sigsetmask(omask);
305#endif
306 return(NOMATCH);
307 }
308 if (FD_ISSET(modem, &rfds)) { /* got something */
309 if (DEV_IS_SYNC) {
310 int length;
311 if ((length=strlen(inbuff))>IBSIZE){
312 bcopy(&(inbuff[IBSIZE]),inbuff,IBSIZE+1); /* shuffle down next part*/
313 length=strlen(inbuff);
314 }
315 nb = read(modem, &(inbuff[length]), IBSIZE);
316 inbuff[nb + length] = 0;
317 connect_log(inbuff,0);
318 if (strstr(inbuff, str)) {
319#ifdef SIGALRM
320 sigsetmask(omask);
321#endif
322 flush_log();
323 return(MATCH);
324 }
325 for (i = 0; i < numaborts; i++) {
326 if (strstr(inbuff, AbortStrings[i])) {
327 LogPrintf(LOG_CHAT_BIT, "Abort: %s\n", AbortStrings[i]);
328#ifdef SIGALRM
329 sigsetmask(omask);
330#endif
331 flush_log();
332 return(ABORT);
333 }
334 }
335 } else {
336 read(modem, &ch, 1);
337 connect_log(&ch,1);
338 *inp++ = ch;
339 if (ch == *s) {
340 s++;
341 if (*s == '\0') {
342#ifdef SIGALRM
343 sigsetmask(omask);
344#endif
345 *inp = 0;
346 flush_log();
347 return(MATCH);
348 }
349 } else {
350 s = str;
351 if (inp == inbuff+ IBSIZE) {
352 bcopy(inp - 100, inbuff, 100);
353 inp = inbuff + 100;
354 }
355 for (i = 0; i < numaborts; i++) { /* Look for Abort strings */
356 int len;
357 char *s1;
358
359 s1 = AbortStrings[i];
360 len = strlen(s1);
361 if ((len <= inp - inbuff) && (strncmp(inp - len, s1, len) == 0)) {
362 LogPrintf(LOG_CHAT_BIT, "Abort: %s\n", s1);
363 *inp = 0;
364#ifdef SIGALRM
365 sigsetmask(omask);
366#endif
367 flush_log();
368 return(ABORT);
369 }
370 }
371 }
372 }
373 }
374 }
375#ifdef SIGALRM
376 sigsetmask(omask);
377#endif
378}
379
380void
381ExecStr(command, out)
382char *command, *out;
383{
384 int pid;
385 int fids[2];
386 char *vector[20];
387 int stat, nb;
388 char *cp;
389 char tmp[300];
390 extern int errno;
391
392 cp = inbuff + strlen(inbuff) - 1;
393 while (cp > inbuff) {
394 if (*cp < ' ' && *cp != '\t') {
395 cp++;
396 break;
397 }
398 cp--;
399 }
400 snprintf(tmp, sizeof tmp, "%s %s", command, cp);
401 (void) MakeArgs(tmp, &vector);
402
403 pipe(fids);
404 pid = fork();
405 if (pid == 0) {
406 TermTimerService();
405 signal(SIGINT, SIG_DFL);
406 signal(SIGQUIT, SIG_DFL);
407 signal(SIGTERM, SIG_DFL);
408 signal(SIGHUP, SIG_DFL);
407 signal(SIGINT, SIG_DFL);
408 signal(SIGQUIT, SIG_DFL);
409 signal(SIGTERM, SIG_DFL);
410 signal(SIGHUP, SIG_DFL);
411 signal(SIGALRM, SIG_DFL);
409 close(fids[0]);
410 dup2(fids[1], 1);
411 close(fids[1]);
412 nb = open("/dev/tty", O_RDWR);
413 dup2(nb, 0);
414 LogPrintf(LOG_CHAT_BIT, "exec: %s\n", command);
415 /* switch back to original privileges */
416 if (setgid(getgid()) < 0) {
417 LogPrintf(LOG_CHAT_BIT, "setgid: %s\n", strerror(errno));
418 exit(1);
419 }
420 if (setuid(getuid()) < 0) {
421 LogPrintf(LOG_CHAT_BIT, "setuid: %s\n", strerror(errno));
422 exit(1);
423 }
424 pid = execvp(command, vector);
425 LogPrintf(LOG_CHAT_BIT, "execvp failed for (%d/%d): %s\n", pid, errno, command);
426 exit(127);
427 } else {
428 close(fids[1]);
429 for (;;) {
430 nb = read(fids[0], out, 1);
431 if (nb <= 0)
432 break;
433 out++;
434 }
435 *out = '\0';
436 close(fids[0]);
437 close(fids[1]);
438 waitpid(pid, &stat, WNOHANG);
439 }
440}
441
442void
443SendString(str)
444char *str;
445{
446 char *cp;
447 int nb, on;
448 char buff[200];
449
450 if (abort_next) {
451 abort_next = 0;
452 ExpandString(str, buff, sizeof(buff), 0);
453 AbortStrings[numaborts++] = strdup(buff);
454 } else if (timeout_next) {
455 timeout_next = 0;
456 TimeoutSec = atoi(str);
457 if (TimeoutSec <= 0)
458 TimeoutSec = 30;
459 } else {
460 if (*str == '!') {
461 (void) ExpandString(str+1, buff+2, sizeof(buff)-2, 0);
462 ExecStr(buff + 2, buff + 2);
463 } else {
464 (void) ExpandString(str, buff+2, sizeof(buff)-2, 1);
465 }
466 if (strstr(str, "\\P")) { /* Do not log the password itself. */
467 LogPrintf(LOG_CHAT_BIT, "sending: %s\n", str);
468 } else {
469 LogPrintf(LOG_CHAT_BIT, "sending: %s\n", buff+2);
470 }
471 cp = buff;
472 if (DEV_IS_SYNC)
473 bcopy("\377\003", buff, 2); /* Prepend HDLC header */
474 else
475 cp += 2;
476 on = strlen(cp);
477 nb = write(modem, cp, on);
478 }
479}
480
481int
482ExpectString(str)
483char *str;
484{
485 char *minus;
486 int state;
487
488 if (strcmp(str, "ABORT") == 0) {
489 ++abort_next;
490 return(MATCH);
491 }
492 if (strcmp(str, "TIMEOUT") == 0) {
493 ++timeout_next;
494 return(MATCH);
495 }
496 LogPrintf(LOG_CHAT_BIT, "Expecting %s\n", str);
497 while (*str) {
498 /*
499 * Check whether if string contains sub-send-expect.
500 */
501 for (minus = str; *minus; minus++) {
502 if (*minus == '-') {
503 if (minus == str || minus[-1] != '\\')
504 break;
505 }
506 }
507 if (*minus == '-') { /* We have sub-send-expect. */
508 *minus++ = '\0';
509 state = WaitforString(str);
510 if (state != NOMATCH)
511 return(state);
512 /*
513 * Can't get expect string. Sendout send part.
514 */
515 str = minus;
516 for (minus = str; *minus; minus++) {
517 if (*minus == '-') {
518 if (minus == str || minus[-1] != '\\')
519 break;
520 }
521 }
522 if (*minus == '-') {
523 *minus++ = '\0';
524 SendString(str);
525 str = minus;
526 } else {
527 SendString(str);
528 return(MATCH);
529 }
530 } else {
531 /*
532 * Simple case. Wait for string.
533 */
534 return(WaitforString(str));
535 }
536 }
537 return(MATCH);
538}
539
540int
541DoChat(script)
542char *script;
543{
544 char *vector[20];
545 char **argv;
546 int argc, n, state;
547#ifdef DEBUG
548 int i;
549#endif
550
551 timeout_next = abort_next = 0;
552 for (n = 0; AbortStrings[n]; n++) {
553 free(AbortStrings[n]);
554 AbortStrings[n] = NULL;
555 }
556 numaborts = 0;
557
558 bzero(vector, sizeof(vector));
559 n = MakeArgs(script, &vector);
560#ifdef DEBUG
561 logprintf("n = %d\n", n);
562 for (i = 0; i < n; i++)
563 logprintf(" %s\n", vector[i]);
564#endif
565 argc = n;
566 argv = vector;
567 TimeoutSec = 30;
568 while (*argv) {
569 if (strcmp(*argv, "P_ZERO") == 0 ||
570 strcmp(*argv, "P_ODD") == 0 || strcmp(*argv, "P_EVEN") == 0) {
571 ChangeParity(*argv++);
572 continue;
573 }
574 state = ExpectString(*argv++);
575 switch (state) {
576 case MATCH:
577 if (*argv)
578 SendString(*argv++);
579 break;
580 case ABORT:
581#ifdef notdef
582 HangupModem();
583#endif
584 case NOMATCH:
585 return(NOMATCH);
586 }
587 }
588 return(MATCH);
589}
412 close(fids[0]);
413 dup2(fids[1], 1);
414 close(fids[1]);
415 nb = open("/dev/tty", O_RDWR);
416 dup2(nb, 0);
417 LogPrintf(LOG_CHAT_BIT, "exec: %s\n", command);
418 /* switch back to original privileges */
419 if (setgid(getgid()) < 0) {
420 LogPrintf(LOG_CHAT_BIT, "setgid: %s\n", strerror(errno));
421 exit(1);
422 }
423 if (setuid(getuid()) < 0) {
424 LogPrintf(LOG_CHAT_BIT, "setuid: %s\n", strerror(errno));
425 exit(1);
426 }
427 pid = execvp(command, vector);
428 LogPrintf(LOG_CHAT_BIT, "execvp failed for (%d/%d): %s\n", pid, errno, command);
429 exit(127);
430 } else {
431 close(fids[1]);
432 for (;;) {
433 nb = read(fids[0], out, 1);
434 if (nb <= 0)
435 break;
436 out++;
437 }
438 *out = '\0';
439 close(fids[0]);
440 close(fids[1]);
441 waitpid(pid, &stat, WNOHANG);
442 }
443}
444
445void
446SendString(str)
447char *str;
448{
449 char *cp;
450 int nb, on;
451 char buff[200];
452
453 if (abort_next) {
454 abort_next = 0;
455 ExpandString(str, buff, sizeof(buff), 0);
456 AbortStrings[numaborts++] = strdup(buff);
457 } else if (timeout_next) {
458 timeout_next = 0;
459 TimeoutSec = atoi(str);
460 if (TimeoutSec <= 0)
461 TimeoutSec = 30;
462 } else {
463 if (*str == '!') {
464 (void) ExpandString(str+1, buff+2, sizeof(buff)-2, 0);
465 ExecStr(buff + 2, buff + 2);
466 } else {
467 (void) ExpandString(str, buff+2, sizeof(buff)-2, 1);
468 }
469 if (strstr(str, "\\P")) { /* Do not log the password itself. */
470 LogPrintf(LOG_CHAT_BIT, "sending: %s\n", str);
471 } else {
472 LogPrintf(LOG_CHAT_BIT, "sending: %s\n", buff+2);
473 }
474 cp = buff;
475 if (DEV_IS_SYNC)
476 bcopy("\377\003", buff, 2); /* Prepend HDLC header */
477 else
478 cp += 2;
479 on = strlen(cp);
480 nb = write(modem, cp, on);
481 }
482}
483
484int
485ExpectString(str)
486char *str;
487{
488 char *minus;
489 int state;
490
491 if (strcmp(str, "ABORT") == 0) {
492 ++abort_next;
493 return(MATCH);
494 }
495 if (strcmp(str, "TIMEOUT") == 0) {
496 ++timeout_next;
497 return(MATCH);
498 }
499 LogPrintf(LOG_CHAT_BIT, "Expecting %s\n", str);
500 while (*str) {
501 /*
502 * Check whether if string contains sub-send-expect.
503 */
504 for (minus = str; *minus; minus++) {
505 if (*minus == '-') {
506 if (minus == str || minus[-1] != '\\')
507 break;
508 }
509 }
510 if (*minus == '-') { /* We have sub-send-expect. */
511 *minus++ = '\0';
512 state = WaitforString(str);
513 if (state != NOMATCH)
514 return(state);
515 /*
516 * Can't get expect string. Sendout send part.
517 */
518 str = minus;
519 for (minus = str; *minus; minus++) {
520 if (*minus == '-') {
521 if (minus == str || minus[-1] != '\\')
522 break;
523 }
524 }
525 if (*minus == '-') {
526 *minus++ = '\0';
527 SendString(str);
528 str = minus;
529 } else {
530 SendString(str);
531 return(MATCH);
532 }
533 } else {
534 /*
535 * Simple case. Wait for string.
536 */
537 return(WaitforString(str));
538 }
539 }
540 return(MATCH);
541}
542
543int
544DoChat(script)
545char *script;
546{
547 char *vector[20];
548 char **argv;
549 int argc, n, state;
550#ifdef DEBUG
551 int i;
552#endif
553
554 timeout_next = abort_next = 0;
555 for (n = 0; AbortStrings[n]; n++) {
556 free(AbortStrings[n]);
557 AbortStrings[n] = NULL;
558 }
559 numaborts = 0;
560
561 bzero(vector, sizeof(vector));
562 n = MakeArgs(script, &vector);
563#ifdef DEBUG
564 logprintf("n = %d\n", n);
565 for (i = 0; i < n; i++)
566 logprintf(" %s\n", vector[i]);
567#endif
568 argc = n;
569 argv = vector;
570 TimeoutSec = 30;
571 while (*argv) {
572 if (strcmp(*argv, "P_ZERO") == 0 ||
573 strcmp(*argv, "P_ODD") == 0 || strcmp(*argv, "P_EVEN") == 0) {
574 ChangeParity(*argv++);
575 continue;
576 }
577 state = ExpectString(*argv++);
578 switch (state) {
579 case MATCH:
580 if (*argv)
581 SendString(*argv++);
582 break;
583 case ABORT:
584#ifdef notdef
585 HangupModem();
586#endif
587 case NOMATCH:
588 return(NOMATCH);
589 }
590 }
591 return(MATCH);
592}