diff options
Diffstat (limited to 'libopts/compat/pathfind.c')
-rw-r--r-- | libopts/compat/pathfind.c | 339 |
1 files changed, 0 insertions, 339 deletions
diff --git a/libopts/compat/pathfind.c b/libopts/compat/pathfind.c deleted file mode 100644 index 96eb771..0000000 --- a/libopts/compat/pathfind.c +++ /dev/null @@ -1,339 +0,0 @@ -/* -*- Mode: C -*- */ - -/* pathfind.c --- find a FILE MODE along PATH */ - -/* - * Author: Gary V Vaughan <gvaughan@oranda.demon.co.uk> - * Time-stamp: "2006-09-23 19:46:16 bkorb" - * Created: Tue Jun 24 15:07:31 1997 - * Last Modified: $Date: 2006/11/27 01:52:23 $ - * by: bkorb - * - * $Id: pathfind.c,v 4.10 2006/11/27 01:52:23 bkorb Exp $ - */ - -/* Code: */ - -#include "compat.h" -#ifndef HAVE_PATHFIND -#if defined(__windows__) && !defined(__CYGWIN__) -char* -pathfind( char const* path, - char const* fileName, - char const* mode ) -{ - return NULL; -} -#else - -static char* make_absolute( char const *string, char const *dot_path ); -static char* canonicalize_pathname( char *path ); -static char* extract_colon_unit( char* dir, char const *string, int *p_index ); - - -/*=export_func pathfind - * - * what: fild a file in a list of directories - * - * ifndef: HAVE_PATHFIND - * - * arg: + char const* + path + colon separated list of search directories + - * arg: + char const* + file + the name of the file to look for + - * arg: + char const* + mode + the mode bits that must be set to match + - * - * ret_type: char* - * ret_desc: the path to the located file - * - * doc: - * - * pathfind looks for a a file with name "FILE" and "MODE" access - * along colon delimited "PATH", and returns the full pathname as a - * string, or NULL if not found. If "FILE" contains a slash, then - * it is treated as a relative or absolute path and "PATH" is ignored. - * - * @strong{NOTE}: this function is compiled into @file{libopts} only if - * it is not natively supplied. - * - * The "MODE" argument is a string of option letters chosen from the - * list below: - * @example - * Letter Meaning - * r readable - * w writable - * x executable - * f normal file (NOT IMPLEMENTED) - * b block special (NOT IMPLEMENTED) - * c character special (NOT IMPLEMENTED) - * d directory (NOT IMPLEMENTED) - * p FIFO (pipe) (NOT IMPLEMENTED) - * u set user ID bit (NOT IMPLEMENTED) - * g set group ID bit (NOT IMPLEMENTED) - * k sticky bit (NOT IMPLEMENTED) - * s size nonzero (NOT IMPLEMENTED) - * @end example - * - * example: - * To find the "ls" command using the "PATH" environment variable: - * @example - * #include <stdlib.h> - * char* pz_ls = pathfind( getenv("PATH"), "ls", "rx" ); - * <<do whatever with pz_ls>> - * free( pz_ls ); - * @end example - * The path is allocated with @code{malloc(3C)}, so you must @code{free(3C)} - * the result. Also, do not use unimplemented file modes. :-) - * - * err: returns NULL if the file is not found. -=*/ -char* -pathfind( char const* path, - char const* fileName, - char const* mode ) -{ - int p_index = 0; - int mode_bits = 0; - char* pathName = NULL; - char zPath[ AG_PATH_MAX + 1 ]; - - if (strchr( mode, 'r' )) mode_bits |= R_OK; - if (strchr( mode, 'w' )) mode_bits |= W_OK; - if (strchr( mode, 'x' )) mode_bits |= X_OK; - - /* - * FOR each non-null entry in the colon-separated path, DO ... - */ - for (;;) { - DIR* dirP; - char* colon_unit = extract_colon_unit( zPath, path, &p_index ); - - /* - * IF no more entries, THEN quit - */ - if (colon_unit == NULL) - break; - - dirP = opendir( colon_unit ); - - /* - * IF the directory is inaccessable, THEN next directory - */ - if (dirP == NULL) - continue; - - /* - * FOR every entry in the given directory, ... - */ - for (;;) { - struct dirent *entP = readdir( dirP ); - - if (entP == (struct dirent*)NULL) - break; - - /* - * IF the file name matches the one we are looking for, ... - */ - if (strcmp( entP->d_name, fileName ) == 0) { - char* pzFullName = make_absolute( fileName, colon_unit); - - /* - * Make sure we can access it in the way we want - */ - if (access( pzFullName, mode_bits ) >= 0) { - /* - * We can, so normalize the name and return it below - */ - pathName = canonicalize_pathname( pzFullName ); - } - - free( (void*)pzFullName ); - break; - } - } - - closedir( dirP ); - - if (pathName != NULL) - break; - } - - return pathName; -} - -/* - * Turn STRING (a pathname) into an absolute pathname, assuming that - * DOT_PATH contains the symbolic location of `.'. This always returns - * a new string, even if STRING was an absolute pathname to begin with. - */ -static char* -make_absolute( char const *string, char const *dot_path ) -{ - char *result; - int result_len; - - if (!dot_path || *string == '/') { - result = strdup( string ); - } else { - if (dot_path && dot_path[0]) { - result = malloc( 2 + strlen( dot_path ) + strlen( string ) ); - strcpy( result, dot_path ); - result_len = strlen( result ); - if (result[result_len - 1] != '/') { - result[result_len++] = '/'; - result[result_len] = '\0'; - } - } else { - result = malloc( 3 + strlen( string ) ); - result[0] = '.'; result[1] = '/'; result[2] = '\0'; - result_len = 2; - } - - strcpy( result + result_len, string ); - } - - return result; -} - -/* - * Canonicalize PATH, and return a new path. The new path differs from - * PATH in that: - * - * Multiple `/'s are collapsed to a single `/'. - * Leading `./'s are removed. - * Trailing `/.'s are removed. - * Trailing `/'s are removed. - * Non-leading `../'s and trailing `..'s are handled by removing - * portions of the path. - */ -static char* -canonicalize_pathname( char *path ) -{ - int i, start; - char stub_char, *result; - - /* The result cannot be larger than the input PATH. */ - result = strdup( path ); - - stub_char = (*path == '/') ? '/' : '.'; - - /* Walk along RESULT looking for things to compact. */ - i = 0; - while (result[i]) { - while (result[i] != '\0' && result[i] != '/') - i++; - - start = i++; - - /* If we didn't find any slashes, then there is nothing left to - * do. - */ - if (!result[start]) - break; - - /* Handle multiple `/'s in a row. */ - while (result[i] == '/') - i++; - -#if !defined (apollo) - if ((start + 1) != i) -#else - if ((start + 1) != i && (start != 0 || i != 2)) -#endif /* apollo */ - { - strcpy( result + start + 1, result + i ); - i = start + 1; - } - - /* Handle backquoted `/'. */ - if (start > 0 && result[start - 1] == '\\') - continue; - - /* Check for trailing `/', and `.' by itself. */ - if ((start && !result[i]) - || (result[i] == '.' && !result[i+1])) { - result[--i] = '\0'; - break; - } - - /* Check for `../', `./' or trailing `.' by itself. */ - if (result[i] == '.') { - /* Handle `./'. */ - if (result[i + 1] == '/') { - strcpy( result + i, result + i + 1 ); - i = (start < 0) ? 0 : start; - continue; - } - - /* Handle `../' or trailing `..' by itself. */ - if (result[i + 1] == '.' && - (result[i + 2] == '/' || !result[i + 2])) { - while (--start > -1 && result[start] != '/') - ; - strcpy( result + start + 1, result + i + 2 ); - i = (start < 0) ? 0 : start; - continue; - } - } - } - - if (!*result) { - *result = stub_char; - result[1] = '\0'; - } - - return result; -} - -/* - * Given a string containing units of information separated by colons, - * return the next one pointed to by (P_INDEX), or NULL if there are no - * more. Advance (P_INDEX) to the character after the colon. - */ -static char* -extract_colon_unit( char* pzDir, char const *string, int *p_index ) -{ - char* pzDest = pzDir; - int ix = *p_index; - - if (string == NULL) - return NULL; - - if ((unsigned)ix >= strlen( string )) - return NULL; - - { - char const* pzSrc = string + ix; - - while (*pzSrc == ':') pzSrc++; - - for (;;) { - char ch = (*(pzDest++) = *(pzSrc++)); - switch (ch) { - case ':': - pzDest[-1] = NUL; - case NUL: - goto copy_done; - } - - if ((pzDest - pzDir) >= AG_PATH_MAX) - break; - } copy_done:; - - ix = pzSrc - string; - } - - if (*pzDir == NUL) - return NULL; - - *p_index = ix; - return pzDir; -} -#endif /* __windows__ / __CYGWIN__ */ -#endif /* HAVE_PATHFIND */ - -/* - * Local Variables: - * mode: C - * c-file-style: "stroustrup" - * indent-tabs-mode: nil - * End: - * end of compat/pathfind.c */ |