From: Todd C. Miller Date: Sat, 4 Sep 1993 12:17:33 +0000 (+0000) Subject: now works correctly (ttaltotal rewrite) X-Git-Tag: SUDO_1_3_0~109 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=223b37b147823f0aecc17c4981d8717fd4d65cbb;p=sudo now works correctly (ttaltotal rewrite) --- diff --git a/qualify.c b/qualify.c index 399a04f04..e62963e24 100644 --- a/qualify.c +++ b/qualify.c @@ -1,51 +1,198 @@ #include #include #include +#include +#include "sudo.h" -char * mfq (p) - char * p; /* path to make fully qualified */ +/* + * qualify() takes a path and makes it fully qualified and resolves + * all symbolic links, returning the fully qualfied path. + */ + +char * qualify(n) + char * n; /* name to make fully qualified */ { - char * tmp1, * tmp2; - static char path[MAXPATHLEN+1]; - int done = 0; + char * beg = NULL; /* begining of a path component */ + char * end; /* end of a path component */ + char * tmp; /* temporary pointer */ + char name[MAXPATHLEN+1]; /* local copy of n */ + char full[MAXPATHLEN+1]; /* the fully qualified name */ + struct stat statbuf; /* for lstat() */ + /* for lint and gcc -Wall */ +#ifdef USE_CWD + char * getcwd(); +#else + char * getwd(); +#endif + int fprintf(); + int readlink(); + int stat(); + int lstat(); + char * strdup(); - if ( *p == '/' ) /* starts at root */ + if (stat(n, &statbuf)) /* is it a bogus path? */ + return(NULL); + + /* if n is relative, fill full with working dir */ + if (*n != '/') { - path[0] = '\0'; - ++p; - } - else -#ifdef hpux - getcwd(path, (size_t)(MAXPATHLEN+1)); +#ifdef USE_CWD + if (!getcwd(full, (size_t)(MAXPATHLEN+1))) #else - getwd(path); + if (!getwd(full)) #endif + { + fprintf(stderr, "Can't get working dir! Quitting\n"); + exit(-1); + } + } + else + full[0] = '\0'; - while ((tmp1 = index(p, '/')) || !done) + strcpy(name, n); /* working copy... */ + + do /* while (end) */ { - if (tmp1) - *tmp1 = '\0'; /* only want up to '/' */ + if (beg) + beg = end + 1; /* skip past the NULL */ else - done = 1; + beg = name; /* just starting out... */ + + /* find and terminate end of path component */ + if ((end = index(beg, '/'))) + *end = '\0'; - if (!strcmp(p, "..")) + if (beg == end) + continue; + else if (!strcmp(beg, ".")) + ; /* ignore "." */ + else if (!strcmp(beg, "..")) { - tmp2 = rindex(path, '/'); - if (tmp2) - *tmp2 = '\0'; /* nuke last component if it exists */ + tmp = rindex(full, '/'); + if (tmp && tmp != &full[0]) + *tmp = '\0'; } - else if (strcmp(p, ".")) /* not .. or . */ + else { - strcat(path, "/"); /* add a '/' */ - strcat(path, p); /* add component form p */ + strcat(full, "/"); + strcat(full, beg); /* copy in new component */ } - if (tmp1) + /* check for symbolic links */ + lstat(full, &statbuf); + if ((statbuf.st_mode & S_IFMT) == S_IFLNK) { - *tmp1 = '/'; /* leave p as we found it */ - p = tmp1 + 1; + char newname[MAXPATHLEN+1]; + int linklen; + + linklen = readlink(full, newname, sizeof(newname)); + newname[linklen] = '\0'; + + /* check to make sure we don't go past MAXPATHLEN */ + ++end; + if (end != (char *)1) + { + if (linklen + strlen(end) >= MAXPATHLEN) + { + fprintf(stderr, "Symbolic link too long! Quitting\n"); + exit(-1); + } + + strcat(newname, "/"); + strcat(newname, end); /* copy what's left of end */ + } + + if (newname[0] == '/') /* reset full if necesary */ + full[0] = '\0'; + else + if ((tmp = rindex(full, '/'))) /* remove component from full */ + *tmp = '\0'; + + strcpy(name, newname); /* reset name with new path */ + beg = NULL; /* since we have a new name */ } } + while (end); + + return(strdup(full)); /* malloc space for return path */ +} + +/****************************************************************** + * + * strdup() + * + * this function returns a pointer a string copied into + * a malloc()ed buffer + */ + +char * strdup(s1) + char *s1; +{ + char * s; + char * strcpy(); + char * malloc(); + + if ((s = (char *) malloc(strlen(s1) + 1)) == NULL) + return (NULL); + + (void)strcpy(s, s1); + return(s); +} + +extern char *malloc(); +extern char *getenv(); + +extern char **Argv; +char *find_path(); +char *strdup(); + + + +/******************************************************************* + * + * find_path() + * + * this function finds the full pathname for a command + */ + +char *find_path(file) +char *file; +{ + register char *n; + char *path=NULL; + char fn[MAXPATHLEN+1]; + char *cmd; + struct stat statbuf; /* for stat() */ + + if ( strlen ( file ) > MAXPATHLEN ) { + fprintf ( stderr, "%s: path too long: %s\n", Argv[0], file ); + exit (1); + } + + /* do we need to search the path? */ + if ( index(file, '/') ) + return (qualify(file)); + + /* grab PATH out of environment and make a local copy */ + if ( ( path = getenv("PATH") ) == NULL ) + return ( NULL ) ; + + if ( ( path=strdup(path) ) == NULL ) { + perror ( "find_path: malloc" ); + exit (1); + } + + while ( n = index ( path, ':' ) ) { + *n='\0'; + strcpy(fn, path); + strcat(fn, "/"); + strcat(fn, file); - return((char *)path); + /* stat the file to make sure it exists and is executable */ + if (!stat(fn, &statbuf) && (statbuf.st_mode & 0000111)) + return (qualify(fn)); + else + path=n+1; + } + return(NULL); }