home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / archie / part03 < prev    next >
Encoding:
Text File  |  1992-11-10  |  54.1 KB  |  1,726 lines

  1. Newsgroups: comp.sources.misc
  2. From: brendan@cygnus.com (Brendan Kehoe)
  3. Subject:  v33i052:  archie - A client to query the Archie FTP databases, v1.4.1, Part03/07
  4. Message-ID: <1992Nov5.210318.25087@sparky.imd.sterling.com>
  5. X-Md4-Signature: 144f81b4b4df854ffd011c1f61e373e1
  6. Date: Thu, 5 Nov 1992 21:03:18 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: brendan@cygnus.com (Brendan Kehoe)
  10. Posting-number: Volume 33, Issue 52
  11. Archive-name: archie/part03
  12. Environment: UNIX, VMS, DOS
  13. Supersedes: archie: Volume 27, Issue 79-84
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # Contents:  archie.c archie.el archie.lnk getopt.c
  20. # Wrapped by kent@sparky on Thu Nov  5 12:53:08 1992
  21. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 3 (of 7)."'
  24. if test -f 'archie.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'archie.c'\"
  26. else
  27.   echo shar: Extracting \"'archie.c'\" \(7386 characters\)
  28.   sed "s/^X//" >'archie.c' <<'END_OF_FILE'
  29. X/*
  30. X * Copyright (c) 1991 by the University of Washington
  31. X *
  32. X * For copying and distribution information, please see the file
  33. X * <copyright.h>.
  34. X */
  35. X
  36. X/*
  37. X * Archie client using the Prospero protocol.
  38. X *
  39. X * Suggestions and improvements to Brendan Kehoe (brendan@cygnus.com).
  40. X */
  41. X
  42. X#include <stdio.h>
  43. X#include <getopt.h>
  44. X
  45. X#if defined(OS2)
  46. X# include <pctcp.h>
  47. X#endif
  48. X
  49. X#ifdef MSDOS
  50. X# include <string.h>
  51. X# include <stdlib.h>
  52. X# ifdef CUTCP
  53. X#  include <msdos/cutcp.h>
  54. X#  include <msdos/hostform.h>
  55. X/* The default stack size for a BC program is 4k; jack it up to 16 and add the
  56. X   Check for Stack Overflow option to the compiler.  */
  57. Xextern unsigned _stklen = 16 * 1024;
  58. X# endif
  59. X#endif
  60. X
  61. X#include <pfs.h>
  62. X#include <rdgram.h>
  63. X#include <archie.h>
  64. X#include <pmachine.h>
  65. X
  66. X/* Whether we should produce single-line listings suitable for frobbing by
  67. X   other programs, or produce nice clean human output (default).  */
  68. Xint listflag = 0;
  69. X
  70. X/* How to sort the data; 1 means by date, 0 is by inverse hostname.  */
  71. Xint sortflag = 0;
  72. X
  73. X/* Used by CUTCP to see if they specified the host with `-h' or if
  74. X   the config.tel file should be consulted.  */ 
  75. Xint hostset = 0;
  76. X
  77. X/* When doing searches, should we make some comments to pacify the user?  */
  78. Xint verbose = 0;
  79. X
  80. X/* Maximum number of hits for this query; pushing this high is very
  81. X   anti-social.  */
  82. Xint max_hits = MAX_HITS;
  83. X
  84. X/* The offset for the Prospero query.  */
  85. Xint offset = 0;
  86. X
  87. X/* Display the Alex filename?  */
  88. Xint alex = 0;
  89. X
  90. X/* The default host to query for searches.  */ 
  91. Xchar *host = ARCHIE_HOST;
  92. X
  93. XFILE *archie_out;
  94. X
  95. X/* The name this program was run with.  */
  96. Xchar *program_name;
  97. X
  98. Xextern int pfs_debug;
  99. Xextern int rdgram_priority;
  100. X
  101. Xvoid usage ();
  102. Xextern char *getenv ();
  103. X
  104. Xvoid
  105. Xmain (argc, argv)
  106. X     int argc;
  107. X     char **argv;
  108. X{
  109. X  Query query = EXACT;
  110. X  int optc, tmp;
  111. X  /* If true, display the release.  */
  112. X  int exitflag = 0;
  113. X  /* The file to print the results to.  Defaults to stdout.  */
  114. X  char *outfile = (char *)NULL;
  115. X  char *p;
  116. X  static char *archies[] = { ARCHIES };
  117. X
  118. X  program_name = argv[0];
  119. X
  120. X  /* Default debugging level.  */
  121. X  pfs_debug = 0;
  122. X
  123. X#ifdef    CUTCP
  124. X  if (getenv ("CONFIGTEL"))
  125. X    if (Shostfile (getenv ("CONFIGTEL")) < 0)
  126. X      {
  127. X    fprintf (stderr, "Error, couldn't open configtel file %s\n",
  128. X         getenv ("CONFIGTEL"));
  129. X    exit (1);
  130. X      }
  131. X#endif
  132. X
  133. X  if ((p = getenv ("ARCHIE_HOST")) != (char *) NULL)
  134. X    host = p;
  135. X
  136. X#ifdef CUTCP
  137. X  while ((optc = getopt (argc, argv, "D:LHN::O:ceh:alm:o:rstvV")) != EOF)
  138. X#else
  139. X  while ((optc = getopt (argc, argv, "D:LN::O:ceh:alm:o:rstvV")) != EOF)
  140. X#endif
  141. X    {
  142. X      switch (optc)
  143. X    {
  144. X    case 'D':
  145. X      pfs_debug = atoi (optarg);
  146. X      break;
  147. X
  148. X    case 'L':
  149. X      printf ("Known archie servers:\n");
  150. X      for (tmp = 0; tmp < NARCHIES; tmp++)
  151. X        printf ("\t%s\n", archies[tmp]);
  152. X      printf (" * %s is the default Archie server.\n", ARCHIE_HOST);
  153. X      printf (" * For the most up-to-date list, write to an Archie server and give it\n   the command `servers'.\n");
  154. X      exitflag = 1;
  155. X      break;
  156. X
  157. X#ifdef CUTCP
  158. X    case 'H':
  159. X      if (Shostfile (optarg) < 0)
  160. X        {
  161. X          fprintf (stderr,
  162. X               "%s: couldn't open configtel file %s\n",
  163. X               program_name, optarg);
  164. X          exit (1);
  165. X        }
  166. X      break;
  167. X#endif
  168. X
  169. X    case 'N':
  170. X      if (optarg)
  171. X        {
  172. X          rdgram_priority = atoi (optarg);
  173. X          if (rdgram_priority > RDGRAM_MAX_SPRI)
  174. X        rdgram_priority = RDGRAM_MAX_PRI;
  175. X          else if (rdgram_priority < RDGRAM_MIN_PRI)
  176. X        rdgram_priority = RDGRAM_MIN_PRI;
  177. X        }
  178. X      else
  179. X        rdgram_priority = RDGRAM_MAX_PRI;
  180. X      break;
  181. X
  182. X    case 'c': /* Substring (case-sensitive).  */
  183. X      query = SUBSTRING_CASE;
  184. X      break;
  185. X
  186. X    case 'e': /* Exact match.  */
  187. X      query = EXACT;
  188. X      break;
  189. X
  190. X    case 'h': /* Archie host.  */
  191. X      host = optarg;
  192. X#ifdef CUTCP
  193. X      hostset = 1;
  194. X#endif
  195. X      break;
  196. X
  197. X    case 'a': /* List matches as Alex filenames.  */
  198. X      alex = 1;
  199. X      break;
  200. X
  201. X    case 'l': /* List one match per line.  */
  202. X      listflag = 1;
  203. X      break;
  204. X
  205. X    case 'm': /* Maximum number of hits for the query.  */
  206. X      max_hits = atoi (optarg);
  207. X      if (max_hits < 1)
  208. X        {
  209. X          fprintf (stderr,
  210. X               "%s: option `-m' requires a max hits value >= 1\n",
  211. X               program_name);
  212. X          exit (ERROR_EXIT);
  213. X        }
  214. X      break;
  215. X
  216. X    case 'o': /* output file */
  217. X      if (outfile)
  218. X        {
  219. X          fprintf (stderr, "%s: multiple output files specified\n",
  220. X               program_name);
  221. X          exit (ERROR_EXIT);
  222. X        }
  223. X      outfile = optarg;
  224. X      break;
  225. X
  226. X    case 'O': /* Specify the offset.  */
  227. X      offset = atoi (optarg);
  228. X      break;
  229. X
  230. X    case 'r': /* Regexp search.  */
  231. X      query = REGEXP;
  232. X      break;
  233. X
  234. X    case 's': /* Substring (case insensitive).  */
  235. X      query = SUBSTRING;
  236. X      break;
  237. X
  238. X    case 't': /* Sort inverted by date.  */
  239. X      sortflag = 1;
  240. X      break;
  241. X
  242. X    case 'v': /* Display version.  */
  243. X      fprintf (stderr,
  244. X           "Client version %s based upon Prospero version %s%s\n",
  245. X           CLIENT_VERSION,
  246. X#ifdef DEBUG
  247. X           PFS_RELEASE, " with debugging.");
  248. X#else
  249. X           PFS_RELEASE, ".");
  250. X#endif
  251. X      exitflag = 1;
  252. X      break;
  253. X
  254. X    case 'V': /* Verbose when search is happening.  */
  255. X      verbose = 1;
  256. X      break;
  257. X
  258. X    default:
  259. X      usage ();
  260. X    }
  261. X    }
  262. X
  263. X  if (exitflag)
  264. X    exit (0);
  265. X  else if (optind == argc)
  266. X    usage ();
  267. X  else if (alex && listflag)
  268. X    {
  269. X      fprintf (stderr, "%s: only one of `-a' or `-l' may be used\n",
  270. X           program_name);
  271. X      exit (ERROR_EXIT);
  272. X    }
  273. X
  274. X  if (outfile)
  275. X    {
  276. X      archie_out = fopen (outfile, "w+");
  277. X      if (archie_out == (FILE *) NULL)
  278. X    {
  279. X      fprintf (stderr, "%s: cannot open %s\n", program_name, outfile);
  280. X      exit (ERROR_EXIT);
  281. X    }
  282. X    }
  283. X  else
  284. X    archie_out = stdout;
  285. X
  286. X#ifdef    CUTCP
  287. X  if (tmp = Snetinit ())
  288. X    {
  289. X      fprintf (stderr, " %d from SNetinit (bad or missing config.tel ?)\n",
  290. X           tmp);
  291. X
  292. X      /* If there was a rarp lookup failure, shut the network card down.  */
  293. X      if (tmp == -2)
  294. X    netshut ();
  295. X      exit (ERROR_EXIT);
  296. X    }
  297. X
  298. X  if (!hostset)
  299. X    {
  300. X      /* Look in config.tel if they didn't give us a host with `-h'.  The
  301. X         entries appear as "name=archie".  */
  302. X      struct machinfo *mp = Shostlook ("archie");
  303. X
  304. X      if (mp)
  305. X    host = mp->hname ? mp->hname : mp->sname;
  306. X    }
  307. X#endif
  308. X
  309. X  for (; optind < argc; ++optind)
  310. X    procquery (host, argv[optind], max_hits, offset, query);
  311. X
  312. X#ifdef CUTCP
  313. X  netshut ();
  314. X#endif
  315. X
  316. X  if (outfile)
  317. X    fclose (archie_out);
  318. X
  319. X  exit (0);
  320. X}
  321. X
  322. X#ifdef CUTCP
  323. X# define HFLAG    "] [H config.tel]"
  324. X#else
  325. X# define HFLAG    "]"
  326. X#endif
  327. X
  328. Xvoid
  329. Xusage ()
  330. X{
  331. X  fprintf (stderr, "\
  332. XUsage: %s [-acelorstvLV] [-m hits%s [-N level] string\n", program_name, HFLAG);
  333. X  fprintf (stderr, "          -a : list matches as Alex filenames\n");
  334. X  fprintf (stderr, "          -c : case sensitive substring search\n");
  335. X  fprintf (stderr, "          -e : exact string match (default)\n");
  336. X  fprintf (stderr, "          -r : regular expression search\n");
  337. X  fprintf (stderr, "          -s : case insensitive substring search\n");
  338. X  fprintf (stderr, "          -l : list one match per line\n");
  339. X  fprintf (stderr, "          -t : sort inverted by date\n");
  340. X  fprintf (stderr, "     -m hits : specifies maximum number of hits to return (default %d)\n", max_hits);
  341. X  fprintf (stderr, " -o filename : specifies file to store results in\n");
  342. X  fprintf (stderr, "     -h host : specifies server host\n");
  343. X  fprintf (stderr, "          -L : list known servers and current default\n");
  344. X  fprintf (stderr, "    -N level : specifies query niceness level (0-35765)\n");
  345. X#ifdef CUTCP
  346. X  fprintf (stderr, "-H config.tel: specify location of config.tel file\n");
  347. X#endif
  348. X
  349. X  exit (ERROR_EXIT);
  350. X}
  351. X
  352. END_OF_FILE
  353.   if test 7386 -ne `wc -c <'archie.c'`; then
  354.     echo shar: \"'archie.c'\" unpacked with wrong size!
  355.   fi
  356.   # end of 'archie.c'
  357. fi
  358. if test -f 'archie.el' -a "${1}" != "-c" ; then 
  359.   echo shar: Will not clobber existing file \"'archie.el'\"
  360. else
  361.   echo shar: Extracting \"'archie.el'\" \(24212 characters\)
  362.   sed "s/^X//" >'archie.el' <<'END_OF_FILE'
  363. X;; Questions about this version to Jack Repenning <jackr@sgi.com>
  364. X;;
  365. X;; archie.el v2.0
  366. X;;   A mock-interface to Archie for Emacs.
  367. X;;
  368. X;;   -- original version by Brendan Kehoe (brendan@cs.widener.edu)
  369. X;;   ange-ftp extensions by Sanjay Mathur (mathur@nas.nasa.gov)
  370. X;;   ----- async support by Andy Norman (ange@hplb.hpl.hp.com)
  371. X;;   ----- convert-to-dired by (drw@bourbaki.mit.edu)
  372. X;;   ----- archie-server-preference-list by Jack Repenning (jackr@sgi.com)
  373. X;;   ----- merge with original archie mode by Piet van Oostrum <piet@cs.ruu.nl>
  374. X;;   ----- many enhancements thanks to the ange-ftp-lovers list
  375. X;;   ----- further archie-mode functions, cleanup, by Rob Austein
  376. X;;         ClearCase: archie.el@@/main/37
  377. X;;         sites:     /ftp@sgigate.sgi.com:/pub/archie-aux/archie.el
  378. X;;                    /ftp@alpha.gnu.ai.mit.edu:ange-ftp/archie.el
  379. X;; 
  380. X;; This file is not part of GNU Emacs but the same permissions apply.
  381. X;; 
  382. X;; GNU Emacs is free software; you can redistribute it and/or modify
  383. X;; it under the terms of the GNU General Public License as published by
  384. X;; the Free Software Foundation; either version 1, or (at your option)
  385. X;; any later version.
  386. X;;
  387. X;; GNU Emacs is distributed in the hope that it will be useful,
  388. X;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  389. X;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  390. X;; GNU General Public License for more details.
  391. X;;
  392. X;; You should have received a copy of the GNU General Public License
  393. X;; along with GNU Emacs; see the file COPYING.  If not, write to
  394. X;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  395. X;;
  396. X;;
  397. X
  398. X;; Usage:
  399. X;;
  400. X;; M-x archie creates a separate buffer from which you can find, copy
  401. X;; or run dired on any of the entries (using ange-ftp) and redo the search
  402. X;; with modified string and/or search-type.
  403. X;; alternatively M-x archie creates a separate buffer in dired mode (q.v).
  404. X
  405. X;;
  406. X
  407. X;; Installation instructions:
  408. X;;
  409. X;; Install this file as archie.el somewhere in your load-path and add the
  410. X;; following two lines to ~/.emacs. (without the semicolon's, of course)
  411. X;;
  412. X;; (autoload 'archie "archie" "Archie interface" t)
  413. X;;
  414. X;; You may have to change the value of archie-program and archie-server
  415. X;; as appropriate for your site.
  416. X;; archie-search-type and archie-download-directory can be modified
  417. X;; to suit personal preferences.
  418. X;;
  419. X;; For use with this package, it is also convenient to set
  420. X;;  (setq ange-ftp-generate-anonymous-password t)
  421. X;;
  422. X;;  Also, the crypt package (available in the LCD archives) is useful
  423. X;;  with archie-find-file, since most archive sites store their files
  424. X;;  in a compressed form.
  425. X
  426. X;;
  427. X;; LCD Archive Entry:
  428. X;; archie|Sanjay R. Mathur|mathur@nas.nasa.gov
  429. X;; |A mock-interface to the archie program.
  430. X;; Wed Apr 22 22:31:46 1992|2.0||
  431. X;;
  432. X
  433. X;; Customization variables
  434. X
  435. X(defvar archie-program "archie"
  436. X  "Program that queries archie servers.")
  437. X
  438. X(defvar archie-server-list
  439. X  '(("archie.funet.fi"      .  "128.214.6.100   (European server in Finland)")
  440. X    ("archie.rutgers.edu"   .  "128.6.18.15     (Rutgers University)")
  441. X    ("archie.sura.net"      .  "128.167.254.179 (SuraNet (Maryland, USA))")
  442. X    ("archie.unl.edu"       .  "129.93.1.14     (University of Nebraska in Lincoln)")
  443. X    ("archie.cs.huji.ac.il" .  "132.65.6.15     (Israel server)")
  444. X    ("archie.au"            .  "139.130.4.6     (Australian server)")
  445. X    ("archie.doc.ic.ac.uk"  .  "146.169.11.3    (UK/England server)")
  446. X    ("archie.ans.net"       .  "147.225.1.2     (ANS archie server)")
  447. X    ("archie.ncu.edu.tw"    .  "140.115.19.24   (Taiwanese server)")
  448. X    ("archie.wide.ad.jp"    .  "133.4.3.6       (Japanese server)"))
  449. X  "List of known archie servers.")
  450. X
  451. X(defvar archie-server nil
  452. X   "*Server for \\[archie] searches.  If ``nil'' (the default), asks.
  453. XKnown archie servers are listed in archie-server-list.")
  454. X
  455. X(defvar archie-download-directory nil
  456. X  "*Default directory into which any files copied by archie-copy are
  457. Xcopied. nil means to use /usr/tmp.")
  458. X
  459. X(defvar archie-search-type "exact"
  460. X  "*Search type for \\[archie] searches.  (Used to set command-line
  461. Xargument for archie program.)  See also archie-search-type-sticky.
  462. X
  463. XCan be one of:
  464. X        exact                   for exact matches (-e) (default)
  465. X        regexp                  for a regexp (-r)
  466. X        substring               for substring searches (-c) 
  467. X        case-insensitive        for a case-insensitive substring search (-s)
  468. X        exact-regexp            for an exact regexp (-er)
  469. X        exact-substring         for an exact substring search (-es)
  470. X        exact-case-insensitive  for exact case-insensitive search (-ec)
  471. X        nil                     to ask every time")
  472. X
  473. X(defvar archie-search-type-sticky t
  474. X  "*Once you specify a search type, should it be made the new default
  475. X(new value of archie-search-type)?")
  476. X
  477. X(defvar archie-search-type-alist
  478. X  ;; This is left as a defvar instead of defconst in case you don't like
  479. X  ;; the keyword choice here, eg, you want "substring" to mean
  480. X  ;; "case-insensitive-substring" (-s) as Allah clearly intended.
  481. X  '(("substring" . "-c")
  482. X    ("exact" . "-e")
  483. X    ("regexp" . "-r")
  484. X    ("case-insensitive" . "-s")
  485. X    ("exact-substring" . "-ec")
  486. X    ("exact-case-insensitive" . "-es")
  487. X    ("exact-regexp" . "-er"))
  488. X  "*Alist of search types for \\[archie] searches.")
  489. X
  490. X(defvar archie-internal-search-type-alist nil
  491. X  "Internal version of archie-search-type-alist (includes switches, as
  492. Xwell as keywords).")
  493. X
  494. X(defun archie-search-type-alist ()
  495. X  "Returns value of archie-internal-search-type-alist, updating it if
  496. Xnecessary."
  497. X  (if (eq archie-search-type-alist
  498. X          (nthcdr (length archie-search-type-alist)
  499. X                  archie-internal-search-type-alist))
  500. X      archie-internal-search-type-alist
  501. X    (setq archie-internal-search-type-alist
  502. X          (nconc (mapcar (function (lambda (x) (cons (cdr x) (cdr x))))
  503. X                         archie-search-type-alist)
  504. X                 archie-search-type-alist))))
  505. X
  506. X(defvar archie-do-convert-to-dired nil
  507. X  "*If t archie buffers are converted to dired-mode, otherwise archie-mode
  508. Xis used.")
  509. X
  510. X(defvar archie-search-hits "1000"
  511. X  "*Maximum number of hits to ask for in search.")
  512. X
  513. X(defvar archie-window-management 'at-end
  514. X  "*When should \\[archie] display the window with the answer?
  515. X        'at-start       When the search is initiated
  516. X        'at-end         When the result is ready
  517. X        'both           Both
  518. X        otherwise       Never")
  519. X
  520. X(defvar archie-server-preference-list nil
  521. X  "*List of regexps for ordering archie results by server.  May be
  522. Xright-anchored with \"$\", e.g.:
  523. X        '(\"erlangen\\.de$\"
  524. X          \"tu-muenchen\\.de$\"
  525. X          \"\\.de$\")")
  526. X
  527. X(defvar archie-dired-unusable-functions
  528. X  (list
  529. X   ;; Classic dired functions
  530. X   'dired-backup-unflag
  531. X   'dired-byte-recompile
  532. X   'dired-chgrp
  533. X   'dired-chmod
  534. X   'dired-chown
  535. X   'dired-clean-directory
  536. X   'dired-compress
  537. X   'dired-do-deletions
  538. X   'dired-flag-auto-save-files
  539. X   'dired-flag-backup-files
  540. X   'dired-flag-file-deleted
  541. X   'dired-rename-file
  542. X   'dired-uncompress
  543. X
  544. X   ;;; Tree-dired functions
  545. X   'dired-backup-diff
  546. X   ;; 'dired-backup-unflag
  547. X   'dired-clean-directory
  548. X   ;; 'dired-create-directory
  549. X   ;; 'dired-diff
  550. X   'dired-do-byte-compile
  551. X   'dired-do-chgrp
  552. X   ;; 'dired-do-chmod
  553. X   'dired-do-chown
  554. X   'dired-do-compress
  555. X   ;; 'dired-do-copy
  556. X   ;; 'dired-do-copy-regexp
  557. X   'dired-do-delete
  558. X   'dired-do-flagged-delete
  559. X   'dired-do-hardlink
  560. X   'dired-do-hardlink-regexp
  561. X   ;; 'dired-do-kill
  562. X   'dired-do-load
  563. X   ;; 'dired-do-move ; amounts to dired-do-copy
  564. X   'dired-do-print
  565. X   ;; 'dired-do-redisplay
  566. X   'dired-do-rename-regexp
  567. X   ;; 'dired-do-shell-command   ; not likely the command knows what to
  568. X                                ; do with such a name, but what the hey
  569. X   'dired-do-symlink
  570. X   'dired-do-symlink-regexp
  571. X   'dired-do-uncompress
  572. X   'dired-downcase
  573. X   ;; 'dired-find-file
  574. X   ;; 'dired-find-file-other-window
  575. X   'dired-flag-auto-save-files
  576. X   'dired-flag-backup-files
  577. X   'dired-flag-file-deleted
  578. X   'dired-flag-regexp-files
  579. X   'dired-hide-all              ; when ``i'' works ...
  580. X   'dired-hide-subdir           ; when ``i'' works ...
  581. X   ;; 'dired-kill-line-or-subdir
  582. X   ;; 'dired-mark-directories
  583. X   ;; 'dired-mark-executables
  584. X   ;; 'dired-mark-files-regexp
  585. X   ;; 'dired-mark-subdir-or-file
  586. X   ;; 'dired-mark-symlinks
  587. X   'dired-maybe-insert-subdir
  588. X   ;; 'dired-next-dirline
  589. X   ;; 'dired-next-line
  590. X   ;; 'dired-next-marked-file
  591. X   ;; 'dired-next-subdir
  592. X   ;; 'dired-prev-dirline
  593. X   ;; 'dired-prev-marked-file
  594. X   ;; 'dired-prev-subdir
  595. X   ;; 'dired-previous-line
  596. X   ;; 'dired-quit
  597. X   'dired-sort-toggle-or-edit
  598. X   ;; 'dired-summary
  599. X   ;; 'dired-tree-down
  600. X   ;; 'dired-tree-up
  601. X   ;; 'dired-undo
  602. X   ;; 'dired-unflag-all-files
  603. X   ;; 'dired-unmark-subdir-or-file
  604. X   ;; 'dired-up-directory
  605. X   'dired-upcase
  606. X   ;; 'dired-view-file
  607. X   ;; 'dired-why
  608. X   ;; 'revert-buffer            ; replaced with archie-modify-query
  609. X   )
  610. X  "*List of dired functions that should be removed from the
  611. Xarchie-dired-mode keymap.")
  612. X
  613. X(defvar archie-mode-hook nil
  614. X  "Hooks to run after entering archie (non-dired) mode.")
  615. X
  616. X(defvar archie-dired-mode-hook nil
  617. X  "Hooks to run after entering archie-dired-mode.")
  618. X
  619. X(defvar archie-anonymous-ftp-username "anonymous"
  620. X  "Username to use for \"anonymous\" FTP connections.
  621. XSet to \"anonymous\" by default, since more sites accept that than any
  622. Xother username (even \"ftp\", and no, not all machines in the world
  623. Xthink they're synonyms).  For dired-mode archie, this only matters for
  624. Xhosts where you've got a non-anonymous username set.")
  625. X
  626. X(defvar archie-display-hook nil
  627. X  "Hook run after displaying the results buffer.")
  628. X
  629. X(defvar archie-load-hook nil
  630. X  "Hooks run after loading archie.el")
  631. X
  632. X
  633. X;; Variables you shouldn't have to customize
  634. X
  635. X(defvar archie-l-output "[0-9]*Z *[0-9]* *\\([^ ]*\\) *\\(.*$\\)"
  636. X  "Regular expression matching the results of archie -l query. The
  637. X   two subexpressions match the host-name and the path respectively.")
  638. X
  639. X(defvar archie-last-query nil)
  640. X(defvar archie-last-type nil)
  641. X
  642. X(defvar archie-mode-map
  643. X  (let ((map (make-sparse-keymap)))
  644. X    (define-key map "f" 'archie-find-file)
  645. X    (define-key map "a" 'archie-modify-query)
  646. X    (define-key map "c" 'archie-copy)
  647. X    (define-key map "x" 'convert-archie-to-dired)
  648. X    (define-key map "d" 'archie-dired)
  649. X    (define-key map "v" 'archie-view-file)
  650. X    (define-key map "n" 'archie-next-line)
  651. X    (define-key map "s" 'archie-change-server)
  652. X    (define-key map " " 'archie-next-line)
  653. X    (define-key map "\C-n" 'archie-next-line)
  654. X    (define-key map "p" 'archie-previous-line)
  655. X    (define-key map "\C-?" 'archie-previous-line)
  656. X    (define-key map "\C-p" 'archie-previous-line)
  657. X    map)
  658. X  "Local keymap used when in archie (non-dired) mode.")
  659. X
  660. X(defvar archie-dired-mode-map nil
  661. X  "Local keymap used when in archie-dired-mode.  Normally cloned from
  662. Xdired-mode-map, after dired-mode-hook is run.")
  663. X
  664. X(defun archie (type string)
  665. X  "Search (with style TYPE, or prompt if arg) for STRING on an Archie
  666. Xserver.
  667. X
  668. XTYPE is the type of search to make -- by default, it's
  669. X`archie-search-type'.  Possible values are exact, substring (case
  670. Xsensitive), case-insensitive and regexp (a regular expression).
  671. XInteractively, a prefix arg will make it prompt for this. If
  672. Xarchie-search-type is NIL, always prompts.  If
  673. Xarchie-search-type-sticky is non-nil, each specified value is used as
  674. Xthe next default; otherwise it reverts to archie-search-type.
  675. X
  676. XSTRING is the string (or regexp) for which to search.
  677. X
  678. XIf archie-do-convert-to-dired is non-NIL, the buffer is converted to a
  679. Xdired buffer.
  680. X
  681. XThe total number of search hits will be limited to (approximately)
  682. Xarchie-search-hits.  If the prefix arg is >= 16 (e.g., ^U ^U
  683. X\\[archie]), then you will be prompted for a new value for
  684. Xarchie-search-hits."
  685. X  (interactive (archie-get-query-args archie-search-type nil))
  686. X  (let ((buf (generate-new-buffer string))
  687. X        (flags (concat (or (cdr (assoc type (archie-search-type-alist)))
  688. X                           (cdr (assoc archie-search-type
  689. X                                       (archie-search-type-alist)))
  690. X                           "-e"))))
  691. X    (save-window-excursion
  692. X      (set-buffer buf)
  693. X      (setq archie-last-query string)
  694. X      (setq archie-last-type type)
  695. X      (setq buffer-read-only nil)
  696. X      (erase-buffer)
  697. X      (archie-mode)
  698. X      (set
  699. X       (make-local-variable 'archie-msg)
  700. X       (message "Asking archie for %s match for \"%s\" ..." type string)))
  701. X    (if (or (eq archie-window-management 'at-start)
  702. X            (eq archie-window-management 'both))
  703. X        (progn
  704. X          (display-buffer buf)
  705. X          (run-hooks 'archie-display-hook)))
  706. X    (let ((proc (start-process "archie" ;name
  707. X                               buf      ;buffer
  708. X                               archie-program ;program
  709. X                               "-h" archie-server ;program args
  710. X                               "-m" archie-search-hits
  711. X                               flags "-l" "-"
  712. X                               string)))
  713. X      (process-kill-without-query proc)
  714. X      (set-process-sentinel proc (function archie-process-sentinel)))))
  715. X
  716. X(defun archie-process-sentinel (proc string)
  717. X  (if (buffer-name (process-buffer proc))
  718. X      (unwind-protect
  719. X          (save-window-excursion
  720. X            (set-buffer (process-buffer proc))
  721. X            (let ((am archie-msg))
  722. X              (message "%s converting." am)
  723. X              (goto-char (point-min))
  724. X              (archie-order-results)
  725. X              (require 'ange-ftp)
  726. X              (if archie-do-convert-to-dired (convert-archie-to-dired))
  727. X              (setq buffer-read-only t)
  728. X              (message "%s done." am)))
  729. X        (if (or (eq archie-window-management 'at-end)
  730. X                (eq archie-window-management 'both))
  731. X            (progn
  732. X              (display-buffer (process-buffer proc))
  733. X              (run-hooks 'archie-display-hook))))))
  734. X
  735. X(defun archie-order-results ()
  736. X  "Order archie results by archie-server-preference-list."
  737. X  (goto-char (point-min))
  738. X  (mapcar
  739. X   (function
  740. X    (lambda (server-re)
  741. X      (let (match)
  742. X        (if (string-match "\\$$" server-re)
  743. X            (setq server-re
  744. X                  (concat (substring server-re 0 -1) " ")))
  745. X        (while
  746. X            (save-excursion
  747. X              (re-search-forward (concat "^[0-9Z]+\\s +[0-9]+ \\S *"
  748. X                                         server-re
  749. X                                         ".*")
  750. X                                 nil t))
  751. X          (setq match (buffer-substring (match-beginning 0) (1+ (match-end 0))))
  752. X          (delete-region  (match-beginning 0) (1+ (match-end 0)))
  753. X          (insert match)))))
  754. X   archie-server-preference-list))
  755. X
  756. X(defun convert-archie-to-dired ()
  757. X  "Convert a buffer containing output in 'archie -l' format into a Dired-mode
  758. Xbuffer in which the usual Dired commands can be used, via ange-ftp."
  759. X  (interactive)
  760. X  (if (not (fboundp 'ange-ftp-get-user)) (load "ange-ftp"))
  761. X  (let (lines b s date size host file type year)
  762. X    (setq year (substring (current-time-string) -4))
  763. X    (setq lines (count-lines (point-min) (point-max)))
  764. X    (setq buffer-read-only nil)
  765. X    (goto-char (point-min))
  766. X    (insert "  total " (int-to-string lines) ?\n)
  767. X    (while (not (eobp))
  768. X      (condition-case error
  769. X          (progn
  770. X            (setq b (point))
  771. X            (beginning-of-line 2)
  772. X            (setq s (buffer-substring b (point)))
  773. X            (or (string-match
  774. X                 "^\\([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\\)Z +\\([0-9]+\\) \\([-_.a-zA-Z0-9]+\\) \\([^ \n]+\\)$"
  775. X                 s)
  776. X                (error "Line not from 'archie -l'"))
  777. X            (setq date (substring s (match-beginning 1) (match-end 1)))
  778. X            (setq size (substring s (match-beginning 2) (match-end 2)))
  779. X            (setq host (substring s (match-beginning 3) (match-end 3)))
  780. X            (setq file (substring s (match-beginning 4) (match-end 4)))
  781. X            (if (string-equal (substring file -1) "/")
  782. X                (setq file (substring file 0 -1)
  783. X                      type "d")
  784. X              (setq type "-"))
  785. X            (save-excursion
  786. X              (insert "  "
  787. X                      ;; - or d, depending on whether it's a file or a directory
  788. X                      type
  789. X                      "r--r--r--  1 ftp"
  790. X                      ;; file size
  791. X                      (make-string (- 8 (length size)) ? )
  792. X                      size
  793. X                      " "
  794. X                      ;; creation date
  795. X                      (condition-case error
  796. X                          (aref
  797. X                           ["Jan" "Feb" "Mar" "Apr" "May" "Jun"
  798. X                            "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"]
  799. X                           (1- (string-to-int (substring date 4 6))))
  800. X                        (error "Jan"))
  801. X                      " "
  802. X                      (if (= (aref date 6) ?0)
  803. X                          (concat " " (substring date 7 8))
  804. X                        (substring date 6 8))
  805. X                      (if (string-equal (substring date 0 4) year)
  806. X                          (concat " " (substring date 8 10) ":" (substring date 10 12))
  807. X                        (concat "  " (substring date 0 4)))
  808. X                      ;; file name, in Ange-FTP format
  809. X                      (archie-get-user-prefix host) host ":" file
  810. X                      ?\n))
  811. X            (delete-region b (point))
  812. X            (forward-line 1))
  813. X        (error (forward-line 1))))
  814. X    (archie-dired-mode)
  815. X    (goto-char (point-min))
  816. X    ;; Set subdir-alist so that Tree Dired will work:
  817. X    (if (fboundp 'dired-simple-subdir-alist)
  818. X        ;; will work even with nested dired format (dired-nstd.el,v 1.15
  819. X        ;; and later)
  820. X        (dired-simple-subdir-alist)
  821. X      ;; else we have an ancient tree dired (or classic dired, where
  822. X      ;; this does no harm) 
  823. X      (set (make-local-variable 'dired-subdir-alist)
  824. X           (list (cons default-directory (point-min-marker)))))))
  825. X
  826. X(defun archie-get-user-prefix (host)
  827. X  "Return a suitable string to affix to the archie filename for this HOST."
  828. X  (if (not (fboundp 'ange-ftp-get-user)) (load "ange-ftp"))
  829. X  (let ((prefix (concat " /" archie-anonymous-ftp-username "@")))
  830. X    (if (or (not ange-ftp-default-user)
  831. X            (stringp ange-ftp-default-user))
  832. X        (let ((user (ange-ftp-get-user host)))
  833. X          (if (or (string-equal user "anonymous")
  834. X                  (string-equal user "ftp"))
  835. X              (setq prefix " /"))))
  836. X    prefix))
  837. X
  838. X(defun archie-dired-mode ()
  839. X  "Mode for handling archie output as a dired buffer.  Uses your own
  840. Xdired mode, as customized by any hooks.  Also runs your own
  841. Xarchie-dired-mode-hook, if any, and uses this modified keymap:
  842. X\\{archie-dired-mode-map}."
  843. X  (if (not (fboundp 'dired-mode)) (load "dired"))
  844. X  (dired-mode (concat "archie " (buffer-name)))
  845. X  (setq default-directory "/usr/tmp/")
  846. X  (if archie-dired-mode-map
  847. X      nil
  848. X    (setq archie-dired-mode-map
  849. X          (copy-keymap (current-local-map)))
  850. X    (mapcar
  851. X     (function (lambda (fn)
  852. X                 (substitute-key-definition fn nil archie-dired-mode-map)))
  853. X     archie-dired-unusable-functions)
  854. X    (substitute-key-definition 'revert-buffer
  855. X                               'archie-modify-query archie-dired-mode-map)
  856. X    (define-key archie-dired-mode-map "s" 'archie-change-server))
  857. X  (use-local-map archie-dired-mode-map)
  858. X  (setq major-mode 'archie-dired-mode)
  859. X  (setq mode-name "Archie Dired")
  860. X  (setq mode-line-buffer-indication '("Archie Dired: %17b"))
  861. X  (run-hooks 'archie-dired-mode-hook))
  862. X
  863. X(defun archie-get-filename ()
  864. X    (beginning-of-line)
  865. X    (if (looking-at archie-l-output)
  866. X        (concat "/" archie-anonymous-ftp-username "@"
  867. X                (buffer-substring (match-beginning 1) (match-end 1))
  868. X                ":"
  869. X                (buffer-substring (match-beginning 2) (match-end 2)))
  870. X      (error "Not archie -l output")))
  871. X
  872. X(defun archie-next-line (arg)
  873. X  (interactive "p")
  874. X  (next-line arg)
  875. X  (if (looking-at archie-l-output)
  876. X      (goto-char (match-beginning 1))))
  877. X
  878. X(defun archie-previous-line (arg)
  879. X  (interactive "p")
  880. X  (previous-line arg)
  881. X  (if (looking-at archie-l-output)
  882. X      (goto-char (match-beginning 1))))
  883. X
  884. X(defun archie-find-file ()
  885. X  "Find the file mentioned on the current line of archie -l output.
  886. XRuns dired if the file is a directory and find-file-run-dired is
  887. Xnon-nil."
  888. X  (interactive)
  889. X  (find-file (archie-get-filename)))
  890. X
  891. X(defun archie-view-file ()
  892. X  "View the file mentioned on the current line of archie -l output."
  893. X  (interactive)
  894. X  (view-file (archie-get-filename)))
  895. X
  896. X(defun archie-copy ()
  897. X  "Copy the file mentioned on the current line of archie -l output.
  898. X   Prompts with the value implied by archie-download-directory
  899. X   as the default directory in which to copy. The file-name part can be
  900. X   empty, in which case the original name is used."
  901. X  (interactive)
  902. X  (let* ((from (archie-get-filename))
  903. X         (from-nondir (file-name-nondirectory from))
  904. X         (to nil))
  905. X    (if (string-equal "" from-nondir)
  906. X        (error "%s is a directory" from))
  907. X    (setq to (read-file-name
  908. X              (format "Copy %s to: " from-nondir)
  909. X              (or archie-download-directory "/usr/tmp")))
  910. X    (if (file-directory-p to)
  911. X        (setq to (concat (file-name-as-directory to) from-nondir)))
  912. X    (copy-file from to 1)))
  913. X
  914. X(defun archie-dired ()
  915. X  "Run dired on the file or directory mentioned on the current line
  916. X   of archie -l output."
  917. X  (interactive)
  918. X  (dired (file-name-directory (archie-get-filename))))
  919. X
  920. X(defun archie-get-query-args (type-defl string-defl)
  921. X  "Queries user for search type (default: TYPE-DEFL) and string
  922. X (default: STRING-DEFL).  Use to prepare args for (interactive)."
  923. X  (let* ((tmp-type (or (if (or current-prefix-arg (null archie-search-type))
  924. X                           (completing-read
  925. X                            "Search type: "
  926. X                            (archie-search-type-alist)
  927. X                            nil
  928. X                            t
  929. X                            type-defl))
  930. X                       archie-search-type))
  931. X         (tmp-string (read-string
  932. X                      (concat "Ask Archie for " tmp-type  " match for: ")
  933. X                      string-defl)))
  934. X    (if archie-search-type-sticky
  935. X        (setq archie-search-type tmp-type))
  936. X    (if (and current-prefix-arg (<= 16 (car current-prefix-arg)))
  937. X        (let (tstr)
  938. X          (setq tstr (read-from-minibuffer "Reset archie-search-hits to: "))
  939. X          (while (>= 0 (string-to-int tstr))
  940. X            (setq tstr
  941. X                  (read-from-minibuffer
  942. X                   "Must be a number greater than zero.  Reset archie-search-hits to: ")))
  943. X          (setq archie-search-hits tstr)))
  944. X    (list tmp-type tmp-string)))
  945. X
  946. X(defun archie-modify-query (type string)
  947. X  "Re-do the last archie search, with modification of the string
  948. Xand/or search type."
  949. X  (interactive (archie-get-query-args archie-last-type archie-last-query))
  950. X  (archie type string))
  951. X
  952. X(defun archie-server ()
  953. X  "Return current server, or prompt for new one."
  954. X  (interactive)
  955. X  (if archie-server
  956. X      archie-server
  957. X    (call-interactively 'archie-change-server)))
  958. X
  959. X(defun archie-change-server (new-server)
  960. X  "Change the current archie server to be NEW-SERVER."
  961. X  (interactive (list
  962. X                (completing-read
  963. X                 (format "Change Archie server (current: %s): " archie-server)
  964. X                 archie-server-list
  965. X                 nil
  966. X                 t)))
  967. X  (setq archie-server new-server))
  968. X
  969. X(defun archie-mode ()
  970. X  "Major mode for interacting with the archie program.
  971. XType: \\[archie-find-file]  to find the file on the current line,
  972. Xor:  \\[archie-copy] to copy it
  973. Xor:  \\[archie-dired] to run dired.
  974. Xor:  \\[convert-archie-to-dired] to convert the buffer to dired.
  975. X
  976. XTo redo the last search with modification of the string and/or
  977. Xswitches, type: \\[archie-modify-query].
  978. X
  979. XIf archie-download-directory is set to non-nil then its value is used
  980. Xas the default directory while prompting for the target file by the
  981. Xarchie-copy command; otherwise, /usr/tmp.
  982. X
  983. X\\{archie-mode-map}
  984. X
  985. XRuns archie-mode-hook, if defined."
  986. X  (kill-all-local-variables)
  987. X  (setq mode-name "Archie")
  988. X  (setq major-mode 'archie-mode)
  989. X  (use-local-map archie-mode-map)
  990. X  (setq mode-line-process '(": %s"))
  991. X  (run-hooks 'archie-mode-hook))
  992. X
  993. X(run-hooks 'archie-load-hook)
  994. X(provide 'archie)
  995. END_OF_FILE
  996.   if test 24212 -ne `wc -c <'archie.el'`; then
  997.     echo shar: \"'archie.el'\" unpacked with wrong size!
  998.   fi
  999.   # end of 'archie.el'
  1000. fi
  1001. if test -f 'archie.lnk' -a "${1}" != "-c" ; then 
  1002.   echo shar: Will not clobber existing file \"'archie.lnk'\"
  1003. else
  1004.   echo shar: Extracting \"'archie.lnk'\" \(237 characters\)
  1005.   sed "s/^X//" >'archie.lnk' <<'END_OF_FILE'
  1006. Xaquery.lo archie.lo atalloc.lo dirsend.lo+
  1007. XGet_pauth.lo get_vdir.lo perrmesg.lo procquery.lo+
  1008. Xptalloc.lo regex.lo stcopy.lo support.lo+
  1009. Xvlalloc.lo vl_comp.lo
  1010. Xarchie.unp
  1011. Xarchie/map/noi/co/li/stack:45000
  1012. Xlsocket lnetlib lconfig lpc llibce
  1013. END_OF_FILE
  1014.   if test 237 -ne `wc -c <'archie.lnk'`; then
  1015.     echo shar: \"'archie.lnk'\" unpacked with wrong size!
  1016.   fi
  1017.   # end of 'archie.lnk'
  1018. fi
  1019. if test -f 'getopt.c' -a "${1}" != "-c" ; then 
  1020.   echo shar: Will not clobber existing file \"'getopt.c'\"
  1021. else
  1022.   echo shar: Extracting \"'getopt.c'\" \(19101 characters\)
  1023.   sed "s/^X//" >'getopt.c' <<'END_OF_FILE'
  1024. X/* Getopt for GNU.
  1025. X   NOTE: getopt is now part of the C library, so if you don't know what
  1026. X   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
  1027. X   before changing it!
  1028. X
  1029. X   Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
  1030. X
  1031. X   This program is free software; you can redistribute it and/or modify it
  1032. X   under the terms of the GNU Library General Public License as published
  1033. X   by the Free Software Foundation; either version 2, or (at your option)
  1034. X   any later version.
  1035. X
  1036. X   This program is distributed in the hope that it will be useful,
  1037. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  1038. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1039. X   GNU General Public License for more details.
  1040. X
  1041. X   You should have received a copy of the GNU Library General Public
  1042. X   License along with this program; if not, write to the Free Software
  1043. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  1044. X
  1045. X/* AIX requires this to be the first thing in the file. */
  1046. X#ifdef __GNUC__
  1047. X#define alloca __builtin_alloca
  1048. X#else /* not __GNUC__ */
  1049. X#if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__))))
  1050. X#include <alloca.h>
  1051. X#else
  1052. X#ifdef _AIX
  1053. X #pragma alloca
  1054. X#else
  1055. Xchar *alloca ();
  1056. X#endif
  1057. X#endif /* alloca.h */
  1058. X#endif /* not __GNUC__ */
  1059. X
  1060. X#include <stdio.h>
  1061. X
  1062. X/* This needs to come after some library #include
  1063. X   to get __GNU_LIBRARY__ defined.  */
  1064. X#ifdef    __GNU_LIBRARY__
  1065. X#undef    alloca
  1066. X#include <stdlib.h>
  1067. X#include <string.h>
  1068. X#else    /* Not GNU C library.  */
  1069. X#define    __alloca    alloca
  1070. X#endif    /* GNU C library.  */
  1071. X
  1072. X
  1073. X#ifndef __STDC__
  1074. X#define const
  1075. X#endif
  1076. X
  1077. X/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
  1078. X   long-named option.  Because this is not POSIX.2 compliant, it is
  1079. X   being phased out. */
  1080. X#undef GETOPT_COMPAT
  1081. X
  1082. X/* This version of `getopt' appears to the caller like standard Unix `getopt'
  1083. X   but it behaves differently for the user, since it allows the user
  1084. X   to intersperse the options with the other arguments.
  1085. X
  1086. X   As `getopt' works, it permutes the elements of ARGV so that,
  1087. X   when it is done, all the options precede everything else.  Thus
  1088. X   all application programs are extended to handle flexible argument order.
  1089. X
  1090. X   Setting the environment variable POSIXLY_CORRECT disables permutation.
  1091. X   Then the behavior is completely standard.
  1092. X
  1093. X   GNU application programs can use a third alternative mode in which
  1094. X   they can distinguish the relative order of options and other arguments.  */
  1095. X
  1096. X#include "getopt.h"
  1097. X
  1098. X/* For communication from `getopt' to the caller.
  1099. X   When `getopt' finds an option that takes an argument,
  1100. X   the argument value is returned here.
  1101. X   Also, when `ordering' is RETURN_IN_ORDER,
  1102. X   each non-option ARGV-element is returned here.  */
  1103. X
  1104. Xchar *optarg = 0;
  1105. X
  1106. X/* Index in ARGV of the next element to be scanned.
  1107. X   This is used for communication to and from the caller
  1108. X   and for communication between successive calls to `getopt'.
  1109. X
  1110. X   On entry to `getopt', zero means this is the first call; initialize.
  1111. X
  1112. X   When `getopt' returns EOF, this is the index of the first of the
  1113. X   non-option elements that the caller should itself scan.
  1114. X
  1115. X   Otherwise, `optind' communicates from one call to the next
  1116. X   how much of ARGV has been scanned so far.  */
  1117. X
  1118. Xint optind = 0;
  1119. X
  1120. X/* The next char to be scanned in the option-element
  1121. X   in which the last option character we returned was found.
  1122. X   This allows us to pick up the scan where we left off.
  1123. X
  1124. X   If this is zero, or a null string, it means resume the scan
  1125. X   by advancing to the next ARGV-element.  */
  1126. X
  1127. Xstatic char *nextchar;
  1128. X
  1129. X/* Callers store zero here to inhibit the error message
  1130. X   for unrecognized options.  */
  1131. X
  1132. Xint opterr = 1;
  1133. X
  1134. X/* Describe how to deal with options that follow non-option ARGV-elements.
  1135. X
  1136. X   If the caller did not specify anything,
  1137. X   the default is REQUIRE_ORDER if the environment variable
  1138. X   POSIXLY_CORRECT is defined, PERMUTE otherwise.
  1139. X
  1140. X   REQUIRE_ORDER means don't recognize them as options;
  1141. X   stop option processing when the first non-option is seen.
  1142. X   This is what Unix does.
  1143. X   This mode of operation is selected by either setting the environment
  1144. X   variable POSIXLY_CORRECT, or using `+' as the first character
  1145. X   of the list of option characters.
  1146. X
  1147. X   PERMUTE is the default.  We permute the contents of ARGV as we scan,
  1148. X   so that eventually all the non-options are at the end.  This allows options
  1149. X   to be given in any order, even with programs that were not written to
  1150. X   expect this.
  1151. X
  1152. X   RETURN_IN_ORDER is an option available to programs that were written
  1153. X   to expect options and other ARGV-elements in any order and that care about
  1154. X   the ordering of the two.  We describe each non-option ARGV-element
  1155. X   as if it were the argument of an option with character code 1.
  1156. X   Using `-' as the first character of the list of option characters
  1157. X   selects this mode of operation.
  1158. X
  1159. X   The special argument `--' forces an end of option-scanning regardless
  1160. X   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
  1161. X   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
  1162. X
  1163. Xstatic enum
  1164. X{
  1165. X  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
  1166. X} ordering;
  1167. X
  1168. X#ifdef    __GNU_LIBRARY__
  1169. X#include <string.h>
  1170. X#define    my_index    strchr
  1171. X#define    my_bcopy(src, dst, n)    memcpy ((dst), (src), (n))
  1172. X#else
  1173. X
  1174. X/* Avoid depending on library functions or files
  1175. X   whose names are inconsistent.  */
  1176. X
  1177. Xchar *getenv ();
  1178. X
  1179. Xstatic char *
  1180. Xmy_index (string, chr)
  1181. X     const char *string;
  1182. X     int chr;
  1183. X{
  1184. X  while (*string)
  1185. X    {
  1186. X      if (*string == chr)
  1187. X    return (char *) string;
  1188. X      string++;
  1189. X    }
  1190. X  return 0;
  1191. X}
  1192. X
  1193. Xstatic void
  1194. Xmy_bcopy (from, to, size)
  1195. X     char *from, *to;
  1196. X     int size;
  1197. X{
  1198. X  int i;
  1199. X  for (i = 0; i < size; i++)
  1200. X    to[i] = from[i];
  1201. X}
  1202. X#endif                /* GNU C library.  */
  1203. X
  1204. X/* Handle permutation of arguments.  */
  1205. X
  1206. X/* Describe the part of ARGV that contains non-options that have
  1207. X   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
  1208. X   `last_nonopt' is the index after the last of them.  */
  1209. X
  1210. Xstatic int first_nonopt;
  1211. Xstatic int last_nonopt;
  1212. X
  1213. X/* Exchange two adjacent subsequences of ARGV.
  1214. X   One subsequence is elements [first_nonopt,last_nonopt)
  1215. X   which contains all the non-options that have been skipped so far.
  1216. X   The other is elements [last_nonopt,optind), which contains all
  1217. X   the options processed since those non-options were skipped.
  1218. X
  1219. X   `first_nonopt' and `last_nonopt' are relocated so that they describe
  1220. X   the new indices of the non-options in ARGV after they are moved.  */
  1221. X
  1222. Xstatic void
  1223. Xexchange (argv)
  1224. X     char **argv;
  1225. X{
  1226. X  int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
  1227. X#ifdef ARCHIE_HOST
  1228. X  char **temp = (char **) malloc (nonopts_size);
  1229. X#else
  1230. X  char **temp = (char **) __alloca (nonopts_size);
  1231. X#endif
  1232. X
  1233. X  /* Interchange the two blocks of data in ARGV.  */
  1234. X
  1235. X  my_bcopy ((char *)&argv[first_nonopt], (char *)temp,
  1236. X        nonopts_size);
  1237. X  my_bcopy ((char *)&argv[last_nonopt], (char *)&argv[first_nonopt],
  1238. X        (optind - last_nonopt) * sizeof (char *));
  1239. X  my_bcopy ((char *)temp, (char *)&argv[first_nonopt + optind - last_nonopt],
  1240. X            nonopts_size);
  1241. X
  1242. X  /* Update records for the slots the non-options now occupy.  */
  1243. X
  1244. X  first_nonopt += (optind - last_nonopt);
  1245. X  last_nonopt = optind;
  1246. X}
  1247. X
  1248. X/* Scan elements of ARGV (whose length is ARGC) for option characters
  1249. X   given in OPTSTRING.
  1250. X
  1251. X   If an element of ARGV starts with '-', and is not exactly "-" or "--",
  1252. X   then it is an option element.  The characters of this element
  1253. X   (aside from the initial '-') are option characters.  If `getopt'
  1254. X   is called repeatedly, it returns successively each of the option characters
  1255. X   from each of the option elements.
  1256. X
  1257. X   If `getopt' finds another option character, it returns that character,
  1258. X   updating `optind' and `nextchar' so that the next call to `getopt' can
  1259. X   resume the scan with the following option character or ARGV-element.
  1260. X
  1261. X   If there are no more option characters, `getopt' returns `EOF'.
  1262. X   Then `optind' is the index in ARGV of the first ARGV-element
  1263. X   that is not an option.  (The ARGV-elements have been permuted
  1264. X   so that those that are not options now come last.)
  1265. X
  1266. X   OPTSTRING is a string containing the legitimate option characters.
  1267. X   If an option character is seen that is not listed in OPTSTRING,
  1268. X   return '?' after printing an error message.  If you set `opterr' to
  1269. X   zero, the error message is suppressed but we still return '?'.
  1270. X
  1271. X   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
  1272. X   so the following text in the same ARGV-element, or the text of the following
  1273. X   ARGV-element, is returned in `optarg'.  Two colons mean an option that
  1274. X   wants an optional arg; if there is text in the current ARGV-element,
  1275. X   it is returned in `optarg', otherwise `optarg' is set to zero.
  1276. X
  1277. X   If OPTSTRING starts with `-' or `+', it requests different methods of
  1278. X   handling the non-option ARGV-elements.
  1279. X   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
  1280. X
  1281. X   Long-named options begin with `--' instead of `-'.
  1282. X   Their names may be abbreviated as long as the abbreviation is unique
  1283. X   or is an exact match for some defined option.  If they have an
  1284. X   argument, it follows the option name in the same ARGV-element, separated
  1285. X   from the option name by a `=', or else the in next ARGV-element.
  1286. X   When `getopt' finds a long-named option, it returns 0 if that option's
  1287. X   `flag' field is nonzero, the value of the option's `val' field
  1288. X   if the `flag' field is zero.
  1289. X
  1290. X   The elements of ARGV aren't really const, because we permute them.
  1291. X   But we pretend they're const in the prototype to be compatible
  1292. X   with other systems.
  1293. X
  1294. X   LONGOPTS is a vector of `struct option' terminated by an
  1295. X   element containing a name which is zero.
  1296. X
  1297. X   LONGIND returns the index in LONGOPT of the long-named option found.
  1298. X   It is only valid when a long-named option has been found by the most
  1299. X   recent call.
  1300. X
  1301. X   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
  1302. X   long-named options.  */
  1303. X
  1304. Xint
  1305. X_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
  1306. X     int argc;
  1307. X     char *const *argv;
  1308. X     const char *optstring;
  1309. X     const struct option *longopts;
  1310. X     int *longind;
  1311. X     int long_only;
  1312. X{
  1313. X  int option_index;
  1314. X
  1315. X  optarg = 0;
  1316. X
  1317. X  /* Initialize the internal data when the first call is made.
  1318. X     Start processing options with ARGV-element 1 (since ARGV-element 0
  1319. X     is the program name); the sequence of previously skipped
  1320. X     non-option ARGV-elements is empty.  */
  1321. X
  1322. X  if (optind == 0)
  1323. X    {
  1324. X      first_nonopt = last_nonopt = optind = 1;
  1325. X
  1326. X      nextchar = NULL;
  1327. X
  1328. X      /* Determine how to handle the ordering of options and nonoptions.  */
  1329. X
  1330. X      if (optstring[0] == '-')
  1331. X    {
  1332. X      ordering = RETURN_IN_ORDER;
  1333. X      ++optstring;
  1334. X    }
  1335. X      else if (optstring[0] == '+')
  1336. X    {
  1337. X      ordering = REQUIRE_ORDER;
  1338. X      ++optstring;
  1339. X    }
  1340. X      else if (getenv ("POSIXLY_CORRECT") != NULL)
  1341. X    ordering = REQUIRE_ORDER;
  1342. X      else
  1343. X    ordering = PERMUTE;
  1344. X    }
  1345. X
  1346. X  if (nextchar == NULL || *nextchar == '\0')
  1347. X    {
  1348. X      if (ordering == PERMUTE)
  1349. X    {
  1350. X      /* If we have just processed some options following some non-options,
  1351. X         exchange them so that the options come first.  */
  1352. X
  1353. X      if (first_nonopt != last_nonopt && last_nonopt != optind)
  1354. X        exchange ((char **) argv);
  1355. X      else if (last_nonopt != optind)
  1356. X        first_nonopt = optind;
  1357. X
  1358. X      /* Now skip any additional non-options
  1359. X         and extend the range of non-options previously skipped.  */
  1360. X
  1361. X      while (optind < argc
  1362. X         && (argv[optind][0] != '-' || argv[optind][1] == '\0')
  1363. X#ifdef GETOPT_COMPAT
  1364. X         && (longopts == NULL
  1365. X             || argv[optind][0] != '+' || argv[optind][1] == '\0')
  1366. X#endif                /* GETOPT_COMPAT */
  1367. X         )
  1368. X        optind++;
  1369. X      last_nonopt = optind;
  1370. X    }
  1371. X
  1372. X      /* Special ARGV-element `--' means premature end of options.
  1373. X     Skip it like a null option,
  1374. X     then exchange with previous non-options as if it were an option,
  1375. X     then skip everything else like a non-option.  */
  1376. X
  1377. X      if (optind != argc && !strcmp (argv[optind], "--"))
  1378. X    {
  1379. X      optind++;
  1380. X
  1381. X      if (first_nonopt != last_nonopt && last_nonopt != optind)
  1382. X        exchange ((char **) argv);
  1383. X      else if (first_nonopt == last_nonopt)
  1384. X        first_nonopt = optind;
  1385. X      last_nonopt = argc;
  1386. X
  1387. X      optind = argc;
  1388. X    }
  1389. X
  1390. X      /* If we have done all the ARGV-elements, stop the scan
  1391. X     and back over any non-options that we skipped and permuted.  */
  1392. X
  1393. X      if (optind == argc)
  1394. X    {
  1395. X      /* Set the next-arg-index to point at the non-options
  1396. X         that we previously skipped, so the caller will digest them.  */
  1397. X      if (first_nonopt != last_nonopt)
  1398. X        optind = first_nonopt;
  1399. X      return EOF;
  1400. X    }
  1401. X
  1402. X      /* If we have come to a non-option and did not permute it,
  1403. X     either stop the scan or describe it to the caller and pass it by.  */
  1404. X
  1405. X      if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
  1406. X#ifdef GETOPT_COMPAT
  1407. X      && (longopts == NULL
  1408. X          || argv[optind][0] != '+' || argv[optind][1] == '\0')
  1409. X#endif                /* GETOPT_COMPAT */
  1410. X      )
  1411. X    {
  1412. X      if (ordering == REQUIRE_ORDER)
  1413. X        return EOF;
  1414. X      optarg = argv[optind++];
  1415. X      return 1;
  1416. X    }
  1417. X
  1418. X      /* We have found another option-ARGV-element.
  1419. X     Start decoding its characters.  */
  1420. X
  1421. X      nextchar = (argv[optind] + 1
  1422. X          + (longopts != NULL && argv[optind][1] == '-'));
  1423. X    }
  1424. X
  1425. X  if (longopts != NULL
  1426. X      && ((argv[optind][0] == '-'
  1427. X       && (argv[optind][1] == '-' || long_only))
  1428. X#ifdef GETOPT_COMPAT
  1429. X      || argv[optind][0] == '+'
  1430. X#endif                /* GETOPT_COMPAT */
  1431. X      ))
  1432. X    {
  1433. X      const struct option *p;
  1434. X      char *s = nextchar;
  1435. X      int exact = 0;
  1436. X      int ambig = 0;
  1437. X      const struct option *pfound = NULL;
  1438. X      int indfound;
  1439. X
  1440. X      while (*s && *s != '=')
  1441. X    s++;
  1442. X
  1443. X      /* Test all options for either exact match or abbreviated matches.  */
  1444. X      for (p = longopts, option_index = 0; p->name;
  1445. X       p++, option_index++)
  1446. X    if (!strncmp (p->name, nextchar, s - nextchar))
  1447. X      {
  1448. X        if (s - nextchar == strlen (p->name))
  1449. X          {
  1450. X        /* Exact match found.  */
  1451. X        pfound = p;
  1452. X        indfound = option_index;
  1453. X        exact = 1;
  1454. X        break;
  1455. X          }
  1456. X        else if (pfound == NULL)
  1457. X          {
  1458. X        /* First nonexact match found.  */
  1459. X        pfound = p;
  1460. X        indfound = option_index;
  1461. X          }
  1462. X        else
  1463. X          /* Second nonexact match found.  */
  1464. X          ambig = 1;
  1465. X      }
  1466. X
  1467. X      if (ambig && !exact)
  1468. X    {
  1469. X      if (opterr)
  1470. X        fprintf (stderr, "%s: option `%s' is ambiguous\n",
  1471. X             argv[0], argv[optind]);
  1472. X      nextchar += strlen (nextchar);
  1473. X      optind++;
  1474. X      return '?';
  1475. X    }
  1476. X
  1477. X      if (pfound != NULL)
  1478. X    {
  1479. X      option_index = indfound;
  1480. X      optind++;
  1481. X      if (*s)
  1482. X        {
  1483. X          /* Don't test has_arg with >, because some C compilers don't
  1484. X         allow it to be used on enums. */
  1485. X          if (pfound->has_arg)
  1486. X        optarg = s + 1;
  1487. X          else
  1488. X        {
  1489. X          if (opterr)
  1490. X            {
  1491. X              if (argv[optind - 1][1] == '-')
  1492. X            /* --option */
  1493. X            fprintf (stderr,
  1494. X                 "%s: option `--%s' doesn't allow an argument\n",
  1495. X                 argv[0], pfound->name);
  1496. X              else
  1497. X            /* +option or -option */
  1498. X            fprintf (stderr,
  1499. X                 "%s: option `%c%s' doesn't allow an argument\n",
  1500. X                 argv[0], argv[optind - 1][0], pfound->name);
  1501. X            }
  1502. X          nextchar += strlen (nextchar);
  1503. X          return '?';
  1504. X        }
  1505. X        }
  1506. X      else if (pfound->has_arg == 1)
  1507. X        {
  1508. X          if (optind < argc)
  1509. X        optarg = argv[optind++];
  1510. X          else
  1511. X        {
  1512. X          if (opterr)
  1513. X            fprintf (stderr, "%s: option `%s' requires an argument\n",
  1514. X                 argv[0], argv[optind - 1]);
  1515. X          nextchar += strlen (nextchar);
  1516. X          return '?';
  1517. X        }
  1518. X        }
  1519. X      nextchar += strlen (nextchar);
  1520. X      if (longind != NULL)
  1521. X        *longind = option_index;
  1522. X      if (pfound->flag)
  1523. X        {
  1524. X          *(pfound->flag) = pfound->val;
  1525. X          return 0;
  1526. X        }
  1527. X      return pfound->val;
  1528. X    }
  1529. X      /* Can't find it as a long option.  If this is not getopt_long_only,
  1530. X     or the option starts with '--' or is not a valid short
  1531. X     option, then it's an error.
  1532. X     Otherwise interpret it as a short option. */
  1533. X      if (!long_only || argv[optind][1] == '-'
  1534. X#ifdef GETOPT_COMPAT
  1535. X      || argv[optind][0] == '+'
  1536. X#endif                /* GETOPT_COMPAT */
  1537. X      || my_index (optstring, *nextchar) == NULL)
  1538. X    {
  1539. X      if (opterr)
  1540. X        {
  1541. X          if (argv[optind][1] == '-')
  1542. X        /* --option */
  1543. X        fprintf (stderr, "%s: unrecognized option `--%s'\n",
  1544. X             argv[0], nextchar);
  1545. X          else
  1546. X        /* +option or -option */
  1547. X        fprintf (stderr, "%s: unrecognized option `%c%s'\n",
  1548. X             argv[0], argv[optind][0], nextchar);
  1549. X        }
  1550. X      nextchar = (char *) "";
  1551. X      optind++;
  1552. X      return '?';
  1553. X    }
  1554. X    }
  1555. X
  1556. X  /* Look at and handle the next option-character.  */
  1557. X
  1558. X  {
  1559. X    char c = *nextchar++;
  1560. X    char *temp = my_index (optstring, c);
  1561. X
  1562. X    /* Increment `optind' when we start to process its last character.  */
  1563. X    if (*nextchar == '\0')
  1564. X      ++optind;
  1565. X
  1566. X    if (temp == NULL || c == ':')
  1567. X      {
  1568. X    if (opterr)
  1569. X      {
  1570. X        if (c < 040 || c >= 0177)
  1571. X          fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
  1572. X               argv[0], c);
  1573. X        else
  1574. X          fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
  1575. X      }
  1576. X    return '?';
  1577. X      }
  1578. X    if (temp[1] == ':')
  1579. X      {
  1580. X    if (temp[2] == ':')
  1581. X      {
  1582. X        /* This is an option that accepts an argument optionally.  */
  1583. X        if (*nextchar != '\0')
  1584. X          {
  1585. X        optarg = nextchar;
  1586. X        optind++;
  1587. X          }
  1588. X        else
  1589. X          optarg = 0;
  1590. X        nextchar = NULL;
  1591. X      }
  1592. X    else
  1593. X      {
  1594. X        /* This is an option that requires an argument.  */
  1595. X        if (*nextchar != '\0')
  1596. X          {
  1597. X        optarg = nextchar;
  1598. X        /* If we end this ARGV-element by taking the rest as an arg,
  1599. X           we must advance to the next element now.  */
  1600. X        optind++;
  1601. X          }
  1602. X        else if (optind == argc)
  1603. X          {
  1604. X        if (opterr)
  1605. X          fprintf (stderr, "%s: option `-%c' requires an argument\n",
  1606. X               argv[0], c);
  1607. X        c = '?';
  1608. X          }
  1609. X        else
  1610. X          /* We already incremented `optind' once;
  1611. X         increment it again when taking next ARGV-elt as argument.  */
  1612. X          optarg = argv[optind++];
  1613. X        nextchar = NULL;
  1614. X      }
  1615. X      }
  1616. X    return c;
  1617. X  }
  1618. X}
  1619. X
  1620. Xint
  1621. Xgetopt (argc, argv, optstring)
  1622. X     int argc;
  1623. X     char *const *argv;
  1624. X     const char *optstring;
  1625. X{
  1626. X  return _getopt_internal (argc, argv, optstring,
  1627. X               (const struct option *) 0,
  1628. X               (int *) 0,
  1629. X               0);
  1630. X}
  1631. X
  1632. X#ifdef TEST
  1633. X
  1634. X/* Compile with -DTEST to make an executable for use in testing
  1635. X   the above definition of `getopt'.  */
  1636. X
  1637. Xint
  1638. Xmain (argc, argv)
  1639. X     int argc;
  1640. X     char **argv;
  1641. X{
  1642. X  int c;
  1643. X  int digit_optind = 0;
  1644. X
  1645. X  while (1)
  1646. X    {
  1647. X      int this_option_optind = optind ? optind : 1;
  1648. X
  1649. X      c = getopt (argc, argv, "abc:d:0123456789");
  1650. X      if (c == EOF)
  1651. X    break;
  1652. X
  1653. X      switch (c)
  1654. X    {
  1655. X    case '0':
  1656. X    case '1':
  1657. X    case '2':
  1658. X    case '3':
  1659. X    case '4':
  1660. X    case '5':
  1661. X    case '6':
  1662. X    case '7':
  1663. X    case '8':
  1664. X    case '9':
  1665. X      if (digit_optind != 0 && digit_optind != this_option_optind)
  1666. X        printf ("digits occur in two different argv-elements.\n");
  1667. X      digit_optind = this_option_optind;
  1668. X      printf ("option %c\n", c);
  1669. X      break;
  1670. X
  1671. X    case 'a':
  1672. X      printf ("option a\n");
  1673. X      break;
  1674. X
  1675. X    case 'b':
  1676. X      printf ("option b\n");
  1677. X      break;
  1678. X
  1679. X    case 'c':
  1680. X      printf ("option c with value `%s'\n", optarg);
  1681. X      break;
  1682. X
  1683. X    case '?':
  1684. X      break;
  1685. X
  1686. X    default:
  1687. X      printf ("?? getopt returned character code 0%o ??\n", c);
  1688. X    }
  1689. X    }
  1690. X
  1691. X  if (optind < argc)
  1692. X    {
  1693. X      printf ("non-option ARGV-elements: ");
  1694. X      while (optind < argc)
  1695. X    printf ("%s ", argv[optind++]);
  1696. X      printf ("\n");
  1697. X    }
  1698. X
  1699. X  exit (0);
  1700. X}
  1701. X
  1702. X#endif /* TEST */
  1703. END_OF_FILE
  1704.   if test 19101 -ne `wc -c <'getopt.c'`; then
  1705.     echo shar: \"'getopt.c'\" unpacked with wrong size!
  1706.   fi
  1707.   # end of 'getopt.c'
  1708. fi
  1709. echo shar: End of archive 3 \(of 7\).
  1710. cp /dev/null ark3isdone
  1711. MISSING=""
  1712. for I in 1 2 3 4 5 6 7 ; do
  1713.     if test ! -f ark${I}isdone ; then
  1714.     MISSING="${MISSING} ${I}"
  1715.     fi
  1716. done
  1717. if test "${MISSING}" = "" ; then
  1718.     echo You have unpacked all 7 archives.
  1719.     rm -f ark[1-9]isdone
  1720. else
  1721.     echo You still must unpack the following archives:
  1722.     echo "        " ${MISSING}
  1723. fi
  1724. exit 0
  1725. exit 0 # Just in case...
  1726.