/* * (C) COPYRIGHT CRAY RESEARCH, INC. * UNPUBLISHED PROPRIETARY INFORMATION. * ALL RIGHTS RESERVED. */ /********************************************************** * * UNICOS Feature Test and Evaluation - Cray Research, Inc. * * FUNCTION NAME : search_path * * FUNCTION TITLE : search PATH locations for desired filename * * SYNOPSIS: * int search_path(cmd, res_path, access_mode, fullpath) * char *cmd; * char *res_path; * int access_mode; * int fullpath; * * AUTHOR : Richard Logan * * INITIAL RELEASE : UNICOS 7.0 * * DESCRIPTION * Search_path will walk through PATH and attempt to find "cmd". If cmd is * a full or relative path, it is checked but PATH locations are not scanned. * search_path will put the resulting path in res_path. It is assumed * that res_path points to a string that is at least PATH_MAX * (or MAXPATHLEN on the suns) in size. Access_mode is just as is * says, the mode to be used on access to determine if cmd can be found. * If fullpath is set, res_path will contain the full path to cmd. * If it is not set, res_path may or may not contain the full path to cmd. * If fullpath is not set, the path in PATH prepended to cmd is used, * which could be a relative path. If fullpath is set, the current * directory is prepended to path/cmd before access is called. * If cmd is found, search_path will return 0. If cmd cannot be * found, 1 is returned. If an error has occurred, -1 is returned * and an error mesg is placed in res_path. * If the length of path/cmd is larger then PATH_MAX, then that path * location is skipped. * *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/ #include #include #include #include #include #include #include #pragma GCC diagnostic ignored "-Wformat-overflow" #pragma GCC diagnostic ignored "-Wformat-truncation" extern int errno; struct stat stbuf; #ifndef AS_CMD #define AS_CMD 0 #endif /* * Make sure PATH_MAX is defined. Define it to MAXPATHLEN, if set. Otherwise * set it to 1024. */ #ifndef PATH_MAX #ifndef MAXPATHLEN #define PATH_MAX 1024 #else /* MAXPATHLEN */ #define PATH_MAX MAXPATHLEN #endif /* MAXPATHLEN */ #endif /* PATH_MAX */ #if AS_CMD main(argc, argv) int argc; char **argv; { char path[PATH_MAX]; int ind; if (argc <= 1 ) { printf("missing argument\n"); exit(1); } for(ind=1;ind < argc; ind++) { if ( search_path(argv[ind], path, F_OK, 0) < 0 ) { printf("ERROR: %s\n", path); } else { printf("path of %s is %s\n", argv[ind], path); } } } #endif /* */ int search_path(cmd, res_path, access_mode, fullpath) const char *cmd; /* The requested filename */ char *res_path; /* The resulting path or error mesg */ int access_mode; /* the mode used by access(2) */ int fullpath; /* if set, cwd will be prepended to all non-full paths */ { char *cp; /* used to scan PATH for directories */ int ret; /* return value from access */ char *pathenv; char tmppath[PATH_MAX]; char curpath[PATH_MAX]; char *path; int lastpath; int toolong=0; #if DEBUG printf("search_path: cmd = %s, access_mode = %d, fullpath = %d\n", cmd, access_mode, fullpath); #endif /* * full or relative path was given */ if ( (cmd[0] == '/') || ( (cp=strchr(cmd, '/')) != NULL )) { if ( access(cmd, access_mode) == 0 ) { if ( cmd[0] != '/' ) { /* relative path */ if ( getcwd(curpath, PATH_MAX) == NULL ) { strcpy(res_path, curpath); return -1; } if ( (strlen(curpath) + strlen(cmd) + 1) > (size_t)PATH_MAX ) { sprintf(res_path, "cmd (as relative path) and cwd is longer than %d", PATH_MAX); return -1; } sprintf(res_path, "%s/%s", curpath, cmd); } else strcpy(res_path, cmd); return 0; } else { sprintf(res_path, "file %s not found", cmd); return -1; } } /* get the PATH variable */ if ( (pathenv=getenv("PATH")) == NULL) { /* no path to scan, return */ sprintf(res_path, "Unable to get PATH env. variable"); return -1; } /* * walk through each path in PATH. * Each path in PATH is placed in tmppath. * pathenv cannot be modified since it will affect PATH. * If a signal came in while we have modified the PATH * memory, we could create a problem for the caller. */ curpath[0]='\0'; cp = pathenv; path = pathenv; lastpath = 0; for (;;) { if ( lastpath ) break; if ( cp != pathenv ) path = ++cp; /* already set on first iteration */ /* find end of current path */ for (; ((*cp != ':') && (*cp != '\0')); cp++); /* * copy path to tmppath so it can be NULL terminated * and so we do not modify path memory. */ strncpy(tmppath, path, (cp-path) ); tmppath[cp-path]='\0'; #if DEBUG printf("search_path: tmppath = %s\n", tmppath); #endif if ( *cp == '\0' ) lastpath=1; /* this is the last path entry */ /* Check lengths so not to overflow res_path */ if ( strlen(tmppath) + strlen(cmd) + 2 > (size_t)PATH_MAX ) { toolong++; continue; } sprintf(res_path, "%s/%s", tmppath, cmd); #if DEBUG printf("search_path: res_path = '%s'\n", res_path); #endif /* if the path is not full at this point, prepend the current * path to get the full path. * Note: this could not be wise to do when under a protected * directory. */ if ( fullpath && res_path[0] != '/' ) { /* not a full path */ if ( curpath[0] == '\0' ) { if ( getcwd(curpath, PATH_MAX) == NULL ) { strcpy(res_path, curpath); return -1; } } if ( (strlen(curpath) + strlen(res_path) + 2) > (size_t)PATH_MAX ) { toolong++; continue; } snprintf(tmppath, sizeof tmppath, "%s/%s", curpath, res_path); strcpy(res_path, tmppath); #if DEBUG printf("search_path: full res_path= '%s'\n", res_path); #endif } if ( (ret=access(res_path, access_mode)) == 0 ) { #if DEBUG printf("search_path: found res_path = %s\n", res_path); #endif return 0; } } /* return failure */ if ( toolong ) sprintf(res_path, "Unable to find file, %d path/file strings were too long", toolong); else strcpy(res_path, "Unable to find file"); return 1; /* not found */ }