17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
539e7390aSna195498 * Common Development and Distribution License (the "License").
639e7390aSna195498 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21965005c8Schin
22965005c8Schin /*
23*db8b037bSRichard PALO * Copyright 2015 PALO, Richard.
24*db8b037bSRichard PALO */
25*db8b037bSRichard PALO
26*db8b037bSRichard PALO /*
2739e7390aSna195498 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
28965005c8Schin * Use is subject to license terms.
29965005c8Schin */
30965005c8Schin
317c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
327c478bd9Sstevel@tonic-gate /* All Rights Reserved */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate * UNIX shell
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate #include "mac.h"
407c478bd9Sstevel@tonic-gate #include <errno.h>
417c478bd9Sstevel@tonic-gate #include <sys/types.h>
427c478bd9Sstevel@tonic-gate #include <sys/stat.h>
437c478bd9Sstevel@tonic-gate #include <limits.h>
4439e7390aSna195498 #include "defs.h"
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #define DOT '.'
47*db8b037bSRichard PALO #define NULLCHAR '\0'
487c478bd9Sstevel@tonic-gate #define SLASH '/'
497c478bd9Sstevel@tonic-gate #define PARTLY 2
507c478bd9Sstevel@tonic-gate
51*db8b037bSRichard PALO static void rmslash(unsigned char *string);
527c478bd9Sstevel@tonic-gate #ifdef __STDC__
537c478bd9Sstevel@tonic-gate extern const char longpwd[];
547c478bd9Sstevel@tonic-gate #else
557c478bd9Sstevel@tonic-gate extern char longpwd[];
567c478bd9Sstevel@tonic-gate #endif
577c478bd9Sstevel@tonic-gate extern char *getcwd();
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate unsigned char cwdname[PATH_MAX+1];
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate static int didpwd = FALSE;
627c478bd9Sstevel@tonic-gate
63965005c8Schin void
cwd(unsigned char * dir)64965005c8Schin cwd(unsigned char *dir)
657c478bd9Sstevel@tonic-gate {
66965005c8Schin unsigned char *pcwd;
67965005c8Schin unsigned char *pdir;
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate /* First remove extra /'s */
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate rmslash(dir);
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate /* Now remove any .'s */
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate pdir = dir;
767c478bd9Sstevel@tonic-gate if (*dir == SLASH)
777c478bd9Sstevel@tonic-gate pdir++;
78*db8b037bSRichard PALO while (*pdir) { /* remove /./ by itself */
79*db8b037bSRichard PALO if ((*pdir == DOT) && (*(pdir+1) == SLASH)) {
807c478bd9Sstevel@tonic-gate movstr(pdir+2, pdir);
817c478bd9Sstevel@tonic-gate continue;
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate pdir++;
847c478bd9Sstevel@tonic-gate while ((*pdir) && (*pdir != SLASH))
857c478bd9Sstevel@tonic-gate pdir++;
867c478bd9Sstevel@tonic-gate if (*pdir)
877c478bd9Sstevel@tonic-gate pdir++;
887c478bd9Sstevel@tonic-gate }
897c478bd9Sstevel@tonic-gate /* take care of trailing /. */
907c478bd9Sstevel@tonic-gate if (*(--pdir) == DOT && pdir > dir && *(--pdir) == SLASH) {
917c478bd9Sstevel@tonic-gate if (pdir > dir) {
92*db8b037bSRichard PALO *pdir = NULLCHAR;
937c478bd9Sstevel@tonic-gate } else {
94*db8b037bSRichard PALO *(pdir+1) = NULLCHAR;
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate /* Remove extra /'s */
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate rmslash(dir);
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate /* Now that the dir is canonicalized, process it */
1047c478bd9Sstevel@tonic-gate
105*db8b037bSRichard PALO if (*dir == DOT && *(dir+1) == NULLCHAR) {
1067c478bd9Sstevel@tonic-gate return;
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate
110*db8b037bSRichard PALO if (*dir == SLASH) {
1117c478bd9Sstevel@tonic-gate /* Absolute path */
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate pcwd = cwdname;
1147c478bd9Sstevel@tonic-gate *pcwd++ = *dir++;
1157c478bd9Sstevel@tonic-gate didpwd = PARTLY;
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate else
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate /* Relative path */
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate if (didpwd == FALSE)
1227c478bd9Sstevel@tonic-gate return;
1237c478bd9Sstevel@tonic-gate didpwd = PARTLY;
1247c478bd9Sstevel@tonic-gate pcwd = cwdname + length(cwdname) - 1;
1257c478bd9Sstevel@tonic-gate if (pcwd != cwdname+1)
1267c478bd9Sstevel@tonic-gate *pcwd++ = SLASH;
1277c478bd9Sstevel@tonic-gate }
128*db8b037bSRichard PALO while (*dir) {
1297c478bd9Sstevel@tonic-gate if (*dir == DOT &&
1307c478bd9Sstevel@tonic-gate *(dir+1) == DOT &&
131*db8b037bSRichard PALO (*(dir+2) == SLASH || *(dir+2) == NULLCHAR)) {
1327c478bd9Sstevel@tonic-gate /* Parent directory, so backup one */
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate if (pcwd > cwdname+2)
1357c478bd9Sstevel@tonic-gate --pcwd;
1367c478bd9Sstevel@tonic-gate while (*(--pcwd) != SLASH)
1377c478bd9Sstevel@tonic-gate ;
1387c478bd9Sstevel@tonic-gate pcwd++;
1397c478bd9Sstevel@tonic-gate dir += 2;
140*db8b037bSRichard PALO if (*dir == SLASH) {
1417c478bd9Sstevel@tonic-gate dir++;
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate continue;
1447c478bd9Sstevel@tonic-gate }
145*db8b037bSRichard PALO if (pcwd >= &cwdname[PATH_MAX+1]) {
1467c478bd9Sstevel@tonic-gate didpwd = FALSE;
1477c478bd9Sstevel@tonic-gate return;
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate *pcwd++ = *dir++;
150*db8b037bSRichard PALO while ((*dir) && (*dir != SLASH)) {
151*db8b037bSRichard PALO if (pcwd >= &cwdname[PATH_MAX+1]) {
1527c478bd9Sstevel@tonic-gate didpwd = FALSE;
1537c478bd9Sstevel@tonic-gate return;
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate *pcwd++ = *dir++;
1567c478bd9Sstevel@tonic-gate }
157*db8b037bSRichard PALO if (*dir) {
158*db8b037bSRichard PALO if (pcwd >= &cwdname[PATH_MAX+1]) {
1597c478bd9Sstevel@tonic-gate didpwd = FALSE;
1607c478bd9Sstevel@tonic-gate return;
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate *pcwd++ = *dir++;
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate }
165*db8b037bSRichard PALO if (pcwd >= &cwdname[PATH_MAX+1]) {
1667c478bd9Sstevel@tonic-gate didpwd = FALSE;
1677c478bd9Sstevel@tonic-gate return;
1687c478bd9Sstevel@tonic-gate }
169*db8b037bSRichard PALO *pcwd = NULLCHAR;
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate --pcwd;
172*db8b037bSRichard PALO if (pcwd > cwdname && *pcwd == SLASH) {
1737c478bd9Sstevel@tonic-gate /* Remove trailing / */
1747c478bd9Sstevel@tonic-gate
175*db8b037bSRichard PALO *pcwd = NULLCHAR;
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate void
cwd2()1807c478bd9Sstevel@tonic-gate cwd2()
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate struct stat stat1, stat2;
1837c478bd9Sstevel@tonic-gate unsigned char *pcwd;
1847c478bd9Sstevel@tonic-gate /* check if there are any symbolic links in pathname */
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate if (didpwd == FALSE)
1877c478bd9Sstevel@tonic-gate return;
1887c478bd9Sstevel@tonic-gate pcwd = cwdname + 1;
1897c478bd9Sstevel@tonic-gate if (didpwd == PARTLY) {
190*db8b037bSRichard PALO while (*pcwd) {
1917c478bd9Sstevel@tonic-gate char c;
192*db8b037bSRichard PALO do {
193*db8b037bSRichard PALO c = *pcwd++;
194*db8b037bSRichard PALO } while (c != SLASH && c != NULLCHAR);
195*db8b037bSRichard PALO *--pcwd = NULLCHAR;
196*db8b037bSRichard PALO if (lstat((char *)cwdname, &stat1) == -1 ||
197*db8b037bSRichard PALO (stat1.st_mode & S_IFMT) == S_IFLNK) {
1987c478bd9Sstevel@tonic-gate didpwd = FALSE;
1997c478bd9Sstevel@tonic-gate *pcwd = c;
2007c478bd9Sstevel@tonic-gate return;
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate *pcwd = c;
2037c478bd9Sstevel@tonic-gate if (c)
2047c478bd9Sstevel@tonic-gate pcwd++;
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate didpwd = TRUE;
2077c478bd9Sstevel@tonic-gate } else
2087c478bd9Sstevel@tonic-gate if (stat((char *)cwdname, &stat1) == -1) {
2097c478bd9Sstevel@tonic-gate didpwd = FALSE;
2107c478bd9Sstevel@tonic-gate return;
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate /*
2137c478bd9Sstevel@tonic-gate * check if ino's and dev's match; pathname could
2147c478bd9Sstevel@tonic-gate * consist of symbolic links with ".."
2157c478bd9Sstevel@tonic-gate */
2167c478bd9Sstevel@tonic-gate
217*db8b037bSRichard PALO if (stat(".", &stat2) == -1 ||
218*db8b037bSRichard PALO stat1.st_dev != stat2.st_dev ||
219*db8b037bSRichard PALO stat1.st_ino != stat2.st_ino)
2207c478bd9Sstevel@tonic-gate didpwd = FALSE;
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate unsigned char *
cwdget()2247c478bd9Sstevel@tonic-gate cwdget()
2257c478bd9Sstevel@tonic-gate {
2267c478bd9Sstevel@tonic-gate cwd2();
2277c478bd9Sstevel@tonic-gate if (didpwd == FALSE) {
22839e7390aSna195498 if (getcwd((char *)cwdname, PATH_MAX+1) == NULL)
229*db8b037bSRichard PALO *cwdname = NULLCHAR;
2307c478bd9Sstevel@tonic-gate didpwd = TRUE;
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate return (cwdname);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate /*
2367c478bd9Sstevel@tonic-gate * Print the current working directory.
2377c478bd9Sstevel@tonic-gate */
2387c478bd9Sstevel@tonic-gate
239965005c8Schin void
cwdprint(void)240965005c8Schin cwdprint(void)
2417c478bd9Sstevel@tonic-gate {
242965005c8Schin unsigned char *cp;
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate cwd2();
2457c478bd9Sstevel@tonic-gate if (didpwd == FALSE) {
24639e7390aSna195498 if (getcwd((char *)cwdname, PATH_MAX+1) == NULL) {
2477c478bd9Sstevel@tonic-gate if (errno && errno != ERANGE)
24839e7390aSna195498 error(badpwd);
2497c478bd9Sstevel@tonic-gate else
2507c478bd9Sstevel@tonic-gate error(longpwd);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate didpwd = TRUE;
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate for (cp = cwdname; *cp; cp++) {
2567c478bd9Sstevel@tonic-gate prc_buff(*cp);
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate prc_buff(NL);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate /*
2637c478bd9Sstevel@tonic-gate * This routine will remove repeated slashes from string.
2647c478bd9Sstevel@tonic-gate */
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate static void
rmslash(unsigned char * string)267*db8b037bSRichard PALO rmslash(unsigned char *string)
2687c478bd9Sstevel@tonic-gate {
269965005c8Schin unsigned char *pstring;
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate pstring = string;
272*db8b037bSRichard PALO while (*pstring) {
273*db8b037bSRichard PALO if (*pstring == SLASH && *(pstring+1) == SLASH) {
2747c478bd9Sstevel@tonic-gate /* Remove repeated SLASH's */
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate movstr(pstring+1, pstring);
2777c478bd9Sstevel@tonic-gate continue;
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate pstring++;
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate --pstring;
283*db8b037bSRichard PALO if (pstring > string && *pstring == SLASH) {
2847c478bd9Sstevel@tonic-gate /* Remove trailing / */
2857c478bd9Sstevel@tonic-gate
286*db8b037bSRichard PALO *pstring = NULLCHAR;
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate }
289