Commit | Line | Data |
---|---|---|
e4b1b510 RG |
1 | /* |
2 | * Chat -- a program for automatic session establishment (i.e. dial | |
3 | * the phone and log in). | |
4 | * | |
5 | * This software is in the public domain. | |
6 | * | |
7 | * Please send all bug reports, requests for information, etc. to: | |
8 | * | |
9 | * Karl Fox <karl@MorningStar.Com> | |
10 | * Morning Star Technologies, Inc. | |
11 | * 1760 Zollinger Road | |
12 | * Columbus, OH 43221 | |
13 | * (614)451-1883 | |
14 | */ | |
15 | ||
16 | static char sccs_id[] = "@(#)chat.c 1.7"; | |
17 | ||
18 | #include <stdio.h> | |
19 | #include <fcntl.h> | |
20 | #include <signal.h> | |
21 | #include <errno.h> | |
22 | #include <sys/types.h> | |
23 | #include <sys/stat.h> | |
24 | #include <varargs.h> | |
25 | #include <syslog.h> | |
26 | ||
27 | #ifdef __386BSD__ | |
28 | #define TERMIOS | |
29 | #define SIGHAND_TYPE __sighandler_t | |
30 | #else | |
31 | #define TERMIO | |
32 | #endif | |
33 | ||
34 | #ifdef sun | |
35 | #define SIGHAND_TYPE int (*)() | |
36 | # if defined(SUNOS) && SUNOS >= 41 | |
37 | # ifndef HDB | |
38 | # define HDB | |
39 | # endif | |
40 | # endif | |
41 | #endif | |
42 | ||
43 | #ifdef TERMIO | |
44 | #include <termio.h> | |
45 | #endif | |
46 | #ifdef TERMIOS | |
47 | #include <sys/ioctl.h> | |
48 | #include <termios.h> | |
49 | #endif | |
50 | ||
51 | #define STR_LEN 1024 | |
52 | ||
53 | #if defined(sun) | defined(SYSV) | defined(POSIX_SOURCE) | |
54 | #define SIGTYPE void | |
55 | #else | |
56 | #define SIGTYPE int | |
57 | #endif | |
58 | ||
59 | /*************** Micro getopt() *********************************************/ | |
60 | #define OPTION(c,v) (_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \ | |
61 | (--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\ | |
62 | &&!v[0][1]?(--c,++v,0):(_O=2,*(*v)++):0)) | |
63 | #define OPTARG(c,v) (_O&2?**v||(++v,--c)?(_O=1,--c,*v++): \ | |
64 | (_O=4,(char*)0):(char*)0) | |
65 | #define OPTONLYARG(c,v) (_O&2&&**v?(_O=1,--c,*v++):(char*)0) | |
66 | #define ARG(c,v) (c?(--c,*v++):(char*)0) | |
67 | ||
68 | static int _O = 0; /* Internal state */ | |
69 | /*************** Micro getopt() *********************************************/ | |
70 | ||
71 | char *program_name; | |
72 | ||
73 | extern char *strcpy(), *strcat(), *malloc(); | |
74 | extern int strlen(); | |
75 | #define copyof(s) ((s) ? strcpy(malloc(strlen(s) + 1), s) : (s)) | |
76 | ||
77 | #ifndef LOCK_DIR | |
78 | # ifdef HDB | |
79 | # define LOCK_DIR "/usr/spool/locks" | |
80 | # else /* HDB */ | |
81 | # define LOCK_DIR "/usr/spool/uucp" | |
82 | # endif /* HDB */ | |
83 | #endif /* LOCK_DIR */ | |
84 | ||
85 | #define MAX_ABORTS 50 | |
86 | #define DEFAULT_CHAT_TIMEOUT 45 | |
87 | ||
88 | int verbose = 0; | |
89 | int quiet = 0; | |
90 | char *lock_file = (char *)0; | |
91 | int timeout = DEFAULT_CHAT_TIMEOUT; | |
92 | ||
93 | int have_tty_parameters = 0; | |
94 | #ifdef TERMIO | |
95 | struct termio saved_tty_parameters; | |
96 | #endif | |
97 | #ifdef TERMIOS | |
98 | struct termios saved_tty_parameters; | |
99 | #endif | |
100 | ||
101 | char *abort_string[MAX_ABORTS], *fail_reason = (char *)0, | |
102 | fail_buffer[50]; | |
103 | int n_aborts = 0, abort_next = 0, timeout_next = 0; | |
104 | ||
105 | /* | |
106 | * chat [ -v ] [ -t timeout ] [ -l lock-file ] \ | |
107 | * [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]] | |
108 | * | |
109 | * Perform a UUCP-dialer-like chat script on stdin and stdout. | |
110 | */ | |
111 | main(argc, argv) | |
112 | int argc; | |
113 | char **argv; | |
114 | { | |
115 | int option, n; | |
116 | char *arg; | |
117 | ||
118 | program_name = *argv; | |
119 | ||
120 | while (option = OPTION(argc, argv)) | |
121 | switch (option) | |
122 | { | |
123 | case 'v': | |
124 | ++verbose; | |
125 | break; | |
126 | ||
127 | case 'l': | |
128 | if (arg = OPTARG(argc, argv)) | |
129 | lock_file = copyof(arg); | |
130 | else | |
131 | usage(); | |
132 | ||
133 | break; | |
134 | ||
135 | case 't': | |
136 | if (arg = OPTARG(argc, argv)) | |
137 | timeout = atoi(arg); | |
138 | else | |
139 | usage(); | |
140 | ||
141 | break; | |
142 | ||
143 | default: | |
144 | usage(); | |
145 | } | |
146 | ||
147 | openlog("chat", LOG_PID | LOG_NDELAY, LOG_LOCAL2); | |
148 | ||
149 | if (verbose) { | |
150 | setlogmask(LOG_UPTO(LOG_INFO)); | |
151 | } else { | |
152 | setlogmask(LOG_UPTO(LOG_WARNING)); | |
153 | } | |
154 | ||
155 | init(); | |
156 | ||
157 | while (arg = ARG(argc, argv)) | |
158 | { | |
159 | chat_expect(arg); | |
160 | ||
161 | if (arg = ARG(argc, argv)) | |
162 | chat_send(arg); | |
163 | } | |
164 | ||
165 | terminate(0); | |
166 | } | |
167 | ||
168 | /* | |
169 | * We got an error parsing the command line. | |
170 | */ | |
171 | usage() | |
172 | { | |
173 | fprintf(stderr, | |
174 | "Usage: %s [ -v ] [ -l lock-file ] [ -t timeout ] chat-script\n", | |
175 | program_name); | |
176 | exit(1); | |
177 | } | |
178 | ||
179 | /* | |
180 | * Print a warning message. | |
181 | */ | |
182 | /*VARARGS1*/ | |
183 | warn(format, arg1, arg2, arg3, arg4) | |
184 | char *format; | |
185 | int arg1, arg2, arg3, arg4; | |
186 | { | |
187 | logf("%s: Warning: ", program_name); | |
188 | logf(format, arg1, arg2, arg3, arg4); | |
189 | logf("\n"); | |
190 | } | |
191 | ||
192 | /* | |
193 | * Print an error message and terminate. | |
194 | */ | |
195 | /*VARARGS1*/ | |
196 | fatal(format, arg1, arg2, arg3, arg4) | |
197 | char *format; | |
198 | int arg1, arg2, arg3, arg4; | |
199 | { | |
200 | logf("%s: ", program_name); | |
201 | logf(format, arg1, arg2, arg3, arg4); | |
202 | logf("\n"); | |
203 | unlock(); | |
204 | terminate(1); | |
205 | } | |
206 | ||
207 | /* | |
208 | * Print an error message along with the system error message and | |
209 | * terminate. | |
210 | */ | |
211 | /*VARARGS1*/ | |
212 | sysfatal(format, arg1, arg2, arg3, arg4) | |
213 | char *format; | |
214 | int arg1, arg2, arg3, arg4; | |
215 | { | |
216 | char message[STR_LEN]; | |
217 | ||
218 | sprintf(message, "%s: ", program_name); | |
219 | sprintf(message + strlen(message), format, arg1, arg2, arg3, arg4); | |
220 | perror(message); | |
221 | unlock(); | |
222 | terminate(1); | |
223 | } | |
224 | ||
225 | int alarmed = 0; | |
226 | ||
227 | SIGTYPE | |
228 | sigalrm() | |
229 | { | |
230 | int flags; | |
231 | ||
232 | alarm(1); alarmed = 1; /* Reset alarm to avoid race window */ | |
233 | signal(SIGALRM, (SIGHAND_TYPE)sigalrm); /* that can cause hanging in read() */ | |
234 | ||
235 | if ((flags = fcntl(0, F_GETFL, 0)) == -1) | |
236 | sysfatal("Can't get file mode flags on stdin"); | |
237 | else | |
238 | if (fcntl(0, F_SETFL, flags | FNDELAY) == -1) | |
239 | sysfatal("Can't set file mode flags on stdin"); | |
240 | ||
241 | if (verbose) | |
242 | { | |
243 | logf("alarm\n"); | |
244 | } | |
245 | } | |
246 | ||
247 | unalarm() | |
248 | { | |
249 | int flags; | |
250 | ||
251 | if ((flags = fcntl(0, F_GETFL, 0)) == -1) | |
252 | sysfatal("Can't get file mode flags on stdin"); | |
253 | else | |
254 | if (fcntl(0, F_SETFL, flags & ~FNDELAY) == -1) | |
255 | sysfatal("Can't set file mode flags on stdin"); | |
256 | } | |
257 | ||
258 | SIGTYPE | |
259 | sigint() | |
260 | { | |
261 | fatal("SIGINT"); | |
262 | } | |
263 | ||
264 | SIGTYPE | |
265 | sigterm() | |
266 | { | |
267 | fatal("SIGTERM"); | |
268 | } | |
269 | ||
270 | SIGTYPE | |
271 | sighup() | |
272 | { | |
273 | fatal("SIGHUP"); | |
274 | } | |
275 | ||
276 | init() | |
277 | { | |
278 | signal(SIGINT, (SIGHAND_TYPE)sigint); | |
279 | signal(SIGTERM, (SIGHAND_TYPE)sigterm); | |
280 | signal(SIGHUP, (SIGHAND_TYPE)sighup); | |
281 | ||
282 | if (lock_file) | |
283 | lock(); | |
284 | ||
285 | set_tty_parameters(); | |
286 | signal(SIGALRM, (SIGHAND_TYPE)sigalrm); | |
287 | alarm(0); alarmed = 0; | |
288 | } | |
289 | ||
290 | ||
291 | set_tty_parameters() | |
292 | { | |
293 | #ifdef TERMIO | |
294 | struct termio t; | |
295 | ||
296 | if (ioctl(0, TCGETA, &t) < 0) | |
297 | sysfatal("Can't get terminal parameters"); | |
298 | #endif | |
299 | #ifdef TERMIOS | |
300 | struct termios t; | |
301 | ||
302 | if (ioctl(0, TIOCGETA, &t) < 0) | |
303 | sysfatal("Can't get terminal parameters"); | |
304 | #endif | |
305 | ||
306 | saved_tty_parameters = t; | |
307 | have_tty_parameters = 1; | |
308 | ||
309 | t.c_iflag = IGNBRK | ISTRIP | IGNPAR; | |
310 | t.c_oflag = 0; | |
311 | t.c_lflag = 0; | |
312 | t.c_cc[VERASE] = t.c_cc[VKILL] = 0; | |
313 | t.c_cc[VMIN] = 1; | |
314 | t.c_cc[VTIME] = 0; | |
315 | ||
316 | #ifdef TERMIO | |
317 | if (ioctl(0, TCSETA, &t) < 0) | |
318 | sysfatal("Can't set terminal parameters"); | |
319 | #endif | |
320 | #ifdef TERMIOS | |
321 | if (ioctl(0, TIOCSETA, &t) < 0) | |
322 | sysfatal("Can't set terminal parameters"); | |
323 | #endif | |
324 | } | |
325 | ||
326 | ||
327 | terminate(status) | |
328 | { | |
329 | if (have_tty_parameters && | |
330 | #ifdef TERMIO | |
331 | ioctl(0, TCSETA, &saved_tty_parameters) < 0 | |
332 | #endif | |
333 | #ifdef TERMIOS | |
334 | ioctl(0, TIOCSETA, &saved_tty_parameters) < 0 | |
335 | #endif | |
336 | ) { | |
337 | perror("Can't restore terminal parameters"); | |
338 | unlock(); | |
339 | exit(1); | |
340 | } | |
341 | exit(status); | |
342 | } | |
343 | ||
344 | /* | |
345 | * Create a lock file for the named lock device | |
346 | */ | |
347 | lock() | |
348 | { | |
349 | char hdb_lock_buffer[12]; | |
350 | int fd, pid; | |
351 | ||
352 | lock_file = strcat(strcat(strcpy(malloc(strlen(LOCK_DIR) | |
353 | + 1 + strlen(lock_file) + 1), | |
354 | LOCK_DIR), "/"), lock_file); | |
355 | ||
356 | if ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) | |
357 | { | |
358 | char *s = lock_file; | |
359 | ||
360 | lock_file = (char *)0; /* Don't remove someone else's lock file! */ | |
361 | sysfatal("Can't get lock file '%s'", s); | |
362 | } | |
363 | ||
364 | # ifdef HDB | |
365 | sprintf(hdb_lock_buffer, "%10d\n", getpid()); | |
366 | write(fd, hdb_lock_buffer, 11); | |
367 | # else /* HDB */ | |
368 | pid = getpid(); | |
369 | write(fd, &pid, sizeof pid); | |
370 | # endif /* HDB */ | |
371 | ||
372 | close(fd); | |
373 | } | |
374 | ||
375 | /* | |
376 | * Remove our lockfile | |
377 | */ | |
378 | unlock() | |
379 | { | |
380 | if (lock_file) | |
381 | { | |
382 | unlink(lock_file); | |
383 | lock_file = (char *)0; | |
384 | } | |
385 | } | |
386 | ||
387 | /* | |
388 | * 'Clean up' this string. | |
389 | */ | |
390 | char *clean(s, sending) | |
391 | register char *s; | |
392 | int sending; | |
393 | { | |
394 | char temp[STR_LEN]; | |
395 | register char *s1; | |
396 | int add_return = sending; | |
397 | ||
398 | for (s1 = temp; *s; ++s) | |
399 | switch (*s) | |
400 | { | |
401 | case '\\': | |
402 | switch (*++s) | |
403 | { | |
404 | case '\\': | |
405 | case 'd': if (sending) | |
406 | *s1++ = '\\'; | |
407 | ||
408 | *s1++ = *s; | |
409 | break; | |
410 | ||
411 | case 'q': quiet = ! quiet; break; | |
412 | case 'r': *s1++ = '\r'; break; | |
413 | case 'n': *s1++ = '\n'; break; | |
414 | case 's': *s1++ = ' '; break; | |
415 | ||
416 | case 'c': if (sending && s[1] == '\0') | |
417 | add_return = 0; | |
418 | else | |
419 | *s1++ = *s; | |
420 | ||
421 | break; | |
422 | ||
423 | default: *s1++ = *s; | |
424 | } | |
425 | ||
426 | break; | |
427 | ||
428 | case '^': | |
429 | *s1++ = (int)(*++s) & 0x1F; | |
430 | break; | |
431 | ||
432 | default: | |
433 | *s1++ = *s; | |
434 | } | |
435 | ||
436 | if (add_return) | |
437 | *s1++ = '\r'; | |
438 | ||
439 | *s1 = '\0'; | |
440 | return (copyof(temp)); | |
441 | } | |
442 | ||
443 | /* | |
444 | * | |
445 | */ | |
446 | chat_expect(s) | |
447 | register char *s; | |
448 | { | |
449 | if (strcmp(s, "ABORT") == 0) | |
450 | { | |
451 | ++abort_next; | |
452 | return; | |
453 | } | |
454 | ||
455 | if (strcmp(s, "TIMEOUT") == 0) | |
456 | { | |
457 | ++timeout_next; | |
458 | return; | |
459 | } | |
460 | ||
461 | while (*s) | |
462 | { | |
463 | register char *hyphen; | |
464 | ||
465 | for (hyphen = s; *hyphen; ++hyphen) | |
466 | if (*hyphen == '-') | |
467 | if (hyphen == s || hyphen[-1] != '\\') | |
468 | break; | |
469 | ||
470 | if (*hyphen == '-') | |
471 | { | |
472 | *hyphen = '\0'; | |
473 | ||
474 | if (get_string(s)) | |
475 | return; | |
476 | else | |
477 | { | |
478 | s = hyphen + 1; | |
479 | ||
480 | for (hyphen = s; *hyphen; ++hyphen) | |
481 | if (*hyphen == '-') | |
482 | if (hyphen == s || hyphen[-1] != '\\') | |
483 | break; | |
484 | ||
485 | if (*hyphen == '-') | |
486 | { | |
487 | *hyphen = '\0'; | |
488 | ||
489 | chat_send(s); | |
490 | s = hyphen + 1; | |
491 | } | |
492 | else | |
493 | { | |
494 | chat_send(s); | |
495 | return; | |
496 | } | |
497 | } | |
498 | } | |
499 | else | |
500 | if (get_string(s)) | |
501 | return; | |
502 | else | |
503 | { | |
504 | if (fail_reason) | |
505 | logf("Failed(%s)\n", fail_reason); | |
506 | else | |
507 | logf("Failed\n"); | |
508 | ||
509 | unlock(); | |
510 | terminate(1); | |
511 | } | |
512 | } | |
513 | } | |
514 | ||
515 | char *character(c) | |
516 | char c; | |
517 | { | |
518 | static char string[10]; | |
519 | char *meta; | |
520 | ||
521 | meta = (c & 0x80) ? "M-" : ""; | |
522 | c &= 0x7F; | |
523 | ||
524 | if (c < 32) | |
525 | sprintf(string, "%s^%c", meta, (int)c + '@'); | |
526 | else | |
527 | if (c == 127) | |
528 | sprintf(string, "%s^?", meta); | |
529 | else | |
530 | sprintf(string, "%s%c", meta, c); | |
531 | ||
532 | return (string); | |
533 | } | |
534 | ||
535 | /* | |
536 | * | |
537 | */ | |
538 | chat_send(s) | |
539 | register char *s; | |
540 | { | |
541 | if (abort_next) | |
542 | { | |
543 | char *s1; | |
544 | ||
545 | abort_next = 0; | |
546 | ||
547 | if (n_aborts >= MAX_ABORTS) | |
548 | fatal("Too many ABORT strings"); | |
549 | ||
550 | s1 = clean(s, 0); | |
551 | ||
552 | if (strlen(s1) > strlen(s)) | |
553 | fatal("Illegal ABORT string ('%s')\n", s); | |
554 | ||
555 | if (strlen(s1) > sizeof fail_buffer - 1) | |
556 | fatal("Too long ABORT string ('%s')\n", s); | |
557 | ||
558 | strcpy(s, s1); | |
559 | abort_string[n_aborts++] = s; | |
560 | ||
561 | if (verbose) | |
562 | { | |
563 | register char *s1 = s; | |
564 | ||
565 | logf("abort on ("); | |
566 | ||
567 | for (s1 = s; *s1; ++s1) | |
568 | logf("%s", character(*s1)); | |
569 | ||
570 | logf(")\n"); | |
571 | } | |
572 | } | |
573 | else | |
574 | if (timeout_next) | |
575 | { | |
576 | timeout_next = 0; | |
577 | timeout = atoi(s); | |
578 | ||
579 | if (timeout <= 0) | |
580 | timeout = DEFAULT_CHAT_TIMEOUT; | |
581 | ||
582 | if (verbose) | |
583 | { | |
584 | logf("timeout set to %d seconds\n", timeout); | |
585 | } | |
586 | } | |
587 | else | |
588 | if ( ! put_string(s)) | |
589 | { | |
590 | logf("Failed\n"); | |
591 | unlock(); | |
592 | terminate(1); | |
593 | } | |
594 | } | |
595 | ||
596 | int get_char() | |
597 | { | |
598 | int status; | |
599 | char c; | |
600 | ||
601 | status = read(0, &c, 1); | |
602 | ||
603 | switch (status) | |
604 | { | |
605 | case 1: | |
606 | return ((int)c & 0x7F); | |
607 | ||
608 | default: | |
609 | warn("read() on stdin returned %d", status); | |
610 | ||
611 | case -1: | |
612 | if ((status = fcntl(0, F_GETFL, 0)) == -1) | |
613 | sysfatal("Can't get file mode flags on stdin"); | |
614 | else | |
615 | if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1) | |
616 | sysfatal("Can't set file mode flags on stdin"); | |
617 | ||
618 | return (-1); | |
619 | } | |
620 | } | |
621 | ||
622 | int put_char(c) | |
623 | char c; | |
624 | { | |
625 | int status; | |
626 | ||
627 | delay(); | |
628 | ||
629 | status = write(1, &c, 1); | |
630 | ||
631 | switch (status) | |
632 | { | |
633 | case 1: | |
634 | return (0); | |
635 | ||
636 | default: | |
637 | warn("write() on stdout returned %d", status); | |
638 | ||
639 | case -1: | |
640 | if ((status = fcntl(0, F_GETFL, 0)) == -1) | |
641 | sysfatal("Can't get file mode flags on stdin"); | |
642 | else | |
643 | if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1) | |
644 | sysfatal("Can't set file mode flags on stdin"); | |
645 | ||
646 | return (-1); | |
647 | } | |
648 | } | |
649 | ||
650 | int put_string(s) | |
651 | register char *s; | |
652 | { | |
653 | s = clean(s, 1); | |
654 | ||
655 | if (verbose) | |
656 | { | |
657 | logf("send ("); | |
658 | ||
659 | if (quiet) | |
660 | logf("??????"); | |
661 | else | |
662 | { | |
663 | register char *s1 = s; | |
664 | ||
665 | for (s1 = s; *s1; ++s1) | |
666 | logf("%s", character(*s1)); | |
667 | } | |
668 | ||
669 | logf(")\n"); | |
670 | } | |
671 | ||
672 | alarm(timeout); alarmed = 0; | |
673 | ||
674 | for ( ; *s; ++s) | |
675 | { | |
676 | register char c = *s; | |
677 | ||
678 | if (c == '\\') | |
679 | if ((c = *++s) == '\0') | |
680 | break; | |
681 | else | |
682 | if (c == 'd') /* \d -- Delay */ | |
683 | { | |
684 | sleep(2); | |
685 | continue; | |
686 | } | |
687 | ||
688 | if (alarmed || put_char(*s) < 0) | |
689 | { | |
690 | extern int errno; | |
691 | ||
692 | alarm(0); alarmed = 0; | |
693 | ||
694 | if (verbose) | |
695 | { | |
696 | if (errno == EINTR || errno == EWOULDBLOCK) | |
697 | logf(" -- write timed out\n"); | |
698 | else | |
699 | syslog(LOG_INFO, " -- write failed: %m"); | |
700 | } | |
701 | ||
702 | return (0); | |
703 | } | |
704 | } | |
705 | ||
706 | alarm(0); alarmed = 0; | |
707 | return (1); | |
708 | } | |
709 | ||
710 | /* | |
711 | * 'Wait for' this string to appear on this file descriptor. | |
712 | */ | |
713 | int get_string(string) | |
714 | register char *string; | |
715 | { | |
716 | char temp[STR_LEN]; | |
717 | int c, printed = 0, len; | |
718 | register char *s = temp, *end = s + STR_LEN; | |
719 | ||
720 | fail_reason = (char *)0; | |
721 | string = clean(string, 0); | |
722 | len = strlen(string); | |
723 | ||
724 | if (verbose) | |
725 | { | |
726 | register char *s1; | |
727 | ||
728 | logf("expect ("); | |
729 | ||
730 | for (s1 = string; *s1; ++s1) | |
731 | logf("%s", character(*s1)); | |
732 | ||
733 | logf(")\n"); | |
734 | } | |
735 | ||
736 | if (len == 0) | |
737 | { | |
738 | if (verbose) | |
739 | { | |
740 | logf("got it\n"); | |
741 | } | |
742 | ||
743 | return (1); | |
744 | } | |
745 | ||
746 | alarm(timeout); alarmed = 0; | |
747 | ||
748 | while ( ! alarmed && (c = get_char()) >= 0) | |
749 | { | |
750 | int n, abort_len; | |
751 | ||
752 | if (verbose) | |
753 | { | |
754 | if (c == '\n') | |
755 | logf("\n"); | |
756 | else | |
757 | logf("%s", character(c)); | |
758 | } | |
759 | ||
760 | *s++ = c; | |
761 | ||
762 | if (s >= end) | |
763 | { | |
764 | if (verbose) | |
765 | { | |
766 | logf(" -- too much data\n"); | |
767 | } | |
768 | ||
769 | alarm(0); alarmed = 0; | |
770 | return (0); | |
771 | } | |
772 | ||
773 | if (s - temp >= len && | |
774 | c == string[len - 1] && | |
775 | strncmp(s - len, string, len) == 0) | |
776 | { | |
777 | if (verbose) | |
778 | { | |
779 | logf("got it\n"); | |
780 | } | |
781 | ||
782 | alarm(0); alarmed = 0; | |
783 | return (1); | |
784 | } | |
785 | ||
786 | for (n = 0; n < n_aborts; ++n) | |
787 | if (s - temp >= (abort_len = strlen(abort_string[n])) && | |
788 | strncmp(s - abort_len, abort_string[n], abort_len) == 0) | |
789 | { | |
790 | if (verbose) | |
791 | { | |
792 | logf(" -- failed\n"); | |
793 | } | |
794 | ||
795 | alarm(0); alarmed = 0; | |
796 | strcpy(fail_reason = fail_buffer, abort_string[n]); | |
797 | return (0); | |
798 | } | |
799 | ||
800 | if (alarmed && verbose) | |
801 | warn("Alarm synchronization problem"); | |
802 | } | |
803 | ||
804 | alarm(0); | |
805 | ||
806 | if (verbose && printed) | |
807 | { | |
808 | extern int errno; | |
809 | ||
810 | if (alarmed) | |
811 | logf(" -- read timed out\n"); | |
812 | else | |
813 | syslog(LOG_INFO, " -- read failed: %m"); | |
814 | } | |
815 | ||
816 | alarmed = 0; | |
817 | return (0); | |
818 | } | |
819 | ||
820 | /* | |
821 | * Delay an amount appropriate for between typed characters. | |
822 | */ | |
823 | delay() | |
824 | { | |
825 | register int i; | |
826 | ||
827 | # ifdef NO_USLEEP | |
828 | for (i = 0; i < 30000; ++i) /* ... did we just say appropriate? */ | |
829 | ; | |
830 | # else /* NO_USLEEP */ | |
831 | usleep(100); | |
832 | # endif /* NO_USLEEP */ | |
833 | } | |
834 | ||
835 | char line[256]; | |
836 | char *p; | |
837 | ||
838 | logf(fmt, va_alist) | |
839 | char *fmt; | |
840 | va_dcl | |
841 | { | |
842 | va_list pvar; | |
843 | char buf[256]; | |
844 | ||
845 | va_start(pvar); | |
846 | vsprintf(buf, fmt, pvar); | |
847 | va_end(pvar); | |
848 | ||
849 | p = line + strlen(line); | |
850 | strcat(p, buf); | |
851 | ||
852 | if (buf[strlen(buf)-1] == '\n') { | |
853 | syslog(LOG_INFO, "%s", line); | |
854 | line[0] = 0; | |
855 | } | |
856 | } |