pathcd.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* K. P. Vo
* G. S. Fowler
* AT&T Research
*/
#include <ast.h>
#include <error.h>
#include <stk.h>
#if DEBUG
#define PATH_MAX 16
static int
{
int n;
{
n = -1;
}
return n;
}
#endif
/*
* set the current directory to path
* if path is long and home!=0 then pathcd(home,0)
* is called on intermediate chdir errors
*/
int
{
register char* p = (char*)path;
register char* s;
register int n;
int i;
int r;
r = 0;
for (;;)
{
/*
* this should work 99% of the time
*/
if (!chdir(p))
return r;
/*
* chdir failed
*/
return -1;
#ifdef ENAMETOOLONG
if (errno != ENAMETOOLONG)
return -1;
#endif
/*
* path is too long -- copy so it can be modified in place
*/
for (;;)
{
/*
* get a short prefix component
*/
s = p + PATH_MAX;
while (--s >= p && *s != '/');
if (s <= p)
break;
/*
* chdir to the prefix
*/
*s++ = 0;
if (chdir(p))
break;
/*
* do the remainder
*/
if ((n -= s - p) < PATH_MAX)
{
if (chdir(s))
break;
return r;
}
p = s;
}
/*
* try to recover back to home
*/
if (!(p = (char*)home))
return -1;
home = 0;
r = -1;
}
}