OSDN Git Service

Importing Egor's testsuite.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / testsuite / libltp / lib / search_path.c
1 /* $Header$ */
2
3 /*
4  *      (C) COPYRIGHT CRAY RESEARCH, INC.
5  *      UNPUBLISHED PROPRIETARY INFORMATION.
6  *      ALL RIGHTS RESERVED.
7  */
8 /**********************************************************
9  * 
10  *    UNICOS Feature Test and Evaluation - Cray Research, Inc.
11  * 
12  *    FUNCTION NAME     : search_path 
13  * 
14  *    FUNCTION TITLE    : search PATH locations for desired filename
15  * 
16  *    SYNOPSIS:
17  *      int search_path(cmd, res_path, access_mode, fullpath)
18  *      char *cmd;
19  *      char *res_path;
20  *      int access_mode;
21  *      int fullpath;
22  * 
23  *    AUTHOR            : Richard Logan
24  * 
25  *    INITIAL RELEASE   : UNICOS 7.0
26  * 
27  *    DESCRIPTION
28  *      Search_path will walk through PATH and attempt to find "cmd".  If cmd is
29  *      a full or relative path, it is checked but PATH locations are not scanned.
30  *      search_path will put the resulting path in res_path.  It is assumed
31  *      that res_path points to a string that is at least PATH_MAX
32  *      (or MAXPATHLEN on the suns) in size.  Access_mode is just as is
33  *      says, the mode to be used on access to determine if cmd can be found.
34  *      If fullpath is set, res_path will contain the full path to cmd.
35  *      If it is not set, res_path may or may not contain the full path to cmd.
36  *      If fullpath is not set, the path in PATH prepended to cmd is used,
37  *      which could be a relative path.  If fullpath is set, the current
38  *      directory is prepended to path/cmd before access is called.
39  *      If cmd is found, search_path will return 0.  If cmd cannot be
40  *      found, 1 is returned.  If an error has occurred, -1 is returned
41  *      and an error mesg is placed in res_path. 
42  *      If the length of path/cmd is larger then PATH_MAX, then that path
43  *      location is skipped.
44  * 
45  *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
46
47 #include <stdio.h>
48 #include <unistd.h>
49 #include <string.h>
50 #include <stdlib.h>
51 #include <sys/errno.h>
52 #include <sys/param.h>
53 #include <sys/stat.h>
54
55 extern int errno;
56
57 struct stat stbuf;
58
59 #ifndef AS_CMD
60 #define AS_CMD  0
61 #endif
62
63 /*
64  * Make sure PATH_MAX is defined.  Define it to MAXPATHLEN, if set. Otherwise
65  * set it to 1024.
66  */
67 #ifndef PATH_MAX
68 #ifndef MAXPATHLEN
69 #define PATH_MAX     1024
70 #else  /* MAXPATHLEN */
71 #define PATH_MAX     MAXPATHLEN
72 #endif  /* MAXPATHLEN */
73 #endif  /* PATH_MAX */
74
75
76 #if AS_CMD
77 main(argc, argv)
78 int argc;
79 char **argv;
80 {
81     char path[PATH_MAX];
82     int ind;
83
84     if (argc <= 1 ) {
85         printf("missing argument\n");
86         exit(1);
87     }
88
89     for(ind=1;ind < argc; ind++) {
90         if ( search_path(argv[ind], path, F_OK, 0) < 0 ) {
91             printf("ERROR: %s\n", path);
92         }
93         else {
94             printf("path of %s is %s\n", argv[ind], path);
95         }
96     }
97     
98 }
99
100 #endif
101
102 /*
103  */
104 int
105 search_path(cmd, res_path, access_mode, fullpath)
106 char *cmd;      /* The requested filename */
107 char *res_path; /* The resulting path or error mesg */
108 int access_mode; /* the mode used by access(2) */
109 int fullpath;   /* if set, cwd will be prepended to all non-full paths */
110 {
111     char *cp;   /* used to scan PATH for directories */
112     int ret;      /* return value from access */
113     char *pathenv;
114     char tmppath[PATH_MAX];
115     char curpath[PATH_MAX];
116     char *path;
117     int lastpath;
118     int toolong=0;
119
120 #if DEBUG
121 printf("search_path: cmd = %s, access_mode = %d, fullpath = %d\n", cmd, access_mode, fullpath);
122 #endif
123
124     /*
125      * full or relative path was given
126      */
127     if ( (cmd[0] == '/') || ( (cp=strchr(cmd, '/')) != NULL )) {  
128         if ( access(cmd, access_mode) == 0 ) {
129
130             if ( cmd[0] != '/' ) { /* relative path */
131                 if ( getcwd(curpath, PATH_MAX) == NULL ) {
132                     strcpy(res_path, curpath);
133                     return -1;
134                 }
135                 if ( (strlen(curpath) + strlen(cmd) + 1) > (size_t)PATH_MAX ) {
136                     sprintf(res_path, "cmd (as relative path) and cwd is longer than %d",
137                         PATH_MAX);
138                     return -1;
139                 }
140                 sprintf(res_path, "%s/%s", curpath, cmd);
141             }
142             else
143                 strcpy(res_path, cmd);
144             return 0;
145         }
146         else {
147             sprintf(res_path, "file %s not found", cmd);
148             return -1;
149         }
150     }
151
152     /* get the PATH variable */
153     if ( (pathenv=getenv("PATH")) == NULL) {
154         /* no path to scan, return */
155         sprintf(res_path, "Unable to get PATH env. variable");
156         return -1;
157     }
158
159     /*
160      * walk through each path in PATH. 
161      * Each path in PATH is placed in tmppath.  
162      * pathenv cannot be modified since it will affect PATH.
163      * If a signal came in while we have modified the PATH
164      * memory, we could create a problem for the caller.
165      */
166
167     curpath[0]='\0';
168
169     cp = pathenv;
170     path = pathenv;
171     lastpath = 0;
172     for (;;) {
173
174         if ( lastpath )
175             break;
176
177         if ( cp != pathenv )
178             path = ++cp;         /* already set on first iteration */
179
180         /* find end of current path */
181
182         for (; ((*cp != ':') && (*cp != '\0')); cp++);
183
184         /*
185          * copy path to tmppath so it can be NULL terminated
186          * and so we do not modify path memory.
187          */
188         strncpy(tmppath, path, (cp-path) );
189         tmppath[cp-path]='\0';
190 #if DEBUG
191 printf("search_path: tmppath = %s\n", tmppath);
192 #endif
193
194         if ( *cp == '\0' )
195             lastpath=1;         /* this is the last path entry */
196
197         /* Check lengths so not to overflow res_path */
198         if ( strlen(tmppath) + strlen(cmd) + 2 > (size_t)PATH_MAX ) {
199             toolong++;
200             continue;
201         }
202
203         sprintf(res_path, "%s/%s", tmppath, cmd);
204 #if DEBUG
205 printf("search_path: res_path = '%s'\n", res_path);
206 #endif
207
208
209             /* if the path is not full at this point, prepend the current
210              * path to get the full path.
211              * Note:  this could not be wise to do when under a protected
212              * directory.  
213              */
214
215         if ( fullpath && res_path[0] != '/' ) { /* not a full path */
216             if ( curpath[0] == '\0' ) {
217                 if ( getcwd(curpath, PATH_MAX) == NULL ) {
218                     strcpy(res_path, curpath);
219                     return -1;
220                 }
221             }
222             if ( (strlen(curpath) + strlen(res_path) + 2) > (size_t)PATH_MAX ) {
223                 toolong++;
224                 continue;
225             }
226             sprintf(tmppath, "%s/%s", curpath, res_path);
227             strcpy(res_path, tmppath);
228 #if DEBUG
229 printf("search_path: full res_path= '%s'\n", res_path);
230 #endif
231
232         }
233
234
235         if ( (ret=access(res_path, access_mode)) == 0 ) {
236 #if DEBUG
237 printf("search_path: found res_path = %s\n", res_path);
238 #endif
239             return 0;
240         }
241     }
242
243     /* return failure */
244     if ( toolong )
245         sprintf(res_path,
246             "Unable to find file, %d path/file strings were too long", toolong);
247     else
248         strcpy(res_path, "Unable to find file");
249     return 1;   /* not found */
250 }
251