]> git.ozlabs.org Git - ppp.git/blobdiff - chat/chat.c
Makefile.am: Add explicit openssl directory to pppd include path
[ppp.git] / chat / chat.c
index d2d255a1c7c015660adb75b0f9dcc21e6953d964..336c0f4995f4ab3dadd1612673d251ec0d3507d5 100644 (file)
@@ -182,7 +182,7 @@ int n_aborts = 0, abort_next = 0, timeout_next = 0, echo_next = 0;
 int clear_abort_next = 0;
 
 char *report_string[MAX_REPORTS] ;
-char  report_buffer[256] ;
+char  report_buffer[4096] ;
 int n_reports = 0, report_next = 0, report_gathering = 0 ; 
 int clear_report_next = 0;
 
@@ -198,10 +198,10 @@ SIGTYPE sigalrm (int signo);
 SIGTYPE sigint (int signo);
 SIGTYPE sigterm (int signo);
 SIGTYPE sighup (int signo);
-void unalarm (void);
+void checksigs(void);
 void init (void);
 void set_tty_parameters (void);
-void echo_stderr (int);
+int  echo_stderr (int);
 void break_sequence (void);
 void terminate (int status);
 void do_file (char *chat_file);
@@ -210,12 +210,11 @@ int  put_string (register char *s);
 int  write_char (int c);
 int  put_char (int c);
 int  get_char (void);
-void chat_send (register char *s);
+int  chat_send (register char *s);
 char *character (int c);
 void chat_expect (register char *s);
 char *clean (register char *s, int sending);
 void break_sequence (void);
-void terminate (int status);
 void pack_array (char **array, int end);
 char *expect_strtok (char *, char *);
 int vfmtmsg (char *, int, const char *, va_list);      /* vsprintf++ */
@@ -347,16 +346,12 @@ main(int argc, char **argv)
        report_fp = stderr;
 
     if (to_log) {
-#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));
-#endif
     }
 
     init();
@@ -373,6 +368,7 @@ main(int argc, char **argv)
 
            if ((arg = ARG(argc, argv)) != NULL)
                chat_send(arg);
+           checksigs();
        }
     }
 
@@ -444,8 +440,10 @@ void do_file (char *chat_file)
            else
                chat_expect (arg);
            sendflg = !sendflg;
+           checksigs();
        }
     }
+    checksigs();
     fclose (cfp);
 }
 
@@ -499,59 +497,68 @@ void fatal(int code, const char *fmt, ...)
 }
 
 int alarmed = 0;
+int alarmsig = 0;
 
 SIGTYPE sigalrm(int signo)
 {
     int flags;
 
     alarm(1);
-    alarmed = 1;               /* Reset alarm to avoid race window */
-    signal(SIGALRM, sigalrm);  /* that can cause hanging in read() */
-
-    if ((flags = fcntl(0, F_GETFL, 0)) == -1)
-       fatal(2, "Can't get file mode flags on stdin: %m");
-
-    if (fcntl(0, F_SETFL, flags | O_NONBLOCK) == -1)
-       fatal(2, "Can't set file mode flags on stdin: %m");
-
-    if (verbose)
-       msgf("alarm");
+    alarmed = 1;
+    alarmsig = 1;
 }
 
-void unalarm(void)
-{
-    int flags;
-
-    if ((flags = fcntl(0, F_GETFL, 0)) == -1)
-       fatal(2, "Can't get file mode flags on stdin: %m");
-
-    if (fcntl(0, F_SETFL, flags & ~O_NONBLOCK) == -1)
-       fatal(2, "Can't set file mode flags on stdin: %m");
-}
+const char *fatalsig = NULL;
 
 SIGTYPE sigint(int signo)
 {
-    fatal(2, "SIGINT");
+    fatalsig = "SIGINT";
 }
 
 SIGTYPE sigterm(int signo)
 {
-    fatal(2, "SIGTERM");
+    fatalsig = "SIGTERM";
 }
 
 SIGTYPE sighup(int signo)
 {
-    fatal(2, "SIGHUP");
+    fatalsig = "SIGHUP";
+}
+
+void checksigs(void)
+{
+    int err;
+    const char *signame;
+
+    if (fatalsig) {
+       signame = fatalsig;
+       fatalsig = NULL;
+       alarmsig = 0;
+       fatal(2, signame);
+    }
+    if (alarmsig && verbose) {
+       err = errno;
+       msgf("alarm");
+       errno = err;
+       alarmsig = 0;
+    }
 }
 
 void init(void)
 {
-    signal(SIGINT, sigint);
-    signal(SIGTERM, sigterm);
-    signal(SIGHUP, sighup);
+    struct sigaction sa;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = sigint;
+    sigaction(SIGINT, &sa, NULL);
+    sa.sa_handler = sigterm;
+    sigaction(SIGTERM, &sa, NULL);
+    sa.sa_handler = sighup;
+    sigaction(SIGHUP, &sa, NULL);
 
     set_tty_parameters();
-    signal(SIGALRM, sigalrm);
+    sa.sa_handler = sigalrm;
+    sigaction(SIGALRM, &sa, NULL);
     alarm(0);
     alarmed = 0;
 }
