Change which(1) over from a perl script to a C program.
authorDavid Rhodus <drhodus@dragonflybsd.org>
Thu, 25 Mar 2004 16:18:40 +0000 (16:18 +0000)
committerDavid Rhodus <drhodus@dragonflybsd.org>
Thu, 25 Mar 2004 16:18:40 +0000 (16:18 +0000)
Patch sent in by: Dheeraj Reddy <dheerajs@comcast.net>

usr.bin/which/Makefile
usr.bin/which/which.1
usr.bin/which/which.c [new file with mode: 0644]
usr.bin/which/which.pl [deleted file]

index 0eec993..d8cecd2 100644 (file)
@@ -1,11 +1,7 @@
 #      @(#)Makefile    8.1 (Berkeley) 6/6/93
 # $FreeBSD: src/usr.bin/which/Makefile,v 1.5.2.3 2002/08/07 16:32:01 ru Exp $
-# $DragonFly: src/usr.bin/which/Makefile,v 1.3 2004/01/31 06:56:44 dillon Exp $
+# $DragonFly: src/usr.bin/which/Makefile,v 1.4 2004/03/25 16:18:40 drhodus Exp $
 
-MAN=   which.1
-
-beforeinstall:
-       ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
-           ${.CURDIR}/which.pl ${DESTDIR}${BINDIR}/which
+PROG = which
 
 .include <bsd.prog.mk>
index 0c7924a..601249d 100644 (file)
@@ -28,7 +28,7 @@
 .\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
 .\" $FreeBSD: src/usr.bin/which/which.1,v 1.16.2.4 2002/06/21 15:30:13 charnier Exp $
-.\" $DragonFly: src/usr.bin/which/which.1,v 1.2 2003/06/17 04:29:33 dillon Exp $
+.\" $DragonFly: src/usr.bin/which/which.1,v 1.3 2004/03/25 16:18:40 drhodus Exp $
 .Dd January 26, 1995
 .Dt WHICH 1
 .Os
@@ -73,10 +73,13 @@ command first appeared in
 .Xr csh 1 ,
 .Xr find 1 ,
 .Xr locate 1 ,
-.Xr perl 1 ,
 .Xr whereis 1
 .Sh AUTHORS
-The PERL script for this more modern version of
+An -nosplit
+The
 .Nm
-was written by
+utility was originally written in Perl and was contributed by
 .An Wolfram Schneider Aq wosch@FreeBSD.org .
+The current version of
+.Nm
+was rewritten in C by Daniel Papasian Aq dpapasia@andrew.cmu.edu
diff --git a/usr.bin/which/which.c b/usr.bin/which/which.c
new file mode 100644 (file)
index 0000000..8a51af8
--- /dev/null
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2000 Dan Papasian.  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. 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 BY THE AUTHOR ``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.
+ * $FreeBSD: src/usr.bin/which/which.c,v 1.5 2002/06/30 06:02:39 tjr Exp $");
+ * $DragonFly: src/usr.bin/which/which.c,v 1.1 2004/03/25 16:18:40 drhodus Exp $
+ */
+
+#include <sys/cdefs.h>
+
+
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void     usage(void);
+static int      print_matches(char *, char *);
+
+int    silent;
+int    allpaths;
+
+int
+main(int argc, char **argv)
+{
+       char *p, *path;
+       ssize_t pathlen;
+       int opt, status;
+
+       status = EXIT_SUCCESS;
+
+       /* If called without args, die silently to conform */
+       if (argc < 2)
+               exit(EXIT_FAILURE);
+
+       while ((opt = getopt(argc, argv, "as")) != -1) {
+               switch (opt) {
+               case 'a':
+                       allpaths = 1;
+                       break;
+               case 's':
+                       silent = 1;
+                       break;
+               default:
+                       usage();
+                       break;
+               }
+       }
+
+       argv += optind;
+       argc -= optind;
+
+       if ((p = getenv("PATH")) == NULL)
+               exit(EXIT_FAILURE);
+       pathlen = strlen(p) + 1;
+       path = malloc(pathlen);
+       if (path == NULL)
+               err(EXIT_FAILURE, NULL);
+
+       if (argc == 0)
+               status = EXIT_FAILURE;
+
+       while (argc > 0) {
+               memcpy(path, p, pathlen);
+
+               if (strlen(*argv) >= FILENAME_MAX ||
+                   print_matches(path, *argv) == -1)
+                       status = EXIT_FAILURE;
+
+               argv++;
+               argc--;
+       }
+
+       exit(status);
+}
+
+static void
+usage(void)
+{
+
+       errx(EXIT_FAILURE, "usage: which [-as] program ...");
+}
+
+static int
+is_there(char *candidate)
+{
+       struct stat fin;
+
+       /* XXX work around access(2) false positives for superuser */
+       if (access(candidate, X_OK) == 0 &&
+           stat(candidate, &fin) == 0 &&
+           S_ISREG(fin.st_mode) &&
+           (getuid() != 0 ||
+           (fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
+               if (!silent)
+                       printf("%s\n", candidate);
+               return (1);
+       }
+       return (0);
+}
+
+static int
+print_matches(char *path, char *filename)
+{
+       char candidate[PATH_MAX];
+       const char *d;
+       int found;
+
+       if (strchr(filename, '/') != NULL)
+               return (is_there(filename) ? 0 : -1);
+       found = 0;
+       while ((d = strsep(&path, ":")) != NULL) {
+               if (*d == '\0')
+                       d = ".";
+               if (snprintf(candidate, sizeof(candidate), "%s/%s", d,
+                   filename) >= (int)sizeof(candidate))
+                       continue;
+               if (is_there(candidate)) {
+                       found = 1;
+                       if (!allpaths)
+                               break;
+               }
+       }
+       return (found ? 0 : -1);
+}
+
diff --git a/usr.bin/which/which.pl b/usr.bin/which/which.pl
deleted file mode 100644 (file)
index ff4ef22..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/perl
-#
-# Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
-# 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.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-#
-# $FreeBSD: src/usr.bin/which/which.pl,v 1.14 1999/08/28 01:07:39 peter Exp $
-# $DragonFly: src/usr.bin/which/Attic/which.pl,v 1.2 2003/06/17 04:29:33 dillon Exp $
-
-$all = $silent = $found = 0;
-@path = split(/:/, $ENV{'PATH'});
-if ($ENV{'PATH'} =~ /:$/) {
-       $#path = $#path + 1;
-       $path[$#path] = "";
-}
-
-if ($ARGV[0] eq "-a") {
-    $all = 1; shift @ARGV;
-} elsif ($ARGV[0] eq "-s") {
-    $silent = 1; shift @ARGV;
-} elsif ($ARGV[0] =~ /^-(h|help|\?)$/) {
-    die "usage: which [-a] [-s] program ...\n";
-}
-
-foreach $prog (@ARGV) {
-    if ("$prog" =~ '/' && -x "$prog" && -f "$prog") {
-       print "$prog\n" unless $silent;
-       $found = 1;
-    } else {
-       foreach $e (@path) {
-           $e = "." if !$e;
-           if (-x "$e/$prog" && -f "$e/$prog") {
-               print "$e/$prog\n" unless $silent;
-               $found = 1;
-               last unless $all;
-           }
-       }
-    }
-}
-
-exit (!$found);