1 1.22 jschauma /* $NetBSD: whereis.c,v 1.22 2025/06/01 15:45:31 jschauma Exp $ */ 2 1.6 jtc 3 1.1 cgd /*- 4 1.5 mycroft * Copyright (c) 1993 5 1.5 mycroft * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.13 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.8 mrg #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.20 lukem __COPYRIGHT("@(#) Copyright (c) 1993\ 35 1.20 lukem The Regents of the University of California. All rights reserved."); 36 1.1 cgd #endif /* not lint */ 37 1.1 cgd 38 1.1 cgd #ifndef lint 39 1.6 jtc #if 0 40 1.6 jtc static char sccsid[] = "@(#)whereis.c 8.3 (Berkeley) 5/4/95"; 41 1.6 jtc #endif 42 1.22 jschauma __RCSID("$NetBSD: whereis.c,v 1.22 2025/06/01 15:45:31 jschauma Exp $"); 43 1.1 cgd #endif /* not lint */ 44 1.1 cgd 45 1.1 cgd #include <sys/param.h> 46 1.5 mycroft #include <sys/stat.h> 47 1.5 mycroft #include <sys/sysctl.h> 48 1.5 mycroft 49 1.5 mycroft #include <err.h> 50 1.5 mycroft #include <errno.h> 51 1.1 cgd #include <stdio.h> 52 1.5 mycroft #include <stdlib.h> 53 1.5 mycroft #include <string.h> 54 1.6 jtc #include <unistd.h> 55 1.5 mycroft 56 1.19 perry static void usage(void) __dead; 57 1.1 cgd 58 1.5 mycroft int 59 1.14 christos main(int argc, char *argv[]) 60 1.1 cgd { 61 1.5 mycroft struct stat sb; 62 1.5 mycroft size_t len; 63 1.14 christos int ch, mib[2]; 64 1.15 christos char *p, *std, path[MAXPATHLEN]; 65 1.15 christos const char *t; 66 1.14 christos int which = strcmp(getprogname(), "which") == 0; 67 1.14 christos int useenvpath = which, found = 0; 68 1.16 christos gid_t egid = getegid(); 69 1.16 christos uid_t euid = geteuid(); 70 1.16 christos 71 1.16 christos /* To make access(2) do what we want */ 72 1.22 jschauma if (setregid(egid, egid) == -1) 73 1.16 christos err(1, "Can't set gid to %lu", (unsigned long)egid); 74 1.22 jschauma if (setreuid(euid, euid) == -1) 75 1.16 christos err(1, "Can't set uid to %lu", (unsigned long)euid); 76 1.5 mycroft 77 1.14 christos while ((ch = getopt(argc, argv, "ap")) != -1) 78 1.5 mycroft switch (ch) { 79 1.14 christos case 'a': 80 1.14 christos which = 0; 81 1.14 christos break; 82 1.9 fair case 'p': 83 1.9 fair useenvpath = 1; /* use environment for PATH */ 84 1.9 fair break; 85 1.9 fair 86 1.5 mycroft case '?': 87 1.5 mycroft default: 88 1.5 mycroft usage(); 89 1.5 mycroft } 90 1.5 mycroft argc -= optind; 91 1.5 mycroft argv += optind; 92 1.1 cgd 93 1.5 mycroft if (argc == 0) 94 1.5 mycroft usage(); 95 1.1 cgd 96 1.9 fair if (useenvpath) { 97 1.9 fair if ((std = getenv("PATH")) == NULL) 98 1.14 christos errx(1, "PATH environment variable is not set"); 99 1.9 fair } else { 100 1.9 fair /* Retrieve the standard path. */ 101 1.9 fair mib[0] = CTL_USER; 102 1.9 fair mib[1] = USER_CS_PATH; 103 1.9 fair if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1) 104 1.14 christos err(1, "sysctl: user.cs_path"); 105 1.9 fair if (len == 0) 106 1.14 christos errx(1, "sysctl: user.cs_path (zero length)"); 107 1.9 fair if ((std = malloc(len)) == NULL) 108 1.10 drochner err(1, NULL); 109 1.14 christos if (sysctl(mib, 2, std, &len, NULL, 0) == -1) 110 1.14 christos err(1, "sysctl: user.cs_path"); 111 1.5 mycroft } 112 1.5 mycroft 113 1.5 mycroft /* For each path, for each program... */ 114 1.21 apb for (; *argv; ++argv) { 115 1.18 martin if (**argv == '/') { 116 1.18 martin if (stat(*argv, &sb) == -1) 117 1.21 apb continue; /* next argv */ 118 1.18 martin if (!S_ISREG(sb.st_mode)) 119 1.21 apb continue; /* next argv */ 120 1.18 martin if (access(*argv, X_OK) == -1) 121 1.21 apb continue; /* next argv */ 122 1.18 martin (void)printf("%s\n", *argv); 123 1.18 martin found++; 124 1.18 martin if (which) 125 1.21 apb continue; /* next argv */ 126 1.21 apb } else for (p = std; p; ) { 127 1.5 mycroft t = p; 128 1.5 mycroft if ((p = strchr(p, ':')) != NULL) { 129 1.5 mycroft *p = '\0'; 130 1.5 mycroft if (t == p) 131 1.5 mycroft t = "."; 132 1.5 mycroft } else 133 1.5 mycroft if (strlen(t) == 0) 134 1.5 mycroft t = "."; 135 1.5 mycroft (void)snprintf(path, sizeof(path), "%s/%s", t, *argv); 136 1.17 christos len = snprintf(path, sizeof(path), "%s/%s", t, *argv); 137 1.21 apb if (p) 138 1.21 apb *p++ = ':'; 139 1.17 christos if (len >= sizeof(path)) 140 1.21 apb continue; /* next p */ 141 1.14 christos if (stat(path, &sb) == -1) 142 1.21 apb continue; /* next p */ 143 1.14 christos if (!S_ISREG(sb.st_mode)) 144 1.21 apb continue; /* next p */ 145 1.14 christos if (access(path, X_OK) == -1) 146 1.21 apb continue; /* next p */ 147 1.14 christos (void)printf("%s\n", path); 148 1.14 christos found++; 149 1.14 christos if (which) 150 1.21 apb break; /* next argv */ 151 1.1 cgd } 152 1.21 apb } 153 1.12 perry 154 1.14 christos return ((found == 0) ? 3 : ((found >= argc) ? 0 : 2)); 155 1.1 cgd } 156 1.1 cgd 157 1.14 christos static void 158 1.14 christos usage(void) 159 1.1 cgd { 160 1.1 cgd 161 1.14 christos (void)fprintf(stderr, "Usage: %s [-ap] program [...]\n", getprogname()); 162 1.14 christos exit(1); 163 1.1 cgd } 164