@@ -602,7 +609,7 @@ void terminate(int status)
        int c, rep_len;
 
        rep_len = strlen(report_buffer);
-       while (rep_len + 1 <= sizeof(report_buffer)) {
+       while (rep_len + 1 < sizeof(report_buffer)) {
            alarm(1);
            c = get_char();
            alarm(0);
@@ -945,6 +952,7 @@ void chat_expect (char *s)
            break;
 
        chat_send (reply);
+       checksigs();
     }
 
 /*
@@ -983,31 +991,37 @@ char *character(int c)
 /*
  *  process the reply string
  */
-void chat_send (register char *s)
+int chat_send (register char *s)
 {
     char file_data[STR_LEN];
+    int len, ret = 0;
+    struct sigaction sa;
 
     if (say_next) {
        say_next = 0;
        s = clean(s, 1);
-       write(2, s, strlen(s));
+       len = strlen(s);
+       ret = write(2, s, len) != len;
         free(s);
-       return;
+       return ret;
     }
 
     if (hup_next) {
         hup_next = 0;
+       memset(&sa, 0, sizeof(sa));
+
        if (strcmp(s, "OFF") == 0)
-           signal(SIGHUP, SIG_IGN);
+           sa.sa_handler = SIG_IGN;
         else
-           signal(SIGHUP, sighup);
-        return;
+           sa.sa_handler = sighup;
+       sigaction(SIGHUP, &sa, NULL);
+        return 0;
     }
 
     if (echo_next) {
        echo_next = 0;
        echo = (strcmp(s, "ON") == 0);
-       return;
+       return 0;
     }
 
     if (abort_next) {
@@ -1027,7 +1041,7 @@ void chat_send (register char *s)
 
        if (verbose)
            msgf("abort on (%v)", s1);
-       return;
+       return 0;
     }
 
     if (clear_abort_next) {
@@ -1057,7 +1071,7 @@ void chat_send (register char *s)
         free(s1);
        if (pack)
            pack_array(abort_string,old_max);
-       return;
+       return 0;
     }
 
     if (report_next) {
@@ -1075,7 +1089,7 @@ void chat_send (register char *s)
        
        if (verbose)
            msgf("report (%v)", s1);
-       return;
+       return 0;
     }
 
     if (clear_report_next) {
@@ -1106,7 +1120,7 @@ void chat_send (register char *s)
         if (pack)
            pack_array(report_string,old_max);
        
-       return;
+       return 0;
     }
 
     if (timeout_next) {
@@ -1119,8 +1133,8 @@ void chat_send (register char *s)
 
        if (verbose)
            msgf("timeout set to %d seconds", timeout);
-
-       return;
+       free(s);
+       return 0;
     }
 
     /*
@@ -1167,6 +1181,8 @@ void chat_send (register char *s)
 
     if (!put_string(s))
        fatal(1, "Failed");
+
+    return 0;
 }
 
 int get_char(void)
@@ -1175,6 +1191,7 @@ int get_char(void)
     char c;
 
     status = read(0, &c, 1);
+    checksigs();
 
     switch (status) {
     case 1:
@@ -1184,12 +1201,6 @@ int get_char(void)
        msgf("warning: read() on stdin returned %d", status);
 
     case -1:
-       if ((status = fcntl(0, F_GETFL, 0)) == -1)
-           fatal(2, "Can't get file mode flags on stdin: %m");
-
-       if (fcntl(0, F_SETFL, status & ~O_NONBLOCK) == -1)
-           fatal(2, "Can't set file mode flags on stdin: %m");
-       
        return (-1);
     }
 }
@@ -1200,8 +1211,10 @@ int put_char(int c)
     char ch = c;
 
     usleep(10000);             /* inter-character typing delay (?) */
+    checksigs();
 
     status = write(1, &ch, 1);
+    checksigs();
 
     switch (status) {
     case 1:
@@ -1211,12 +1224,6 @@ int put_char(int c)
        msgf("warning: write() on stdout returned %d", status);
        
     case -1:
-       if ((status = fcntl(0, F_GETFL, 0)) == -1)
-           fatal(2, "Can't get file mode flags on stdin, %m");
-
-       if (fcntl(0, F_SETFL, status & ~O_NONBLOCK) == -1)
-           fatal(2, "Can't set file mode flags on stdin: %m");
-       
        return (-1);
     }
 }
@@ -1240,8 +1247,11 @@ int write_char(int c)
 
 int put_string(register char *s)
 {
+    char *s1;
     quiet = 0;
+
     s = clean(s, 1);
+    s1 = s;
 
     if (verbose) {
        if (quiet)
@@ -1256,8 +1266,10 @@ int put_string(register char *s)
        register char c = *s++;
 
        if (c != '\\') {
-           if (!write_char (c))
+           if (!write_char (c)) {
+               free(s1);
                return 0;
+           }
            continue;
        }
 
@@ -1276,14 +1288,18 @@ int put_string(register char *s)
            break;
 
        default:
-           if (!write_char (c))
+           if (!write_char (c)) {
+               free(s1);
                return 0;
+           }
            break;
        }
+       checksigs();
     }
 
     alarm(0);
     alarmed = 0;
+    free(s1);
     return (1);
 }
 
