Hi,
deraadt@ discovered that pasting long lines in csh with filec enabled is
currently broken. NUL-terminating the input buffer from tenex()
instructs csh that the buffer contains a complete command. This is wrong
and should only happen when buffer is not full, otherwise more data has
to be read in order form a complete command.

While here, I did also discover that the prompt is printed again when
the input exceeds the input buffer. This is also true when inputting a
line continuation (i.e. backslash). In order to prevent printing the
prompt again, only print the prompt in tenex() when `needprompt == 1`.

Comments? OK?

Index: csh.c
===================================================================
RCS file: /cvs/src/bin/csh/csh.c,v
retrieving revision 1.40
diff -u -p -r1.40 csh.c
--- csh.c       26 Jul 2017 19:15:09 -0000      1.40
+++ csh.c       28 Aug 2017 07:10:31 -0000
@@ -1008,7 +1008,8 @@ process(bool catch)
             * read fresh stuff. Otherwise, we are rereading input and don't
             * need or want to prompt.
             */
-           if (!filec && aret == F_SEEK && fseekp == feobp)
+           needprompt = aret == F_SEEK && fseekp == feobp;
+           if (!filec && needprompt)
                printprompt();
            (void) fflush(cshout);
        }
Index: csh.h
===================================================================
RCS file: /cvs/src/bin/csh/csh.h,v
retrieving revision 1.29
diff -u -p -r1.29 csh.h
--- csh.h       22 Jul 2017 09:37:21 -0000      1.29
+++ csh.h       28 Aug 2017 07:10:31 -0000
@@ -108,6 +108,7 @@ bool    timflg;                     /* Time the next waite
 bool    havhash;               /* path hashing is available */
 
 bool    filec;                 /* doing filename expansion */
+bool    needprompt;            /* print prompt, used by filec */
 
 /*
  * Global i/o info
Index: file.c
===================================================================
RCS file: /cvs/src/bin/csh/file.c,v
retrieving revision 1.33
diff -u -p -r1.33 file.c
--- file.c      26 Jul 2017 19:20:51 -0000      1.33
+++ file.c      28 Aug 2017 07:10:31 -0000
@@ -779,8 +779,11 @@ tenex(Char *inputline, int inputline_siz
        cl.size = sizeof(buf);
        if (tio->c_lflag & ALTWERASE)
                cl.flags |= CL_ALTWERASE;
-       cl.flags |= CL_PROMPT;
-       cl_flush(&cl);  /* print prompt */
+       if (needprompt) {
+               needprompt = 0;
+               cl.flags |= CL_PROMPT;
+               cl_flush(&cl);
+       }
 
        for (;;) {
                if ((c = cl_getc(&cl)) == 0)
@@ -799,7 +802,14 @@ tenex(Char *inputline, int inputline_siz
 
        for (i = 0; i < cl.len; i++)
                inputline[i] = cl.buf[i];
-       inputline[i] = '\0';
+       /*
+        * NUL-terminating the buffer implies that it contains a complete
+        * command ready to be executed. Therefore, don't terminate if the
+        * buffer is full since more characters must be read in order to form a
+        * complete command.
+        */
+       if (i < sizeof(buf))
+               inputline[i] = '\0';
 
        return cl.len;
 }
Index: func.c
===================================================================
RCS file: /cvs/src/bin/csh/func.c,v
retrieving revision 1.34
diff -u -p -r1.34 func.c
--- func.c      26 Jul 2017 19:15:09 -0000      1.34
+++ func.c      28 Aug 2017 07:10:32 -0000
@@ -589,7 +589,8 @@ search(int type, int level, Char *goal)
        bseek(&a);
     }
     do {
-       if (intty && !filec && fseekp == feobp && aret == F_SEEK)
+       needprompt = intty && fseekp == feobp && aret == F_SEEK;
+       if (!filec && needprompt)
            (void) fprintf(cshout, "? "), (void) fflush(cshout);
        aword[0] = 0;
        (void) getword(aword);

Reply via email to