home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume5 / which2-v2 < prev    next >
Text File  |  1989-02-03  |  7KB  |  350 lines

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