cd.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*	$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $	*/
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*-
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (c) 1991, 1993
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *	The Regents of the University of California.  All rights reserved.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * This code is derived from software contributed to Berkeley by
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Kenneth Almquist.
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Redistribution and use in source and binary forms, with or without
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * modification, are permitted provided that the following conditions
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * are met:
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    documentation and/or other materials provided with the distribution.
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 3. Neither the name of the University nor the names of its contributors
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    may be used to endorse or promote products derived from this software
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    without specific prior written permission.
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * SUCH DAMAGE.
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/cdefs.h>
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef lint
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic char sccsid[] = "@(#)cd.c	8.2 (Berkeley) 5/4/95";
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project__RCSID("$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $");
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* not lint */
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The cd and pwd commands.
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "shell.h"
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "var.h"
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "nodes.h"	/* for jobs.h */
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "jobs.h"
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "options.h"
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "output.h"
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "memalloc.h"
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "error.h"
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "exec.h"
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "redir.h"
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "mystring.h"
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "show.h"
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "cd.h"
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC int docd(char *, int);
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC char *getcomponent(void);
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void updatepwd(char *);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void find_curdir(int noerror);
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectchar *curdir = NULL;		/* current working directory */
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectchar *prevdir;			/* previous working directory */
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC char *cdcomppath;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcdcmd(int argc, char **argv)
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const char *dest;
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const char *path;
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p, *d;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct stat statb;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int print = cdprint;	/* set -cdprint to enable */
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	nextopt(nullstr);
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/*
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * Try (quite hard) to have 'curdir' defined, nothing has set
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * it on entry to the shell, but we want 'cd fred; cd -' to work.
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 */
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	getpwd(1);
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	dest = *argptr;
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (dest == NULL) {
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		dest = bltinlookup("HOME", 1);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (dest == NULL)
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			error("HOME not set");
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else {
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (argptr[1]) {
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/* Do 'ksh' style substitution */
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (!curdir)
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				error("PWD not set");
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			p = strstr(curdir, dest);
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (!p)
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				error("bad substitution");
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			d = stalloc(strlen(curdir) + strlen(argptr[1]) + 1);
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			memcpy(d, curdir, p - curdir);
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			strcpy(d + (p - curdir), argptr[1]);
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			strcat(d, p + strlen(dest));
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			dest = d;
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			print = 1;
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (dest[0] == '-' && dest[1] == '\0') {
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		dest = prevdir ? prevdir : curdir;
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		print = 1;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*dest == '\0')
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	        dest = ".";
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		path = nullstr;
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while ((p = padvance(&path, dest)) != NULL) {
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (!print) {
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				/*
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				 * XXX - rethink
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				 */
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					p += 2;
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				print = strcmp(p, dest);
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (docd(p, print) >= 0)
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				return 0;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	error("can't cd to %s", dest);
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/* NOTREACHED */
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Actually do the chdir.  In an interactive shell, print the
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * directory name if "print" is nonzero.
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC int
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdocd(char *dest, int print)
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *q;
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *component;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct stat statb;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int first;
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int badstat;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	TRACE(("docd(\"%s\", %d) called\n", dest, print));
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/*
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 *  Check each component of the path. If we find a symlink or
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 *  something we can't stat, clear curdir to force a getcwd()
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 *  next time we get the value of the current directory.
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 */
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	badstat = 0;
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	cdcomppath = stalloc(strlen(dest) + 1);
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	scopy(dest, cdcomppath);
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STARTSTACKSTR(p);
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*dest == '/') {
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		STPUTC('/', p);
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		cdcomppath++;
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	first = 1;
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while ((q = getcomponent()) != NULL) {
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			continue;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (! first)
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC('/', p);
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		first = 0;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		component = q;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		while (*q)
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC(*q++, p);
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (equal(component, ".."))
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			continue;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		STACKSTRNUL(p);
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if ((lstat(stackblock(), &statb) < 0)
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		    || (S_ISLNK(statb.st_mode)))  {
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/* print = 1; */
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			badstat = 1;
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	INTOFF;
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (chdir(dest) < 0) {
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTON;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return -1;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	updatepwd(badstat ? NULL : dest);
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	INTON;
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (print && iflag && curdir)
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		out1fmt("%s\n", curdir);
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return 0;
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Get the next component of the path name pointed to by cdcomppath.
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * This routine overwrites the string pointed to by cdcomppath.
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC char *
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectgetcomponent()
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *start;
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if ((p = cdcomppath) == NULL)
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return NULL;
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	start = cdcomppath;
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (*p != '/' && *p != '\0')
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p++;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*p == '\0') {
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		cdcomppath = NULL;
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else {
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		*p++ = '\0';
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		cdcomppath = p;
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return start;
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Update curdir (the name of the current directory) in response to a
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * cd command.  We also call hashcd to let the routines in exec.c know
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * that the current directory has changed.
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectupdatepwd(char *dir)
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *new;
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	hashcd();				/* update command hash table */
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/*
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * If our argument is NULL, we don't know the current directory
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * any more because we traversed a symbolic link or something
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * we couldn't stat().
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 */
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (dir == NULL || curdir == NULL)  {
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (prevdir)
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ckfree(prevdir);
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTOFF;
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		prevdir = curdir;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		curdir = NULL;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		getpwd(1);
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTON;
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (curdir)
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			setvar("PWD", curdir, VEXPORT);
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		else
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			unsetvar("PWD", 0);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	cdcomppath = stalloc(strlen(dir) + 1);
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	scopy(dir, cdcomppath);
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STARTSTACKSTR(new);
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*dir != '/') {
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p = curdir;
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		while (*p)
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC(*p++, new);
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (p[-1] == '/')
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STUNPUTC(new);
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while ((p = getcomponent()) != NULL) {
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (equal(p, "..")) {
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			while (new > stackblock() && (STUNPUTC(new), *new) != '/');
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		} else if (*p != '\0' && ! equal(p, ".")) {
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC('/', new);
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			while (*p)
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STPUTC(*p++, new);
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (new == stackblock())
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		STPUTC('/', new);
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STACKSTRNUL(new);
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	INTOFF;
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (prevdir)
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ckfree(prevdir);
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	prevdir = curdir;
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	curdir = savestr(stackblock());
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	setvar("PWD", curdir, VEXPORT);
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	INTON;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Posix says the default should be 'pwd -L' (as below), however
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * the 'cd' command (above) does something much nearer to the
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * posix 'cd -P' (not the posix default of 'cd -L').
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * If 'cd' is changed to support -P/L then the default here
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * needs to be revisited if the historic behaviour is to be kept.
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectpwdcmd(int argc, char **argv)
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int i;
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char opt = 'L';
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while ((i = nextopt("LP")) != '\0')
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		opt = i;
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*argptr)
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		error("unexpected argument");
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (opt == 'L')
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		getpwd(0);
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	else
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		find_curdir(0);
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	setvar("PWD", curdir, VEXPORT);
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	out1str(curdir);
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	out1c('\n');
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return 0;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define MAXPWD 256
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Find out what the current directory is. If we already know the current
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * directory, this routine returns immediately.
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectgetpwd(int noerror)
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *pwd;
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct stat stdot, stpwd;
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	static int first = 1;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (curdir)
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (first) {
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		first = 0;
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		pwd = getenv("PWD");
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		    stat(pwd, &stpwd) != -1 &&
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		    stdot.st_dev == stpwd.st_dev &&
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		    stdot.st_ino == stpwd.st_ino) {
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			curdir = savestr(pwd);
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return;
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	find_curdir(noerror);
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return;
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfind_curdir(int noerror)
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int i;
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *pwd;
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/*
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * Things are a bit complicated here; we could have just used
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * getcwd, but traditionally getcwd is implemented using popen
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * to /bin/pwd. This creates a problem for us, since we cannot
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * keep track of the job if it is being ran behind our backs.
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * So we re-implement getcwd(), and we suppress interrupts
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * throughout the process. This is not completely safe, since
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * the user can still break out of it by killing the pwd program.
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * We still try to use getcwd for systems that we know have a
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * c implementation of getcwd, that does not open a pipe to
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * /bin/pwd.
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 */
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if defined(__NetBSD__) || defined(__SVR4) || defined(__linux__)
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for (i = MAXPWD;; i *= 2) {
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		pwd = stalloc(i);
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (getcwd(pwd, i) != NULL) {
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			curdir = savestr(pwd);
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return;
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		stunalloc(pwd);
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (errno == ERANGE)
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			continue;
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (!noerror)
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			error("getcwd() failed: %s", strerror(errno));
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	{
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		char *p;
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		int status;
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		struct job *jp;
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		int pip[2];
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		pwd = stalloc(MAXPWD);
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTOFF;
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (pipe(pip) < 0)
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			error("Pipe call failed");
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		jp = makejob((union node *)NULL, 1);
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			(void) close(pip[0]);
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (pip[1] != 1) {
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				close(1);
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				copyfd(pip[1], 1);
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				close(pip[1]);
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			(void) execl("/bin/pwd", "pwd", (char *)0);
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			sh_warn("Cannot exec /bin/pwd");
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			exit(1);
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		(void) close(pip[1]);
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		pip[1] = -1;
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p = pwd;
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		while ((i = read(pip[0], p, pwd + MAXPWD - p)) > 0
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		     || (i == -1 && errno == EINTR)) {
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (i > 0)
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p += i;
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		(void) close(pip[0]);
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		pip[0] = -1;
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		status = waitforjob(jp);
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (status != 0)
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			error((char *)0);
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (i < 0 || p == pwd || p[-1] != '\n') {
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (noerror) {
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				INTON;
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				return;
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			error("pwd command failed");
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p[-1] = '\0';
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTON;
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		curdir = savestr(pwd);
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
447