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);