Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Oct 1997 03:24:19 -0800 (PST)
From:      asami@cs.berkeley.edu (Satoshi Asami)
To:        peter@spinner.netplex.com.au
Cc:        freebsd-current@freefall.FreeBSD.org
Subject:   Re: bad system call - world build
Message-ID:  <199710291124.DAA14565@silvia.HIP.Berkeley.EDU>
In-Reply-To: <1126.878119837@critter.freebsd.dk> (message from Poul-Henning Kamp on Wed, 29 Oct 1997 11:10:37 %2B0100)

next in thread | previous in thread | raw e-mail | index | archive | help
Peter,

I took a look at your patch (attached below for the readers'
convenience):

===================================================================
RCS file: /home/ncvs/src/lib/libc/gen/getcwd.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -p -u -r1.13 -r1.14
--- src/lib/libc/gen/getcwd.c	1997/09/15 17:40:15	1.13
+++ /home/ncvs/src/lib/libc/gen/getcwd.c	1997/09/16 06:00:50	1.14
@@ -45,11 +45,14 @@ static char sccsid[] = "@(#)getcwd.c	8.5
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <signal.h>
 
 #define	ISDOT(dp) \
 	(dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
 	    (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
 
+static int have__getcwd = 1;	/* 0 = no, 1 = perhaps, 2 = yes */
+
 char *
 getcwd(pt, size)
 	char *pt;
@@ -89,17 +92,40 @@ getcwd(pt, size)
 			return (NULL);
 		ept = pt + ptsize;
 	}
-	if (!__getcwd(pt, ept - pt)) {
-		if (*pt != '/') {
-			bpt = pt;
-			ept = pt + strlen(pt) - 1;
-			while (bpt < ept) {
-				c = *bpt;
-				*bpt++ = *ept;
-				*ept-- = c;
+	if (have__getcwd) {
+		struct sigaction sa, osa;
+		int sigsys_installed = 0;
+		int ret;
+
+		if (have__getcwd == 1) {	/* unsure? */
+			bzero(&sa, sizeof(sa));
+			sa.sa_handler = SIG_IGN;
+			if (sigaction(SIGSYS, &sa, &osa) >= 0)
+				sigsys_installed = 1;
+		}
+		ret = __getcwd(pt, ept - pt);
+		if (sigsys_installed == 1) {
+			int oerrno = errno;
+			sigaction(SIGSYS, &osa, NULL);
+			errno = oerrno;
+		}
+		/* XXX a bogus syscall seems to return EINVAL(!) */
+		if (ret < 0 && (errno == ENOSYS || errno == EINVAL))
+			have__getcwd = 0;
+		else if (have__getcwd == 1)
+			have__getcwd = 2;	/* yep, remember we have it */
+		if (ret == 0) {
+			if (*pt != '/') {
+				bpt = pt;
+				ept = pt + strlen(pt) - 1;
+				while (bpt < ept) {
+					c = *bpt;
+					*bpt++ = *ept;
+					*ept-- = c;
+				}
 			}
+			return (pt);
 		}
-		return (pt);
 	}
 	bpt = ept - 1;
 	*bpt = '\0';
=======

It appears to be fine, I can't find anything wrong with it except the
"else if (have__getcwd == 1)" is sort of redundant ("else" is good
enough here).

This is what I know about the "make world" problem:

(1) It only breaks on some programs, most notably vi during termcap
    compilation.  There should be some other programs before vi that
    use getcwd(), I wonder why they don't die.

(2) It only breaks on older systems, like 2.1.5 or 2.2.2.  I think it
    works on a recent 2.2-stable (I'm not sure, testing now).

Do you have any idea what's going on?  Especially (2), was there a
matching commit that went into RELENG_2_2 at that time?

Thanks
Satoshi



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199710291124.DAA14565>