Ultrix-3.1/src/cmd/sh5/pwd.c
/**********************************************************************
* Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. *
* All Rights Reserved. *
* Reference "/usr/src/COPYRIGHT" for applicable restrictions. *
**********************************************************************/
/*
* SCCSID: @(#)pwd.c 3.0 4/22/86
* (System V) pwd.c 1.3
*/
/*
* UNIX shell
*
* Bell Telephone Laboratories
*
*/
#include "mac.h"
#define DOT '.'
#define NULL 0
#define SLASH '/'
#define MAXPWD 256
extern char longpwd[];
static char cwdname[MAXPWD];
static int didpwd = FALSE;
cwd(dir)
register char *dir;
{
register char *pcwd;
register char *pdir;
/* First remove extra /'s */
rmslash(dir);
/* Now remove any .'s */
pdir = dir;
while(*pdir) /* remove /./ by itself */
{
if((*pdir==DOT) && (*(pdir+1)==SLASH))
{
movstr(pdir+2, pdir);
continue;
}
pdir++;
while ((*pdir) && (*pdir != SLASH))
pdir++;
if (*pdir)
pdir++;
}
if(*(--pdir)==DOT && pdir>dir && *(--pdir)==SLASH)
*pdir = NULL;
/* Remove extra /'s */
rmslash(dir);
/* Now that the dir is canonicalized, process it */
if(*dir==DOT && *(dir+1)==NULL)
{
return;
}
if(*dir==SLASH)
{
/* Absolute path */
pcwd = cwdname;
didpwd = TRUE;
}
else
{
/* Relative path */
if (didpwd == FALSE)
return;
pcwd = cwdname + length(cwdname) - 1;
if(pcwd != cwdname+1)
{
*pcwd++ = SLASH;
}
}
while(*dir)
{
if(*dir==DOT &&
*(dir+1)==DOT &&
(*(dir+2)==SLASH || *(dir+2)==NULL))
{
/* Parent directory, so backup one */
if( pcwd > cwdname+2 )
--pcwd;
while(*(--pcwd) != SLASH)
;
pcwd++;
dir += 2;
if(*dir==SLASH)
{
dir++;
}
continue;
}
*pcwd++ = *dir++;
while((*dir) && (*dir != SLASH))
*pcwd++ = *dir++;
if (*dir)
*pcwd++ = *dir++;
}
*pcwd = NULL;
--pcwd;
if(pcwd>cwdname && *pcwd==SLASH)
{
/* Remove trailing / */
*pcwd = NULL;
}
return;
}
/*
* Print the current working directory.
*/
cwdprint()
{
if (didpwd == FALSE)
pwd();
prs_buff(cwdname);
prc_buff(NL);
return;
}
/*
* This routine will remove repeated slashes from string.
*/
static
rmslash(string)
char *string;
{
register char *pstring;
pstring = string;
while(*pstring)
{
if(*pstring==SLASH && *(pstring+1)==SLASH)
{
/* Remove repeated SLASH's */
movstr(pstring+1, pstring);
continue;
}
pstring++;
}
--pstring;
if(pstring>string && *pstring==SLASH)
{
/* Remove trailing / */
*pstring = NULL;
}
return;
}
/*
* Find the current directory the hard way.
*/
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
static char dotdots[] =
"../../../../../../../../../../../../../../../../../../../../../../../..";
extern struct direct *getdir();
extern char *movstrn();
static
pwd()
{
struct stat cdir; /* current directory status */
struct stat tdir;
struct stat pdir; /* parent directory status */
int pdfd; /* parent directory file descriptor */
struct direct *dir;
char *dot = dotdots + sizeof(dotdots) - 3;
int index = sizeof(dotdots) - 2;
int cwdindex = MAXPWD - 1;
int i;
cwdname[cwdindex] = 0;
dotdots[index] = 0;
if(stat(dot, &pdir) < 0)
{
error("pwd: cannot stat .");
}
dotdots[index] = '.';
for(;;)
{
cdir = pdir;
if ((pdfd = open(dot, 0)) < 0)
{
error("pwd: cannot open ..");
}
if(fstat(pdfd, &pdir) < 0)
{
close(pdfd);
error("pwd: cannot stat ..");
}
if(cdir.st_dev == pdir.st_dev)
{
if(cdir.st_ino == pdir.st_ino)
{
didpwd = TRUE;
close(pdfd);
if (cwdindex == (MAXPWD - 1))
cwdname[--cwdindex] = SLASH;
movstr(&cwdname[cwdindex], cwdname);
return;
}
do
{
if ((dir = getdir(pdfd)) == 0)
{
close(pdfd);
reset_dir();
error("pwd: read error in ..");
}
}
while (dir->d_ino != cdir.st_ino);
}
else
{
char name[512];
movstr(dot, name);
i = length(name) - 1;
name[i++] = '/';
do
{
if ((dir = getdir(pdfd)) == 0)
{
close(pdfd);
reset_dir();
error("pwd: read error in ..");
}
*(movstrn(dir->d_name, &name[i], DIRSIZ)) = 0;
stat(name, &tdir);
}
while(tdir.st_ino != cdir.st_ino || tdir.st_dev != cdir.st_dev);
}
close(pdfd);
reset_dir();
for (i = 0; i < DIRSIZ; i++)
if (dir->d_name[i] == 0)
break;
if (i > cwdindex - 1)
error(longpwd);
else
{
cwdindex -= i;
movstrn(dir->d_name, &cwdname[cwdindex], i);
cwdname[--cwdindex] = SLASH;
}
dot -= 3;
if (dot<dotdots)
error(longpwd);
}
}