@@ -1292,10 +1308,11 @@ int put_string(register char *s)
  *     When called with -1, a '\n' character is generated when
  *     the cursor is not at the beginning of a line.
  */
-void echo_stderr(int n)
+int echo_stderr(int n)
 {
     static int need_lf;
     char *s;
+    int len, ret = 0;
 
     switch (n) {
     case '\r':         /* ignore '\r' */
@@ -1305,15 +1322,18 @@ void echo_stderr(int n)
            break;
        /* fall through */
     case '\n':
-       write(2, "\n", 1);
+       ret = write(2, "\n", 1) != 1;
        need_lf = 0;
        break;
     default:
        s = character(n);
-       write(2, s, strlen(s));
+       len = strlen(s);
+       ret = write(2, s, len) != len;
        need_lf = 1;
        break;
     }
+    checksigs();
+    return ret;
 }
 
 /*
@@ -1324,10 +1344,10 @@ int get_string(register char *string)
     char temp[STR_LEN];
     int c, printed = 0, len, minlen;
     register char *s = temp, *end = s + STR_LEN;
-    char *logged = temp;
+    char *s1, *logged = temp;
 
     fail_reason = (char *)0;
-    string = clean(string, 0);
+    string = s1 = clean(string, 0);
     len = strlen(string);
     minlen = (len > sizeof(fail_buffer)? len: sizeof(fail_buffer)) - 1;
 
@@ -1337,12 +1357,14 @@ int get_string(register char *string)
     if (len > STR_LEN) {
        msgf("expect string is too long");
        exit_code = 1;
+       free(s1);
        return 0;
     }
 
     if (len == 0) {
        if (verbose)
            msgf("got it");
+       free(s1);
        return (1);
     }
 
@@ -1352,8 +1374,11 @@ int get_string(register char *string)
     while ( ! alarmed && (c = get_char()) >= 0) {
        int n, abort_len, report_len;
 
-       if (echo)
-           echo_stderr(c);
+       if (echo) {
+           if (echo_stderr(c) != 0) {
+               fatal(2, "Could not write to stderr, %m");
+           }
+       }
        if (verbose && c == '\n') {
            if (s == logged)
                msgf("");       /* blank line */
@@ -1387,6 +1412,7 @@ int get_string(register char *string)
                    strftime (report_buffer, 20, "%b %d %H:%M:%S ", tm_now);
                    strcat (report_buffer, report_string[n]);
 
+                   free(report_string[n]);
                    report_string[n] = (char *) NULL;
                    report_gathering = 1;
                    break;
@@ -1396,8 +1422,10 @@ int get_string(register char *string)
        else {
            if (!iscntrl (c)) {
                int rep_len = strlen (report_buffer);
-               report_buffer[rep_len]     = c;
-               report_buffer[rep_len + 1] = '\0';
+               if ((rep_len + 1) < sizeof(report_buffer)) {
+                   report_buffer[rep_len]     = c;
+                   report_buffer[rep_len + 1] = '\0';
+               }
            }
            else {
                report_gathering = 0;
@@ -1416,6 +1444,7 @@ int get_string(register char *string)
 
            alarm(0);
            alarmed = 0;
+           free(s1);
            return (1);
        }
 
@@ -1432,6 +1461,7 @@ int get_string(register char *string)
                alarmed = 0;
                exit_code = n + 4;
                strcpy(fail_reason = fail_buffer, abort_string[n]);
+               free(s1);
                return (0);
            }
        }
@@ -1463,6 +1493,7 @@ int get_string(register char *string)
 
     exit_code = 3;
     alarmed   = 0;
+    free(s1);
     return (0);
 }