14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin /* 244887Schin * K. P. Vo 254887Schin * G. S. Fowler 264887Schin * AT&T Research 274887Schin */ 284887Schin 294887Schin #include <ast.h> 304887Schin #include <error.h> 314887Schin #include <stk.h> 324887Schin 334887Schin #if DEBUG 344887Schin 354887Schin #undef PATH_MAX 364887Schin 374887Schin #define PATH_MAX 16 384887Schin 394887Schin static int vchdir(const char * path)404887Schinvchdir(const char* path) 414887Schin { 424887Schin int n; 434887Schin 444887Schin if (strlen(path) >= PATH_MAX) 454887Schin { 464887Schin errno = ENAMETOOLONG; 474887Schin n = -1; 484887Schin } 494887Schin else n = chdir(path); 504887Schin return n; 514887Schin } 524887Schin 534887Schin #define chdir(p) vchdir(p) 544887Schin 554887Schin #endif 564887Schin 574887Schin /* 584887Schin * set the current directory to path 594887Schin * if path is long and home!=0 then pathcd(home,0) 604887Schin * is called on intermediate chdir errors 614887Schin */ 624887Schin 634887Schin int pathcd(const char * path,const char * home)644887Schinpathcd(const char* path, const char* home) 654887Schin { 664887Schin register char* p = (char*)path; 674887Schin register char* s; 684887Schin register int n; 694887Schin int i; 704887Schin int r; 714887Schin 724887Schin r = 0; 734887Schin for (;;) 744887Schin { 754887Schin /* 764887Schin * this should work 99% of the time 774887Schin */ 784887Schin 794887Schin if (!chdir(p)) 804887Schin return r; 814887Schin 824887Schin /* 834887Schin * chdir failed 844887Schin */ 854887Schin 864887Schin if ((n = strlen(p)) < PATH_MAX) 874887Schin return -1; 884887Schin #ifdef ENAMETOOLONG 894887Schin if (errno != ENAMETOOLONG) 904887Schin return -1; 914887Schin #endif 924887Schin 934887Schin /* 944887Schin * path is too long -- copy so it can be modified in place 954887Schin */ 964887Schin 974887Schin i = stktell(stkstd); 984887Schin sfputr(stkstd, p, 0); 994887Schin stkseek(stkstd, i); 1004887Schin p = stkptr(stkstd, i); 1014887Schin for (;;) 1024887Schin { 1034887Schin /* 1044887Schin * get a short prefix component 1054887Schin */ 1064887Schin 1074887Schin s = p + PATH_MAX; 1084887Schin while (--s >= p && *s != '/'); 1094887Schin if (s <= p) 1104887Schin break; 1114887Schin 1124887Schin /* 1134887Schin * chdir to the prefix 1144887Schin */ 1154887Schin 1164887Schin *s++ = 0; 1174887Schin if (chdir(p)) 1184887Schin break; 1194887Schin 1204887Schin /* 1214887Schin * do the remainder 1224887Schin */ 1234887Schin 1244887Schin if ((n -= s - p) < PATH_MAX) 1254887Schin { 1264887Schin if (chdir(s)) 1274887Schin break; 1284887Schin return r; 1294887Schin } 1304887Schin p = s; 1314887Schin } 1324887Schin 1334887Schin /* 1344887Schin * try to recover back to home 1354887Schin */ 1364887Schin 1374887Schin if (!(p = (char*)home)) 1384887Schin return -1; 1394887Schin home = 0; 1404887Schin r = -1; 1414887Schin } 1424887Schin } 143