From owner-freebsd-current Sat Dec 21 13:57:57 1996 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.4/8.8.4) id NAA03416 for current-outgoing; Sat, 21 Dec 1996 13:57:57 -0800 (PST) Received: from fly.HiWAAY.net (root@fly.HiWAAY.net [204.214.4.2]) by freefall.freebsd.org (8.8.4/8.8.4) with ESMTP id NAA03411 for ; Sat, 21 Dec 1996 13:57:55 -0800 (PST) Received: from bonsai.hiwaay.net by fly.HiWAAY.net; (8.8.4/1.1.8.2/21Sep95-1003PM) id PAA03622; Sat, 21 Dec 1996 15:57:49 -0600 (CST) Message-ID: <32BC5D1F.2F1CF0FB@hiwaay.net> Date: Sat, 21 Dec 1996 15:56:47 -0600 From: Steve Price X-Mailer: Mozilla 3.01 (X11; I; FreeBSD 3.0-CURRENT i386) MIME-Version: 1.0 To: freebsd-current@freefall.freebsd.org Subject: Re: cannot bootstrap to -current References: Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: owner-current@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk Howdy all, For all those having this problem, below is a patch that fixes the problem. Just for the record, the problem was not introduced with recent commits to sh(1), rather uncovered by recent changes elsewhere. Don't get me wrong sh(1) IS at fault and I have tried to correct the problem with the attached patch. The problem goes like this: Upon startup sh(1) tries to ascertain what directory it is being started in. If for some reason this directory does not exist, it bails with 'pwd: No such file of directory' It shouldn't do this (at least using the other shells as examples). I am waiting for feedback to make sure that this doesn't create anymore problems before I commit it. So for all those having problems, please try this patch and let me know how it goes. Yes, the patch is long. While I was in there I also made sh(1) use getcwd(3) instead of /bin/pwd (as suggested by Joerg), removed some unneeded #if SYMLINKS stuff, and cleaned up the format a little. Thanks, Steve Index: cd.c =================================================================== RCS file: /u/FreeBSD/cvs/src/bin/sh/cd.c,v retrieving revision 1.7 diff -u -r1.7 cd.c --- cd.c 1996/12/14 06:19:09 1.7 +++ cd.c 1996/12/21 19:43:50 @@ -46,6 +46,7 @@ #include #include #include +#include /* * The cd and pwd commands. @@ -120,16 +121,9 @@ /* - * Actually do the chdir. If the name refers to symbolic links, we - * compute the actual directory name before doing the cd. In an - * interactive shell, print the directory name if "print" is nonzero - * or if the name refers to a symbolic link. We also print the name - * if "/u/logname" was expanded in it, since this is similar to a - * symbolic link. (The check for this breaks if the user gives the - * cd command some additional, unused arguments.) + * Actually do the chdir. In an interactive shell, print the + * directory name if "print" is nonzero. */ - -#if SYMLINKS == 0 STATIC int docd(dest, print) char *dest; @@ -149,107 +143,14 @@ return 0; } -#else - - - -STATIC int -docd(dest, print) - char *dest; - int print; -{ - register char *p; - register char *q; - char *symlink; - char *component; - struct stat statb; - int first; - int i; - - TRACE(("docd(\"%s\", %d) called\n", dest, print)); - -top: - cdcomppath = dest; - STARTSTACKSTR(p); - if (*dest == '/') { - STPUTC('/', p); - cdcomppath++; - } - first = 1; - while ((q = getcomponent()) != NULL) { - if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0')) - continue; - if (! first) - STPUTC('/', p); - first = 0; - component = q; - while (*q) - STPUTC(*q++, p); - if (equal(component, "..")) - continue; - STACKSTRNUL(p); - if (lstat(stackblock(), &statb) < 0) - error("lstat %s failed", stackblock()); - if (!S_ISLNK(statb.st_mode)) - continue; - - /* Hit a symbolic link. We have to start all over again. */ - print = 1; - STPUTC('\0', p); - symlink = grabstackstr(p); - i = (int)statb.st_size + 2; /* 2 for '/' and '\0' */ - if (cdcomppath != NULL) - i += strlen(cdcomppath); - p = stalloc(i); - if (readlink(symlink, p, (int)statb.st_size) < 0) { - error("readlink %s failed", stackblock()); - } - if (cdcomppath != NULL) { - p[(int)statb.st_size] = '/'; - scopy(cdcomppath, p + (int)statb.st_size + 1); - } else { - p[(int)statb.st_size] = '\0'; - } - if (p[0] != '/') { /* relative path name */ - char *r; - q = r = symlink; - while (*q) { - if (*q++ == '/') - r = q; - } - *r = '\0'; - dest = stalloc(strlen(symlink) + strlen(p) + 1); - scopy(symlink, dest); - strcat(dest, p); - } else { - dest = p; - } - goto top; - } - STPUTC('\0', p); - p = grabstackstr(p); - INTOFF; - if (chdir(*p ? p : ".") < 0) { - INTON; - return -1; - } - updatepwd(p); - INTON; - if (print && iflag) - out1fmt("%s\n", p); - return 0; -} -#endif /* SYMLINKS */ - - /* * Get the next component of the path name pointed to by cdcomppath. * This routine overwrites the string pointed to by cdcomppath. */ - STATIC char * -getcomponent() { +getcomponent() +{ register char *p; char *start; @@ -268,19 +169,15 @@ } - /* * Update curdir (the name of the current directory) in response to a * cd command. We also call hashcd to let the routines in exec.c know * that the current directory has changed. */ - -void hashcd(); - STATIC void updatepwd(dir) char *dir; - { +{ char *new; char *p; @@ -318,75 +215,31 @@ } - int pwdcmd(argc, argv) int argc; char **argv; { - getpwd(); + if(!getpwd()) + error("getcwd() failed: %s", strerror(errno)); out1str(curdir); out1c('\n'); return 0; } - - -#define MAXPWD 256 - /* - * Run /bin/pwd to find out what the current directory is. We suppress - * interrupts throughout most of this, but the user can still break out - * of it by killing the pwd program. If we already know the current + * Find out what the current directory is. If we already know the current * directory, this routine returns immediately. */ -void +char * getpwd() { - char buf[MAXPWD]; - char *p; - int i; - int status; - struct job *jp; - int pip[2]; - char *pwd_bin = "/bin/pwd"; + char buf[_POSIX_PATH_MAX]; if (curdir) - return; - INTOFF; - if (pipe(pip) < 0) - error("Pipe call failed"); - /* make a fall-back guess, otherwise we're simply screwed */ - if (access(pwd_bin, X_OK) == -1) - pwd_bin = "/stand/pwd"; - jp = makejob((union node *)NULL, 1); - if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) { - close(pip[0]); - if (pip[1] != 1) { - close(1); - copyfd(pip[1], 1); - close(pip[1]); - } - (void) execl(pwd_bin, "pwd", (char *)0); - error("Cannot exec %s", pwd_bin); - } - (void) close(pip[1]); - pip[1] = -1; - p = buf; - while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0 - || (i == -1 && errno == EINTR)) { - if (i > 0) - p += i; - } - (void) close(pip[0]); - pip[0] = -1; - status = waitforjob(jp); - if (status != 0) - error((char *)0); - if (i < 0 || p == buf || p[-1] != '\n') - error("pwd command failed"); - p[-1] = '\0'; - curdir = savestr(buf); - INTON; + return (curdir); + if (getcwd(buf, sizeof(buf)) == NULL) + return (NULL); + return ((curdir = savestr(buf))); } Index: cd.h =================================================================== RCS file: /u/FreeBSD/cvs/src/bin/sh/cd.h,v retrieving revision 1.1 diff -u -r1.1 cd.h --- cd.h 1996/12/14 06:19:09 1.1 +++ cd.h 1996/12/21 19:22:30 @@ -31,4 +31,4 @@ * SUCH DAMAGE. */ -void getpwd __P((void)); +char *getpwd __P((void)); Index: main.c =================================================================== RCS file: /u/FreeBSD/cvs/src/bin/sh/main.c,v retrieving revision 1.10 diff -u -r1.10 main.c --- main.c 1996/12/14 06:19:19 1.10 +++ main.c 1996/12/21 19:40:33 @@ -171,7 +171,8 @@ init(); setstackmark(&smark); procargs(argc, argv); - getpwd(); + if (getpwd() == NULL && iflag) + out2str("sh: cannot determine working directory\n"); if (argv[0] && argv[0][0] == '-') { state = 1; read_profile("/etc/profile"); Index: shell.h =================================================================== RCS file: /u/FreeBSD/cvs/src/bin/sh/shell.h,v retrieving revision 1.7 diff -u -r1.7 shell.h --- shell.h 1996/12/14 06:19:30 1.7 +++ shell.h 1996/12/21 14:19:20 @@ -40,7 +40,6 @@ /* * The follow should be set to reflect the type of system you have: * JOBS -> 1 if you have Berkeley job control, 0 otherwise. - * SYMLINKS -> 1 if your system includes symbolic links, 0 otherwise. * SHORTNAMES -> 1 if your linker cannot handle long names. * define BSD if you are running 4.2 BSD or later. * define SYSV if you are running under System V. @@ -53,7 +52,6 @@ #define JOBS 1 -#define SYMLINKS 1 #ifndef BSD #define BSD 1 #endif