Subject: bin/2130: /bin/sh: unpaired INTON in bin/sh/cd.c causes SIGINT problems
To: None <gnats-bugs@NetBSD.ORG>
From: None <leo@marco.de>
List: netbsd-bugs
Date: 02/26/1996 13:19:00
>Number:         2130
>Category:       bin
>Synopsis:       /bin/sh: unpaired INTON in bin/sh/cd.c causes SIGINT problems
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 26 07:35:01 1996
>Last-Modified:
>Originator:     Matthias Pfaller
>Organization:
	marco GmbH, Dachau, Germany
>Release:        960224
>Environment:
	
System: NetBSD klondike 1.1A NetBSD 1.1A (KLONDIKE) #67: Sun Feb 25 13:59:48 MET 1996 leo@klondike:/usr/src/sys/arch/pc532/compile/KLONDIKE pc532


>Description:
	The two macros INTOFF and INTON are used in /bin/sh to disable/enable
	software interrupts. These macros have to be used in pairs.
	In bin/sh/cd.c:getpwd() INTON is used without a INTOFF.
>How-To-Repeat:
	$ /bin/sh
	$ cd /usr
	$ <press ^C here>
	After this ^C the shell behaves very strange.
>Fix:
	The following patch fixes the problem. I think the INTOFF, INTON and
	FORCEINT macros should abort when suppressint is smaller then zero.
	The patch to error.h implements this.
--- bin/sh/cd.c.ORIG	Mon Dec 11 21:04:02 1995
+++ bin/sh/cd.c	Sun Feb 25 19:09:33 1996
@@ -356,6 +356,7 @@
 #if defined(__NetBSD__) || defined(__svr4__)
 	if (getcwd(buf, sizeof(buf)) == NULL)
 		error("getcwd() failed");
+	curdir = savestr(buf);
 #else
 	{
 		char *p;
@@ -395,7 +396,7 @@
 			error("pwd command failed");
 		p[-1] = '\0';
 	}
-#endif
 	curdir = savestr(buf);
 	INTON;
+#endif
 }
--- bin/sh/error.h.ORIG	Sat Oct 14 00:43:58 1995
+++ bin/sh/error.h	Sun Feb 25 19:21:45 1996
@@ -83,9 +83,9 @@
 extern volatile int intpending;
 extern char *commandname;	/* name of command--printed on error */
 
-#define INTOFF suppressint++
-#define INTON { if (--suppressint == 0 && intpending) onint(); }
-#define FORCEINTON {suppressint = 0; if (intpending) onint();}
+#define INTOFF do { if (suppressint++ < 0) abort(); } while (0)
+#define INTON { if (suppressint < 0) abort(); if (--suppressint == 0 && intpending) onint(); }
+#define FORCEINTON { if (suppressint < 0) abort(); suppressint = 0; if (intpending) onint(); }
 #define CLEAR_PENDING_INT intpending = 0
 #define int_pending() intpending
 
>Audit-Trail:
>Unformatted: