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