⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pathfind.c

📁 基于ntp协议的网络时间服务程序
💻 C
字号:
/*  -*- 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;}#elsestatic 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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -