home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume36 / unpost / part06 < prev    next >
Encoding:
Text File  |  1993-04-18  |  60.0 KB  |  1,990 lines

  1. Newsgroups: comp.sources.misc,alt.binaries.pictures.utilities
  2. From: jstevens@teal.csn.org (John W.M. Stevens)
  3. Subject: v36i119:  unpost - Smart multi-part uudecoder v2.1.2, Part06/07
  4. Message-ID: <1993Apr19.052617.29435@sparky.imd.sterling.com>
  5. X-Md4-Signature: a5dca11aa0a4398800ec30d4343ad257
  6. Date: Mon, 19 Apr 1993 05:26:17 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jstevens@teal.csn.org (John W.M. Stevens)
  10. Posting-number: Volume 36, Issue 119
  11. Archive-name: unpost/part06
  12. Environment: UNIX, MS-DOS, OS/2, Windows, MacIntosh, Amiga, Vax/VMS
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  cfg/cbip.cfg cfg/def.cfg compiler.h list.c modflnm.c
  19. #   nntp/client.doc retest.c summary.doc utils.c utils/trie.c
  20. # Wrapped by kent@sparky on Sun Apr 18 23:10:31 1993
  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 6 (of 7)."'
  24. if test -f 'cfg/cbip.cfg' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'cfg/cbip.cfg'\"
  26. else
  27.   echo shar: Extracting \"'cfg/cbip.cfg'\" \(3793 characters\)
  28.   sed "s/^X//" >'cfg/cbip.cfg' <<'END_OF_FILE'
  29. X#   This is the default configuration modifed to ignore the leading
  30. X#   stuff on the subject line of comp.binaries.ibm.pc and
  31. X#   comp.binaries.ms-windows postings.
  32. X
  33. Xsegment "^(Article[:]?|X-NEWS:)"
  34. X{
  35. X    header
  36. X    {
  37. X        "^Subject:"
  38. X        {
  39. X            "^Subject:.*:(.*)[[({]Part[_   ]*([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
  40. X            {
  41. X                id 1
  42. X                segment number 2
  43. X                segments 3
  44. X                alternate id 4
  45. X                case ignore
  46. X            }
  47. X            "^Subject:.*:(.*)Part[_    ]*[[({]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
  48. X            {
  49. X                id 1
  50. X                segment number 2
  51. X                segments 3
  52. X                alternate id 4
  53. X                case ignore
  54. X            }
  55. X            "^Subject:.*:(.*)Part[_    ]+([0-9]+)[^0-9]+([0-9]+)(.*)"
  56. X            {
  57. X                id 1
  58. X                segment number 2
  59. X                segments 3
  60. X                alternate id 4
  61. X                case ignore
  62. X            }
  63. X            "^Subject:.*:(.*)[([{]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
  64. X            {
  65. X                id 1
  66. X                segment number 2
  67. X                segments 3
  68. X                alternate id 4
  69. X                case ignore
  70. X            }
  71. X            "^Subject:.*:(.*)([0-9]+)([/|]|[ \t]+of[ \t]+)([0-9]+)(.*)"
  72. X            {
  73. X                id 1
  74. X                segment number 2
  75. X                segments 4
  76. X                alternate id 5
  77. X                case ignore
  78. X            }
  79. X            "^Subject:.*:(.*)"
  80. X            {
  81. X                id 1
  82. X                segment number 0
  83. X                segments 0
  84. X                alternate id 0
  85. X                case ignore
  86. X            }
  87. X        }
  88. X        "^X-File-Name:"
  89. X        {
  90. X            "^X-File-Name:[     ]+(.*)"
  91. X            {
  92. X                id 1
  93. X                segment number 0
  94. X                segments 0
  95. X                 alternate id 0
  96. X                case sensitive
  97. X            }
  98. X        }
  99. X        "^X-Part:"
  100. X        {
  101. X            "^X-Part:[  ]+([0-9]+)"
  102. X            {
  103. X                id 0
  104. X                segment number 1
  105. X                segments 0
  106. X                alternate id 0
  107. X                case sensitive
  108. X            }
  109. X        }
  110. X        "^X-Part-Total:"
  111. X        {
  112. X            "^X-Part-Total:[    ]+([0-9]+)"
  113. X            {
  114. X                id 0
  115. X                segment number 0
  116. X                segments 1
  117. X                alternate id 0
  118. X                case sensitive
  119. X            }
  120. X        }
  121. X        "^Uusplit-part:"
  122. X        {
  123. X            "^Uusplit-part:[    ]+([0-9]+)"
  124. X            {
  125. X                id 0
  126. X                segment number 1
  127. X                segments 0
  128. X                alternate id 0
  129. X                case sensitive
  130. X            }
  131. X        }
  132. X        "^Uusplit-parts:"
  133. X        {
  134. X            "^Uusplit-parts:[   ]+([0-9]+)"
  135. X            {
  136. X                id 0
  137. X                segment number 0
  138. X                segments 1
  139. X                alternate id 0
  140. X                case sensitive
  141. X            }
  142. X        }
  143. X    }
  144. X    body
  145. X    {
  146. X        "^section [0-9]+ of uuencode [0-9]+\.[0-9]+ of file "
  147. X        "[^     ]+    by R.E.M."
  148. X        {
  149. X            "^section ([0-9]+) of uuencode [0-9]+\.[0-9]+ of file "
  150. X            "([^    ]+)[    ]+by R.E.M."
  151. X            {
  152. X                id 2
  153. X                segment number 1
  154. X                segments 0
  155. X                alternate id 0
  156. X                case sensitive
  157. X            }
  158. X        }
  159. X        "^[^    ]+[     ]+section[  ]+[0-9]+/[0-9]+[    ]+UUXFER "
  160. X        "ver [^     ]+ by David M. Read"
  161. X         {
  162. X            "^([^ \t]+)[ \t]+section[ \t]+([0-9]+)/([0-9]+)[ \t]+UUXFER "
  163. X            "ver [^ \t]+ by David M. Read"
  164. X            {
  165. X                id 1
  166. X                segment number 2
  167. X                segments 3
  168. X                alternate id 0
  169. X                case sensitive
  170. X            }
  171. X        }
  172. X    }
  173. X}
  174. END_OF_FILE
  175.   if test 3793 -ne `wc -c <'cfg/cbip.cfg'`; then
  176.     echo shar: \"'cfg/cbip.cfg'\" unpacked with wrong size!
  177.   fi
  178.   # end of 'cfg/cbip.cfg'
  179. fi
  180. if test -f 'cfg/def.cfg' -a "${1}" != "-c" ; then 
  181.   echo shar: Will not clobber existing file \"'cfg/def.cfg'\"
  182. else
  183.   echo shar: Extracting \"'cfg/def.cfg'\" \(5229 characters\)
  184.   sed "s/^X//" >'cfg/def.cfg' <<'END_OF_FILE'
  185. X#   This is the default configuration of UNPOST, shown in configuration
  186. X#   file format for instructional purposes, and for use in situations
  187. X#   where the default needs to be modified.
  188. X
  189. Xsegment "^(Article[:]?|X-NEWS:)"
  190. X{
  191. X    header
  192. X    {
  193. X        "^Subject:"
  194. X        {
  195. X            "^Subject:(.*)[[({]Part[_   ]*([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
  196. X            {
  197. X                id 1
  198. X                segment number 2
  199. X                segments 3
  200. X                alternate id 4
  201. X                case ignore
  202. X            }
  203. X            "^Subject:(.*)Part[_    ]*[[({]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
  204. X            {
  205. X                id 1
  206. X                segment number 2
  207. X                segments 3
  208. X                alternate id 4
  209. X                case ignore
  210. X            }
  211. X            "^Subject:(.*)Part[_    ]+([0-9]+)[^0-9]+([0-9]+)(.*)"
  212. X            {
  213. X                id 1
  214. X                segment number 2
  215. X                segments 3
  216. X                alternate id 4
  217. X                case ignore
  218. X            }
  219. X            "^Subject:(.*)[([{]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
  220. X            {
  221. X                id 1
  222. X                segment number 2
  223. X                segments 3
  224. X                alternate id 4
  225. X                case ignore
  226. X            }
  227. X            "^Subject:(.*)([0-9]+)([/|]|[ \t]+of[ \t]+)([0-9]+)(.*)"
  228. X            {
  229. X                id 1
  230. X                segment number 2
  231. X                segments 4
  232. X                alternate id 5
  233. X                case ignore
  234. X            }
  235. X            "^Subject:(.*)"
  236. X            {
  237. X                id 1
  238. X                segment number 0
  239. X                segments 0
  240. X                alternate id 0
  241. X                case ignore
  242. X            }
  243. X        }
  244. X        "^X-File-Name:"
  245. X        {
  246. X            "^X-File-Name:[     ]+(.*)"
  247. X            {
  248. X                id 1
  249. X                segment number 0
  250. X                segments 0
  251. X                 alternate id 0
  252. X                case sensitive
  253. X            }
  254. X        }
  255. X        "^X-Part:"
  256. X        {
  257. X            "^X-Part:[  ]+([0-9]+)"
  258. X            {
  259. X                id 0
  260. X                segment number 1
  261. X                segments 0
  262. X                alternate id 0
  263. X                case sensitive
  264. X            }
  265. X        }
  266. X        "^X-Part-Total:"
  267. X        {
  268. X            "^X-Part-Total:[    ]+([0-9]+)"
  269. X            {
  270. X                id 0
  271. X                segment number 0
  272. X                segments 1
  273. X                alternate id 0
  274. X                case sensitive
  275. X            }
  276. X        }
  277. X        "^Uusplit-part:"
  278. X        {
  279. X            "^Uusplit-part:[    ]+([0-9]+)"
  280. X            {
  281. X                id 0
  282. X                segment number 1
  283. X                segments 0
  284. X                alternate id 0
  285. X                case sensitive
  286. X            }
  287. X        }
  288. X        "^Uusplit-parts:"
  289. X        {
  290. X            "^Uusplit-parts:[   ]+([0-9]+)"
  291. X            {
  292. X                id 0
  293. X                segment number 0
  294. X                segments 1
  295. X                alternate id 0
  296. X                case sensitive
  297. X            }
  298. X        }
  299. X    }
  300. X    body
  301. X    {
  302. X        "^section [0-9]+ of uuencode [0-9]+\.[0-9]+ of file "
  303. X        "[^     ]+    by R.E.M."
  304. X        {
  305. X            "^section ([0-9]+) of uuencode [0-9]+\.[0-9]+ of file "
  306. X            "([^    ]+)[    ]+by R.E.M."
  307. X            {
  308. X                id 2
  309. X                segment number 1
  310. X                segments 0
  311. X                alternate id 0
  312. X                case sensitive
  313. X            }
  314. X        }
  315. X        "^[^    ]+[     ]+section[  ]+[0-9]+/[0-9]+[    ]+UUXFER "
  316. X        "ver [^     ]+ by David M. Read"
  317. X         {
  318. X            "^([^ \t]+)[ \t]+section[ \t]+([0-9]+)/([0-9]+)[ \t]+UUXFER "
  319. X            "ver [^ \t]+ by David M. Read"
  320. X            {
  321. X                id 1
  322. X                segment number 2
  323. X                segments 3
  324. X                alternate id 0
  325. X                case sensitive
  326. X            }
  327. X        }
  328. X        "^Subject:"
  329. X        {
  330. X            "^Subject:(.*)[[({]Part[_   ]*([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
  331. X            {
  332. X                id 1
  333. X                segment number 2
  334. X                segments 3
  335. X                alternate id 4
  336. X                case ignore
  337. X            }
  338. X            "^Subject:(.*)Part[_    ]*[[({]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
  339. X            {
  340. X                id 1
  341. X                segment number 2
  342. X                segments 3
  343. X                alternate id 4
  344. X                case ignore
  345. X            }
  346. X            "^Subject:(.*)Part[_    ]+([0-9]+)[^0-9]+([0-9]+)(.*)"
  347. X            {
  348. X                id 1
  349. X                segment number 2
  350. X                segments 3
  351. X                alternate id 4
  352. X                case ignore
  353. X            }
  354. X            "^Subject:(.*)[([{]([0-9]+)[^0-9]+([0-9]+)[)\]}](.*)"
  355. X            {
  356. X                id 1
  357. X                segment number 2
  358. X                segments 3
  359. X                alternate id 4
  360. X                case ignore
  361. X            }
  362. X            "^Subject:(.*)([0-9]+)([/|]|[ \t]+of[ \t]+)([0-9]+)(.*)"
  363. X            {
  364. X                id 1
  365. X                segment number 2
  366. X                segments 4
  367. X                alternate id 5
  368. X                case ignore
  369. X            }
  370. X            "^Subject:(.*)"
  371. X            {
  372. X                id 1
  373. X                segment number 0
  374. X                segments 0
  375. X                alternate id 0
  376. X                case ignore
  377. X            }
  378. X        }
  379. X    }
  380. X}
  381. END_OF_FILE
  382.   if test 5229 -ne `wc -c <'cfg/def.cfg'`; then
  383.     echo shar: \"'cfg/def.cfg'\" unpacked with wrong size!
  384.   fi
  385.   # end of 'cfg/def.cfg'
  386. fi
  387. if test -f 'compiler.h' -a "${1}" != "-c" ; then 
  388.   echo shar: Will not clobber existing file \"'compiler.h'\"
  389. else
  390.   echo shar: Extracting \"'compiler.h'\" \(4622 characters\)
  391.   sed "s/^X//" >'compiler.h' <<'END_OF_FILE'
  392. X/******************************************************************************
  393. X* Module    :   Compiler include files, separated out to make configuration
  394. X*               different systems a little easier (I hate this, I really
  395. X*               hate this, but it has been requested, so here it is).
  396. X*
  397. X* Author    :   John W. M. Stevens
  398. X******************************************************************************/
  399. X
  400. X#include    <stdio.h>
  401. X#include    <stdlib.h>
  402. X#include    <ctype.h>
  403. X#include    <errno.h>
  404. X#include    <string.h>
  405. X
  406. X/*=============================================================================
  407. X*   Configure the program. . .
  408. X*
  409. X*   WARNING!  Be sure what you are doing here. . .
  410. X=============================================================================*/
  411. X
  412. X/*  Debug macro.  Uncomment to get debug output.    */
  413. X/*  #define UNPOST_DEBUG    1   */
  414. X
  415. X/*  Uncomment to give you different file name munging under OS/2
  416. X*   on the basis of the File System.
  417. X*
  418. X*   Suggestions and help courtesy of:
  419. X*
  420. X*   Darrel R Hankerson <hankedr@mail.auburn.edu>
  421. X*
  422. X*   Without whose help and discussion, this would not have been done.
  423. X*   In other words, blame it all on him. . . :-)
  424. X*/
  425. X/*  #define     MUNGE_FILE_NAMES_PER_FS     1   */
  426. X
  427. X/*  Change the one to a zero to make file name mungling default to
  428. X*   being off.
  429. X*/
  430. X#define     MUNGE_FILE_NMS      1
  431. X
  432. X/*  Change the one to a zero to make description file dumping
  433. X*   default to being off.
  434. X*/
  435. X#define     DUMP_DESC_FILES     1
  436. X
  437. X/*  Change zero to one to make incompletes separation be turned on
  438. X*   by default.
  439. X*/
  440. X#define     SEP_INCOMPLETES     0
  441. X
  442. X/*-----------------------------------------------------------------------------
  443. X*   Compiler specific stuff below.
  444. X*
  445. X*   The first set is for the Lattice C compiler on the Amiga.
  446. X-----------------------------------------------------------------------------*/
  447. X#if     defined(LATTICE_C_COMPILER)
  448. X
  449. X/*  Defines for fopen calls.    */
  450. X#define     TXT_APPEND  "at"
  451. X#define     TXT_READ    "rt"
  452. X#define     BIN_READ    "rb"
  453. X#define     TXT_WRITE   "wt"
  454. X#define     BIN_WRITE   "wb"
  455. X
  456. X#define     SEEK_SET    0
  457. X
  458. X/*-----------------------------------------------------------------------------
  459. X*   This set is for the GCC compiler on Unix systems.
  460. X-----------------------------------------------------------------------------*/
  461. X#elif   defined(GCC_COMPILER)
  462. X
  463. X/*  Defines for fopen calls.    */
  464. X#define     TXT_APPEND  "at"
  465. X#define     TXT_READ    "rt"
  466. X#define     BIN_READ    "rb"
  467. X#define     TXT_WRITE   "wt"
  468. X#define     BIN_WRITE   "wb"
  469. X
  470. X#include    <malloc.h>
  471. X#include    <unistd.h>
  472. X
  473. Xextern  char    *sys_errlist[];
  474. X
  475. X/*-----------------------------------------------------------------------------
  476. X*   The GCC compiler on OS/2.
  477. X-----------------------------------------------------------------------------*/
  478. X#elif   defined(EMX_GCC_COMPILER)
  479. X
  480. X/*  Defines for fopen calls.    */
  481. X#define     TXT_APPEND  "at"
  482. X#define     TXT_READ    "rt"
  483. X#define     BIN_READ    "rb"
  484. X#define     TXT_WRITE   "wt"
  485. X#define     BIN_WRITE   "wb"
  486. X
  487. X#include    <sys/types.h>
  488. X#include    <sys/stat.h>
  489. X
  490. X#if defined(SYSTEM_OS_2)
  491. X#define INCL_DOSFILEMGR
  492. X#include    <os2.h>
  493. X#else
  494. X#include    <dos.h>
  495. X#endif
  496. X
  497. X#include    <malloc.h>
  498. X#include    <unistd.h>
  499. X
  500. X/*-----------------------------------------------------------------------------
  501. X*   The MSC compiler on OS/2.
  502. X-----------------------------------------------------------------------------*/
  503. X#elif   defined(OS_2_MSC_COMPILER)
  504. X
  505. X/*  Defines for fopen calls.    */
  506. X#define     TXT_APPEND  "at"
  507. X#define     TXT_READ    "rt"
  508. X#define     BIN_READ    "rb"
  509. X#define     TXT_WRITE   "wt"
  510. X#define     BIN_WRITE   "wb"
  511. X
  512. X#include    <sys/types.h>
  513. X#include    <sys/stat.h>
  514. X
  515. X#if defined(SYSTEM_OS_2)
  516. X#define INCL_DOSFILEMGR
  517. X#include    <os2.h>
  518. X#else
  519. X#include    <dos.h>
  520. X#endif
  521. X
  522. X/*-----------------------------------------------------------------------------
  523. X*   The BCC compiler on MS-DOS.
  524. X-----------------------------------------------------------------------------*/
  525. X#elif   defined(BCC_COMPILER)
  526. X
  527. X/*  Defines for fopen calls.    */
  528. X#define     TXT_APPEND  "at"
  529. X#define     TXT_READ    "rt"
  530. X#define     BIN_READ    "rb"
  531. X#define     TXT_WRITE   "wt"
  532. X#define     BIN_WRITE   "wb"
  533. X
  534. X#include    <malloc.h>
  535. X
  536. X/*-----------------------------------------------------------------------------
  537. X*   All others (Non-ANSI compatible).
  538. X-----------------------------------------------------------------------------*/
  539. X#else
  540. X
  541. X/*  Defines for fopen calls.    */
  542. X#define     TXT_APPEND  "a"
  543. X#define     TXT_READ    "r"
  544. X#define     BIN_READ    "r"
  545. X#define     TXT_WRITE   "w"
  546. X#define     BIN_WRITE   "w"
  547. X
  548. X#include    <malloc.h>
  549. X
  550. X#endif
  551. END_OF_FILE
  552.   if test 4622 -ne `wc -c <'compiler.h'`; then
  553.     echo shar: \"'compiler.h'\" unpacked with wrong size!
  554.   fi
  555.   # end of 'compiler.h'
  556. fi
  557. if test -f 'list.c' -a "${1}" != "-c" ; then 
  558.   echo shar: Will not clobber existing file \"'list.c'\"
  559. else
  560.   echo shar: Extracting \"'list.c'\" \(6508 characters\)
  561.   sed "s/^X//" >'list.c' <<'END_OF_FILE'
  562. X/******************************************************************************
  563. X* Module    :   List --- List building and maintenance module.
  564. X*
  565. X* Author    :   John Stevens.
  566. X******************************************************************************/
  567. X
  568. X#include    "compiler.h"
  569. X
  570. X#include    "unpost.h"
  571. X#include    "list.h"
  572. X#include    "utils.h"
  573. X
  574. X#define INIT_SIZE   2
  575. X#define INCREASE    5
  576. X
  577. X/*-----------------------------------------------------------------------------
  578. X| Routine   :   AddList() --- Add an element to a list.
  579. X|
  580. X| Inputs    :   Head    - Pointer to begining of list.
  581. X|               Elem    - New element to add to list.
  582. X|               InsPt   - List ordinal for add.
  583. X|
  584. X| Returns   :   Pointer to list head.
  585. X-----------------------------------------------------------------------------*/
  586. X
  587. Xvoid    *AddList(LIST   *Head,
  588. X                 void   *Elem,
  589. X                 int    InsPt)
  590. X{
  591. X    auto        char    *List;
  592. X    extern      FILE    *ErrFile;
  593. X
  594. X    /*  Create or add to list.  */
  595. X    if (Head->NoElems >= Head->TotElems)
  596. X    {
  597. X        auto    int     NewSize;
  598. X
  599. X        /*  Reallocate the list header. */
  600. X        NewSize = (Head->TotElems + INCREASE) * Head->ElemSz + sizeof( LIST );
  601. X        if ((Head = (LIST *) realloc(Head, NewSize)) == NULL)
  602. X        {
  603. X            fprintf(ErrFile,
  604. X                    "%s %d : Error - Out of memory.\n",
  605. X                    __FILE__,
  606. X                    __LINE__);
  607. X            exit( 1 );
  608. X        }
  609. X
  610. X        /*  Update list size.   */
  611. X        Head->TotElems += INCREASE;
  612. X    }
  613. X
  614. X    /*  Move list elements up to make room. */
  615. X    List = Head->List + Head->ElemSz * InsPt;
  616. X    if (InsPt < Head->NoElems)
  617. X    {
  618. X        MemMove(List +  Head->ElemSz,
  619. X                List,
  620. X                Head->ElemSz * (Head->NoElems - InsPt));
  621. X    }
  622. X
  623. X    /*  Copy new element to it's proper location.   */
  624. X    MemCopy(List, Elem, Head->ElemSz);
  625. X    Head->NoElems++;
  626. X    return( Head );
  627. X}
  628. X
  629. X/*-----------------------------------------------------------------------------
  630. X| Routine   :   CrtList() --- Create a new (empty) list.
  631. X|
  632. X| Inputs    :   ElemSz  - Size of element in bytes.
  633. X|
  634. X| Returns   :   Pointer to list head.
  635. X-----------------------------------------------------------------------------*/
  636. X
  637. Xvoid    *CrtList(int    ElemSz)
  638. X{
  639. X    auto    LIST    *Head;
  640. X    auto    int     Size;
  641. X    extern  FILE    *ErrFile;
  642. X
  643. X    /*  Calculate the size of the new list and allocate it. */
  644. X    Size = INIT_SIZE * ElemSz + sizeof( LIST );
  645. X    if ((Head = (LIST *) calloc(1, Size)) == NULL)
  646. X    {
  647. X        fprintf(ErrFile,
  648. X                "%s %d : Error - Out of memory.\n",
  649. X                __FILE__,
  650. X                __LINE__);
  651. X        exit( 1 );
  652. X    }
  653. X
  654. X    /*  Return the pointer to the list. */
  655. X    Head->ElemSz = ElemSz;
  656. X    Head->TotElems = INIT_SIZE;
  657. X    return( Head );
  658. X}
  659. X
  660. X/*-----------------------------------------------------------------------------
  661. X| Routine   :   SrchList() --- Search the list.
  662. X|
  663. X| Inputs    :   Head    - Pointer to begining of list.
  664. X|               Elem    - Element to search list for.
  665. X|               CmpFn   - Function to compare in search.
  666. X| Outputs   :   InsPt   - List pointer for insert/found.
  667. X|
  668. X| Returns   :   TRUE for found, FALSE for not found.
  669. X-----------------------------------------------------------------------------*/
  670. X
  671. Xint     SrchList(LIST   *Head,
  672. X                 void   *Elem,
  673. X                 int    (*CmpFn)(void *, void *),
  674. X                 int    *InsPt)
  675. X{
  676. X    /*  Search the list for an element.
  677. X    *
  678. X    *   Do binary search.
  679. X    */
  680. X    if (Head->NoElems > 0)
  681. X    {
  682. X        auto    char    *List;
  683. X        auto    int     hi;
  684. X        auto    int     lo;
  685. X        auto    int     ret;
  686. X        auto    int     mid;
  687. X
  688. X        lo = 0;
  689. X        hi = Head->NoElems - 1;
  690. X        do
  691. X        {
  692. X            /*  Get midpoint of list.   */
  693. X            mid = (hi + lo) >> 1;
  694. X            List = Head->List + Head->ElemSz * mid;
  695. X
  696. X            /*  Do string compare.  */
  697. X            ret = CmpFn(Elem, List);
  698. X
  699. X            /*  Adjust array pointers.  */
  700. X            if (ret <= 0)
  701. X                hi = mid - 1;
  702. X            if (ret >= 0)
  703. X                lo = mid + 1;
  704. X        } while (hi >= lo);
  705. X
  706. X        /*  Did we find it? */
  707. X        if (ret == 0)
  708. X        {
  709. X            /*  We found it.    */
  710. X            *InsPt = mid;
  711. X            return( TRUE );
  712. X        }
  713. X
  714. X        /*  We did not find it. */
  715. X        *InsPt = lo;
  716. X        return( FALSE );
  717. X    }
  718. X
  719. X    /*  Return that we did not find it, and the point at
  720. X    *   which it should be inserted.
  721. X    */
  722. X    *InsPt = 0;
  723. X    return( FALSE );
  724. X}
  725. X
  726. X/*-----------------------------------------------------------------------------
  727. X| Routine   :   ListIdx() --- Get pointer to a list element.
  728. X|
  729. X| Inputs    :   Head    - Pointer to begining of list.
  730. X|               Index   - Index of element to return pointer for.
  731. X|
  732. X| Returns   :   NULL for index outside of list limits, Pointer to list
  733. X|               element otherwise.
  734. X-----------------------------------------------------------------------------*/
  735. X
  736. Xvoid    *ListIdx(LIST   *Head,
  737. X                 int    Index)
  738. X{
  739. X    /*  Determine if index is inside list limits.   */
  740. X    if (Index < 0 || Index >= Head->NoElems)
  741. X        return( NULL );
  742. X    return( Head->List + Index * Head->ElemSz );
  743. X}
  744. X
  745. X/*-----------------------------------------------------------------------------
  746. X| Routine   :   AppList() --- Append an element to a list.
  747. X|
  748. X| Inputs    :   Head    - Pointer to begining of list.
  749. X|               Elem    - New element to add to list.
  750. X|
  751. X| Returns   :   Pointer to list head.
  752. X-----------------------------------------------------------------------------*/
  753. X
  754. Xvoid    *AppList(LIST   *Head,
  755. X                 void   *Elem)
  756. X{
  757. X    auto        char    *List;
  758. X    extern      FILE    *ErrFile;
  759. X
  760. X    /*  Create or add to list.  */
  761. X    if (Head->NoElems >= Head->TotElems)
  762. X    {
  763. X        auto    int     NewSize;
  764. X
  765. X        /*  Reallocate the list header. */
  766. X        NewSize = (Head->TotElems + INCREASE) * Head->ElemSz + sizeof( LIST );
  767. X        if ((Head = (LIST *) realloc(Head, NewSize)) == NULL)
  768. X        {
  769. X            fprintf(ErrFile,
  770. X                    "%s %d : Error - Out of memory.\n",
  771. X                    __FILE__,
  772. X                    __LINE__);
  773. X            exit( 1 );
  774. X        }
  775. X
  776. X        /*  Update list size.   */
  777. X        Head->TotElems += INCREASE;
  778. X    }
  779. X
  780. X    /*  Copy new element to it's proper location.   */
  781. X    List = Head->List + Head->ElemSz * Head->NoElems;
  782. X    MemCopy(List, Elem, Head->ElemSz);
  783. X    Head->NoElems++;
  784. X    return( Head );
  785. X}
  786. END_OF_FILE
  787.   if test 6508 -ne `wc -c <'list.c'`; then
  788.     echo shar: \"'list.c'\" unpacked with wrong size!
  789.   fi
  790.   # end of 'list.c'
  791. fi
  792. if test -f 'modflnm.c' -a "${1}" != "-c" ; then 
  793.   echo shar: Will not clobber existing file \"'modflnm.c'\"
  794. else
  795.   echo shar: Extracting \"'modflnm.c'\" \(8353 characters\)
  796.   sed "s/^X//" >'modflnm.c' <<'END_OF_FILE'
  797. X/******************************************************************************
  798. X* Module    :   File Names --- File name utilities.
  799. X*
  800. X* Author    :   John W. M. Stevens
  801. X******************************************************************************/
  802. X
  803. X#include    "compiler.h"
  804. X
  805. X#include    "unpost.h"
  806. X#include    "sets.h"
  807. X#include    "modflnm.h"
  808. X
  809. X/*  Sets.   */
  810. Xstatic      int     InitSets = 1;
  811. Xstatic      SET     StandSet;
  812. Xstatic      SET     ThrowSet;
  813. Xstatic      SET     NoSet;
  814. Xstatic      SET     AlphaSet;
  815. X
  816. X/*  Strings for character sets. */
  817. Xstatic      char    *Stand = "a-z0-9_.-";
  818. Xstatic      char    *Throw = "aeiouy_-";
  819. Xstatic      char    *Numbers = "0-9";
  820. Xstatic      char    *Alpha = "a-z";
  821. X
  822. X/*-----------------------------------------------------------------------------
  823. X| Routine   :   ChkFlNmLen() --- Check the file name length.
  824. X|
  825. X| Inputs    :   FileName    - File name.
  826. X-----------------------------------------------------------------------------*/
  827. X
  828. Xstatic
  829. Xint     ChkFlNmLen(char     *FileNm)
  830. X{
  831. X    register    int     i;
  832. X
  833. X    /*  Count file characters.  */
  834. X    for (i = 0;
  835. X         FileNm[i] && FileNm[i] != EXT_SEP_CHAR;
  836. X         i++)
  837. X        ;
  838. X
  839. X    /*  Return True or False.   */
  840. X    return( i );
  841. X}
  842. X
  843. X/*-----------------------------------------------------------------------------
  844. X| Routine   :   FlNmFilter() --- Filter a string so that only characters from
  845. X|               the set of standard file name characters are left.
  846. X|
  847. X| Inputs    :
  848. X-----------------------------------------------------------------------------*/
  849. X
  850. Xvoid    FlNmFilter(char     *FlName)
  851. X{
  852. X    auto        char    *cp;
  853. X    auto        char    *tp;
  854. X    auto        char    c;
  855. X
  856. X    /*  Create character sets.  */
  857. X    if ( InitSets )
  858. X    {
  859. X        tp = Stand;
  860. X        CrtSet(&tp, StandSet);
  861. X        tp = Throw;
  862. X        CrtSet(&tp, ThrowSet);
  863. X        tp = Numbers;
  864. X        CrtSet(&tp, NoSet);
  865. X        tp = Alpha;
  866. X        CrtSet(&tp, AlphaSet);
  867. X        InitSets = 0;
  868. X    }
  869. X
  870. X    /*  Convert string to lower case and strip out illegal characters.  */
  871. X    for (cp = tp = FlName; *tp; tp++)
  872. X    {
  873. X        /*  First, convert to lower case.   */
  874. X        c = (char) tolower( *tp );
  875. X
  876. X        /*  Next, check for standards conformity.   */
  877. X        if (c == ' ' || c == '\t' || InSet(StandSet, c))
  878. X            *cp++ = c;
  879. X    }
  880. X    *cp = '\0';
  881. X}
  882. X
  883. X/*-----------------------------------------------------------------------------
  884. X| Routine   :   ModifyFlNm() --- Convert to lower case and make sure that
  885. X|               this file name conforms to MS-DOS restrictions/limitations
  886. X|               and USENET posting standards.
  887. X|
  888. X| Inputs    :   FlName  - File name.
  889. X|               Ext     - Extension.
  890. X| Outputs   :   OutName - Modified file name.
  891. X-----------------------------------------------------------------------------*/
  892. X
  893. Xint     ModifyFlNm(char     *FlName,
  894. X                   char     *Ext,
  895. X                   char     *OutName)
  896. X{
  897. X    register    int     i;
  898. X    auto        int     len;
  899. X    auto        int     ChopFlag;
  900. X    auto        char    *cp;
  901. X    auto        char    *tp;
  902. X    auto        char    c;
  903. X    extern      FILE    *ErrFile;
  904. X
  905. X    /*  Create character sets.  */
  906. X    if ( InitSets )
  907. X    {
  908. X        tp = Stand;
  909. X        CrtSet(&tp, StandSet);
  910. X        tp = Throw;
  911. X        CrtSet(&tp, ThrowSet);
  912. X        tp = Numbers;
  913. X        CrtSet(&tp, NoSet);
  914. X        tp = Alpha;
  915. X        CrtSet(&tp, AlphaSet);
  916. X        InitSets = 0;
  917. X    }
  918. X
  919. X    /*  Convert string to lower case and strip out illegal characters.  */
  920. X    for (cp = OutName, tp = FlName; *tp; tp++)
  921. X    {
  922. X        /*  First, convert to lower case.   */
  923. X        c = (char) tolower( *tp );
  924. X
  925. X        /*  Next, check for standards conformity.   */
  926. X        if ( InSet(StandSet, c) )
  927. X            *cp++ = c;
  928. X    }
  929. X    *cp = '\0';
  930. X
  931. X    /*  If we have more than MAX_FILE characters in the file name,
  932. X    *   then shorten the file name.
  933. X    */
  934. X    if ((len = ChkFlNmLen( OutName )) > MAX_FILE)
  935. X    {
  936. X        /*  Shorten by removing vowels and separator characters.    */
  937. X        for (tp = cp = OutName, i = len;
  938. X             *tp && *tp != EXT_SEP_CHAR && i > MAX_FILE;
  939. X             tp++)
  940. X        {
  941. X            /*  If this is not a throw away character, save it back
  942. X            *   in the string.
  943. X            */
  944. X            if (! InSet(ThrowSet, *tp))
  945. X            {
  946. X                *cp++ = *tp;
  947. X                continue;
  948. X            }
  949. X            else if (tp == OutName)
  950. X            {
  951. X                *cp++ = *tp;
  952. X                continue;
  953. X            }
  954. X
  955. X            /*  Decrement the file name size.   */
  956. X            i--;
  957. X        }
  958. X        strcpy(cp, tp);
  959. X    }
  960. X    else
  961. X        goto ShortEnough;
  962. X
  963. X    /*  If we still have more than MAX_FILE characters in the file
  964. X    *   name, chop off leading zeros in any numeric strings in the
  965. X    *   file name.
  966. X    */
  967. X    if ((len = ChkFlNmLen( OutName )) > MAX_FILE)
  968. X    {
  969. X        /*  Loop through string.    */
  970. X        for (tp = cp = OutName, i = len;
  971. X             *tp && *tp != EXT_SEP_CHAR && i > MAX_FILE;
  972. X             tp++)
  973. X        {
  974. X            /*  If this is a numeric sub-string, strip any leading
  975. X            *   zeros.
  976. X            */
  977. X            if (tp[1] && tp[1] != '.' &&
  978. X                InSet(NoSet, *tp) && InSet(NoSet, tp[1]) &&
  979. X                *tp == '0')
  980. X            {
  981. X                i--;
  982. X                continue;
  983. X            }
  984. X
  985. X            /*  Copy character in.  */
  986. X            *cp++ = *tp;
  987. X        }
  988. X        strcpy(cp, tp);
  989. X    }
  990. X    else
  991. X        goto ShortEnough;
  992. X
  993. X    /*  If we still have more than MAX_FILE characters in the file name, chop
  994. X    *   alphabetic strings short by throwing away excess characters.
  995. X    */
  996. X    while ((len = ChkFlNmLen( OutName )) > MAX_FILE)
  997. X    {
  998. X        /*  Loop through string.    */
  999. X        for (tp = cp = OutName, ChopFlag = 0, i = len;
  1000. X             *tp && *tp != EXT_SEP_CHAR && i > MAX_FILE;
  1001. X             tp++)
  1002. X        {
  1003. X            /*  Do not throw away numeric characters at this point. */
  1004. X            if ( InSet(NoSet, *tp) )
  1005. X            {
  1006. X                *cp++ = *tp;
  1007. X                continue;
  1008. X            }
  1009. X
  1010. X            /*  Throw away the trailing character in an alphabetic
  1011. X            *   substring.
  1012. X            */
  1013. X            if (*tp && tp[1] != EXT_SEP_CHAR &&
  1014. X                InSet(AlphaSet, *tp) && InSet(AlphaSet, tp[1]))
  1015. X            {
  1016. X                *cp++ = *tp;
  1017. X                continue;
  1018. X            }
  1019. X
  1020. X            /*  Yup, we are chopping out a character.   */
  1021. X            i--;
  1022. X            ChopFlag = 1;
  1023. X        }
  1024. X        strcpy(cp, tp);
  1025. X
  1026. X        /*  If not even one character is chopped out in a pass
  1027. X        *   through the file name list, drop out and issue an
  1028. X        *   error.
  1029. X        */
  1030. X        if (ChopFlag == 0)
  1031. X        {
  1032. X            fprintf(ErrFile,
  1033. X                    "%s %d : Error - Could not modify file name to be ",
  1034. X                    __FILE__,
  1035. X                    __LINE__);
  1036. X            fprintf(ErrFile,
  1037. X                    "MS-DOS conformant.\n");
  1038. X            return( 1 );
  1039. X        }
  1040. X    }
  1041. X
  1042. X    /*  Done with file name, now fix extension. */
  1043. XShortEnough:
  1044. X    for (tp = OutName;
  1045. X         *tp && *tp != EXT_SEP_CHAR;
  1046. X         tp++)
  1047. X        ;
  1048. X    if (*tp == EXT_SEP_CHAR)
  1049. X    {
  1050. X        /*  Were we able to identify this file? */
  1051. X        if ( *Ext )
  1052. X            strcpy(tp, Ext);
  1053. X        else
  1054. X        {
  1055. X            /*  Move four characters across (including '.') and we
  1056. X            *   are done.
  1057. X            */
  1058. X            for (i = 0, tp++;
  1059. X                 *tp && *tp != EXT_SEP_CHAR && i < MAX_EXT;
  1060. X                 i++, tp++)
  1061. X                ;
  1062. X            *tp = '\0';
  1063. X        }
  1064. X    }
  1065. X    else
  1066. X    {
  1067. X        /*  No extension, so append one.    */
  1068. X        strcpy(tp, Ext);
  1069. X    }
  1070. X
  1071. X    /*  Return no error.    */
  1072. X    return( 0 );
  1073. X}
  1074. X
  1075. X/*-----------------------------------------------------------------------------
  1076. X| Routine   :   ModExten() --- Modify the file name extension.
  1077. X|
  1078. X| Inputs    :   FlName  - File name.
  1079. X-----------------------------------------------------------------------------*/
  1080. X
  1081. Xvoid    ModExten(char   *FlName,
  1082. X                 char   *Exten,
  1083. X                 char   *OutFlNm)
  1084. X{
  1085. X    auto    char    *tp;
  1086. X    auto    char    *op;
  1087. X
  1088. X    /*  Search for the first file name extension separator character.   */
  1089. X    for (tp = FlName, op = OutFlNm;
  1090. X         *tp && *tp != EXT_SEP_CHAR;
  1091. X         )
  1092. X        *op++ = *tp++;
  1093. X
  1094. X    /*  Copy in new extension.  */
  1095. X    strcpy(op, Exten);
  1096. X}
  1097. END_OF_FILE
  1098.   if test 8353 -ne `wc -c <'modflnm.c'`; then
  1099.     echo shar: \"'modflnm.c'\" unpacked with wrong size!
  1100.   fi
  1101.   # end of 'modflnm.c'
  1102. fi
  1103. if test -f 'nntp/client.doc' -a "${1}" != "-c" ; then 
  1104.   echo shar: Will not clobber existing file \"'nntp/client.doc'\"
  1105. else
  1106.   echo shar: Extracting \"'nntp/client.doc'\" \(6565 characters\)
  1107.   sed "s/^X//" >'nntp/client.doc' <<'END_OF_FILE'
  1108. XCLIENT
  1109. X
  1110. XName:
  1111. X
  1112. X    client - Attach to an NNTP (network news transfer protocol) server,
  1113. X             extract all unread postings to the specified newsgroup
  1114. X             and write them to a specified file.
  1115. X
  1116. XSynopsis:
  1117. X
  1118. X    client <server name> <configuration file>
  1119. X
  1120. XDescription:
  1121. X
  1122. X    CLIENT is a program that is designed to act as an assitant to
  1123. X    UNPOST.  It's primarily designed to create the files that UNPOST
  1124. X    works on.  It is very simple, and quite stupid.
  1125. X
  1126. X    It starts by attempting to get the server address from the
  1127. X    /etc/hosts file based on the server name given on the command
  1128. X    line, then it attempts to get the NNTP foreign port number (which,
  1129. X    according to the spec, should ALWAYS be 119, but I decided not to
  1130. X    take any chances) and then connect to the NNTP News server.
  1131. X
  1132. X    If CLIENT successfully connects to the server, it opens the
  1133. X    configuration file and reads a line from it.
  1134. X
  1135. X    These lines should look like:
  1136. X
  1137. X    group <news group name> <file name> <next article number>
  1138. X
  1139. X    Where news group name is the name of the news group that you want
  1140. X    CLIENT to read from, file name is the name of the file you want
  1141. X    CLIENT to write all articles to, and next article number is
  1142. X    the first article number to read.
  1143. X
  1144. X    Example:
  1145. X
  1146. X    group alt.binaries.pictures.utilites abpu.uue 231
  1147. X
  1148. X    Which says read from group alt.binaries.pictures.utilities, write
  1149. X    all unread articles (all articles with numbers greater than or
  1150. X    equal to 231) to a file called abpu.uue.
  1151. X
  1152. X    After reading every unread article from a.b.p.u and writing them to
  1153. X    the file abpu.uue, CLIENT will read the next line from the
  1154. X    configuration file and start all over again.
  1155. X
  1156. X    After reading all articles from all of the specified news groups,
  1157. X    CLIENT will rewrite the configuration file to specify the next
  1158. X    new article number and then close the connection to the News
  1159. X    server and exit.
  1160. X
  1161. XOptions:
  1162. X
  1163. X    <server name>           - Internet server name, example: news.llmt.org
  1164. X
  1165. X    <configuration file>    - Name of configuration file.
  1166. X
  1167. XStandards:
  1168. X
  1169. X    CLIENT follows the standard described in RFC 977.
  1170. X
  1171. XNotes:
  1172. X
  1173. X    To use this program to collect all of the binaries posted to, say,
  1174. X    the alt.binaries.misc group on a daily basis, create a configuration
  1175. X    file that looks like:
  1176. X
  1177. X    group alt.binaries.misc abm.uue 0
  1178. X
  1179. X    and is named client.cfg.
  1180. X
  1181. X    Then you need to set up a script that calls client on a daily basis,
  1182. X    using the CRON or AT facility.  See your local man pages for these
  1183. X    services.
  1184. X
  1185. X    The script should contain the line:
  1186. X
  1187. X    client news.llmat.org client.cfg 2> client.err
  1188. X
  1189. X    Be aware that if you use AT or CRON, you may need to add path names
  1190. X    to both the script, and the file names in the configuration file.
  1191. X
  1192. XDiagnostics:
  1193. X
  1194. X    Error in writing to news server.
  1195. X        Return = #, Error number = #
  1196. X
  1197. X        CLIENT tried to write a message to the server, but there
  1198. X        was an error.  If you are C fluent, you might look in errno.h
  1199. X        to see what the Error number means, if anything.
  1200. X
  1201. X        I can't do anything about this error, sorry.
  1202. X
  1203. X    Error in reading from news server.
  1204. X        Return = #, Error number = #
  1205. X
  1206. X        CLIENT tried to read a message from the server, but there
  1207. X        was an error.  If you are C fluent, you might look in errno.h
  1208. X        to see what the Error number means, if anything.
  1209. X
  1210. X        I can't do anything about this error, sorry.
  1211. X
  1212. X    Error, response to ARTICLE = #.
  1213. X
  1214. X        CLIENT asked for an article and got back the status # from
  1215. X        the server.  Most probably, # will be 221, 222 or 223.
  1216. X
  1217. X    Error, no news group selected.
  1218. X
  1219. X        Ooops.  This shouldn't happen.  Somehow, CLIENT thinks that
  1220. X        it's GROUP selection command was succesful, and the server
  1221. X        disagrees.
  1222. X
  1223. X    Error, no current article selected.
  1224. X
  1225. X        Same as above, CLIENT and server disagree about the success
  1226. X        of an ARTICLE command.
  1227. X
  1228. X    Warning - saw '\\n' before '\\r'.
  1229. X    Warning - saw '.\\r' but no '\\n'.
  1230. X    Warning - saw '.\\r' but no '\\n'.
  1231. X
  1232. X        The standard says that all lines are terminated with a carriage
  1233. X        return followed by a line feed.  Either the order is wrong
  1234. X        (LF-CR), or there is a missing line feed, or a missing
  1235. X        carriage return.
  1236. X
  1237. X    Warning - did not use all of article.
  1238. X
  1239. X        The server sent the whole article, but for some reason CLIENT
  1240. X        decided that it saw a ".\r\n" before the actual end of the
  1241. X        article text.  (".\r\n" is the end of an article, according
  1242. X        to the standard).
  1243. X
  1244. X    Error - Could not convert 'server' to a host address.
  1245. X
  1246. X        Evidently, there is no server named 'server' in the hosts table.
  1247. X        You can try the actual internet address, if you know it.
  1248. X
  1249. X    Error - bogus port number 'nntp'.
  1250. X
  1251. X        Couldn't find the NNTP port in the services table.
  1252. X
  1253. X    Error - could not connect to news server.
  1254. X
  1255. X        There are any number of reasons that you might get this message,
  1256. X        and some of them will be given in the error message given just
  1257. X        before this one.
  1258. X
  1259. X        One reason may be that the server is limited in the number of
  1260. X        clients it may serve at one time, and it may have refused
  1261. X        connection because it is at quota already.
  1262. X
  1263. X    Error, could not open configuration file.
  1264. X
  1265. X        Couldn't find the file, couldn't read it, whatever.
  1266. X
  1267. X    Error, could not open new configuration file.
  1268. X
  1269. X        CLIENT opens a temporary file to write the new configuration to
  1270. X        at the end, and for some reason, it couldn't create a new file
  1271. X        for writing.  Full disk, maybe?
  1272. X
  1273. X    Error - bad configuration file line.
  1274. X        'configuration file line'
  1275. X
  1276. X        Check the syntax of your configuration file.  The line given
  1277. X        is not correct, according to CLIENT.
  1278. X
  1279. X    Error, no such news group 's'.
  1280. X
  1281. X        According to the server, there is no such group as 's'.
  1282. X
  1283. X    No news in group 's'.
  1284. X
  1285. X        According to the server, there are no articles in news group
  1286. X        's'.
  1287. X
  1288. X    Error, could not open file 's' for writing.
  1289. X
  1290. X        CLIENT is attempting to open the file that you want the
  1291. X        articles for this group written to, but cannot, for some
  1292. X        reason.
  1293. X
  1294. XFuture:
  1295. X
  1296. X    I am planning to integrate CLIENT and UNPOST in the near future, as
  1297. X    CLIENT makes it easy to know where articles begin and end.
  1298. X
  1299. X    I will be modifying UNPOST to build either the current version
  1300. X    (work from a file) or to use CLIENT.
  1301. X
  1302. XBugs:
  1303. X
  1304. X    None currently known, but I'm sure that will change.
  1305. X
  1306. XAuthor:
  1307. X
  1308. X    John W. M. Stevens  -   jstevens@csn.org
  1309. END_OF_FILE
  1310.   if test 6565 -ne `wc -c <'nntp/client.doc'`; then
  1311.     echo shar: \"'nntp/client.doc'\" unpacked with wrong size!
  1312.   fi
  1313.   # end of 'nntp/client.doc'
  1314. fi
  1315. if test -f 'retest.c' -a "${1}" != "-c" ; then 
  1316.   echo shar: Will not clobber existing file \"'retest.c'\"
  1317. else
  1318.   echo shar: Extracting \"'retest.c'\" \(1892 characters\)
  1319.   sed "s/^X//" >'retest.c' <<'END_OF_FILE'
  1320. X/******************************************************************************
  1321. X* Module    :   Regular Expression Test Driver --- Test the regular expression
  1322. X*               package.
  1323. X*
  1324. X* Author    :   John Stevens
  1325. X******************************************************************************/
  1326. X
  1327. X#include    "compiler.h"
  1328. X
  1329. X#include    "sets.h"
  1330. X#include    "regexp.h"
  1331. X#include    "utils.h"
  1332. X
  1333. XFILE    *ErrFile = stderr;
  1334. X
  1335. Xint     main(int    argc,
  1336. X             char   **argv)
  1337. X{
  1338. X    register    int             i;
  1339. X    auto        REG_EXP_NODE    *ReExpr;
  1340. X    auto        FILE            *fp;
  1341. X    auto        char            **SubStrs;
  1342. X    auto        char            Bfr[256];
  1343. X
  1344. X    /*  Check command line parameters.  */
  1345. X    if (argc != 3)
  1346. X    {
  1347. X        fprintf(stderr,
  1348. X                "%s %d : Error - Syntax is: ",
  1349. X                __FILE__,
  1350. X                __LINE__);
  1351. X        fprintf(stderr,
  1352. X                "%s <regular expression> <file name>\n",
  1353. X                argv[0]);
  1354. X        exit( 1 );
  1355. X    }
  1356. X
  1357. X    /*  Compile the regular expression. */
  1358. X    ReExpr = ReCompile( argv[1] );
  1359. X
  1360. X    /*  Match against a line from a test file.  */
  1361. X    if ((fp = fopen(argv[2], TXT_READ)) == NULL)
  1362. X    {
  1363. X        fprintf(stderr,
  1364. X                "Error, could not open file '%s' for reading.\n",
  1365. X                argv[2]);
  1366. X        exit( 1 );
  1367. X    }
  1368. X
  1369. X    /*  Search file for matching regular expressions, and print all
  1370. X    *   matched sub-strings.
  1371. X    */
  1372. X    while (fgets(Bfr, 256, fp) != NULL)
  1373. X    {
  1374. X        /*  Attempt match.  */
  1375. X        SubStrs = NULL;
  1376. X        if (ReMatch(Bfr, CASE_SENSITIVE, ReExpr, &SubStrs) != 0)
  1377. X        {
  1378. X            /*  Print matching line and matching sub-strings.   */
  1379. X            printf("Line: '%s'\n", Bfr);
  1380. X            for (i = 0; i < MAX_SUB_EXPRS; i++)
  1381. X                if ( SubStrs[i] )
  1382. X                    printf("    #%2d: '%s'\n", i, SubStrs[i]);
  1383. X        }
  1384. X    }
  1385. X    return( 0 );
  1386. X}
  1387. END_OF_FILE
  1388.   if test 1892 -ne `wc -c <'retest.c'`; then
  1389.     echo shar: \"'retest.c'\" unpacked with wrong size!
  1390.   fi
  1391.   # end of 'retest.c'
  1392. fi
  1393. if test -f 'summary.doc' -a "${1}" != "-c" ; then 
  1394.   echo shar: Will not clobber existing file \"'summary.doc'\"
  1395. else
  1396.   echo shar: Extracting \"'summary.doc'\" \(6853 characters\)
  1397.   sed "s/^X//" >'summary.doc' <<'END_OF_FILE'
  1398. XUNPOST Version 2.1.0
  1399. X
  1400. XMore bug fixes, documentation updates, a new configuration file, etc.
  1401. X
  1402. XUNPOST is a "smart" uudecoder that is designed to extract binaries from
  1403. Xmulti-part USENET or email uuencoded binaries.
  1404. X
  1405. XFeatures:
  1406. X
  1407. X1)  PORTABILITY!  UNPOST has been compiled and sucessfully run on
  1408. X    MS-DOS, OS/2, Windows, Unix workstations, MacIntoshes, Amiga's
  1409. X    and VAX/VMS systems.
  1410. X
  1411. X    The code is written to be pure ANSI C, within reasonable limits.
  1412. X    (some ANSI C capabilities are not used where they would be
  1413. X    appropriate due to lagging compliance in most compilers.  Hey,
  1414. X    Unix types!  MS-DOS (Borland C++ 3.1) is a MUCH better compiler
  1415. X    than anything I've seen on a Unix workstation!  And their debugger
  1416. X    is the best I've used, as well).  Unfortunately, there are still
  1417. X    a lot of Unix boxes that have only a K&R compiler, so it may
  1418. X    not port well to those.  I personally check to make sure that it
  1419. X    will compile and run on an MS-DOS box running MS-DOS 5 and Windows
  1420. X    3.1, using the Borland 3.1 C++ compiler, as well as a Sun (running
  1421. X    SunOs 4.1.1 sun4c) using the gcc compiler (version 2.1).  I know
  1422. X    for a fact that the Sun cc compiler will NOT compile UNPOST
  1423. X    succesfully.
  1424. X
  1425. X    K&R compatibility is being considered, but it is a low priority
  1426. X    feature.
  1427. X
  1428. X2)  CONFIGURABILITY!  UNPOST comes with a default set of rules for
  1429. X    detecting and parsing a VERY wide range of possible Subject:
  1430. X    line formats, but no configuration can be correct for every
  1431. X    situation.
  1432. X
  1433. X    With that in mind, UNPOST can be configured by the user by creating
  1434. X    a text file that contains the regular expressions, etc. that
  1435. X    UNPOST uses to recognize, parse, etc.  WARNING!  UNPOST depends
  1436. X    almost ENTIRELY on the contents of it's configuration file for
  1437. X    correct operation.
  1438. X
  1439. X    Regular expressions are complex, and writing one that works the
  1440. X    way you expect it to takes care and, most importantly,
  1441. X    experimentation.
  1442. X
  1443. X    To this end, the standard UNPOST installation creates both the
  1444. X    UNPOST executable and a regular expression test program called
  1445. X    RETEST.  RETEST is like grep, feed it a regular expression and
  1446. X    a file, and RETEST will tell you what it matched and the sub
  1447. X    strings that it extracted.
  1448. X
  1449. X3)  INTELLIGENCE!  UNPOST uses every trick in the book to try to
  1450. X    guess what the poster/sender REALLY meant.
  1451. X
  1452. X    Also, UNPOST is not limited to finding all of it's information
  1453. X    on a single line, or even in the header of a posting/letter.
  1454. X
  1455. X    UNPOST has succesfully extracted binaries from postings that had,
  1456. X    as a subject line,
  1457. X
  1458. X    Subject: aaaa
  1459. X
  1460. X    because UNPOST recognized the signature placed into the body of
  1461. X    the article by a uuencode/split program.
  1462. X
  1463. X4)  FLEXIBILITY!  UNPOST has switches that allow it to be configured
  1464. X    to do different things for different tastes.  For instance, UNPOST
  1465. X    will intelligently sort out articles into four different classes:
  1466. X
  1467. X    1)  Articles that are part of a complete and correct binary in
  1468. X        the input file.  These are sorted, concatenated, uudecoded
  1469. X        and written out to a file name that is the same as that
  1470. X        on the uuencode begin line.
  1471. X
  1472. X        Depending on the setting of the file name switch, the file
  1473. X        name of the binary may be modified.  See below.
  1474. X
  1475. X    2)  Articles that are pure text (no uuencoded data in them).
  1476. X
  1477. X        If the -t switch and a file name are specified, these
  1478. X        articles will be written out to the file for reading.
  1479. X
  1480. X        Obviously, these articles should NEVER be encountered in
  1481. X        a binaries news group, but not a single day has ever gone
  1482. X        by that I did not see non-binary postings to binary news
  1483. X        groups.
  1484. X
  1485. X    3)  Articles that are part of incomplete postings (four parts,
  1486. X        but only three have shown up so far), or that comprise
  1487. X        a complete binary, but one that had an error in uudecoding,
  1488. X        interpretation, etc.
  1489. X
  1490. X        If the -i flag and a file name are specified, these articles
  1491. X        will be written out to the file.  If the -b switch is
  1492. X        on, incompletes will be written to separate files.  If
  1493. X        both are on, those incompletes that can be guessed at
  1494. X        as having a file name will be written to a separate file,
  1495. X        all else will be written to the file named by the -i
  1496. X        switch.
  1497. X
  1498. X        In my experience, two types of articles end up in an
  1499. X        incompletes file, those that have missing parts, and
  1500. X        those that have been misinterpreted by UNPOST as belonging
  1501. X        to a different binary than they really do.
  1502. X
  1503. X    4)  Articles that are pure text that describe a posting
  1504. X        (these are usually found only in the pictures groups).
  1505. X
  1506. X        If the -d flag is set, and the binary to which they
  1507. X        belong is correct and complete, this article, as well as
  1508. X        the header and body up to the uuencode begin line of the
  1509. X        first article, will be written to a file that has the same
  1510. X        base name as the binary, but with the extension .inf.
  1511. X
  1512. X    UNPOST automatically mungles binary file names to be MS-DOS
  1513. X    compatible (the lowest common denominator).  This is switch
  1514. X    controllable, and can be turned on or off (depending on the
  1515. X    default setting selected by the person who compiled UNPOST).
  1516. X
  1517. X    UNPOST also has two lesser modes, sorted mode and uudecode mode.
  1518. X
  1519. X    In sorted mode, UNPOST assumes that the articles still have
  1520. X    headers, and that there may be un-uuencoded lines in the middle
  1521. X    of a uuencoded file that have to be filtered out, but it assumes
  1522. X    that all parts are present, and that they are in order.  Header
  1523. X    information, however, is ignored.
  1524. X
  1525. X    If you use the incompletes file capability of UNPOST, you will
  1526. X    notice that it writes out the segments that it did interpret
  1527. X    correctly in sorted order.
  1528. X
  1529. X    In uudecode mode, UNPOST acts like a simple uudecoder.  UUencoded
  1530. X    files must be complete, with a begin and end line, and no
  1531. X    un-uuencoded lines can appear between the begin and end lines.
  1532. X
  1533. X    However, uudecode mode is the ONLY mode where UNPOST will accept
  1534. X    a short line (one that was space terminated, but had the spaces
  1535. X    chopped off) as a legal uuencoded line and properly decode it.
  1536. X
  1537. X5)  INFORMATIVE!  UNPOST is a very talkative program.  It detects
  1538. X    and reports many kinds of problems, tells you what it thinks
  1539. X    is going on, and tells you what it is doing.  All this information
  1540. X    is written to standard error, or if the -e switch and a file
  1541. X    name are specified, written to that file.
  1542. X
  1543. XChanges for UNPOST Version 2.1.2
  1544. X--------------------------------
  1545. X
  1546. X1)  Bug fix.  I screwed up the regular expression compilation for the
  1547. X        -r switch.  Fixed.  See note 5 for version 2.1.1 in the changes.doc
  1548. X        file for information on how to select one of four sources for your
  1549. X        news.
  1550. X
  1551. Xjstevens@csn.org
  1552. END_OF_FILE
  1553.   if test 6853 -ne `wc -c <'summary.doc'`; then
  1554.     echo shar: \"'summary.doc'\" unpacked with wrong size!
  1555.   fi
  1556.   # end of 'summary.doc'
  1557. fi
  1558. if test -f 'utils.c' -a "${1}" != "-c" ; then 
  1559.   echo shar: Will not clobber existing file \"'utils.c'\"
  1560. else
  1561.   echo shar: Extracting \"'utils.c'\" \(3764 characters\)
  1562.   sed "s/^X//" >'utils.c' <<'END_OF_FILE'
  1563. X/******************************************************************************
  1564. X* Module    :   Utility Routines --- Replacement functions for compiler
  1565. X*               library functions.  This module exists to avoid having to
  1566. X*               if def the hell out of the code for systems that, for
  1567. X*               example, have bcopy, but not memmove.
  1568. X*
  1569. X* Author    :   John W. M. Stevens
  1570. X******************************************************************************/
  1571. X
  1572. X#include    "compiler.h"
  1573. X
  1574. X#include    "utils.h"
  1575. X
  1576. X/*-----------------------------------------------------------------------------
  1577. X| Routine   :   StrDup() --- String duplication function.
  1578. X|
  1579. X| Inputs    :   Str - A pointer to the string to duplicate.
  1580. X-----------------------------------------------------------------------------*/
  1581. X
  1582. Xchar    *StrDup(char    *Str)
  1583. X{
  1584. X    register    int     StrLen;
  1585. X    auto        char    *Tmp;
  1586. X    extern      FILE    *ErrFile;
  1587. X
  1588. X    /*  Determine lenght of string to duplicate.    */
  1589. X    StrLen = strlen( Str ) + 1;
  1590. X
  1591. X    /*  Allocate the memory.    */
  1592. X    if ((Tmp = calloc(1, StrLen)) == NULL)
  1593. X    {
  1594. X        fprintf(ErrFile,
  1595. X                "%s %d : Error - out of memory.\n",
  1596. X                __FILE__,
  1597. X                __LINE__);
  1598. X        exit( 1 );
  1599. X    }
  1600. X
  1601. X    /*  Copy string contents in.    */
  1602. X    strcpy(Tmp, Str);
  1603. X    return( Tmp );
  1604. X}
  1605. X
  1606. X/*-----------------------------------------------------------------------------
  1607. X| Routine   :   FileExists() --- Check to see if a file already exists.
  1608. X|
  1609. X| Inputs    :   FlName  - Name of file.
  1610. X|
  1611. X| Returns   :   Returns zero for file does not exist, non-zero for it does.
  1612. X-----------------------------------------------------------------------------*/
  1613. X
  1614. Xint     FileExists(char     *FlName)
  1615. X{
  1616. X    auto    FILE    *fp;
  1617. X
  1618. X    /*  Attempt to open the file as read only to determine if it exists.
  1619. X    *   Don't you wish that ANSI C had a standard library function for
  1620. X    *   this?
  1621. X    */
  1622. X    if ((fp = fopen(FlName, TXT_READ)) != NULL)
  1623. X    {
  1624. X        /*  It exists, so close it and return.  */
  1625. X        fclose( fp );
  1626. X        return( 1 );
  1627. X    }
  1628. X    return( 0 );
  1629. X}
  1630. X
  1631. X/*-----------------------------------------------------------------------------
  1632. X| Routine   :   MemCopy() --- Copy memory.
  1633. X|
  1634. X| Inputs    :   Dest    - Destination address.
  1635. X|               Source  - Source address.
  1636. X|               NoBytes - Number of bytes to copy.
  1637. X-----------------------------------------------------------------------------*/
  1638. X
  1639. Xvoid    MemCopy(void    *Dest,
  1640. X                void    *Source,
  1641. X                int     NoBytes)
  1642. X{
  1643. X    register    int     i;
  1644. X    auto        char    *d;
  1645. X    auto        char    *s;
  1646. X
  1647. X    /*  Copy bytes. */
  1648. X    for (d = (char *) Dest, s = (char *) Source, i = 0;
  1649. X         i < NoBytes;
  1650. X         i++)
  1651. X        *d++ = *s++;
  1652. X}
  1653. X
  1654. X/*-----------------------------------------------------------------------------
  1655. X| Routine   :   MemMove() --- Move memory, taking into account possible
  1656. X|               overlap.
  1657. X|
  1658. X| Inputs    :   Dest    - Destination address.
  1659. X|               Source  - Source address.
  1660. X|               NoBytes - Number of bytes to copy.
  1661. X-----------------------------------------------------------------------------*/
  1662. X
  1663. Xvoid    MemMove(void    *Dest,
  1664. X                void    *Source,
  1665. X                int     NoBytes)
  1666. X{
  1667. X    register    int     i;
  1668. X    auto        char    *d;
  1669. X    auto        char    *s;
  1670. X
  1671. X    /*  Pointer conversion. */
  1672. X    d = (char *) Dest;
  1673. X    s = (char *) Source;
  1674. X
  1675. X    /*  Check copy direction.   */
  1676. X    if (d < s)
  1677. X    {
  1678. X        /*  Copy up.    */
  1679. X        for (i = 0; i < NoBytes; i++)
  1680. X            *d++ = *s++;
  1681. X    }
  1682. X    else if (d > s)
  1683. X    {
  1684. X        /*  Copy down.  */
  1685. X        for (d += NoBytes - 1, s += NoBytes - 1, i = 0;
  1686. X             i < NoBytes;
  1687. X             i++)
  1688. X            *d-- = *s--;
  1689. X    }
  1690. X}
  1691. END_OF_FILE
  1692.   if test 3764 -ne `wc -c <'utils.c'`; then
  1693.     echo shar: \"'utils.c'\" unpacked with wrong size!
  1694.   fi
  1695.   # end of 'utils.c'
  1696. fi
  1697. if test -f 'utils/trie.c' -a "${1}" != "-c" ; then 
  1698.   echo shar: Will not clobber existing file \"'utils/trie.c'\"
  1699. else
  1700.   echo shar: Extracting \"'utils/trie.c'\" \(6820 characters\)
  1701.   sed "s/^X//" >'utils/trie.c' <<'END_OF_FILE'
  1702. X/*****************************************************************************
  1703. X* Program:  Trie --- Create a trie in a 'C' compiler readable format.
  1704. X*
  1705. X* Author :  John W. M. Stevens
  1706. X*****************************************************************************/
  1707. X
  1708. X#include    <stdio.h>
  1709. X#include    <stdlib.h>
  1710. X#include    <fcntl.h>
  1711. X#include    <string.h>
  1712. X#include    <strings.h>
  1713. X
  1714. X/* Type definition. */
  1715. Xtypedef struct  {
  1716. X    char    c;
  1717. X    char    *val;
  1718. X    struct  trie    *branch;
  1719. X} KEY;
  1720. X
  1721. Xtypedef struct  trie    {
  1722. X    int     NoEls;
  1723. X    int     Size;
  1724. X    char    Lbl[10];
  1725. X    KEY     Keys[1];
  1726. X} TRIE;
  1727. X
  1728. Xstatic  TRIE    *Head = NULL;
  1729. X
  1730. X/*----------------------------------------------------------------------------
  1731. X| Routine:  TrieIns() --- Insert a string into the trie.
  1732. X|
  1733. X| Inputs :  Trie    - The trie to insert into.
  1734. X|           str - The string to insert.
  1735. X|           val - The value string for this key string.
  1736. X| Outputs:  Returns the pointer to the trie level.
  1737. X----------------------------------------------------------------------------*/
  1738. X
  1739. Xstatic  long    LblNo = 0L;
  1740. X
  1741. XTRIE    *TrieIns(TRIE   *Trie,
  1742. X                 char   *str,
  1743. X                 char   *val)
  1744. X{
  1745. X    register    int     i;
  1746. X    register    int     j;
  1747. X
  1748. X    auto        int     hi;
  1749. X    auto        int     lo;
  1750. X    auto        int     ret;
  1751. X
  1752. X    /* Create a level if neccesary. */
  1753. X    if (Trie == NULL)
  1754. X    {
  1755. X        /* Calculate the size of the level in bytes.    */
  1756. X        i = sizeof( TRIE ) + 4 * sizeof( KEY );
  1757. X
  1758. X        /* Allocate a level.    */
  1759. X        if ((Trie = malloc( i )) == NULL)
  1760. X        {
  1761. X            perror( "TrieIns (malloc) " );
  1762. X            return( NULL );
  1763. X        }
  1764. X
  1765. X        /* Clear the memory to all zeros.   */
  1766. X        memset((char *) Trie, '\0', i);
  1767. X
  1768. X         /* Initialize the new trie level.   */
  1769. X        Trie->NoEls = 1;
  1770. X        Trie->Size  = 5;
  1771. X        Trie->Keys[0].c = *str++;
  1772. X        sprintf(Trie->Lbl, "%x", LblNo++);
  1773. X
  1774. X        /* End of string?   */
  1775. X        if ( *str )
  1776. X        {
  1777. X            Trie->Keys[0].val = "0";
  1778. X            Trie->Keys[0].branch = TrieIns(NULL, str, val);
  1779. X        }
  1780. X        else
  1781. X            Trie->Keys[0].val = val;
  1782. X        return( Trie );
  1783. X    }
  1784. X
  1785. X    /* Search for the current character of the string to insert.    */
  1786. X    hi = Trie->NoEls - 1;
  1787. X    lo = 0;
  1788. X    do
  1789. X    {
  1790. X        /* Find mid point of current array piece.   */
  1791. X        i = (hi + lo) >> 1;
  1792. X
  1793. X        /* Do character comparison. */
  1794. X        ret = *str - Trie->Keys[i].c;
  1795. X
  1796. X        /* Shrink the search limits.    */
  1797. X        if (ret <= 0)
  1798. X            hi = i - 1;
  1799. X        if (ret >= 0)
  1800. X            lo = i + 1;
  1801. X
  1802. X    }  while (hi >= lo);
  1803. X
  1804. X    /* Did we find the character?   */
  1805. X    if (ret == 0)
  1806. X    {
  1807. X        /* Yes, continue the search.    */
  1808. X        if ( *++str )
  1809. X            Trie->Keys[i].branch = TrieIns(Trie->Keys[i].branch, str, val);
  1810. X        return( Trie );
  1811. X    }
  1812. X
  1813. X    /* If the trie level is not big enough, reallocate it.  */
  1814. X    if (Trie->Size == Trie->NoEls)
  1815. X    {
  1816. X        /* Calculate the size of the new level. */
  1817. X        i = sizeof( TRIE ) + (5 + Trie->Size) * sizeof( KEY );
  1818. X
  1819. X        /* Attempt to reallocate the trie level.    */
  1820. X        if ((Trie = realloc(Trie, i)) == NULL)
  1821. X        {
  1822. X            perror( "TrieIns (realloc) " );
  1823. X            return( NULL );
  1824. X        }
  1825. X
  1826. X        /* Up the size of the trie level.   */
  1827. X        Trie->Size += 5;
  1828. X    }
  1829. X
  1830. X    /* Make room for new character. */
  1831. X    if (hi < Trie->NoEls - 1)
  1832. X    {
  1833. X        j = sizeof( KEY ) * (Trie->NoEls - lo);
  1834. X         memmove(Trie->Keys + lo + 1,
  1835. X                Trie->Keys + lo,
  1836. X                j);
  1837. X    }
  1838. X
  1839. X    /* Insert new object.   */
  1840. X    i = lo;
  1841. X    Trie->Keys[i].c      = *str++;
  1842. X    Trie->Keys[i].branch = NULL;
  1843. X    Trie->NoEls++;
  1844. X
  1845. X    /* Continue insert if not at end of string. */
  1846. X    if ( *str )
  1847. X    {
  1848. X        Trie->Keys[i].val = "0";
  1849. X        Trie->Keys[i].branch = TrieIns(NULL, str, val);
  1850. X    }
  1851. X    else
  1852. X        Trie->Keys[i].val = val;
  1853. X    return( Trie );
  1854. X
  1855. X}
  1856. X
  1857. X/*----------------------------------------------------------------------------
  1858. X| Routine:  TrieDump() --- Dump the trie in a form usable by the 'C'
  1859. X|           compiler.
  1860. X|
  1861. X| Inputs :  Trie    - The trie to dump.
  1862. X|           Lable   - Trie level label.
  1863. X| Outputs:  Returns the pointer to the trie level.
  1864. X----------------------------------------------------------------------------*/
  1865. X
  1866. Xvoid    TrieDump(TRIE   *Trie)
  1867. X{
  1868. X    register    int     i;
  1869. X    register    int     j;
  1870. X    auto        char    NxtLbl[12];
  1871. X
  1872. X    /* Do a post order traversal of tree.   */
  1873. X    for (i = j = 0; i < Trie->NoEls; i++)
  1874. X    {
  1875. X        /* Check for children.  */
  1876. X        if (Trie->Keys[i].branch == NULL)
  1877. X            continue;
  1878. X
  1879. X        /* Do current branch.   */
  1880. X        TrieDump( Trie->Keys[i].branch );
  1881. X    }
  1882. X
  1883. X    /* Print label for this level.  */
  1884. X    printf("static\nKEY\tT%s[%d] = {\n", Trie->Lbl, Trie->NoEls + 1);
  1885. X    printf("\t{\t' ',\t%15d,\t%-20s\t}", Trie->NoEls + 1, "NULL");
  1886. X
  1887. X    /* Dump current level.  */
  1888. X    for (i = j = 0; i < Trie->NoEls; i++)
  1889. X    {
  1890. X        /* Check for children.  */
  1891. X        printf(",\n\t");
  1892. X        if (Trie->Keys[i].branch == NULL)
  1893. X        {
  1894. X            printf("{\t'%c',\t%15s,\t%-20s\t}", Trie->Keys[i].c,
  1895. X            Trie->Keys[i].val, "NULL");
  1896. X            continue;
  1897. X        }
  1898. X
  1899. X        /* Print the key.   */
  1900. X         printf("{\t'%c',\t%15s,\tT%-19s\t}", Trie->Keys[i].c,
  1901. X            Trie->Keys[i].val, Trie->Keys[i].branch->Lbl);
  1902. X    }
  1903. X    printf("\n};\n\n");
  1904. X
  1905. X}
  1906. X
  1907. Xvoid    main(int    argc,
  1908. X         char   *argv[])
  1909. X{
  1910. X    auto    FILE    *fp;
  1911. X    auto    char    bf[256];
  1912. X    auto    char    *tp;
  1913. X    auto    char    *token;
  1914. X    auto    char    *val;
  1915. X
  1916. X    /* Check the number of command line parameters. */
  1917. X    if (argc != 2)
  1918. X    {
  1919. X        fprintf(stderr, "Syntax error: trie <token file>\n");
  1920. X        exit( -1 );
  1921. X    }
  1922. X
  1923. X    /* Open the token file for reading. */
  1924. X    if ((fp = fopen(argv[1], "rt")) == NULL)
  1925. X    {
  1926. X        perror( "trie (fopen) " );
  1927. X        exit( -1 );
  1928. X    }
  1929. X
  1930. X    /* Get and insert all strings into the trie.    */
  1931. X    while ( fgets(bf, 256, fp) )
  1932. X    {
  1933. X        /* Strip white space.   */
  1934. X        tp = bf;
  1935. X        while (*tp == ' ' || *tp == '\t')
  1936. X            tp++;
  1937. X
  1938. X        /* Find end of token.   */
  1939. X        token = tp;
  1940. X        while (*tp != ' ' && *tp != '\t' && *tp != '\n')
  1941. X            tp++;
  1942. X        *tp++ = '\0';
  1943. X
  1944. X        /* Strip white space.   */
  1945. X        while (*tp == ' ' || *tp == '\t')
  1946. X            tp++;
  1947. X
  1948. X        /* Find end of the value string.    */
  1949. X        val = tp;
  1950. X        while (*tp != ' ' && *tp != '\t' && *tp != '\n')
  1951. X            tp++;
  1952. X        *tp = '\0';
  1953. X
  1954. X        /* Duplicate the value string.  */
  1955. X        if ((val = strdup( val )) == NULL)
  1956. X        {
  1957. X            perror( "trie (strdup) " );
  1958. X            exit( -1 );
  1959. X        }
  1960. X
  1961. X        /* Do string insert into trie.  */
  1962. X        Head = TrieIns(Head, token, val);
  1963. X    }
  1964. X
  1965. X    TrieDump( Head );
  1966. X}
  1967. END_OF_FILE
  1968.   if test 6820 -ne `wc -c <'utils/trie.c'`; then
  1969.     echo shar: \"'utils/trie.c'\" unpacked with wrong size!
  1970.   fi
  1971.   # end of 'utils/trie.c'
  1972. fi
  1973. echo shar: End of archive 6 \(of 7\).
  1974. cp /dev/null ark6isdone
  1975. MISSING=""
  1976. for I in 1 2 3 4 5 6 7 ; do
  1977.     if test ! -f ark${I}isdone ; then
  1978.     MISSING="${MISSING} ${I}"
  1979.     fi
  1980. done
  1981. if test "${MISSING}" = "" ; then
  1982.     echo You have unpacked all 7 archives.
  1983.     rm -f ark[1-9]isdone
  1984. else
  1985.     echo You still must unpack the following archives:
  1986.     echo "        " ${MISSING}
  1987. fi
  1988. exit 0
  1989. exit 0 # Just in case...
  1990.