1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 /* 33 * UNIX shell 34 */ 35 36 #include "mac.h" 37 #include <errno.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <limits.h> 41 #include "defs.h" 42 43 #define DOT '.' 44 #define NULL 0 45 #define SLASH '/' 46 #define PARTLY 2 47 48 static void rmslash(); 49 #ifdef __STDC__ 50 extern const char longpwd[]; 51 #else 52 extern char longpwd[]; 53 #endif 54 extern char *getcwd(); 55 56 unsigned char cwdname[PATH_MAX+1]; 57 58 static int didpwd = FALSE; 59 60 void 61 cwd(unsigned char *dir) 62 { 63 unsigned char *pcwd; 64 unsigned char *pdir; 65 66 /* First remove extra /'s */ 67 68 rmslash(dir); 69 70 /* Now remove any .'s */ 71 72 pdir = dir; 73 if(*dir == SLASH) 74 pdir++; 75 while(*pdir) /* remove /./ by itself */ 76 { 77 if((*pdir==DOT) && (*(pdir+1)==SLASH)) 78 { 79 movstr(pdir+2, pdir); 80 continue; 81 } 82 pdir++; 83 while ((*pdir) && (*pdir != SLASH)) 84 pdir++; 85 if (*pdir) 86 pdir++; 87 } 88 /* take care of trailing /. */ 89 if(*(--pdir)==DOT && pdir > dir && *(--pdir)==SLASH) { 90 if(pdir > dir) { 91 *pdir = NULL; 92 } else { 93 *(pdir+1) = NULL; 94 } 95 96 } 97 98 /* Remove extra /'s */ 99 100 rmslash(dir); 101 102 /* Now that the dir is canonicalized, process it */ 103 104 if(*dir==DOT && *(dir+1)==NULL) 105 { 106 return; 107 } 108 109 110 if(*dir==SLASH) 111 { 112 /* Absolute path */ 113 114 pcwd = cwdname; 115 *pcwd++ = *dir++; 116 didpwd = PARTLY; 117 } 118 else 119 { 120 /* Relative path */ 121 122 if (didpwd == FALSE) 123 return; 124 didpwd = PARTLY; 125 pcwd = cwdname + length(cwdname) - 1; 126 if(pcwd != cwdname+1) 127 *pcwd++ = SLASH; 128 } 129 while(*dir) 130 { 131 if(*dir==DOT && 132 *(dir+1)==DOT && 133 (*(dir+2)==SLASH || *(dir+2)==NULL)) 134 { 135 /* Parent directory, so backup one */ 136 137 if( pcwd > cwdname+2 ) 138 --pcwd; 139 while(*(--pcwd) != SLASH) 140 ; 141 pcwd++; 142 dir += 2; 143 if(*dir==SLASH) 144 { 145 dir++; 146 } 147 continue; 148 } 149 if (pcwd >= &cwdname[PATH_MAX+1]) 150 { 151 didpwd=FALSE; 152 return; 153 } 154 *pcwd++ = *dir++; 155 while((*dir) && (*dir != SLASH)) 156 { 157 if (pcwd >= &cwdname[PATH_MAX+1]) 158 { 159 didpwd=FALSE; 160 return; 161 } 162 *pcwd++ = *dir++; 163 } 164 if (*dir) 165 { 166 if (pcwd >= &cwdname[PATH_MAX+1]) 167 { 168 didpwd=FALSE; 169 return; 170 } 171 *pcwd++ = *dir++; 172 } 173 } 174 if (pcwd >= &cwdname[PATH_MAX+1]) 175 { 176 didpwd=FALSE; 177 return; 178 } 179 *pcwd = NULL; 180 181 --pcwd; 182 if(pcwd>cwdname && *pcwd==SLASH) 183 { 184 /* Remove trailing / */ 185 186 *pcwd = NULL; 187 } 188 return; 189 } 190 191 void 192 cwd2() 193 { 194 struct stat stat1, stat2; 195 unsigned char *pcwd; 196 /* check if there are any symbolic links in pathname */ 197 198 if(didpwd == FALSE) 199 return; 200 pcwd = cwdname + 1; 201 if(didpwd == PARTLY) { 202 while (*pcwd) 203 { 204 char c; 205 while((c = *pcwd++) != SLASH && c != '\0'); 206 *--pcwd = '\0'; 207 if (lstat((char *)cwdname, &stat1) == -1 208 || (stat1.st_mode & S_IFMT) == S_IFLNK) { 209 didpwd = FALSE; 210 *pcwd = c; 211 return; 212 } 213 *pcwd = c; 214 if(c) 215 pcwd++; 216 } 217 didpwd = TRUE; 218 } else 219 if (stat((char *)cwdname, &stat1) == -1) { 220 didpwd = FALSE; 221 return; 222 } 223 /* 224 * check if ino's and dev's match; pathname could 225 * consist of symbolic links with ".." 226 */ 227 228 if (stat(".", &stat2) == -1 229 || stat1.st_dev != stat2.st_dev 230 || stat1.st_ino != stat2.st_ino) 231 didpwd = FALSE; 232 return; 233 } 234 235 unsigned char * 236 cwdget() 237 { 238 cwd2(); 239 if (didpwd == FALSE) { 240 if (getcwd((char *)cwdname, PATH_MAX+1) == NULL) 241 *cwdname = 0; 242 didpwd = TRUE; 243 } 244 return (cwdname); 245 } 246 247 /* 248 * Print the current working directory. 249 */ 250 251 void 252 cwdprint(void) 253 { 254 unsigned char *cp; 255 256 cwd2(); 257 if (didpwd == FALSE) { 258 if (getcwd((char *)cwdname, PATH_MAX+1) == NULL) { 259 if (errno && errno != ERANGE) 260 error(badpwd); 261 else 262 error(longpwd); 263 } 264 didpwd = TRUE; 265 } 266 267 for (cp = cwdname; *cp; cp++) { 268 prc_buff(*cp); 269 } 270 271 prc_buff(NL); 272 return; 273 } 274 275 /* 276 * This routine will remove repeated slashes from string. 277 */ 278 279 static void 280 rmslash(string) 281 unsigned char *string; 282 { 283 unsigned char *pstring; 284 285 pstring = string; 286 while(*pstring) 287 { 288 if(*pstring==SLASH && *(pstring+1)==SLASH) 289 { 290 /* Remove repeated SLASH's */ 291 292 movstr(pstring+1, pstring); 293 continue; 294 } 295 pstring++; 296 } 297 298 --pstring; 299 if(pstring>string && *pstring==SLASH) 300 { 301 /* Remove trailing / */ 302 303 *pstring = NULL; 304 } 305 return; 306 } 307