maart@cs.vu.nl (Maarten Litmaath) (01/06/90)
: This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin:/usr/ucb echo Extracting 'Makefile' sed 's/^X//' > 'Makefile' << '+ END-OF-FILE ''Makefile' X# Makefile for /usr/local/bin/which X Xwhich: which.c X cc -O which.c -o which X Xinstall: which X /bin/mv -f which /usr/local/bin X Xdoc: X nroff -man which.1 > which.man + END-OF-FILE Makefile chmod 'u=rw,g=r,o=r' 'Makefile' set `wc -c 'Makefile'` count=$1 case $count in 167) :;; *) echo 'Bad character count in ''Makefile' >&2 echo 'Count should be 167' >&2 esac echo Extracting 'which.1' sed 's/^X//' > 'which.1' << '+ END-OF-FILE ''which.1' X.TH WHICH 1 Sep\ 21\ 1989 X.SH NAME Xwhich \- give alias, function or path expansion of command X.SH SYNOPSIS X.B which X[ X.B \-i X] [ X.B \-a X] [ X.B \-\- X] [ X.I command X] X.SH DESCRIPTION X.I Which Xprovides the user with the full expansion of the X.I command Xargument, be it either an \fIalias\fR, a \fIshell function\fR Xor an executable file (default). To enable search for X.I aliases Xand \fIshell functions\fR Xthe user should supply the `\fI\-i\fR' X(= interactive) flag. In that case X.I which Xexpects as standard input the expansion of the \fIalias\fR Xor \fIshell function\fR. XIf the standard input is empty or the `\fI\-i\fR' flag has not been Xgiven, \fIwhich\fR will try to locate \fIcommand\fR Xin the user's \fIPATH\fR. XThe interactive mode is easily used by setting an X.I alias Xlike the following: X.ft B X.nf X X alias which alias !\\$ \\| /usr/local/bin/which \-i !\\* X X.fi X.ft R Xin \fIcsh\fR, or X.ft B X.nf X X alias which eval alias '\\"\\$$#\\" |' \\ X /usr/local/bin/which \-i '${1+"$@"}' X X.fi X.ft R Xin shells which are supersets of X.I sh Xand which know \fIaliases\fR. If your shell has \fIshell functions\fR, you Xcan use the following function: X.ft B X.nf X X which() X { X eval last=\\"\\$$#\\" X set | sed \-n "/^$last(){$/,/^}$/p" | X /usr/local/bin/which \-i ${1+"$@"} X } X X.fi X.ft R XIf the `\fI\-a\fR' (= all) flag is given, X.I which Xwill not stop after the first `match', but search for all occurrences of X.I command Xin the user's X.I PATH. XThe `\fI\-\-\fR' Xflag can be used to end the list of options: the next argument (if present) Xwill be taken as \fIcommand\fR, even if it starts with a `\-'. X\fIWhich [\-i] [\-a] [\-\-]\fR Xwithout further arguments prints the user's X.I PATH Xbroken up into its components, Xone per line. X.PP XThis new version of the X.I which Xcommand is not a X.I csh Xscript. XBeing an executable it is much faster, and not sourcing X.I .cshrc Xit gives a true picture of one's X.I aliases. X.SH EXAMPLE X.ft B X.nf X% alias Xwhich alias !$ | /usr/local/bin/which \-i !* X% which which Xwhich alias !$ | /usr/local/bin/which \-i !* X% which \-a which Xwhich alias !$ | /usr/local/bin/which \-i !* X/usr/local/bin/which X/usr/ucb/which X% X.fi X.ft R X.SH AUTHOR XMaarten Litmaath @ VU Informatika Amsterdam + END-OF-FILE which.1 chmod 'u=rw,g=r,o=r' 'which.1' set `wc -c 'which.1'` count=$1 case $count in 2205) :;; *) echo 'Bad character count in ''which.1' >&2 echo 'Count should be 2205' >&2 esac echo Extracting 'which.c' sed 's/^X//' > 'which.c' << '+ END-OF-FILE ''which.c' X/* X * which [-i] [-a] [--] [<command>] X * alias which alias !\$ \| /usr/local/bin/which -i !\* X * alias which 'eval alias \$$# | /usr/local/bin/which -i ${1+"$@"}' X * which() X * { X * eval last=\"\$$#\" X * set | sed -n "/^$last(){$/,/^}$/p" | X * /usr/local/bin/which -i ${1+"$@"} X * } X * X * author: Maarten Litmaath @ VU University Amsterdam (maart@cs.vu.nl) X * first change: X * Emile LeBlanc (leblanc%math.Berkeley.EDU@ucbvax.berkeley.edu) notes X * the access() system call considering everything executable for X * root (!), so we give root a special treatment X * 'which', 'which -i' and 'which -a' with no further arguments now X * return the PATH environment variable, split up into its components X * the aliases defined above are slightly different from the previous X * version - now it's the shell who's doing the alias checking X * second change: X * added support for shell functions and multiline aliases, added the X * `--' option, changed the source style X */ X X#include <sys/types.h> X#include <sys/stat.h> X#include <stdio.h> X X#define BUF_SIZE 512 X Xchar Version[] = X "@(#)which 3.0 89/09/21 Maarten Litmaath @ VU Informatika Amsterdam"; Xchar *Prog; X X Xvoid usage() X{ X fprintf(stderr, "Usage: %s [-i] [-a] [--] [<command>]\n", Prog); X exit(1); X} X X Xmain(argc, argv) Xint argc; Xregister char **argv; X{ X register char *path, *s; X char *save, *strcpy(), *getenv(), *fgets(), buf[BUF_SIZE]; X int all = 0, inter = 0, stop = 0, found = 0, uid; X struct stat st; X void usage(), convert(); X X X Prog = *argv++; X --argc; X X while (!stop && (s = *argv) && (*s == '-')) { X ++argv; X --argc; X ++s; X while (*s) X switch (*s++) { X case 'a': X all = 1; X break; X case 'i': X inter = 1; X break; X case '-': X stop = 1; X break; X default: X usage(); X } X } X X if (argc > 1) X usage(); X X if (inter && *argv) { X while (fgets(buf, sizeof buf, stdin)) { X if (!found) { X printf("%s", *argv); X found = 1; X } X printf("\t%s", buf); X } X if (found && !all) X exit(0); X } X X if (!(save = path = getenv("PATH"))) { X fprintf(stderr, "%s: no PATH in environment!\n", Prog); X exit(1); X } X X if (!*path) X save = path = "."; X X if (!*argv) { X convert(path, buf); X puts(buf); X exit(0); X } X X uid = getuid(); X X while (*path) { X s = buf; X while ((*s++ = *path) && *path++ != ':') X ; X if (*buf == ':') { X /* X * to deal with the dubious convention that a spurious X * colon is equivalent to a dot... X */ X *buf = '.'; X ++s; X } X (void) strcpy(s, *argv); X *--s = '/'; X if (stat(buf, &st) != 0 || (st.st_mode & S_IFMT) != S_IFREG) X continue; X X /* file exists and is regular */ X X if (uid == 0 ? !(st.st_mode & 0111) : access(buf, 1) != 0) X continue; X X /* file is executable */ X X *s = 0; X if (uid == 0 && stat(buf, &st) != 0) { X perror(buf); X continue; X } X X if (uid == 0 ? !(st.st_mode & 0444) : access(buf, 4) != 0) { X fprintf(stderr, X "%s: %s found in unreadable directory %s!\n", X Prog, *argv, buf); X continue; X } X X /* directory is readable */ X X *s = '/'; X puts(buf); X if (!all) X exit(0); X found = 1; X } X X if (found) X exit(0); X X convert(save, buf); X fprintf(stderr, "%s not found in\n%s\n", *argv, buf); X exit(1); X} X X Xvoid convert(path, buf) Xregister char *path, *buf; X{ X for (;;) { X while ((*buf++ = *path) && *path++ != ':') X ; X if (!*path) X break; X *buf++ = '\n'; X } X *buf = '\0'; /* to cope with a PATH ending in ':' */ X} + END-OF-FILE which.c chmod 'u=rw,g=r,o=r' 'which.c' set `wc -c 'which.c'` count=$1 case $count in 3392) :;; *) echo 'Bad character count in ''which.c' >&2 echo 'Count should be 3392' >&2 esac exit 0 -- 1755 EST, Dec 14, 1992: Henry Spencer is put on a one-way mission to the moon.| Maarten Litmaath @ VU Amsterdam: maart@cs.vu.nl, uunet!mcsun!botter!maart