-.\" $OpenBSD: which.1,v 1.3 1997/01/07 15:57:48 niklas Exp $
+.\" $OpenBSD: which.1,v 1.4 1997/02/21 18:34:59 millert Exp $
.\" Copyright (c) 1980, 1991 Regents of the University of California.
.\" All rights reserved.
.\"
.\"
.\" from: @(#)which.1 6.3 (Berkeley) 4/23/91
.\"
-.Dd April 23, 1991
+.Dd February 21, 1997
.Dt WHICH 1
-.Os BSD 3
+.Os
.Sh NAME
.Nm which
-.Nd "locate a program file including aliases and paths"
-.Pq Xr csh 1
-only)
+.Nd "locate a program file (or files) in the path"
.Sh SYNOPSIS
.Nm which
.Op Ar name
.Nm Which
takes a list of names and looks for the files which would be
executed had these names been given as commands.
-Each argument is expanded if it is aliased,
-and searched for along the user's path.
-Both aliases and path are taken from the user's
-.Pa \&.cshrc
-file.
-.Pp
+Each argument is searched for along the user's path.
+.Sh RETURN VALUES
The
-.Nm which
+.Nm
utility exits with one of the following values:
.Bl -tag -width 4n
.It 0
Some names got resolved but not all.
.It 2
No names got resolved.
-.El
-.Sh FILES
-.Bl -tag -width ~/\&.cshrc
-.It Pa ~/\&.cshrc
-source of aliases and path values
+.It -1
+A system error occurred.
.El
.Sh DIAGNOSTICS
-A diagnostic is given for names which are aliased to more than a single
-word,
-or if an executable file with the argument name was not found in the path.
-.Sh BUGS
-Must be executed by a
+A diagnostic is given if an executable file with the argument
+name was not found in the path.
+.Sh ENVIRONMENT VARIABLES
+.Bl -tag -width PATH
+.It Ev PATH
+.Nm
+uses the environment variable
+.Ev PATH
+as a colon-separated list of directories in which to find executables.
+If
+.Ev PATH
+is not set, and the given name is not a fully-qualified
+or relative pathname,
+.Nm
+will fail.
+.El
+.Sh CAVEATS
+The
+.Nm
+command formerly was a
+.Xr csh 1
+script and could expand aliases.
+.Xr csh 1
+now has a built-in
+.Nm
+comand so this version is intended for use
+with other shells like
+.Xr sh 1 .
+.Sh SEE ALSO
.Xr csh 1 ,
-or some other shell which knows about aliases.
+.Xr sh 1 ,
+.Xr environ 7
.Sh HISTORY
-The
+A
.Nm
command appeared in
.Bx 3.0 .
--- /dev/null
+/* $OpenBSD: which.c,v 1.1 1997/02/21 18:35:00 millert Exp $ */
+
+/*
+ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Todd C. Miller.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char rcsid[] = "$OpenBSD: which.c,v 1.1 1997/02/21 18:35:00 millert Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+extern char *__progname;
+
+int which __P((char *, char *));
+void usage __P((void));
+
+/*
+ * which(1) -- find an executable(s) in the user's path
+ *
+ * Return values:
+ * 0 - all executables found
+ * 1 - some found, some not
+ * 2 - none found
+ */
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *path;
+ int n, notfound = 0;
+
+ (void)setlocale(LC_ALL, "");
+
+ if (argc == 1)
+ usage();
+
+ if ((path = getenv("PATH")) == NULL)
+ err(-1, "Can't get $PATH from environment");
+
+ /* To make access(2) do what we want */
+ if (setgid(getegid()))
+ err(-1, "Can't set gid to %u", getegid());
+ if (setuid(geteuid()))
+ err(-1, "Can't set uid to %u", geteuid());
+
+ for (n = 1; n < argc; n++)
+ if (which(argv[n], path) == 0)
+ notfound++;
+
+ exit((notfound == 0) ? 0 : ((notfound == argc - 1) ? 2 : 1));
+}
+
+int
+which(prog, path)
+ char *prog;
+ char *path;
+{
+ char *p, filename[MAXPATHLEN];
+ int proglen, plen;
+ struct stat sbuf;
+
+ /* Special case if prog contains '/' */
+ if (strchr(prog, '/')) {
+ if ((stat(prog, &sbuf) == 0) && S_ISREG(sbuf.st_mode) &&
+ access(prog, X_OK) == 0) {
+ (void)puts(prog);
+ return(1);
+ } else {
+ (void)printf("%s: Command not found.\n", prog);
+ return(0);
+ }
+ }
+
+ if ((path = strdup(path)) == NULL)
+ errx(1, "Can't allocate memory.");
+
+ proglen = strlen(prog);
+ while ((p = strsep(&path, ":")) != NULL) {
+ if (*p == '\0')
+ p = ".";
+
+ plen = strlen(p);
+ while (p[plen-1] == '/')
+ p[--plen] = '\0'; /* strip trailing '/' */
+
+ if (plen + 1 + proglen >= sizeof(filename)) {
+ warnx("%s/%s: %s", p, prog, strerror(ENAMETOOLONG));
+ return(0);
+ }
+
+ (void)strcpy(filename, p);
+ filename[plen] = '/';
+ (void)strcpy(filename + plen + 1, prog);
+ if ((stat(filename, &sbuf) == 0) && S_ISREG(sbuf.st_mode) &&
+ access(filename, X_OK) == 0) {
+ (void)puts(filename);
+ return(1);
+ }
+ }
+ (void)free(path);
+
+ (void)printf("%s: Command not found.\n", prog);
+ return(0);
+}
+
+void
+usage()
+{
+ (void) fprintf(stderr, "Usage: %s [name ...]\n", __progname);
+ exit(1);
+}
+++ /dev/null
-#!/bin/csh
-# $OpenBSD: which.csh,v 1.3 1997/01/07 15:38:58 niklas Exp $
-
-#
-# DO NOT USE "csh -f"
-#
-# Copyright (c) 1983 The Regents of the University of California.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-# must display the following acknowledgement:
-# This product includes software developed by the University of
-# California, Berkeley and its contributors.
-# 4. Neither the name of the University nor the names of its contributors
-# may be used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# @(#)which.csh 5.5 (Berkeley) 4/18/91
-#
-
-# which : tells you which program you get
-#
-set prompt = "% "
-set noglob
-foreach arg ( $argv )
- set alius = `alias $arg`
- switch ( $#alius )
- case 0 :
- breaksw
- case 1 :
- set arg = $alius[1]
- breaksw
- default :
- echo ${arg}: " " aliased to $alius
- continue
- endsw
- unset found
- if ( $arg:h != $arg:t ) then
- if ( -e $arg ) then
- echo $arg
- else
- echo $arg not found
- endif
- continue
- else
- foreach i ( $path )
- if ( -x $i/$arg && ! -d $i/$arg ) then
- echo $i/$arg
- set found
- set one_found
- break
- endif
- end
- endif
- if ( ! $?found ) then
- echo no $arg in $path
- set one_missed
- endif
-end
-if ( $?one_missed ) then
- if ( $?one_found ) then
- exit 1
- else
- exit 2
- endif
-else
- exit 0
-endif