home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume24
/
mkid2
/
part02
/
cannoname.c
next >
Wrap
C/C++ Source or Header
|
1991-10-09
|
4KB
|
171 lines
/* This file contains routines which put a file name into cannonical
* form.
*/
#define NULL 0
/* define special name components */
static char slash[] = "/" ;
static char dot[] = "." ;
static char dotdot[] = ".." ;
/* nextc points to the next character to look at in the string or is
* null if the end of string was reached.
*
* namep points to buffer that holds the components.
*/
static char * nextc = NULL ;
static char * namep ;
/* lexname - Return next name component. Uses global variables initialized
* by cannoname to figure out what it is scanning.
*/
static char *
lexname()
{
char c ;
char * d ;
if (nextc) {
c = *nextc++ ;
if (c == '\0') {
nextc = NULL ;
return(NULL) ;
}
if (c == '/') {
return(&slash[0]) ;
}
if (c == '.') {
if ((*nextc == '/') || (*nextc == '\0')) return(&dot[0]) ;
if (*nextc == '.' && (*(nextc+1) == '/' || *(nextc+1) == '\0')) {
++nextc ;
return(&dotdot[0]) ;
}
}
d = namep;
*namep++ = c;
while ((c = *nextc) != '/') {
*namep++ = c ;
if (c == '\0') {
nextc = NULL ;
return(d) ;
}
++nextc;
}
*namep++ = '\0' ;
return(d) ;
} else {
return(NULL) ;
}
}
/* cannoname - Put a file name in cannonical form. Looks for all the
* whacky wonderful things a demented *ni* programmer might put
* in a file name and reduces the name to cannonical form.
*/
void
cannoname(n)
char * n;
{
char * components[1024] ;
char ** cap = &components[0] ;
char ** cad ;
char * cp ;
char namebuf[2048] ;
char * s ;
/* initialize scanner */
nextc = n ;
namep = &namebuf[0] ;
/* break the file name into individual components */
while ((cp = lexname()) != NULL) {
*cap++ = cp ;
}
/* If name is empty, leave it that way */
if (cap == &components[0]) return ;
/* flag end of component list */
*cap = NULL ;
/* remove all trailing slashes and dots */
while ((--cap != &components[0]) &&
((*cap == &slash[0]) || (*cap == &dot[0]))) *cap = NULL ;
/* squeeze out all . / component sequences */
cap = &components[0] ;
cad = cap ;
while (*cap != NULL) {
if ((*cap == &dot[0]) && (*(cap+1) == &slash[0])) {
cap += 2;
} else {
*cad++ = *cap++ ;
}
}
*cad++ = NULL ;
/* find multiple // and use last slash as root, except on apollo which
* apparently actually uses // in real file names (don't ask me why).
*/
#ifndef apollo
s = NULL ;
cap = &components[0] ;
cad = cap ;
while (*cap != NULL) {
if ((s == &slash[0]) && (*cap == &slash[0])) {
cad = &components[0];
}
s = *cap++;
*cad++ = s;
}
*cad = NULL ;
#endif
/* if this is absolute name get rid of any /.. at beginning */
if ((components[0] == &slash[0]) && (components[1] == &dotdot[0])) {
cap = &components[1] ;
cad = cap ;
while (*cap == &dotdot[0]) {
++cap;
if (*cap == NULL) break ;
if (*cap == &slash[0]) ++cap ;
}
while (*cap != NULL) {
*cad++ = *cap++ ;
}
*cad = NULL ;
}
/* squeeze out any name/.. sequences (but leave leading ../..) */
cap = &components[0] ;
cad = cap ;
while (*cap != NULL) {
if ((*cap == &dotdot[0]) &&
((cad-2) >= &components[0]) &&
((*(cad-2)) != &dotdot[0])) {
cad -= 2 ;
++cap;
if (*cap != NULL) ++cap;
} else {
*cad++ = *cap++ ;
}
}
/* squeezing out a trailing /.. can leave unsightly trailing /s */
if ((cad >= &components[2]) && ((*(cad-1)) == &slash[0])) --cad ;
*cad = NULL ;
/* if it was just name/.. it now becomes . */
if (components[0] == NULL) {
components[0] = &dot[0] ;
components[1] = NULL ;
}
/* re-assemble components */
cap = &components[0] ;
while ((s = *cap++) != NULL) {
while (*s != NULL) *n++ = *s++;
}
*n++ = '\0' ;
}