home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume10 / which4 < prev   
Encoding:
Internet Message Format  |  1991-08-27  |  8.6 KB

  1. From decwrl!lll-winken!uunet!allbery Sun Feb 18 00:49:59 PST 1990
  2. Article 1335 of comp.sources.misc:
  3. Path: decwrl!lll-winken!uunet!allbery
  4. From: maart@cs.vu.nl (Maarten Litmaath)
  5. Newsgroups: comp.sources.misc
  6. Subject: v10i064: which4 - supersedes fast which2.c
  7. Message-ID: <78923@uunet.UU.NET>
  8. Date: 14 Feb 90 02:02:15 GMT
  9. Sender: allbery@uunet.UU.NET
  10. Lines: 373
  11. Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  12.  
  13. Posting-number: Volume 10, Issue 64
  14. Submitted-by: maart@cs.vu.nl (Maarten Litmaath)
  15. Archive-name: which4
  16.  
  17. Dear moderator,
  18. below is the latest version of which2.c, the fast form of the which(1)
  19. command.  Besides aliases and executables, shell functions are now
  20. recognized too.  Furthermore the output will be correct even if the
  21. effective uid (gid) of the invoker doesn't equal the real uid (gid).
  22.  
  23. An updated manual is included.
  24.  
  25. I suggest the previous 2 versions (v04i010, v05i016) to be deleted from
  26. the archives, or to be replaced with pointers to which4.
  27.  
  28. Thanks for your time,
  29.                 Maarten Litmaath @ VU Amsterdam:
  30.                 maart@cs.vu.nl, uunet!mcsun!botter!maart
  31.  
  32. : This is a shar archive.  Extract with sh, not csh.
  33. : This archive ends with exit, so do not worry about trailing junk.
  34. : --------------------------- cut here --------------------------
  35. PATH=/bin:/usr/bin:/usr/ucb
  36. echo Extracting 'which.1'
  37. sed 's/^X//' > 'which.1' << '+ END-OF-FILE ''which.1'
  38. X.TH WHICH 1 Sep\ 21\ 1989
  39. X.SH NAME
  40. Xwhich \- give alias, function or path expansion of command
  41. X.SH SYNOPSIS
  42. X.B which
  43. X[
  44. X.B \-i
  45. X] [
  46. X.B \-a
  47. X] [
  48. X.B \-\-
  49. X] [
  50. X.I command
  51. X]
  52. X.SH DESCRIPTION
  53. X.I Which
  54. Xprovides the user with the full expansion of the
  55. X.I command
  56. Xargument, be it either an \fIalias\fR, a \fIshell function\fR
  57. Xor an executable file (default). To enable search for
  58. X.I aliases
  59. Xand \fIshell functions\fR
  60. Xthe user should supply the `\fI\-i\fR'
  61. X(= interactive) flag. In that case
  62. X.I which
  63. Xexpects as standard input the expansion of the \fIalias\fR
  64. Xor \fIshell function\fR.
  65. XIf the standard input is empty or the `\fI\-i\fR' flag has not been
  66. Xgiven, \fIwhich\fR will try to locate \fIcommand\fR
  67. Xin the user's \fIPATH\fR.
  68. XThe interactive mode is easily used by setting an
  69. X.I alias
  70. Xlike the following:
  71. X.ft B
  72. X.nf
  73. X
  74. X    alias    which    alias !\\$ \\| /usr/local/bin/which \-i !\\*
  75. X
  76. X.fi
  77. X.ft R
  78. Xin \fIcsh\fR, or
  79. X.ft B
  80. X.nf
  81. X
  82. X    alias    which    eval alias '\\"\\$$#\\" |' \\
  83. X            /usr/local/bin/which \-i '${1+"$@"}'
  84. X
  85. X.fi
  86. X.ft R
  87. Xin shells which are supersets of
  88. X.I sh
  89. Xand which know \fIaliases\fR. If your shell has \fIshell functions\fR, you
  90. Xcan use the following function:
  91. X.ft B
  92. X.nf
  93. X
  94. X    which()
  95. X    {
  96. X        eval last=\\"\\$$#\\"
  97. X        set | sed \-n "/^$last(){$/,/^}$/p" |
  98. X            /usr/local/bin/which \-i ${1+"$@"}
  99. X    }
  100. X
  101. X.fi
  102. X.ft R
  103. XIf the `\fI\-a\fR' (= all) flag is given,
  104. X.I which
  105. Xwill not stop after the first `match', but search for all occurrences of
  106. X.I command
  107. Xin the user's
  108. X.I PATH.
  109. XThe `\fI\-\-\fR'
  110. Xflag can be used to end the list of options: the next argument (if present)
  111. Xwill be taken as \fIcommand\fR, even if it starts with a `\-'.
  112. X\fIWhich [\-i] [\-a] [\-\-]\fR
  113. Xwithout further arguments prints the user's
  114. X.I PATH
  115. Xbroken up into its components,
  116. Xone per line.
  117. X.PP
  118. XThis new version of the
  119. X.I which
  120. Xcommand is not a
  121. X.I csh
  122. Xscript.
  123. XBeing an executable it is much faster, and not sourcing 
  124. X.I .cshrc
  125. Xit gives a true picture of one's
  126. X.I aliases.
  127. X.SH EXAMPLE
  128. X.ft B
  129. X.nf
  130. X% alias
  131. Xwhich    alias !$ | /usr/local/bin/which \-i !*
  132. X% which which
  133. Xwhich    alias !$ | /usr/local/bin/which \-i !*
  134. X% which \-a which
  135. Xwhich    alias !$ | /usr/local/bin/which \-i !*
  136. X/usr/local/bin/which
  137. X/usr/ucb/which
  138. X%
  139. X.fi
  140. X.ft R
  141. X.SH AUTHOR
  142. XMaarten Litmaath @ VU Informatika Amsterdam
  143. + END-OF-FILE which.1
  144. chmod 'u=rw,g=r,o=r' 'which.1'
  145. set `wc -c 'which.1'`
  146. count=$1
  147. case $count in
  148. 2205)    :;;
  149. *)    echo 'Bad character count in ''which.1' >&2
  150.         echo 'Count should be 2205' >&2
  151. esac
  152. echo Extracting 'Makefile'
  153. sed 's/^X//' > 'Makefile' << '+ END-OF-FILE ''Makefile'
  154. X# Makefile for /usr/local/bin/which
  155. X
  156. Xwhich:        which4.c
  157. X        cc -O which4.c -o which
  158. X
  159. Xinstall:    which
  160. X        /bin/mv -f which /usr/local/bin
  161. X
  162. Xdoc:
  163. X        nroff -man which.1 > which.man
  164. + END-OF-FILE Makefile
  165. chmod 'u=rw,g=r,o=r' 'Makefile'
  166. set `wc -c 'Makefile'`
  167. count=$1
  168. case $count in
  169. 169)    :;;
  170. *)    echo 'Bad character count in ''Makefile' >&2
  171.         echo 'Count should be 169' >&2
  172. esac
  173. echo Extracting 'which4.c'
  174. sed 's/^X//' > 'which4.c' << '+ END-OF-FILE ''which4.c'
  175. X/*
  176. X * which [-i] [-a] [--] [<command>]
  177. X * alias which alias !\$ \| /usr/local/bin/which -i !\*
  178. X * alias which 'eval alias \$$# | /usr/local/bin/which -i ${1+"$@"}'
  179. X * which()
  180. X * {
  181. X *    eval last=\"\$$#\"
  182. X *    set | sed -n "/^$last(){$/,/^}$/p" |
  183. X *        /usr/local/bin/which -i ${1+"$@"}
  184. X * }
  185. X *
  186. X * author: Maarten Litmaath @ VU University Amsterdam (maart@cs.vu.nl)
  187. X * first change:
  188. X *    Emile LeBlanc (leblanc%math.Berkeley.EDU@ucbvax.berkeley.edu) notes
  189. X *    the access() system call considering everything executable for
  190. X *    root (!), so we give root a special treatment
  191. X *    'which', 'which -i' and 'which -a' with no further arguments now
  192. X *    return the PATH environment variable, split up into its components
  193. X *    the aliases defined above are slightly different from the previous
  194. X *    version - now it's the shell who's doing the alias checking
  195. X * second change:
  196. X *    added support for shell functions and multiline aliases, added the
  197. X *    `--' option, changed the source style
  198. X * third change:
  199. X *    to hell with access()!
  200. X *    now stat() is used to give the right answer even if the effective
  201. X *    uid (gid) differs from the real uid (gid)
  202. X *    we can't use setuid(geteuid()), because that's nonportable :-(
  203. X */
  204. X
  205. X#include    <sys/types.h>
  206. X#include    <sys/stat.h>
  207. X#include    <stdio.h>
  208. X
  209. X#define        BUF_SIZE    512
  210. X#define        M_USR        0700
  211. X#define        M_GRP        0070
  212. X#define        M_OTH        0007
  213. X#define        X_ALL        0111
  214. X#define        R_ALL        0444
  215. X
  216. Xchar    Version[] =
  217. X    "@(#)which 4.0 90/01/24 Maarten Litmaath @ VU Informatika Amsterdam";
  218. Xchar    *Prog;
  219. X
  220. X
  221. Xvoid    usage()
  222. X{
  223. X    fprintf(stderr, "Usage: %s [-i] [-a] [--] [<command>]\n", Prog);
  224. X    exit(1);
  225. X}
  226. X
  227. X
  228. Xmain(argc, argv) 
  229. Xint    argc;
  230. Xregister char    **argv;
  231. X{
  232. X    register char    *path, *s;
  233. X    char    *save, *strcpy(), *getenv(), *fgets(), buf[BUF_SIZE];
  234. X    int    all = 0, inter = 0, stop = 0, found = 0, uid, gid, mask,
  235. X        xmask, rmask;
  236. X    struct    stat    st;
  237. X    void    usage(), convert();
  238. X
  239. X
  240. X    Prog = *argv++;
  241. X    --argc;
  242. X
  243. X    while (!stop && (s = *argv) && (*s == '-')) {
  244. X        ++argv;
  245. X        --argc;
  246. X        ++s;
  247. X        while (*s)
  248. X            switch (*s++) {
  249. X            case 'a':
  250. X                all = 1;
  251. X                break;
  252. X            case 'i':
  253. X                inter = 1;
  254. X                break;
  255. X            case '-':
  256. X                stop = 1;
  257. X                break;
  258. X            default:
  259. X                usage();
  260. X            }
  261. X    }
  262. X
  263. X    if (argc > 1)
  264. X        usage();
  265. X
  266. X    if (inter && *argv) {
  267. X        while (fgets(buf, sizeof buf, stdin)) {
  268. X            if (!found) {
  269. X                printf("%s", *argv);
  270. X                found = 1;
  271. X            }
  272. X            printf("\t%s", buf);
  273. X        }
  274. X        if (found && !all)
  275. X            exit(0);
  276. X    }
  277. X
  278. X    if (!(save = path = getenv("PATH"))) {
  279. X        fprintf(stderr, "%s: no PATH in environment!\n", Prog);
  280. X        exit(1);
  281. X    }
  282. X
  283. X    if (!*path)
  284. X        save = path = ".";
  285. X
  286. X    if (!*argv) {
  287. X        convert(path, buf);
  288. X        puts(buf);
  289. X        exit(0);
  290. X    }
  291. X
  292. X    uid = geteuid();
  293. X    gid = getegid();
  294. X    if (uid == 0) {
  295. X        xmask = X_ALL;
  296. X        rmask = R_ALL;
  297. X    }
  298. X
  299. X    while (*path) {
  300. X        s = buf;
  301. X        while ((*s++ = *path) && *path++ != ':')
  302. X            ;
  303. X        if (*buf == ':') {
  304. X            /*
  305. X             * to deal with the dubious convention that a
  306. X             * spurious colon is equivalent to a dot...
  307. X             */
  308. X            *buf = '.';
  309. X            ++s;
  310. X        }
  311. X        (void) strcpy(s, *argv);
  312. X        *--s = '/';
  313. X
  314. X        if (stat(buf, &st) != 0 || (st.st_mode & S_IFMT) != S_IFREG)
  315. X            continue;
  316. X
  317. X        /* file exists and is regular */
  318. X
  319. X        if (uid != 0) {
  320. X            mask = st.st_uid == uid ? M_USR :
  321. X                st.st_gid == gid ? M_GRP : M_OTH;
  322. X            xmask = X_ALL & mask;
  323. X            rmask = R_ALL & mask;
  324. X        }
  325. X
  326. X        if (!(st.st_mode & xmask))
  327. X            continue;
  328. X
  329. X        /* file is executable */
  330. X
  331. X        *s = 0;
  332. X        if (stat(buf, &st) != 0) {
  333. X            perror(buf);
  334. X            continue;
  335. X        }
  336. X
  337. X        if (!(st.st_mode & rmask)) {
  338. X            fprintf(stderr,
  339. X                "%s: %s found in unreadable directory %s!\n",
  340. X                Prog, *argv, buf);
  341. X            found = 1;
  342. X            continue;
  343. X        }
  344. X
  345. X        /* directory is readable */
  346. X
  347. X        *s = '/';
  348. X        puts(buf);
  349. X        if (!all)
  350. X            exit(0);
  351. X        found = 1;
  352. X    }
  353. X
  354. X    if (found)
  355. X        exit(0);
  356. X
  357. X    convert(save, buf);
  358. X    fprintf(stderr, "%s not found in\n%s\n", *argv, buf);
  359. X    exit(1);
  360. X}
  361. X
  362. X
  363. Xvoid    convert(path, buf)
  364. Xregister char    *path, *buf;
  365. X{
  366. X    for (;;) {
  367. X        while ((*buf++ = *path) && *path++ != ':')
  368. X            ;
  369. X        if (!*path)
  370. X            break;
  371. X        *buf++ = '\n';
  372. X    }
  373. X    *buf = '\0';        /* to cope with a PATH ending in ':' */
  374. X}
  375. + END-OF-FILE which4.c
  376. chmod 'u=rw,g=r,o=r' 'which4.c'
  377. set `wc -c 'which4.c'`
  378. count=$1
  379. case $count in
  380. 3907)    :;;
  381. *)    echo 'Bad character count in ''which4.c' >&2
  382.         echo 'Count should be 3907' >&2
  383. esac
  384. exit 0
  385.  
  386.  
  387.