1*4de49944Sapb /* $NetBSD: whereis.c,v 1.21 2008/10/17 10:53:26 apb Exp $ */
2be667101Sjtc
361f28255Scgd /*-
4dd831dd1Smycroft * Copyright (c) 1993
5dd831dd1Smycroft * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * Redistribution and use in source and binary forms, with or without
861f28255Scgd * modification, are permitted provided that the following conditions
961f28255Scgd * are met:
1061f28255Scgd * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd * notice, this list of conditions and the following disclaimer.
1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer in the
1461f28255Scgd * documentation and/or other materials provided with the distribution.
1589aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd * may be used to endorse or promote products derived from this software
1761f28255Scgd * without specific prior written permission.
1861f28255Scgd *
1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd * SUCH DAMAGE.
3061f28255Scgd */
3161f28255Scgd
329998247bSmrg #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3498e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1993\
3598e5374cSlukem The Regents of the University of California. All rights reserved.");
3661f28255Scgd #endif /* not lint */
3761f28255Scgd
3861f28255Scgd #ifndef lint
39be667101Sjtc #if 0
40be667101Sjtc static char sccsid[] = "@(#)whereis.c 8.3 (Berkeley) 5/4/95";
41be667101Sjtc #endif
42*4de49944Sapb __RCSID("$NetBSD: whereis.c,v 1.21 2008/10/17 10:53:26 apb Exp $");
4361f28255Scgd #endif /* not lint */
4461f28255Scgd
4561f28255Scgd #include <sys/param.h>
46dd831dd1Smycroft #include <sys/stat.h>
47dd831dd1Smycroft #include <sys/sysctl.h>
48dd831dd1Smycroft
49dd831dd1Smycroft #include <err.h>
50dd831dd1Smycroft #include <errno.h>
5161f28255Scgd #include <stdio.h>
52dd831dd1Smycroft #include <stdlib.h>
53dd831dd1Smycroft #include <string.h>
54be667101Sjtc #include <unistd.h>
5561f28255Scgd
568b0f9554Sperry static void usage(void) __dead;
5761f28255Scgd
58dd831dd1Smycroft int
main(int argc,char * argv[])59745a6d0fSchristos main(int argc, char *argv[])
6061f28255Scgd {
61dd831dd1Smycroft struct stat sb;
62dd831dd1Smycroft size_t len;
63745a6d0fSchristos int ch, mib[2];
6460a197ffSchristos char *p, *std, path[MAXPATHLEN];
6560a197ffSchristos const char *t;
66745a6d0fSchristos int which = strcmp(getprogname(), "which") == 0;
67745a6d0fSchristos int useenvpath = which, found = 0;
6854c75404Schristos gid_t egid = getegid();
6954c75404Schristos uid_t euid = geteuid();
7054c75404Schristos
7154c75404Schristos /* To make access(2) do what we want */
7254c75404Schristos if (setgid(egid) == -1)
7354c75404Schristos err(1, "Can't set gid to %lu", (unsigned long)egid);
7454c75404Schristos if (setuid(euid) == -1)
7554c75404Schristos err(1, "Can't set uid to %lu", (unsigned long)euid);
7661f28255Scgd
77745a6d0fSchristos while ((ch = getopt(argc, argv, "ap")) != -1)
78dd831dd1Smycroft switch (ch) {
79745a6d0fSchristos case 'a':
80745a6d0fSchristos which = 0;
81745a6d0fSchristos break;
8264b15518Sfair case 'p':
8364b15518Sfair useenvpath = 1; /* use environment for PATH */
8464b15518Sfair break;
8564b15518Sfair
86dd831dd1Smycroft case '?':
8761f28255Scgd default:
88dd831dd1Smycroft usage();
8961f28255Scgd }
90dd831dd1Smycroft argc -= optind;
91dd831dd1Smycroft argv += optind;
92dd831dd1Smycroft
93dd831dd1Smycroft if (argc == 0)
94dd831dd1Smycroft usage();
95dd831dd1Smycroft
9664b15518Sfair if (useenvpath) {
9764b15518Sfair if ((std = getenv("PATH")) == NULL)
98745a6d0fSchristos errx(1, "PATH environment variable is not set");
9964b15518Sfair } else {
100dd831dd1Smycroft /* Retrieve the standard path. */
101dd831dd1Smycroft mib[0] = CTL_USER;
102dd831dd1Smycroft mib[1] = USER_CS_PATH;
103dd831dd1Smycroft if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1)
104745a6d0fSchristos err(1, "sysctl: user.cs_path");
105dd831dd1Smycroft if (len == 0)
106745a6d0fSchristos errx(1, "sysctl: user.cs_path (zero length)");
107dd831dd1Smycroft if ((std = malloc(len)) == NULL)
10885cbf55dSdrochner err(1, NULL);
109745a6d0fSchristos if (sysctl(mib, 2, std, &len, NULL, 0) == -1)
110745a6d0fSchristos err(1, "sysctl: user.cs_path");
11164b15518Sfair }
112dd831dd1Smycroft
113dd831dd1Smycroft /* For each path, for each program... */
114*4de49944Sapb for (; *argv; ++argv) {
115ef30089dSmartin if (**argv == '/') {
116ef30089dSmartin if (stat(*argv, &sb) == -1)
117*4de49944Sapb continue; /* next argv */
118ef30089dSmartin if (!S_ISREG(sb.st_mode))
119*4de49944Sapb continue; /* next argv */
120ef30089dSmartin if (access(*argv, X_OK) == -1)
121*4de49944Sapb continue; /* next argv */
122ef30089dSmartin (void)printf("%s\n", *argv);
123ef30089dSmartin found++;
124ef30089dSmartin if (which)
125*4de49944Sapb continue; /* next argv */
126*4de49944Sapb } else for (p = std; p; ) {
127dd831dd1Smycroft t = p;
128dd831dd1Smycroft if ((p = strchr(p, ':')) != NULL) {
129dd831dd1Smycroft *p = '\0';
130dd831dd1Smycroft if (t == p)
131dd831dd1Smycroft t = ".";
13261f28255Scgd } else
133dd831dd1Smycroft if (strlen(t) == 0)
134dd831dd1Smycroft t = ".";
135dd831dd1Smycroft (void)snprintf(path, sizeof(path), "%s/%s", t, *argv);
136dbf34104Schristos len = snprintf(path, sizeof(path), "%s/%s", t, *argv);
137*4de49944Sapb if (p)
138*4de49944Sapb *p++ = ':';
139dbf34104Schristos if (len >= sizeof(path))
140*4de49944Sapb continue; /* next p */
141745a6d0fSchristos if (stat(path, &sb) == -1)
142*4de49944Sapb continue; /* next p */
143745a6d0fSchristos if (!S_ISREG(sb.st_mode))
144*4de49944Sapb continue; /* next p */
145745a6d0fSchristos if (access(path, X_OK) == -1)
146*4de49944Sapb continue; /* next p */
147dd831dd1Smycroft (void)printf("%s\n", path);
148df28067fSperry found++;
149745a6d0fSchristos if (which)
150*4de49944Sapb break; /* next argv */
151*4de49944Sapb }
15261f28255Scgd }
153f5a8ade2Smikel
154745a6d0fSchristos return ((found == 0) ? 3 : ((found >= argc) ? 0 : 2));
15561f28255Scgd }
15661f28255Scgd
157745a6d0fSchristos static void
usage(void)158745a6d0fSchristos usage(void)
15961f28255Scgd {
16061f28255Scgd
161745a6d0fSchristos (void)fprintf(stderr, "Usage: %s [-ap] program [...]\n", getprogname());
162dd831dd1Smycroft exit(1);
16361f28255Scgd }
164