X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=chat%2Fchat.c;h=f7aaabf1a30050d66130078c018a6d469b0b265c;hp=498736952df06658a434258ed104f386e5398e2a;hb=68dd74f4cd673377343a4b950272e66203cf1785;hpb=bb7b484642ea1b3efdd2f3fd9fa9e0126748d3a5 diff --git a/chat/chat.c b/chat/chat.c index 4987369..f7aaabf 100644 --- a/chat/chat.c +++ b/chat/chat.c @@ -2,45 +2,53 @@ * Chat -- a program for automatic session establishment (i.e. dial * the phone and log in). * + * Standard termination codes: + * 0 - successful completion of the script + * 1 - invalid argument, expect string too large, etc. + * 2 - error on an I/O operation or fatal error condtion. + * 3 - timeout waiting for a simple string. + * 4 - the first string declared as "ABORT" + * 5 - the second string declared as "ABORT" + * 6 - ... and so on for successive ABORT strings. + * * This software is in the public domain. * * Please send all bug reports, requests for information, etc. to: * + * Al Longyear (longyear@netcom.com) + * (I was the last person to change this code.) + * + * Added -r "report file" switch & REPORT keyword. + * Robert Geer + * + * The original author is: + * * Karl Fox * Morning Star Technologies, Inc. * 1760 Zollinger Road * Columbus, OH 43221 * (614)451-1883 + * */ -/*static char sccs_id[] = "@(#)chat.c 1.7";*/ -static char rcsid[] = "$Id: chat.c,v 1.1 1994/05/20 05:32:16 paulus Exp $"; +static char rcsid[] = "$Id: chat.c,v 1.9 1995/06/12 11:24:15 paulus Exp $"; #include +#include #include #include #include +#include +#include #include #include -#include #include #ifndef TERMIO +#undef TERMIOS #define TERMIOS #endif -#ifdef sun -# if defined(SUNOS) && SUNOS >= 41 -# ifndef HDB -# define HDB -# endif -# endif -#endif - -#ifdef ultrix -#define SIGHAND_TYPE int (*)() -#endif - #ifdef TERMIO #include #endif @@ -54,6 +62,18 @@ static char rcsid[] = "$Id: chat.c,v 1.1 1994/05/20 05:32:16 paulus Exp $"; #define SIGTYPE void #endif +#ifdef __STDC__ +#undef __P +#define __P(x) x +#else +#define __P(x) () +#define const +#endif + +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + /*************** Micro getopt() *********************************************/ #define OPTION(c,v) (_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \ (--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\ @@ -68,37 +88,32 @@ static int _O = 0; /* Internal state */ char *program_name; -extern char *strcpy(), *strcat(), *malloc(); -extern int strlen(); -#define copyof(s) ((s) ? strcpy(malloc(strlen(s) + 1), s) : (s)) - -#ifndef LOCK_DIR -# ifdef __NetBSD__ -# define PIDSTRING -# define LOCK_DIR "/var/spool/lock" -# else -# ifdef HDB -# define PIDSTRING -# define LOCK_DIR "/usr/spool/locks" -# else /* HDB */ -# define LOCK_DIR "/usr/spool/uucp" -# endif /* HDB */ -# endif -#endif /* LOCK_DIR */ - #define MAX_ABORTS 50 +#define MAX_REPORTS 50 #define DEFAULT_CHAT_TIMEOUT 45 -int verbose = 0; -int quiet = 0; -char *lock_file = (char *)0; -int timeout = DEFAULT_CHAT_TIMEOUT; +int verbose = 0; +int quiet = 0; +int report = 0; +int exit_code = 0; +FILE* report_fp = (FILE *) 0; +char *report_file = (char *) 0; +char *chat_file = (char *) 0; +int timeout = DEFAULT_CHAT_TIMEOUT; int have_tty_parameters = 0; + #ifdef TERMIO +#define term_parms struct termio +#define get_term_param(param) ioctl(0, TCGETA, param) +#define set_term_param(param) ioctl(0, TCSETA, param) struct termio saved_tty_parameters; #endif + #ifdef TERMIOS +#define term_parms struct termios +#define get_term_param(param) tcgetattr(0, param) +#define set_term_param(param) tcsetattr(0, TCSANOW, param) struct termios saved_tty_parameters; #endif @@ -106,291 +121,480 @@ char *abort_string[MAX_ABORTS], *fail_reason = (char *)0, fail_buffer[50]; int n_aborts = 0, abort_next = 0, timeout_next = 0; +char *report_string[MAX_REPORTS] ; +char report_buffer[50] ; +int n_reports = 0, report_next = 0, report_gathering = 0 ; + +void *dup_mem __P((void *b, size_t c)); +void *copy_of __P((char *s)); +void usage __P((void)); +void logf __P((const char *str)); +void logflush __P((void)); +void fatal __P((const char *msg)); +void sysfatal __P((const char *msg)); +SIGTYPE sigalrm __P((int signo)); +SIGTYPE sigint __P((int signo)); +SIGTYPE sigterm __P((int signo)); +SIGTYPE sighup __P((int signo)); +void unalarm __P((void)); +void init __P((void)); +void set_tty_parameters __P((void)); +void break_sequence __P((void)); +void terminate __P((int status)); +void do_file __P((char *chat_file)); +int get_string __P((register char *string)); +int put_string __P((register char *s)); +int write_char __P((int c)); +int put_char __P((int c)); +int get_char __P((void)); +void chat_send __P((register char *s)); +char *character __P((int c)); +void chat_expect __P((register char *s)); +char *clean __P((register char *s, int sending)); +void break_sequence __P((void)); +void terminate __P((int status)); +void die __P((void)); + +void *dup_mem(b, c) +void *b; +size_t c; + { + void *ans = malloc (c); + if (!ans) + { + fatal ("memory error!\n"); + } + memcpy (ans, b, c); + return ans; + } + +void *copy_of (s) +char *s; + { + return dup_mem (s, strlen (s) + 1); + } + /* - * chat [ -v ] [ -t timeout ] [ -l lock-file ] \ + * chat [ -v ] [ -t timeout ] [ -f chat-file ] [ -r report-file ] \ * [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]] * * Perform a UUCP-dialer-like chat script on stdin and stdout. */ +int main(argc, argv) int argc; char **argv; { - int option, n; + int option; char *arg; program_name = *argv; + tzset(); while (option = OPTION(argc, argv)) + { switch (option) { case 'v': ++verbose; break; - case 'l': + case 'f': if (arg = OPTARG(argc, argv)) - lock_file = copyof(arg); + { + chat_file = copy_of(arg); + } else + { usage(); - + } break; case 't': if (arg = OPTARG(argc, argv)) + { timeout = atoi(arg); + } else + { usage(); + } + break; + case 'r': + arg = OPTARG (argc, argv); + if (arg) + { + if (report_fp != NULL) + { + fclose (report_fp); + } + report_file = copy_of (arg); + report_fp = fopen (report_file, "a"); + if (report_fp != NULL) + { + if (verbose) + { + fprintf (report_fp, "Opening \"%s\"...\n", + report_file); + } + report = 1; + } + } break; default: usage(); + break; } + } +/* + * Default the report file to the stderr location + */ + if (report_fp == NULL) + { + report_fp = stderr; + } #ifdef ultrix openlog("chat", LOG_PID); #else openlog("chat", LOG_PID | LOG_NDELAY, LOG_LOCAL2); - if (verbose) { - setlogmask(LOG_UPTO(LOG_INFO)); - } else { - setlogmask(LOG_UPTO(LOG_WARNING)); - } + if (verbose) + { + setlogmask(LOG_UPTO(LOG_INFO)); + } + else + { + setlogmask(LOG_UPTO(LOG_WARNING)); + } #endif - init(); - while (arg = ARG(argc, argv)) + if (chat_file != NULL) { - chat_expect(arg); + arg = ARG(argc, argv); + if (arg != NULL) + { + usage(); + } + else + { + do_file (chat_file); + } + } + else + { + while (arg = ARG(argc, argv)) + { + chat_expect(arg); - if (arg = ARG(argc, argv)) - chat_send(arg); + if (arg = ARG(argc, argv)) + { + chat_send(arg); + } + } } terminate(0); } +/* + * Process a chat script when read from a file. + */ + +void do_file (chat_file) +char *chat_file; + { + int linect, len, sendflg; + char *sp, *arg, quote; + char buf [STR_LEN]; + FILE *cfp; + + cfp = fopen (chat_file, "r"); + if (cfp == NULL) + { + syslog (LOG_ERR, "%s -- open failed: %m", chat_file); + terminate (1); + } + + linect = 0; + sendflg = 0; + + while (fgets(buf, STR_LEN, cfp) != NULL) + { + sp = strchr (buf, '\n'); + if (sp) + { + *sp = '\0'; + } + + linect++; + sp = buf; + while (*sp != '\0') + { + if (*sp == ' ' || *sp == '\t') + { + ++sp; + continue; + } + + if (*sp == '"' || *sp == '\'') + { + quote = *sp++; + arg = sp; + while (*sp != quote) + { + if (*sp == '\0') + { + syslog (LOG_ERR, "unterminated quote (line %d)", + linect); + terminate (1); + } + + if (*sp++ == '\\') + { + if (*sp != '\0') + { + ++sp; + } + } + } + } + else + { + arg = sp; + while (*sp != '\0' && *sp != ' ' && *sp != '\t') + { + ++sp; + } + } + + if (*sp != '\0') + { + *sp++ = '\0'; + } + + if (sendflg) + { + chat_send (arg); + } + else + { + chat_expect (arg); + } + sendflg = !sendflg; + } + } + fclose (cfp); + } + /* * We got an error parsing the command line. */ -usage() +void usage() { - fprintf(stderr, - "Usage: %s [ -v ] [ -l lock-file ] [ -t timeout ] chat-script\n", + fprintf(stderr, "\ +Usage: %s [-v] [-t timeout] [-r report-file] {-f chat-file | chat-script}\n", program_name); exit(1); } +char line[256]; +char *p; + +void logf (str) +const char *str; + { + p = line + strlen(line); + strcat (p, str); + + if (str[strlen(str)-1] == '\n') + { + syslog (LOG_INFO, "%s", line); + line[0] = 0; + } + } + +void logflush() + { + if (line[0] != 0) + { + syslog(LOG_INFO, "%s", line); + line[0] = 0; + } + } + /* - * Print a warning message. + * Terminate with an error. */ -/*VARARGS1*/ -warn(format, arg1, arg2, arg3, arg4) -char *format; -int arg1, arg2, arg3, arg4; +void die() { - logf("%s: Warning: ", program_name); - logf(format, arg1, arg2, arg3, arg4); - logf("\n"); + terminate(1); } /* * Print an error message and terminate. */ -/*VARARGS1*/ -fatal(format, arg1, arg2, arg3, arg4) -char *format; -int arg1, arg2, arg3, arg4; + +void fatal (msg) +const char *msg; { - logf("%s: ", program_name); - logf(format, arg1, arg2, arg3, arg4); - logf("\n"); - unlock(); - terminate(1); + syslog(LOG_ERR, "%s", msg); + terminate(2); } /* * Print an error message along with the system error message and * terminate. */ -/*VARARGS1*/ -sysfatal(format, arg1, arg2, arg3, arg4) -char *format; -int arg1, arg2, arg3, arg4; - { - char message[STR_LEN]; - sprintf(message, "%s: ", program_name); - sprintf(message + strlen(message), format, arg1, arg2, arg3, arg4); - perror(message); - unlock(); - terminate(1); +void sysfatal (msg) +const char *msg; + { + syslog(LOG_ERR, "%s: %m", msg); + terminate(2); } int alarmed = 0; -SIGTYPE - sigalrm() -{ +SIGTYPE sigalrm(signo) +int signo; + { int flags; - alarm(1); alarmed = 1; /* Reset alarm to avoid race window */ + alarm(1); + alarmed = 1; /* Reset alarm to avoid race window */ signal(SIGALRM, sigalrm); /* that can cause hanging in read() */ + logflush(); if ((flags = fcntl(0, F_GETFL, 0)) == -1) + { sysfatal("Can't get file mode flags on stdin"); + } else - if (fcntl(0, F_SETFL, flags | FNDELAY) == -1) + { + if (fcntl(0, F_SETFL, flags | O_NONBLOCK) == -1) + { sysfatal("Can't set file mode flags on stdin"); + } + } if (verbose) { - logf("alarm\n"); + syslog(LOG_INFO, "alarm"); } } -unalarm() +void unalarm() { int flags; if ((flags = fcntl(0, F_GETFL, 0)) == -1) + { sysfatal("Can't get file mode flags on stdin"); + } else - if (fcntl(0, F_SETFL, flags & ~FNDELAY) == -1) + { + if (fcntl(0, F_SETFL, flags & ~O_NONBLOCK) == -1) + { sysfatal("Can't set file mode flags on stdin"); + } + } } -SIGTYPE - sigint() -{ - fatal("SIGINT"); -} +SIGTYPE sigint(signo) +int signo; + { + fatal("SIGINT"); + } -SIGTYPE - sigterm() -{ - fatal("SIGTERM"); -} +SIGTYPE sigterm(signo) +int signo; + { + fatal("SIGTERM"); + } -SIGTYPE - sighup() -{ - fatal("SIGHUP"); -} +SIGTYPE sighup(signo) +int signo; + { + fatal("SIGHUP"); + } -init() +void init() { signal(SIGINT, sigint); signal(SIGTERM, sigterm); signal(SIGHUP, sighup); - if (lock_file) - lock(); - set_tty_parameters(); signal(SIGALRM, sigalrm); - alarm(0); alarmed = 0; + alarm(0); + alarmed = 0; } - -set_tty_parameters() +void set_tty_parameters() { -#ifdef TERMIO - struct termio t; +#if defined(get_term_param) + term_parms t; - if (ioctl(0, TCGETA, &t) < 0) + if (get_term_param (&t) < 0) + { sysfatal("Can't get terminal parameters"); -#endif -#ifdef TERMIOS - struct termios t; - - if (tcgetattr(0, &t) < 0) - sysfatal("Can't get terminal parameters"); -#endif + } saved_tty_parameters = t; - have_tty_parameters = 1; - - t.c_iflag = IGNBRK | ISTRIP | IGNPAR; - t.c_oflag = 0; - t.c_lflag = 0; - t.c_cc[VERASE] = t.c_cc[VKILL] = 0; - t.c_cc[VMIN] = 1; - t.c_cc[VTIME] = 0; - -#ifdef TERMIO - if (ioctl(0, TCSETA, &t) < 0) - sysfatal("Can't set terminal parameters"); -#endif -#ifdef TERMIOS - if (tcsetattr(0, TCSANOW, &t) < 0) + have_tty_parameters = 1; + + t.c_iflag |= IGNBRK | ISTRIP | IGNPAR; + t.c_oflag = 0; + t.c_lflag = 0; + t.c_cc[VERASE] = + t.c_cc[VKILL] = 0; + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + + if (set_term_param (&t) < 0) + { sysfatal("Can't set terminal parameters"); + } #endif } - -terminate(status) -{ - if (have_tty_parameters && -#ifdef TERMIO - ioctl(0, TCSETA, &saved_tty_parameters) < 0 -#endif +void break_sequence() + { #ifdef TERMIOS - tcsetattr(0, TCSANOW, &saved_tty_parameters) < 0 + tcsendbreak (0, 0); #endif - ) { - perror("Can't restore terminal parameters"); - unlock(); - exit(1); - } - exit(status); -} - -/* - * Create a lock file for the named lock device - */ -lock() - { - char hdb_lock_buffer[12]; - int fd, pid; - - lock_file = strcat(strcat(strcpy(malloc(strlen(LOCK_DIR) - + 1 + strlen(lock_file) + 1), - LOCK_DIR), "/"), lock_file); - - if ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) - { - char *s = lock_file; - - lock_file = (char *)0; /* Don't remove someone else's lock file! */ - sysfatal("Can't get lock file '%s'", s); - } - -# ifdef PIDSTRING - sprintf(hdb_lock_buffer, "%10d\n", getpid()); - write(fd, hdb_lock_buffer, 11); -# else - pid = getpid(); - write(fd, &pid, sizeof pid); -# endif - - close(fd); } -/* - * Remove our lockfile - */ -unlock() +void terminate(status) +int status; { - if (lock_file) - { - unlink(lock_file); - lock_file = (char *)0; - } + if (report_file != (char *) 0 && report_fp != (FILE *) NULL) + { + if (verbose) + { + fprintf (report_fp, "Closing \"%s\".\n", report_file); + } + fclose (report_fp); + report_fp = (FILE*) NULL; + } + +#if defined(get_term_param) + if (have_tty_parameters) + { + if (set_term_param (&saved_tty_parameters) < 0) + { + syslog(LOG_ERR, "Can't restore terminal parameters: %m"); + exit(1); + } + } +#endif + + exit(status); } /* @@ -400,59 +604,158 @@ char *clean(s, sending) register char *s; int sending; { - char temp[STR_LEN]; + char temp[STR_LEN], cur_chr; register char *s1; int add_return = sending; +#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7')) - for (s1 = temp; *s; ++s) - switch (*s) - { - case '\\': - switch (*++s) - { - case '\\': - case 'd': if (sending) - *s1++ = '\\'; - - *s1++ = *s; - break; - - case 'q': quiet = ! quiet; break; - case 'r': *s1++ = '\r'; break; - case 'n': *s1++ = '\n'; break; - case 's': *s1++ = ' '; break; + s1 = temp; + while (*s) + { + cur_chr = *s++; + if (cur_chr == '^') + { + cur_chr = *s++; + if (cur_chr == '\0') + { + *s1++ = '^'; + break; + } + cur_chr &= 0x1F; + if (cur_chr != 0) + { + *s1++ = cur_chr; + } + continue; + } - case 'c': if (sending && s[1] == '\0') - add_return = 0; - else - *s1++ = *s; + if (cur_chr != '\\') + { + *s1++ = cur_chr; + continue; + } - break; + cur_chr = *s++; + if (cur_chr == '\0') + { + if (sending) + { + *s1++ = '\\'; + *s1++ = '\\'; + } + break; + } - default: *s1++ = *s; - } + switch (cur_chr) + { + case 'b': + *s1++ = '\b'; + break; + + case 'c': + if (sending && *s == '\0') + { + add_return = 0; + } + else + { + *s1++ = cur_chr; + } + break; + + case '\\': + case 'K': + case 'p': + case 'd': + if (sending) + { + *s1++ = '\\'; + } + + *s1++ = cur_chr; + break; + + case 'q': + quiet = ! quiet; + break; + + case 'r': + *s1++ = '\r'; + break; + + case 'n': + *s1++ = '\n'; + break; + + case 's': + *s1++ = ' '; + break; + + case 't': + *s1++ = '\t'; + break; + + case 'N': + if (sending) + { + *s1++ = '\\'; + *s1++ = '\0'; + } + else + { + *s1++ = 'N'; + } + break; + + default: + if (isoctal (cur_chr)) + { + cur_chr &= 0x07; + if (isoctal (*s)) + { + cur_chr <<= 3; + cur_chr |= *s++ - '0'; + if (isoctal (*s)) + { + cur_chr <<= 3; + cur_chr |= *s++ - '0'; + } + } - break; + if (cur_chr != 0 || sending) + { + if (sending && (cur_chr == '\\' || cur_chr == 0)) + { + *s1++ = '\\'; + } + *s1++ = cur_chr; + } + break; + } - case '^': - *s1++ = (int)(*++s) & 0x1F; - break; + if (sending) + { + *s1++ = '\\'; + } + *s1++ = cur_chr; + break; + } + } - default: - *s1++ = *s; - } - if (add_return) + { *s1++ = '\r'; + } - *s1 = '\0'; - return (copyof(temp)); + *s1++ = '\0'; /* guarantee closure */ + *s1++ = '\0'; /* terminate the string */ + return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */ } /* - * + * Process the expect string */ -chat_expect(s) +void chat_expect(s) register char *s; { if (strcmp(s, "ABORT") == 0) @@ -461,6 +764,12 @@ register char *s; return; } + if (strcmp(s, "REPORT") == 0) + { + ++report_next; + return; + } + if (strcmp(s, "TIMEOUT") == 0) { ++timeout_next; @@ -472,24 +781,38 @@ register char *s; register char *hyphen; for (hyphen = s; *hyphen; ++hyphen) + { if (*hyphen == '-') + { if (hyphen == s || hyphen[-1] != '\\') + { break; + } + } + } if (*hyphen == '-') { *hyphen = '\0'; if (get_string(s)) + { return; + } else { s = hyphen + 1; for (hyphen = s; *hyphen; ++hyphen) + { if (*hyphen == '-') + { if (hyphen == s || hyphen[-1] != '\\') + { break; + } + } + } if (*hyphen == '-') { @@ -506,23 +829,30 @@ register char *s; } } else + { if (get_string(s)) + { return; + } else { if (fail_reason) - logf("Failed(%s)\n", fail_reason); + { + syslog(LOG_INFO, "Failed (%s)", fail_reason); + } else - logf("Failed\n"); + { + syslog(LOG_INFO, "Failed"); + } - unlock(); - terminate(1); + terminate(exit_code); } + } } } char *character(c) -char c; +int c; { static char string[10]; char *meta; @@ -531,75 +861,134 @@ char c; c &= 0x7F; if (c < 32) + { sprintf(string, "%s^%c", meta, (int)c + '@'); + } else + { if (c == 127) + { sprintf(string, "%s^?", meta); + } else + { sprintf(string, "%s%c", meta, c); + } + } return (string); } /* - * + * process the reply string */ -chat_send(s) +void chat_send (s) register char *s; { if (abort_next) - { + { char *s1; - + abort_next = 0; - + if (n_aborts >= MAX_ABORTS) + { fatal("Too many ABORT strings"); - + } + s1 = clean(s, 0); + + if (strlen(s1) > strlen(s) + || strlen(s1) + 1 > sizeof(fail_buffer)) + { + syslog(LOG_WARNING, "Illegal or too-long ABORT string ('%s')", s); + die(); + } - if (strlen(s1) > strlen(s)) - fatal("Illegal ABORT string ('%s')\n", s); - - if (strlen(s1) > sizeof fail_buffer - 1) - fatal("Too long ABORT string ('%s')\n", s); - - strcpy(s, s1); - abort_string[n_aborts++] = s; + abort_string[n_aborts++] = s1; if (verbose) { - register char *s1 = s; - logf("abort on ("); for (s1 = s; *s1; ++s1) - logf("%s", character(*s1)); + { + logf(character(*s1)); + } logf(")\n"); } + return; } - else - if (timeout_next) + + if (report_next) + { + char *s1; + + report_next = 0; + if (n_reports >= MAX_REPORTS) + { + fatal("Too many REPORT strings"); + } + + s1 = clean(s, 0); + + if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1) { - timeout_next = 0; - timeout = atoi(s); + syslog(LOG_WARNING, "Illegal or too-long REPORT string ('%s')", s); + die(); + } + + report_string[n_reports++] = s1; + + if (verbose) + { + logf("report ("); + s1 = s; + while (*s1) + { + logf(character(*s1)); + ++s1; + } + logf(")\n"); + } + return; + } - if (timeout <= 0) - timeout = DEFAULT_CHAT_TIMEOUT; + if (timeout_next) + { + timeout_next = 0; + timeout = atoi(s); + + if (timeout <= 0) + { + timeout = DEFAULT_CHAT_TIMEOUT; + } - if (verbose) - { - logf("timeout set to %d seconds\n", timeout); - } + if (verbose) + { + syslog(LOG_INFO, "timeout set to %d seconds", timeout); } - else - if ( ! put_string(s)) - { - logf("Failed\n"); - unlock(); - terminate(1); - } + return; + } + + if (strcmp(s, "EOT") == 0) + { + s = "^D\\c"; + } + else + { + if (strcmp(s, "BREAK") == 0) + { + s = "\\K\\c"; + } + } + + if (!put_string(s)) + { + syslog(LOG_INFO, "Failed"); + terminate(1); + } } int get_char() @@ -610,53 +999,94 @@ int get_char() status = read(0, &c, 1); switch (status) - { - case 1: - return ((int)c & 0x7F); + { + case 1: + return ((int)c & 0x7F); - default: - warn("read() on stdin returned %d", status); - - case -1: - if ((status = fcntl(0, F_GETFL, 0)) == -1) - sysfatal("Can't get file mode flags on stdin"); - else - if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1) - sysfatal("Can't set file mode flags on stdin"); + default: + syslog(LOG_WARNING, "warning: read() on stdin returned %d", + status); - return (-1); - } + case -1: + if ((status = fcntl(0, F_GETFL, 0)) == -1) + { + sysfatal("Can't get file mode flags on stdin"); + } + else + { + if (fcntl(0, F_SETFL, status & ~O_NONBLOCK) == -1) + { + sysfatal("Can't set file mode flags on stdin"); + } + } + + return (-1); + } } int put_char(c) -char c; +int c; { int status; + char ch = c; - delay(); + usleep(10000); /* inter-character typing delay (?) */ - status = write(1, &c, 1); + status = write(1, &ch, 1); switch (status) + { + case 1: + return (0); + + default: + syslog(LOG_WARNING, "warning: write() on stdout returned %d", + status); + + case -1: + if ((status = fcntl(0, F_GETFL, 0)) == -1) + { + sysfatal("Can't get file mode flags on stdin"); + } + else + { + if (fcntl(0, F_SETFL, status & ~O_NONBLOCK) == -1) + { + sysfatal("Can't set file mode flags on stdin"); + } + } + + return (-1); + } + } + +int write_char (c) +int c; + { + if (alarmed || put_char(c) < 0) { - case 1: - return (0); + extern int errno; - default: - warn("write() on stdout returned %d", status); + alarm(0); + alarmed = 0; - case -1: - if ((status = fcntl(0, F_GETFL, 0)) == -1) - sysfatal("Can't get file mode flags on stdin"); + if (verbose) + { + if (errno == EINTR || errno == EWOULDBLOCK) + { + syslog(LOG_INFO, " -- write timed out"); + } else - if (fcntl(0, F_SETFL, status & ~FNDELAY) == -1) - sysfatal("Can't set file mode flags on stdin"); - - return (-1); + { + syslog(LOG_INFO, " -- write failed: %m"); + } + } + return (0); } + return (1); } -int put_string(s) +int put_string (s) register char *s; { s = clean(s, 1); @@ -666,13 +1096,17 @@ register char *s; logf("send ("); if (quiet) + { logf("??????"); + } else { register char *s1 = s; for (s1 = s; *s1; ++s1) - logf("%s", character(*s1)); + { + logf(character(*s1)); + } } logf(")\n"); @@ -680,39 +1114,43 @@ register char *s; alarm(timeout); alarmed = 0; - for ( ; *s; ++s) + while (*s) { - register char c = *s; + register char c = *s++; - if (c == '\\') - if ((c = *++s) == '\0') - break; - else - if (c == 'd') /* \d -- Delay */ - { - sleep(2); - continue; - } + if (c != '\\') + { + if (!write_char (c)) + { + return 0; + } + continue; + } - if (alarmed || put_char(*s) < 0) + c = *s++; + switch (c) { - extern int errno; + case 'd': + sleep(1); + break; - alarm(0); alarmed = 0; + case 'K': + break_sequence(); + break; - if (verbose) - { - if (errno == EINTR || errno == EWOULDBLOCK) - logf(" -- write timed out\n"); - else - syslog(LOG_INFO, " -- write failed: %m"); - } + case 'p': + usleep(10000); /* 1/100th of a second (arg is microseconds) */ + break; - return (0); + default: + if (!write_char (c)) + return 0; + break; } } - alarm(0); alarmed = 0; + alarm(0); + alarmed = 0; return (1); } @@ -738,39 +1176,47 @@ register char *string; logf("expect ("); for (s1 = string; *s1; ++s1) - logf("%s", character(*s1)); + { + logf(character(*s1)); + } logf(")\n"); } if (len > STR_LEN) { - logf("expect string is too long\n"); - return; + syslog(LOG_INFO, "expect string is too long"); + exit_code = 1; + return 0; } if (len == 0) { if (verbose) { - logf("got it\n"); + syslog(LOG_INFO, "got it"); } return (1); } - alarm(timeout); alarmed = 0; + alarm(timeout); + alarmed = 0; while ( ! alarmed && (c = get_char()) >= 0) { - int n, abort_len; + int n, abort_len, report_len; if (verbose) { if (c == '\n') + { logf("\n"); + } else - logf("%s", character(c)); + { + logf(character(c)); + } } *s++ = c; @@ -781,91 +1227,100 @@ register char *string; { if (verbose) { - logf("got it\n"); + logf(" -- got it\n"); } - alarm(0); alarmed = 0; + alarm(0); + alarmed = 0; return (1); } for (n = 0; n < n_aborts; ++n) + { if (s - temp >= (abort_len = strlen(abort_string[n])) && strncmp(s - abort_len, abort_string[n], abort_len) == 0) - { + { if (verbose) { logf(" -- failed\n"); } - - alarm(0); alarmed = 0; + + alarm(0); + alarmed = 0; + exit_code = n + 4; strcpy(fail_reason = fail_buffer, abort_string[n]); return (0); - } + } + } + + if (!report_gathering) + { + for (n = 0; n < n_reports; ++n) + { + if ((report_string[n] != (char*) NULL) && + s - temp >= (report_len = strlen(report_string[n])) && + strncmp(s - report_len, report_string[n], report_len) == 0) + { + time_t time_now = time ((time_t*) NULL); + struct tm* tm_now = localtime (&time_now); + + strftime (report_buffer, 20, "%b %d %H:%M:%S ", tm_now); + strcat (report_buffer, report_string[n]); + + report_string[n] = (char *) NULL; + report_gathering = 1; + break; + } + } + } + else + { + if (!iscntrl (c)) + { + int rep_len = strlen (report_buffer); + report_buffer[rep_len] = c; + report_buffer[rep_len + 1] = '\0'; + } + else + { + report_gathering = 0; + fprintf (report_fp, "chat: %s\n", report_buffer); + } + } if (s >= end) { - strncpy(temp, s - minlen, minlen); + strncpy (temp, s - minlen, minlen); s = temp + minlen; } if (alarmed && verbose) - warn("Alarm synchronization problem"); + { + syslog(LOG_WARNING, "warning: alarm synchronization problem"); + } } alarm(0); if (verbose && printed) { - extern int errno; - if (alarmed) + { logf(" -- read timed out\n"); + } else + { + logflush(); syslog(LOG_INFO, " -- read failed: %m"); + } } - alarmed = 0; + exit_code = 3; + alarmed = 0; return (0); } -/* - * Delay an amount appropriate for between typed characters. - */ -delay() - { - register int i; - -# ifdef NO_USLEEP - for (i = 0; i < 30000; ++i) /* ... did we just say appropriate? */ - ; -# else /* NO_USLEEP */ - usleep(100); -# endif /* NO_USLEEP */ - } - -char line[256]; -char *p; - -logf(fmt, va_alist) -char *fmt; -va_dcl -{ - va_list pvar; - char buf[256]; - - va_start(pvar); - vsprintf(buf, fmt, pvar); - va_end(pvar); - - p = line + strlen(line); - strcat(p, buf); - - if (buf[strlen(buf)-1] == '\n') { - syslog(LOG_INFO, "%s", line); - line[0] = 0; - } -} -#ifdef ultrix +#ifdef NO_USLEEP #include #include @@ -874,19 +1329,19 @@ va_dcl last edit: 29-Oct-1984 D A Gwyn */ -extern int select(); +extern int select(); int -usleep( usec ) /* returns 0 if ok, else -1 */ - long usec; /* delay in microseconds */ +usleep( usec ) /* returns 0 if ok, else -1 */ + long usec; /* delay in microseconds */ { - static struct /* `timeval' */ - { - long tv_sec; /* seconds */ - long tv_usec; /* microsecs */ - } delay; /* _select() timeout */ + static struct /* `timeval' */ + { + long tv_sec; /* seconds */ + long tv_usec; /* microsecs */ + } delay; /* _select() timeout */ - delay.tv_sec = usec / 1000000L; + delay.tv_sec = usec / 1000000L; delay.tv_usec = usec % 1000000L; return select( 0, (long *)0, (long *)0, (long *)0, &delay );