Author: cem
Date: Fri Feb  9 19:46:51 2018
New Revision: 329077
URL: https://svnweb.freebsd.org/changeset/base/329077

Log:
  tftp(1): Fix libedit state corruption involving signals
  
  This bug was first reported 14 years ago.  The problem was understood 8.5
  years ago.  A patch that is functionally identical to this one was proposed
  almost 8 years ago and languished in the PR system / Bugzilla.
  
  PR:           63197
  Submitted by: lxv AT omut.org, fernando.apesteguia AT gmail.com
  Reported by:  freebsd AT nbritton.org

Modified:
  head/usr.bin/tftp/main.c

Modified: head/usr.bin/tftp/main.c
==============================================================================
--- head/usr.bin/tftp/main.c    Fri Feb  9 19:10:46 2018        (r329076)
+++ head/usr.bin/tftp/main.c    Fri Feb  9 19:46:51 2018        (r329077)
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
 #include <netdb.h>
 #include <setjmp.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -114,7 +115,7 @@ static void setoptions(int, char **);
 static void    setrollover(int, char **);
 static void    setpacketdrop(int, char **);
 
-static void command(void) __dead2;
+static void command(bool, EditLine *, History *, HistEvent *) __dead2;
 static const char *command_prompt(void);
 
 static void urihandling(char *URI);
@@ -176,11 +177,28 @@ static struct     modes {
 int
 main(int argc, char *argv[])
 {
+       HistEvent he;
+       EditLine *el;
+       History *hist;
+       bool interactive;
 
        acting_as_client = 1;
        peer = -1;
        strcpy(mode, "netascii");
        signal(SIGINT, intr);
+
+       interactive = isatty(STDIN_FILENO);
+       if (interactive) {
+               el = el_init("tftp", stdin, stdout, stderr);
+               hist = history_init();
+               history(hist, &he, H_SETSIZE, 100);
+               el_set(el, EL_HIST, history, hist);
+               el_set(el, EL_EDITOR, "emacs");
+               el_set(el, EL_PROMPT, command_prompt);
+               el_set(el, EL_SIGNAL, 1);
+               el_source(el, NULL);
+       }
+
        if (argc > 1) {
                if (setjmp(toplevel) != 0)
                        exit(txrx_error);
@@ -192,11 +210,15 @@ main(int argc, char *argv[])
 
                setpeer(argc, argv);
        }
-       if (setjmp(toplevel) != 0)
+
+       if (setjmp(toplevel) != 0) {
+               if (interactive)
+                       el_reset(el);
                (void)putchar('\n');
+       }
 
        init_options();
-       command();
+       command(interactive, el, hist, &he);
 }
 
 /*
@@ -703,36 +725,22 @@ command_prompt(void)
  * Command parser.
  */
 static void
-command(void)
+command(bool interactive, EditLine *el, History *hist, HistEvent *hep)
 {
-       HistEvent he;
        struct cmd *c;
-       static EditLine *el;
-       static History *hist;
        const char *bp;
        char *cp;
-       int len, num, vrbose;
+       int len, num;
        char    line[MAXLINE];
 
-       vrbose = isatty(0);
-       if (vrbose) {
-               el = el_init("tftp", stdin, stdout, stderr);
-               hist = history_init();
-               history(hist, &he, H_SETSIZE, 100);
-               el_set(el, EL_HIST, history, hist);
-               el_set(el, EL_EDITOR, "emacs");
-               el_set(el, EL_PROMPT, command_prompt);
-               el_set(el, EL_SIGNAL, 1);
-               el_source(el, NULL);
-       }
        for (;;) {
-               if (vrbose) {
+               if (interactive) {
                         if ((bp = el_gets(el, &num)) == NULL || num == 0)
                                 exit(0);
                         len = MIN(MAXLINE, num);
                         memcpy(line, bp, len);
                         line[len] = '\0';
-                        history(hist, &he, H_ENTER, bp);
+                       history(hist, hep, H_ENTER, bp);
                } else {
                        line[0] = 0;
                        if (fgets(line, sizeof line , stdin) == NULL) {
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to