home *** CD-ROM | disk | FTP | other *** search
- /* 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 */
- 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 ;
-
- /* 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' ;
- }
-