250 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *	(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 <stdio.h>
 | |
| #include <unistd.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <sys/errno.h>
 | |
| #include <sys/param.h>
 | |
| #include <sys/stat.h>
 | |
| 
 | |
| 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;
 | |
|             }
 | |
|             sprintf(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 */
 | |
| }
 | |
| 
 |