1 /* $OpenBSD: which.c,v 1.26 2016/10/28 07:22:59 schwarze Exp $ */
4 * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 #define PROG_WHEREIS 2
33 extern char *__progname
;
35 int findprog(char *, char *, int, int);
36 static void __dead
usage(void);
39 * which(1) -- find an executable(s) in the user's path
40 * whereis(1) -- find an executable(s) in the default user path
43 * 0 - all executables found
44 * 1 - some found, some not
49 main(int argc
, char *argv
[])
53 int ch
, allmatches
= 0, notfound
= 0, progmode
= PROG_WHICH
;
55 while ((ch
= getopt(argc
, argv
, "a")) != -1)
69 if (strcmp(__progname
, "whereis") == 0) {
70 progmode
= PROG_WHEREIS
;
73 if ((path
= getenv("PATH")) == NULL
|| *path
== '\0')
77 /* To make access(2) do what we want */
78 if (setgid(getegid()))
79 err(1, "Can't set gid to %u", getegid());
80 if (setuid(geteuid()))
81 err(1, "Can't set uid to %u", geteuid());
83 if (pledge("stdio rpath", NULL
) == -1)
86 for (n
= 0; n
< argc
; n
++)
87 if (findprog(argv
[n
], path
, progmode
, allmatches
) == 0)
90 return ((notfound
== 0) ? 0 : ((notfound
== argc
) ? 2 : 1));
94 findprog(char *prog
, char *path
, int progmode
, int allmatches
)
96 char *p
, filename
[PATH_MAX
];
101 /* Special case if prog contains '/' */
102 if (strchr(prog
, '/')) {
103 if ((stat(prog
, &sbuf
) == 0) && S_ISREG(sbuf
.st_mode
) &&
104 access(prog
, X_OK
) == 0) {
108 warnx("%s: Command not found.", prog
);
113 if ((path
= strdup(path
)) == NULL
)
117 while ((p
= strsep(&pathcpy
, ":")) != NULL
) {
122 while (len
> 0 && p
[len
-1] == '/')
123 p
[--len
] = '\0'; /* strip trailing '/' */
125 len
= snprintf(filename
, sizeof(filename
), "%s/%s", p
, prog
);
126 if (len
< 0 || len
>= sizeof(filename
)) {
127 warnc(ENAMETOOLONG
, "%s/%s", p
, prog
);
131 if ((stat(filename
, &sbuf
) == 0) && S_ISREG(sbuf
.st_mode
) &&
132 access(filename
, X_OK
) == 0) {
133 (void)puts(filename
);
143 /* whereis(1) is silent on failure. */
144 if (!rval
&& progmode
!= PROG_WHEREIS
)
145 warnx("%s: Command not found.", prog
);
152 (void)fprintf(stderr
, "usage: %s [-a] name ...\n", __progname
);