home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / sources / misc / 4057 < prev    next >
Encoding:
Text File  |  1992-11-05  |  54.3 KB  |  1,732 lines

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