From b8cffa329b528f8b072d8efd0fed75bcc22f2cdd Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Fri, 27 Aug 2021 09:36:06 +0100
Subject: 49290: Replace stdio for buffered shell input.
The previous method allowed memory management to interact with signal
handlers, causing occasional crashes on some system.
Instead, use a simple pre-allocated buffer and raw system calls.
(cherry picked from commit e5cd2dd980302f328d232d933f646c3dc02828bf)
---
Src/input.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 111 insertions(+), 11 deletions(-)
(limited to 'Src/input.c')
diff --git a/Src/input.c b/Src/input.c
index e9989ffe4..874776c59 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -80,11 +80,6 @@
/**/
int SHIN;
-/* buffered shell input for non-interactive shells */
-
-/**/
-FILE *bshin;
-
/* != 0 means we are reading input from a string */
/**/
@@ -129,7 +124,116 @@ static struct instacks *instack, *instacktop;
static int instacksz = INSTACK_INITIAL;
-/* Read a line from bshin. Convert tokens and *
+/* Size of buffer for non-interactive command input */
+
+#define SHINBUFSIZE 8192
+
+/* Input buffer for non-interactive command input */
+static char *shinbuffer;
+
+/* Pointer into shinbuffer */
+static char *shinbufptr;
+
+/* End of contents read into shinbuffer */
+static char *shinbufendptr;
+
+/* Entry on SHIN buffer save stack */
+struct shinsaveentry {
+ /* Next entry on stack */
+ struct shinsaveentry *next;
+ /* Saved shinbuffer */
+ char *buffer;
+ /* Saved shinbufptr */
+ char *ptr;
+ /* Saved shinbufendptr */
+ char *endptr;
+};
+
+/* SHIN buffer save stack */
+struct shinsaveentry *shinsavestack;
+
+/* Reset the input buffer for SHIN, discarding any pending input */
+
+/**/
+void
+shinbufreset(void)
+{
+ shinbufendptr = shinbufptr = shinbuffer;
+}
+
+/* Allocate a new shinbuffer
+ *
+ * Only called at shell initialisation and when saving on the stack.
+ */
+
+/**/
+void
+shinbufalloc(void)
+{
+ shinbuffer = zalloc(SHINBUFSIZE);
+ shinbufreset();
+}
+
+/* Save entry on SHIN buffer save stack */
+
+/**/
+void
+shinbufsave(void)
+{
+ struct shinsaveentry *entry =
+ (struct shinsaveentry *)zalloc(sizeof(struct shinsaveentry));
+
+ entry->next = shinsavestack;
+ entry->buffer = shinbuffer;
+ entry->ptr = shinbufptr;
+ entry->endptr = shinbufendptr;
+
+ shinsavestack = entry;
+
+ shinbufalloc();
+}
+
+/* Restore entry from SHIN buffer save stack */
+
+/**/
+void
+shinbufrestore(void)
+{
+ struct shinsaveentry *entry = shinsavestack;
+
+ zfree(shinbuffer, SHINBUFSIZE);
+
+ shinbuffer = entry->buffer;
+ shinbufptr = entry->ptr;
+ shinbufendptr = entry->endptr;
+
+ shinsavestack = entry->next;
+ zfree(entry, sizeof(struct shinsaveentry));
+}
+
+/* Get a character from SHIN, -1 if none available */
+
+/**/
+static int
+shingetchar(void)
+{
+ int nread;
+
+ if (shinbufptr < shinbufendptr)
+ return STOUC(*shinbufptr++);
+
+ shinbufreset();
+ do {
+ errno = 0;
+ nread = read(SHIN, shinbuffer, SHINBUFSIZE);
+ } while (nread < 0 && errno == EINTR);
+ if (nread <= 0)
+ return -1;
+ shinbufendptr = shinbuffer + nread;
+ return STOUC(*shinbufptr++);
+}
+
+/* Read a line from SHIN. Convert tokens and *
* null characters to Meta c^32 character pairs. */
/**/
@@ -147,11 +251,7 @@ shingetline(void)
winch_unblock();
dont_queue_signals();
for (;;) {
- /* Can't fgets() here because we need to accept '\0' bytes */
- do {
- errno = 0;
- c = fgetc(bshin);
- } while (c < 0 && errno == EINTR);
+ c = shingetchar();
if (c < 0 || c == '\n') {
winch_block();
restore_queue_signals(q);
--
cgit v1.2.3
From 27cd80938327388bcbed615dbbdba0eddd16a255 Mon Sep 17 00:00:00 2001
From: Jun-ichi Takimoto
Date: Wed, 8 Sep 2021 10:18:51 +0900
Subject: unposted: add 'static' to shinsavestack
(cherry picked from commit 309d899507adc62de5a6c37c32386898b44895fd)
---
ChangeLog | 3 +++
Src/input.c | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
(limited to 'Src/input.c')
diff --git a/ChangeLog b/ChangeLog
index 96484aba2..b46044ae4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2022-01-27 dana
+ * Jun-ichi Takimoto: unposted: Src/input.c: add 'static' to
+ shinsavestack
+
* Peter Stephenson: 49290: Src/init.c, Src/input.c: Replace
stdio for buffered shell input to avoid memory management
interacting with signal handlers.
diff --git a/Src/input.c b/Src/input.c
index 874776c59..18228b37d 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -150,7 +150,7 @@ struct shinsaveentry {
};
/* SHIN buffer save stack */
-struct shinsaveentry *shinsavestack;
+static struct shinsaveentry *shinsavestack;
/* Reset the input buffer for SHIN, discarding any pending input */
--
cgit v1.2.3