char *curdir;
char *curdir = NULL;
STATIC char *getcomponent __P((void));STATIC void updatepwd __P((char *));STATIC void getpwd __P((void));char *curdir;			/* current working directory */char *prevdir;			/* previous working directory */STATIC char *cdcomppath;intcdcmd(argc, argv)	int argc;	char **argv; {	char *dest;	char *path;	char *p;	struct stat statb;	char *padvance();	int print = 0;	nextopt(nullstr);	if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)		error("HOME not set");	if (dest[0] == '-' && dest[1] == '\0') {		dest = prevdir ? prevdir : curdir;		print = 1;	}	if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)		path = nullstr;	while ((p = padvance(&path, dest)) != NULL) {		if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {			if (!print) {				/*				 * XXX - rethink				 */				if (p[0] == '.' && p[1] == '/')					p += 2;				print = strcmp(p, dest);			}			if (docd(p, print) >= 0)				return 0;		}	}	error("can't cd to %s", dest);	/*NOTREACHED*/	return 0;}/* * 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.) */#if SYMLINKS == 0STATIC intdocd(dest, print)	char *dest;	{	INTOFF;	if (chdir(dest) < 0) {		INTON;		return -1;	}	updatepwd(dest);	INTON;	if (print && iflag)		out1fmt("%s\n", stackblock());	return 0;}#elseSTATIC intdocd(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) < 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() {	register char *p;	char *start;	if ((p = cdcomppath) == NULL)		return NULL;	start = cdcomppath;	while (*p != '/' && *p != '\0')		p++;	if (*p == '\0') {		cdcomppath = NULL;	} else {		*p++ = '\0';		cdcomppath = p;	}	return start;}