home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume10
/
which4
< prev
next >
Wrap
Text File
|
1990-02-13
|
9KB
|
379 lines
Newsgroups: comp.sources.misc
subject: v10i064: which4 - supersedes fast which2.c
From: maart@cs.vu.nl (Maarten Litmaath)
Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
Posting-number: Volume 10, Issue 64
Submitted-by: maart@cs.vu.nl (Maarten Litmaath)
Archive-name: which4
Dear moderator,
below is the latest version of which2.c, the fast form of the which(1)
command. Besides aliases and executables, shell functions are now
recognized too. Furthermore the output will be correct even if the
effective uid (gid) of the invoker doesn't equal the real uid (gid).
An updated manual is included.
I suggest the previous 2 versions (v04i010, v05i016) to be deleted from
the archives, or to be replaced with pointers to which4.
Thanks for your time,
Maarten Litmaath @ VU Amsterdam:
maart@cs.vu.nl, uunet!mcsun!botter!maart
: 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 '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 'Makefile'
sed 's/^X//' > 'Makefile' << '+ END-OF-FILE ''Makefile'
X# Makefile for /usr/local/bin/which
X
Xwhich: which4.c
X cc -O which4.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
169) :;;
*) echo 'Bad character count in ''Makefile' >&2
echo 'Count should be 169' >&2
esac
echo Extracting 'which4.c'
sed 's/^X//' > 'which4.c' << '+ END-OF-FILE ''which4.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 * third change:
X * to hell with access()!
X * now stat() is used to give the right answer even if the effective
X * uid (gid) differs from the real uid (gid)
X * we can't use setuid(geteuid()), because that's nonportable :-(
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <stdio.h>
X
X#define BUF_SIZE 512
X#define M_USR 0700
X#define M_GRP 0070
X#define M_OTH 0007
X#define X_ALL 0111
X#define R_ALL 0444
X
Xchar Version[] =
X "@(#)which 4.0 90/01/24 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, gid, mask,
X xmask, rmask;
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 = geteuid();
X gid = getegid();
X if (uid == 0) {
X xmask = X_ALL;
X rmask = R_ALL;
X }
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
X * spurious colon is equivalent to a dot...
X */
X *buf = '.';
X ++s;
X }
X (void) strcpy(s, *argv);
X *--s = '/';
X
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) {
X mask = st.st_uid == uid ? M_USR :
X st.st_gid == gid ? M_GRP : M_OTH;
X xmask = X_ALL & mask;
X rmask = R_ALL & mask;
X }
X
X if (!(st.st_mode & xmask))
X continue;
X
X /* file is executable */
X
X *s = 0;
X if (stat(buf, &st) != 0) {
X perror(buf);
X continue;
X }
X
X if (!(st.st_mode & rmask)) {
X fprintf(stderr,
X "%s: %s found in unreadable directory %s!\n",
X Prog, *argv, buf);
X found = 1;
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 which4.c
chmod 'u=rw,g=r,o=r' 'which4.c'
set `wc -c 'which4.c'`
count=$1
case $count in
3907) :;;
*) echo 'Bad character count in ''which4.c' >&2
echo 'Count should be 3907' >&2
esac
exit 0