[comp.sources.misc] v04i010: New version of fast which

maart@uunet.uu.net@cs.vu.nl.UUCP (Maarten Litmaath) (07/23/88)

Posting-number: Volume 4, Issue 10
Submitted-by: "Maarten Litmaath" <maart@uunet.uu.net@cs.vu.nl.UUCP>
Archive-name: which2

Here's yet another which(1). Its pluses compared to /usr/ucb/which and other
FAST versions, are described in the manual.  Enjoy!

: 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
echo Extracting \w\h\i\c\h\.\1
sed 's/^X//' > \w\h\i\c\h\.\1 << '+ END-OF-FILE '\w\h\i\c\h\.\1
X.TH WHICH 1 LOCAL
X.SH NAME
Xwhich \- give alias or path expansion of command
X.SH SYNOPSIS
X.B which
X[
X.B \-i
X] [
X.B \-a
X] 
X.I command
X.SH DESCRIPTION
X.B Which
Xprovides the user with the full expansion of the
X.I command
Xargument, be it either an
X.I alias
Xor an executable file (default). To enable search for
X.I aliases
Xthe user should supply the
X.B \-i
X(= interactive) flag. In that case
X.B which
Xexpects as standard input the output of the
X.I csh
X.I alias
Xcommand. This demand is easily met by setting an alias like the following:
X.IP
X.B
Xalias which alias \\| /usr/local/bin/which \-i
X.LP
X.sp
XIf the
X.B \-i
Xflag is not supplied, only the user's
X.I PATH
Xis searched for the
X.I command.
XIf the
X.B \-a
X(= all) flag is given,
X.B which
Xwill not stop after the first 'match', but search for all occurrences of
X.I command
Xin the user's
X.I PATH.
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
Xand can be safely used between backquotes, like:
X.sp
X.RS
X.B
X$ file `which which`
X.br
X.B /usr/local/bin/which: pure executable
X.br
X.B $
X.RE
X.SH EXAMPLE
X.B % alias
X.br
X.B which \t alias | /usr/local/bin/which \-i
X.br
X.B % which which
X.br
X.B which \t alias | /usr/local/bin/which \-i
X.br
X.B % which \-a which
X.br
X.B which \t alias | /usr/local/bin/which \-i
X.br
X.B /usr/local/bin/which
X.br
X.B /usr/ucb/which
X.br
X.B %
X.SH AUTHOR
XMaarten Litmaath
X.SH BUGS
XStrange behaviour occurs at power failures.
+ END-OF-FILE which.1
chmod 'u=rw,g=r,o=r' \w\h\i\c\h\.\1
set `sum \w\h\i\c\h\.\1`
sum=$1
case $sum in
52618)	:;;
*)	echo 'Bad sum in '\w\h\i\c\h\.\1 >&2
esac
echo Extracting \w\h\i\c\h\.\c
sed 's/^X//' > \w\h\i\c\h\.\c << '+ END-OF-FILE '\w\h\i\c\h\.\c
X/*
X * which [-a] [-i] <command>
X * alias which alias \| /usr/local/bin/which -i
X *
X * author: Maarten Litmaath @ Free U Amsterdam
X */
X
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	<stdio.h>
X
X#define		BUF_SIZE	512
X
Xchar	E_usage[] = "Usage: [alias |] %s [-a] [-i] <command>\n",
X	E_read[] = "%s - read error in ",
X	E_path[] = "no PATH in environment!\n",
X	E_dir[] = "%s found in unreadable directory %s!\n",
X	E_notfound[] = "%s not found\n",
X	*prog;
X
X
Xmain(argc, argv) 
Xint	argc;
Xregister char	**argv;
X{
X	register char	*path, *s;
X	char	*strcpy(), *getenv(), *gets(), buf[BUF_SIZE];
X	int	n, all = 0, inter = 0, found = 0;
X	struct	stat	st;
X	void	usage();
X
X
X	prog = *argv++;
X
X	if (argc < 2 || argc > 4)
X		usage();
X
X	if (--argc > 1) {
X		while (--argc) {
X			s = *argv++;
X			if (*s++ != '-')
X				usage();
X			while (*s)
X				switch (*s++) {
X					case 'a':
X						all = 1;
X						break;
X					case 'i':
X						inter = 1;
X						break;
X					default:
X						usage();
X				}
X		}
X		if (inter) {
X			n = strlen(*argv);
X			while (gets(buf))
X				if (buf[n] == '\t' &&
X					!strncmp(buf, *argv, n)) {
X					puts(buf);
X					if (!all)
X						exit(0);
X					found = 1;
X					break;
X				}
X			if (ferror(stdin)) {
X				fprintf(stderr, E_read, prog);
X				perror("stdin");
X				exit(1);
X			}
X		}
X	}
X
X	if (!(path = getenv("PATH"))) {
X		fprintf(stderr, E_path);
X		exit(1);
X	}
X
X	for ( ; *path; ) {
X		s = buf;
X		while ((*s++ = *path) && *path++ != ':')
X			;
X		(void) strcpy(s, *argv);
X		*--s = '/';
X		if (access(buf, 1) == 0) {	/* file is executable */
X			if (stat(buf, &st) == 0 && (st.st_mode & S_IFMT)
X				== S_IFREG) {	/* file is regular,   */
X				*s = 0;		/* is not a directory */
X				if (access(buf, 4) == 0) {  /* directory is */
X					*s = '/';	    /* readable     */
X					puts(buf);
X					if (!all)
X						exit(0);
X					found = 1;
X				}
X				else
X					fprintf(stderr, E_dir, *argv, buf);
X			}
X		}
X	}
X
X	if (found)
X		exit(0);
X
X	fprintf(stderr, E_notfound, *argv);
X	exit(1);
X}
X
X
Xvoid	usage()
X{
X	fprintf(stderr, E_usage, prog);
X	exit(1);
X}
+ END-OF-FILE which.c
chmod 'u=rw,g=r,o=r' \w\h\i\c\h\.\c
set `sum \w\h\i\c\h\.\c`
sum=$1
case $sum in
21648)	:;;
*)	echo 'Bad sum in '\w\h\i\c\h\.\c >&2
esac
exit 0
-- 
I'd rather live in Russia             |Maarten Litmaath @ Free U Amsterdam:
              than in South-Africa... |maart@cs.vu.nl, mcvax!hp4nl!botter!maart