Imported Upstream version 1.6.6
[debian/sudo] / find_path.c
1 /*
2  * Copyright (c) 1996, 1998-2001 Todd C. Miller <Todd.Miller@courtesan.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * 4. Products derived from this software may not be called "Sudo" nor
20  *    may "Sudo" appear in their names without specific prior written
21  *    permission from the author.
22  *
23  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
26  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include "config.h"
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/stat.h>
40 #include <stdio.h>
41 #ifdef STDC_HEADERS
42 # include <stdlib.h>
43 # include <stddef.h>
44 #else
45 # ifdef HAVE_STDLIB_H
46 #  include <stdlib.h>
47 # endif
48 #endif /* STDC_HEADERS */
49 #ifdef HAVE_STRING_H
50 # include <string.h>
51 #else
52 # ifdef HAVE_STRINGS_H
53 #  include <strings.h>
54 # endif
55 #endif /* HAVE_STRING_H */
56 #ifdef HAVE_UNISTD_H
57 # include <unistd.h>
58 #endif /* HAVE_UNISTD_H */
59 #include <errno.h>
60
61 #include "sudo.h"
62
63 #ifndef lint
64 static const char rcsid[] = "$Sudo: find_path.c,v 1.98 2001/12/14 06:40:03 millert Exp $";
65 #endif /* lint */
66
67 /*
68  * This function finds the full pathname for a command and
69  * stores it in a statically allocated array, filling in a pointer
70  * to the array.  Returns FOUND if the command was found, NOT_FOUND
71  * if it was not found, or NOT_FOUND_DOT if it would have been found
72  * but it is in '.' and IGNORE_DOT is set.
73  */
74 int
75 find_path(infile, outfile, path)
76     char *infile;               /* file to find */
77     char **outfile;             /* result parameter */
78     char *path;                 /* path to search */
79 {
80     static char command[MAXPATHLEN]; /* qualified filename */
81     char *n;                    /* for traversing path */
82     char *origpath;             /* so we can free path later */
83     char *result = NULL;        /* result of path/file lookup */
84     int checkdot = 0;           /* check current dir? */
85
86     if (strlen(infile) >= MAXPATHLEN) {
87         (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile);
88         exit(1);
89     }
90
91     /*
92      * If we were given a fully qualified or relative path
93      * there is no need to look at $PATH.
94      */
95     if (strchr(infile, '/')) {
96         (void) strcpy(command, infile);
97         if (sudo_goodpath(command)) {
98             *outfile = command;
99             return(FOUND);
100         } else
101             return(NOT_FOUND);
102     }
103
104     /* Use PATH passed in unless SECURE_PATH is in effect.  */
105 #ifdef SECURE_PATH
106     if (!user_is_exempt())
107         path = SECURE_PATH;
108 #endif /* SECURE_PATH */
109     if (path == NULL)
110         return(NOT_FOUND);
111     path = estrdup(path);
112     origpath = path;
113
114     do {
115         if ((n = strchr(path, ':')))
116             *n = '\0';
117
118         /*
119          * Search current dir last if it is in PATH This will miss sneaky
120          * things like using './' or './/' 
121          */
122         if (*path == '\0' || (*path == '.' && *(path + 1) == '\0')) {
123             checkdot = 1;
124             path = n + 1;
125             continue;
126         }
127
128         /*
129          * Resolve the path and exit the loop if found.
130          */
131         if (strlen(path) + strlen(infile) + 1 >= MAXPATHLEN) {
132             (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile);
133             exit(1);
134         }
135         (void) sprintf(command, "%s/%s", path, infile);
136         if ((result = sudo_goodpath(command)))
137             break;
138
139         path = n + 1;
140
141     } while (n);
142     free(origpath);
143
144     /*
145      * Check current dir if dot was in the PATH
146      */
147     if (!result && checkdot) {
148         result = sudo_goodpath(infile);
149         if (result && def_flag(I_IGNORE_DOT))
150             return(NOT_FOUND_DOT);
151     }
152
153     if (result) {
154         *outfile = result;
155         return(FOUND);
156     } else
157         return(NOT_FOUND);
158 }