home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume05 / which2.v2 < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  7.1 KB

  1. From decwrl!labrea!rutgers!ukma!cwjcc!hal!ncoast!allbery Sun Oct 30 15:06:39 PST 1988
  2. Article 693 of comp.sources.misc:
  3. Path: granite!decwrl!labrea!rutgers!ukma!cwjcc!hal!ncoast!allbery
  4. From: maart@cs.vu.nl.UUCP (Maarten Litmaath)
  5. Newsgroups: comp.sources.misc
  6. Subject: v05i016: which2 version 2 (includes bug-fix)
  7. Message-ID: <8810261300.aa18153@star.cs.vu.nl>
  8. Date: 28 Oct 88 02:50:24 GMT
  9. Sender: allbery@ncoast.UUCP
  10. Reply-To: maart@cs.vu.nl.UUCP (Maarten Litmaath)
  11. Lines: 338
  12. Approved: allbery@ncoast.UUCP
  13.  
  14. Posting-number: Volume 5, Issue 16
  15. Submitted-by: "Maarten Litmaath" <maart@cs.vu.nl.UUCP>
  16. Archive-name: which2-v2
  17.  
  18. Dear moderator, included below is the new and enhanced version of `which2'.
  19. I think the comments in the source header and the manual describe the
  20. changes clearly. This version is to supersede the previous one.
  21. Special thanks to Emile LeBlanc for catching the bug and testing the fix.
  22. Thanks for your attention.
  23. Regards & enjoy!
  24.                 Maarten Litmaath @ VU Amsterdam:
  25.                 maart@cs.vu.nl, mcvax!botter!maart
  26.  
  27. : This is a shar archive.  Extract with sh, not csh.
  28. : This archive ends with exit, so do not worry about trailing junk.
  29. : --------------------------- cut here --------------------------
  30. PATH=/bin:/usr/bin:/usr/ucb
  31. echo Extracting 'which.c'
  32. sed 's/^X//' > 'which.c' << '+ END-OF-FILE ''which.c'
  33. X/*
  34. X * [alias <command> |] which [-i] [-a] [<command>]
  35. X * alias which alias !\$ \| /usr/local/bin/which -i !\*
  36. X * alias which eval alias '\$$# |' /usr/local/bin/which -i $\*
  37. X *
  38. X * author: Maarten Litmaath @ Free U Amsterdam (maart@cs.vu.nl)
  39. X * first change:
  40. X *    Emile LeBlanc (leblanc%math.Berkeley.EDU@ucbvax.berkeley.edu) notes
  41. X *    the access() system call considering everything executable for
  42. X *    root (!), so we give root a special treatment
  43. X *    'which', 'which -i' and 'which -a' with no further arguments now
  44. X *    return the PATH environment variable, split up into its components
  45. X *    the aliases defined above are slightly different from the previous
  46. X *    version - now it's the shell who's doing the alias checking
  47. X */
  48. X
  49. X#include    <sys/types.h>
  50. X#include    <sys/stat.h>
  51. X#include    <stdio.h>
  52. X
  53. X#define        BUF_SIZE    512
  54. X
  55. Xchar    E_usage[] = "Usage: [alias <command> |] %s [-i] [-a] [<command>]\n",
  56. X    E_read[] = "%s - read error in ",
  57. X    E_path[] = "no PATH in environment!\n",
  58. X    E_dir[] = "%s found in unreadable directory %s!\n",
  59. X    E_notfound[] = "%s not found in\n%s\n",
  60. X    *prog;
  61. Xint    uid;
  62. X
  63. X
  64. Xmain(argc, argv) 
  65. Xint    argc;
  66. Xregister char    **argv;
  67. X{
  68. X    register char    *path, *s;
  69. X    char    *save, *strcpy(), *getenv(), *gets(), buf[BUF_SIZE];
  70. X    int    all = 0, inter = 0, found = 0;
  71. X    struct    stat    st;
  72. X    void    usage(), convert();
  73. X
  74. X
  75. X    prog = *argv++;
  76. X
  77. X    if (argc > 4)
  78. X        usage();
  79. X
  80. X    while (--argc > 1) {
  81. X        s = *argv++;
  82. X        if (*s++ != '-')
  83. X            usage();
  84. X        while (*s)
  85. X            switch (*s++) {
  86. X                case 'a':
  87. X                    all = 1;
  88. X                    break;
  89. X                case 'i':
  90. X                    inter = 1;
  91. X                    break;
  92. X                default:
  93. X                    usage();
  94. X            }
  95. X    }
  96. X
  97. X    if (inter) {
  98. X        if (gets(buf) && *buf != '\n') {
  99. X            printf("%s\t%s\n", *argv, buf);
  100. X            if (!all)
  101. X                exit(0);
  102. X            found = 1;
  103. X        }
  104. X        if (ferror(stdin)) {
  105. X            fprintf(stderr, E_read, prog);
  106. X            perror("stdin");
  107. X            exit(1);
  108. X        }
  109. X    }
  110. X
  111. X    if (!(save = path = getenv("PATH"))) {
  112. X        fprintf(stderr, E_path);
  113. X        exit(1);
  114. X    }
  115. X
  116. X    if (!*path)
  117. X        save = path = ".";
  118. X
  119. X    if (argc == 0) {
  120. X        convert(path, buf);
  121. X        puts(buf);
  122. X        exit(0);
  123. X    }
  124. X
  125. X    if (**argv == '-' && (*argv)[1] && !(*argv)[2])
  126. X        switch ((*argv)[1]) {
  127. X            case 'i':
  128. X            case 'a':
  129. X                convert(path, buf);
  130. X                puts(buf);
  131. X                exit(0);
  132. X        }
  133. X
  134. X    uid = getuid();
  135. X
  136. X    while (*path) {
  137. X        s = buf;
  138. X        while ((*s++ = *path) && *path++ != ':')
  139. X            ;
  140. X        if (*buf == ':') {
  141. X            /*
  142. X             * to deal with the dubious convention that a spurious
  143. X             * colon is equivalent to a dot...
  144. X             */
  145. X            *buf = '.';
  146. X            ++s;
  147. X        }
  148. X        (void) strcpy(s, *argv);
  149. X        *--s = '/';
  150. X        if (stat(buf, &st) != 0 || (st.st_mode & S_IFMT) != S_IFREG)
  151. X            continue;
  152. X
  153. X        /* file exists and is regular */
  154. X
  155. X        if (uid == 0 ? !(st.st_mode & 0111) : access(buf, 1) != 0)
  156. X            continue;
  157. X
  158. X        /* file is executable */
  159. X
  160. X        *s = 0;
  161. X        if (uid == 0 && stat(buf, &st) != 0) {
  162. X            perror(buf);
  163. X            continue;
  164. X        }
  165. X
  166. X        if (uid == 0 ? !(st.st_mode & 0444) : access(buf, 4) != 0) {
  167. X            fprintf(stderr, E_dir, *argv, buf);
  168. X            continue;
  169. X        }
  170. X
  171. X        /* directory is readable */
  172. X
  173. X        *s = '/';
  174. X        puts(buf);
  175. X        if (!all)
  176. X            exit(0);
  177. X        found = 1;
  178. X    }
  179. X
  180. X    if (found)
  181. X        exit(0);
  182. X
  183. X    convert(save, buf);
  184. X    fprintf(stderr, E_notfound, *argv, buf);
  185. X    exit(1);
  186. X}
  187. X
  188. X
  189. Xvoid    usage()
  190. X{
  191. X    fprintf(stderr, E_usage, prog);
  192. X    exit(1);
  193. X}
  194. X
  195. X
  196. Xvoid    convert(path, buf)
  197. Xregister char    *path, *buf;
  198. X{
  199. X    for (;;) {
  200. X        while ((*buf++ = *path) && *path++ != ':')
  201. X            ;
  202. X        if (!*path)
  203. X            break;
  204. X        *buf++ = '\n';
  205. X    }
  206. X    *buf = '\0';        /* to cope with a PATH ending in ':' */
  207. X}
  208. + END-OF-FILE which.c
  209. chmod 'u=rw,g=r,o=r' 'which.c'
  210. set `wc -c 'which.c'`
  211. count=$1
  212. case $count in
  213. 3306)    :;;
  214. *)    echo 'Bad character count in ''which.c' >&2
  215.         echo 'Count should be 3306' >&2
  216. esac
  217. echo Extracting 'which.1'
  218. sed 's/^X//' > 'which.1' << '+ END-OF-FILE ''which.1'
  219. X.TH WHICH 1 Oct\ 3\ 1988
  220. X.SH NAME
  221. Xwhich \- give alias or path expansion of command
  222. X.SH SYNOPSIS
  223. X.B which
  224. X[
  225. X.B \-i
  226. X] [
  227. X.B \-a
  228. X] [
  229. X.I command
  230. X]
  231. X.SH DESCRIPTION
  232. X.B Which
  233. Xprovides the user with the full expansion of the
  234. X.I command
  235. Xargument, be it either an
  236. X.I alias
  237. Xor an executable file (default). To enable search for
  238. X.I aliases
  239. Xthe user should supply the
  240. X.B \-i
  241. X(= interactive) flag. In that case
  242. X.B which
  243. Xexpects as standard input the output of an
  244. X.I alias
  245. Xcommand. This demand is easily met by setting an
  246. X.I alias
  247. Xlike the following:
  248. X.br
  249. X
  250. X.br
  251. X.RS
  252. X.B alias \t which \t \\\\
  253. X.RS
  254. X.B
  255. Xalias !\\$ \\| /usr/local/bin/which \-i !\\*
  256. X.RE
  257. X.RE
  258. X.br
  259. X
  260. X.br
  261. Xin
  262. X.I csh,
  263. Xor
  264. X.br
  265. X
  266. X.br
  267. X.RS
  268. X.B alias \t which \t \\\\
  269. X.RS
  270. X.B
  271. Xeval alias '\\$$# |' /usr/local/bin/which \-i $\\*
  272. X.RE
  273. X.RE
  274. X.br
  275. X
  276. X.br
  277. Xin shells which are supersets of
  278. X.I sh.
  279. X.sp
  280. XIf the
  281. X.B \-i
  282. Xflag is not supplied, only the user's
  283. X.I PATH
  284. Xis searched for the
  285. X.I command.
  286. XIf the
  287. X.B \-a
  288. X(= all) flag is given,
  289. X.B which
  290. Xwill not stop after the first 'match', but search for all occurrences of
  291. X.I command
  292. Xin the user's
  293. X.I PATH.
  294. X.B Which [-i | -a]
  295. Xwithout further argument prints the user's
  296. X.I PATH
  297. Xbroken up into its components,
  298. Xone per line.
  299. X.PP
  300. XThis new version of the
  301. X.I which
  302. Xcommand is not a
  303. X.I csh
  304. Xscript.
  305. XBeing an executable it is much faster, and not sourcing 
  306. X.I .cshrc
  307. Xit gives a true picture of one's
  308. X.I aliases
  309. Xand can be used safely between backquotes, like:
  310. X.sp
  311. X.RS
  312. X.B
  313. X$ file `which which`
  314. X.br
  315. X.B /usr/local/bin/which: pure executable
  316. X.br
  317. X.B $
  318. X.RE
  319. X.SH EXAMPLE
  320. X.B % alias
  321. X.br
  322. X.B which \t alias !$ | /usr/local/bin/which
  323. X.B \-i !*
  324. X.br
  325. X.B % which which
  326. X.br
  327. X.B which \t alias !$ | /usr/local/bin/which
  328. X.B \-i !*
  329. X.br
  330. X.B % which \-a which
  331. X.br
  332. X.B which \t alias !$ | /usr/local/bin/which
  333. X.B \-i !*
  334. X.br
  335. X.B /usr/local/bin/which
  336. X.br
  337. X.B /usr/ucb/which
  338. X.br
  339. X.B %
  340. X.SH AUTHOR
  341. XMaarten Litmaath @ Free University Amsterdam
  342. + END-OF-FILE which.1
  343. chmod 'u=rw,g=r,o=r' 'which.1'
  344. set `wc -c 'which.1'`
  345. count=$1
  346. case $count in
  347. 1852)    :;;
  348. *)    echo 'Bad character count in ''which.1' >&2
  349.         echo 'Count should be 1852' >&2
  350. esac
  351. exit 0
  352.  
  353.  
  354.