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

  1. Newsgroups: comp.sources.misc,alt.binaries.pictures.utilities
  2. From: jstevens@teal.csn.org (John W.M. Stevens)
  3. Subject: v36i115:  unpost - Smart multi-part uudecoder v2.1.2, Part02/07
  4. Message-ID: <1993Apr19.052156.28711@sparky.imd.sterling.com>
  5. X-Md4-Signature: 97215d8e94a24d3e286cbbb240948847
  6. Date: Mon, 19 Apr 1993 05:21:56 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 115
  11. Archive-name: unpost/part02
  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:  lex.c segment.h unpost.doc
  19. # Wrapped by kent@sparky on Sun Apr 18 23:10:30 1993
  20. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  21. echo If this archive is complete, you will see the following message:
  22. echo '          "shar: End of archive 2 (of 7)."'
  23. if test -f 'lex.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'lex.c'\"
  25. else
  26.   echo shar: Extracting \"'lex.c'\" \(16470 characters\)
  27.   sed "s/^X//" >'lex.c' <<'END_OF_FILE'
  28. X/******************************************************************************
  29. X* Module    :   Lexical Analyzer --- Process the input text file into tokens
  30. X*               that the configuration file parser can understand.
  31. X*
  32. X* Routines  :   Lex()   - Return the next token from the file.
  33. X*               OpenPrg - Open the back up program script file.
  34. X*
  35. X* Author    :   John W. M. Stevens
  36. X******************************************************************************/
  37. X
  38. X#include    "compiler.h"
  39. X
  40. X#include    "lex.h"
  41. X
  42. X/* Type definitions for this file.  */
  43. Xtypedef struct  key_st  {
  44. X    char    c;
  45. X    TKNS    val;
  46. X    struct  key_st  *branch;
  47. X} KEY;
  48. X
  49. X/* Constants local to this file.    */
  50. X#define     NOT_FND     -2
  51. X
  52. X/* Object Data. */
  53. Xstatic  char    word[80];   /* Last string analyzed.                        */
  54. Xstatic  int     LnNo = 0;   /* The current line number reading the script.  */
  55. Xstatic  FILE    *PrgFl;     /* Pointer to the ASCII file that contains the
  56. X                            *   backup program script.
  57. X                            */
  58. X
  59. X/* Trie data structure containing all the keywords and punctuation marks for
  60. X*   the backup language.
  61. X*/
  62. Xstatic
  63. XKEY T8[2] = {
  64. X    {   ' ',                  2,    NULL                    },
  65. X    {   'e',        T_ALTERNATE,    NULL                    }
  66. X};
  67. X
  68. Xstatic
  69. XKEY T7[2] = {
  70. X    {   ' ',                  2,    NULL                    },
  71. X    {   't',                  0,    T8                      }
  72. X};
  73. X
  74. Xstatic
  75. XKEY T6[2] = {
  76. X    {   ' ',                  2,    NULL                    },
  77. X    {   'a',                  0,    T7                      }
  78. X};
  79. X
  80. Xstatic
  81. XKEY T5[2] = {
  82. X    {   ' ',                  2,    NULL                    },
  83. X    {   'n',                  0,    T6                      }
  84. X};
  85. X
  86. Xstatic
  87. XKEY T4[2] = {
  88. X    {   ' ',                  2,    NULL                    },
  89. X     {   'r',                  0,    T5                      }
  90. X};
  91. X
  92. Xstatic
  93. XKEY T3[2] = {
  94. X    {   ' ',                  2,    NULL                    },
  95. X    {   'e',                  0,    T4                      }
  96. X};
  97. X
  98. Xstatic
  99. XKEY T2[2] = {
  100. X    {   ' ',                  2,    NULL                    },
  101. X    {   't',                  0,    T3                      }
  102. X};
  103. X
  104. Xstatic
  105. XKEY T1[2] = {
  106. X    {   ' ',                  2,    NULL                    },
  107. X    {   'l',                  0,    T2                      }
  108. X};
  109. X
  110. Xstatic
  111. XKEY Tb[2] = {
  112. X    {   ' ',                  2,    NULL                    },
  113. X    {   'y',             T_BODY,    NULL                    }
  114. X};
  115. X
  116. Xstatic
  117. XKEY Ta[2] = {
  118. X    {   ' ',                  2,    NULL                    },
  119. X    {   'd',                  0,    Tb                      }
  120. X};
  121. X
  122. Xstatic
  123. XKEY T9[2] = {
  124. X    {   ' ',                  2,    NULL                    },
  125. X    {   'o',                  0,    Ta                      }
  126. X};
  127. X
  128. Xstatic
  129. XKEY Te[2] = {
  130. X    {   ' ',                  2,    NULL                    },
  131. X    {   'e',             T_CASE,    NULL                    }
  132. X};
  133. X
  134. Xstatic
  135. XKEY Td[2] = {
  136. X    {   ' ',                  2,    NULL                    },
  137. X    {   's',                  0,    Te                      }
  138. X};
  139. X
  140. Xstatic
  141. XKEY Tc[2] = {
  142. X    {   ' ',                  2,    NULL                    },
  143. X    {   'a',                  0,    Td                      }
  144. X};
  145. X
  146. Xstatic
  147. XKEY T13[2] = {
  148. X    {   ' ',                  2,    NULL                    },
  149. X    {   'r',           T_HEADER,    NULL                    }
  150. X};
  151. X
  152. Xstatic
  153. XKEY T12[2] = {
  154. X    {   ' ',                  2,    NULL                    },
  155. X     {   'e',                  0,    T13                     }
  156. X};
  157. X
  158. Xstatic
  159. XKEY T11[2] = {
  160. X    {   ' ',                  2,    NULL                    },
  161. X    {   'd',                  0,    T12                     }
  162. X};
  163. X
  164. Xstatic
  165. XKEY T10[2] = {
  166. X    {   ' ',                  2,    NULL                    },
  167. X    {   'a',                  0,    T11                     }
  168. X};
  169. X
  170. Xstatic
  171. XKEY Tf[2] = {
  172. X    {   ' ',                  2,    NULL                    },
  173. X    {   'e',                  0,    T10                     }
  174. X};
  175. X
  176. Xstatic
  177. XKEY T18[2] = {
  178. X    {   ' ',                  2,    NULL                    },
  179. X    {   'e',           T_IGNORE,    NULL                    }
  180. X};
  181. X
  182. Xstatic
  183. XKEY T17[2] = {
  184. X    {   ' ',                  2,    NULL                    },
  185. X    {   'r',                  0,    T18                     }
  186. X};
  187. X
  188. Xstatic
  189. XKEY T16[2] = {
  190. X    {   ' ',                  2,    NULL                    },
  191. X    {   'o',                  0,    T17                     }
  192. X};
  193. X
  194. Xstatic
  195. XKEY T15[2] = {
  196. X    {   ' ',                  2,    NULL                    },
  197. X    {   'n',                  0,    T16                     }
  198. X};
  199. X
  200. Xstatic
  201. XKEY T14[3] = {
  202. X    {   ' ',                  3,    NULL                    },
  203. X    {   'd',               T_ID,    NULL                    },
  204. X    {   'g',                  0,    T15                     }
  205. X};
  206. X
  207. Xstatic
  208. XKEY T1d[2] = {
  209. X    {   ' ',                  2,    NULL                    },
  210. X    {   'r',           T_NUMBER,    NULL                    }
  211. X};
  212. X
  213. Xstatic
  214. XKEY T1c[2] = {
  215. X    {   ' ',                  2,    NULL                    },
  216. X    {   'e',                  0,    T1d                     }
  217. X};
  218. X
  219. Xstatic
  220. XKEY T1b[2] = {
  221. X     {   ' ',                  2,    NULL                    },
  222. X    {   'b',                  0,    T1c                     }
  223. X};
  224. X
  225. Xstatic
  226. XKEY T1a[2] = {
  227. X    {   ' ',                  2,    NULL                    },
  228. X    {   'm',                  0,    T1b                     }
  229. X};
  230. X
  231. Xstatic
  232. XKEY T19[2] = {
  233. X    {   ' ',                  2,    NULL                    },
  234. X    {   'u',                  0,    T1a                     }
  235. X};
  236. X
  237. Xstatic
  238. XKEY T20[2] = {
  239. X    {   ' ',                  2,    NULL                    },
  240. X    {   't',             T_PART,    NULL                    }
  241. X};
  242. X
  243. Xstatic
  244. XKEY T1f[2] = {
  245. X    {   ' ',                  2,    NULL                    },
  246. X    {   'r',                  0,    T20                     }
  247. X};
  248. X
  249. Xstatic
  250. XKEY T1e[2] = {
  251. X    {   ' ',                  2,    NULL                    },
  252. X    {   'a',                  0,    T1f                     }
  253. X};
  254. X
  255. Xstatic
  256. XKEY T27[2] = {
  257. X    {   ' ',                  2,    NULL                    },
  258. X    {   's',         T_SEGMENTS,    NULL                    }
  259. X};
  260. X
  261. Xstatic
  262. XKEY T26[2] = {
  263. X    {   ' ',                  2,    NULL                    },
  264. X    {   't',          T_SEGMENT,    T27                     }
  265. X};
  266. X
  267. Xstatic
  268. XKEY T25[2] = {
  269. X    {   ' ',                  2,    NULL                    },
  270. X    {   'n',                  0,    T26                     }
  271. X};
  272. X
  273. Xstatic
  274. XKEY T24[2] = {
  275. X    {   ' ',                  2,    NULL                    },
  276. X    {   'e',                  0,    T25                     }
  277. X};
  278. X
  279. Xstatic
  280. XKEY T23[2] = {
  281. X    {   ' ',                  2,    NULL                    },
  282. X    {   'm',                  0,    T24                     }
  283. X};
  284. X
  285. Xstatic
  286. XKEY T2d[2] = {
  287. X     {   ' ',                  2,    NULL                    },
  288. X    {   'e',        T_SENSITIVE,    NULL                    }
  289. X};
  290. X
  291. Xstatic
  292. XKEY T2c[2] = {
  293. X    {   ' ',                  2,    NULL                    },
  294. X    {   'v',                  0,    T2d                     }
  295. X};
  296. X
  297. Xstatic
  298. XKEY T2b[2] = {
  299. X    {   ' ',                  2,    NULL                    },
  300. X    {   'i',                  0,    T2c                     }
  301. X};
  302. X
  303. Xstatic
  304. XKEY T2a[2] = {
  305. X    {   ' ',                  2,    NULL                    },
  306. X    {   't',                  0,    T2b                     }
  307. X};
  308. X
  309. Xstatic
  310. XKEY T29[2] = {
  311. X    {   ' ',                  2,    NULL                    },
  312. X    {   'i',                  0,    T2a                     }
  313. X};
  314. X
  315. Xstatic
  316. XKEY T28[2] = {
  317. X    {   ' ',                  2,    NULL                    },
  318. X    {   's',                  0,    T29                     }
  319. X};
  320. X
  321. Xstatic
  322. XKEY T22[3] = {
  323. X    {   ' ',                  3,    NULL                    },
  324. X    {   'g',                  0,    T23                     },
  325. X    {   'n',                  0,    T28                     }
  326. X};
  327. X
  328. Xstatic
  329. XKEY T31[2] = {
  330. X    {   ' ',                  2,    NULL                    },
  331. X    {   'g',           T_STRING,    NULL                    }
  332. X};
  333. X
  334. Xstatic
  335. XKEY T30[2] = {
  336. X    {   ' ',                  2,    NULL                    },
  337. X    {   'n',                  0,    T31                     }
  338. X};
  339. X
  340. Xstatic
  341. XKEY T2f[2] = {
  342. X    {   ' ',                  2,    NULL                    },
  343. X    {   'i',                  0,    T30                     }
  344. X};
  345. X
  346. Xstatic
  347. XKEY T2e[2] = {
  348. X    {   ' ',                  2,    NULL                    },
  349. X    {   'r',                  0,    T2f                     }
  350. X};
  351. X
  352. Xstatic
  353. XKEY  T21[3] = {
  354. X    {   ' ',                  3,    NULL                    },
  355. X    {   'e',                  0,    T22                     },
  356. X    {   't',                  0,    T2e                     }
  357. X};
  358. X
  359. Xstatic
  360. XKEY T35[2] = {
  361. X    {   ' ',                  2,    NULL                    },
  362. X    {   'l',            T_TOTAL,    NULL                    }
  363. X};
  364. X
  365. Xstatic
  366. XKEY T34[2] = {
  367. X    {   ' ',                  2,    NULL                    },
  368. X    {   'a',                  0,    T35                     }
  369. X};
  370. X
  371. Xstatic
  372. XKEY T33[2] = {
  373. X    {   ' ',                  2,    NULL                    },
  374. X    {   't',                  0,    T34                     }
  375. X};
  376. X
  377. Xstatic
  378. XKEY T32[2] = {
  379. X    {   ' ',                  2,    NULL                    },
  380. X    {   'o',                  0,    T33                     }
  381. X};
  382. X
  383. Xstatic
  384. XKEY T0[12] = {
  385. X    {   ' ',                 12,    NULL                    },
  386. X    {   'a',                  0,    T1                      },
  387. X    {   'b',                  0,    T9                      },
  388. X    {   'c',                  0,    Tc                      },
  389. X    {   'h',                  0,    Tf                      },
  390. X    {   'i',                  0,    T14                     },
  391. X    {   'n',                  0,    T19                     },
  392. X    {   'p',                  0,    T1e                     },
  393. X    {   's',                  0,    T21                     },
  394. X    {   't',                  0,    T32                     },
  395. X    {   '{',          T_L_BRACE,    NULL                    },
  396. X    {   '}',          T_R_BRACE,    NULL                    }
  397. X};
  398. X
  399. X/*-----------------------------------------------------------------------------
  400. X| Routine   :   TrieSrch() --- Search the trie for a token.
  401. X|
  402. X| Inputs    :   Keys    - The trie level pointer.
  403. X|               ch      - The current character to search for.
  404. X|               WordPtr - The pointer to the current byte of the word buffer.
  405. X| Outputs   :   The token number or TKN_NOT_FND for not found.
  406. X-----------------------------------------------------------------------------*/
  407. X
  408. Xstatic
  409. Xint     TrieSrch(KEY    *Keys,
  410. X                 int    ch,
  411. X                 char   *WordPtr)
  412. X{
  413. X    register    int     mid;        /* Mid point of array piece.            */
  414. X    register    TKNS    ret;        /* Return value of comparison.          */
  415. X
  416. X    auto        int     lo;         /* Limits of current array piece.       */
  417. X    auto        int     hi;
  418. X
  419. X     /* Make sure that input is lower case.  */
  420. X    ch = tolower( ch );
  421. X
  422. X    /* Search for a token.  */
  423. X    hi = Keys[0].val - 1;
  424. X    lo = 1;
  425. X    do
  426. X    {
  427. X        /* Find mid point of current array piece.   */
  428. X        mid = (lo + hi) >> 1;
  429. X
  430. X        /* Do character comparison. */
  431. X        ret = ch - Keys[mid].c;
  432. X
  433. X        /* Fix the array limits.    */
  434. X        if (ret <= 0)
  435. X            hi = mid - 1;
  436. X        if (ret >= 0)
  437. X            lo = mid + 1;
  438. X
  439. X    }  while (hi >= lo);
  440. X
  441. X    /*  If the character matches one of the entries in this level and this
  442. X    *   entry has a child, recurse.  If a match is found but the matching
  443. X    *   entry has no child, return the token value associated with the
  444. X    *   match.  If the return value from the recursive call indicates that
  445. X    *   no match was found at a lower level, return the token value
  446. X    *   associated with the match at this level of the trie.
  447. X    */
  448. X    if (ret == 0)
  449. X    {
  450. X        /* Save the current character.  */
  451. X        *WordPtr++ = ch;
  452. X
  453. X        /* Is this the last character in the string?    */
  454. X        if ( Keys[mid].branch )
  455. X        {
  456. X            /* Get the next character.  */
  457. X            if ((ch = fgetc( PrgFl )) == EOF)
  458. X                return( EOF );
  459. X
  460. X            /* Search next level.   */
  461. X            if ((ret = TrieSrch(Keys[mid].branch, ch, WordPtr)) == T_NOT_FND)
  462. X            {
  463. X                ungetc(ch, PrgFl);
  464. X                return( Keys[mid].val );
  465. X            }
  466. X            return( ret );
  467. X        }
  468. X        else
  469. X        {
  470. X            *WordPtr = '\0';
  471. X            return( Keys[mid].val );
  472. X        }
  473. X    }
  474. X
  475. X    /* Return not found.    */
  476. X    *WordPtr = '\0';
  477. X    return( T_NOT_FND );
  478. X}
  479. X
  480. X/*-----------------------------------------------------------------------------
  481. X| Routine   :   Lex() --- Get the next key word from the input file.
  482. X|
  483. X| Outputs   :   sym - The symbolic data read from the file.
  484. X|
  485. X| Return :   Returns the token read or EOF.
  486. X-----------------------------------------------------------------------------*/
  487. X
  488. Xint     Lex(TOKEN   *sym)
  489. X{
  490. X    register    int     tkn;
  491. X    auto        int     ch;
  492. X    extern      FILE    *ErrFile;
  493. X
  494. X    /* Strip comments and white space.  If the character read is a '#',
  495. X    *   every thing to the end of the line is a comment.
  496. X    */
  497. X    ch = fgetc( PrgFl );
  498. X    while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#')
  499. X    {
  500. X        /* Process the special characters '#' and '\n'.     */
  501. X        if (ch == '\n')
  502. X            LnNo++;
  503. X        else if (ch == '#')
  504. X        {
  505. X            while (fgetc( PrgFl ) != '\n')
  506. X                ;
  507. X            LnNo++;
  508. X        }
  509. X
  510. X        /* Get the next character.  */
  511. X        ch = fgetc( PrgFl );
  512. X    }
  513. X
  514. X    /* Get strings, etc.    */
  515. X    if (ch == '"')
  516. X    {
  517. X        auto    char    *bf;
  518. X
  519. X        /* Get contents of string.  */
  520. X        bf = sym->str;
  521. X        while ((ch = fgetc( PrgFl )) != '"' && ch != EOF)
  522. X            *bf++ = ch;
  523. X        *bf = '\0';
  524. X
  525. X        /* Return string token. */
  526. X        return( T_DBL_QUOTE );
  527. X    }
  528. X    else if (ch >= '0' && ch <= '9')
  529. X    {
  530. X        /* Get the number.  */
  531. X        sym->no = 0;
  532. X        do
  533. X        {
  534. X            sym->no = sym->no * 10 + (ch - '0');
  535. X        }  while ((ch = fgetc( PrgFl )) >= '0' && ch <= '9');
  536. X
  537. X        /* Return the unused character. */
  538. X        ungetc(ch, PrgFl);
  539. X        return( T_INT_NO );
  540. X    }
  541. X    else if (ch == EOF)
  542. X        return( EOF );
  543. X
  544. X    /* Call the trie search routine to return the next token, EOF
  545. X    *   or NOT_FND.  If not found, print an error and quit.
  546. X    */
  547. X    if ((tkn = TrieSrch(T0, ch, word)) == T_NOT_FND || tkn == 0)
  548. X    {
  549. X        fprintf(ErrFile,
  550. X                "%s %d : Error - cannot identify string '%s' ",
  551. X                 __FILE__,
  552. X                __LINE__,
  553. X                word);
  554. X        fprintf(ErrFile,
  555. X                "in line %d\n",
  556. X                LnNo + 1);
  557. X        exit( 1 );
  558. X    }
  559. X
  560. X    /* Return the token found.  */
  561. X    return( tkn );
  562. X}
  563. X
  564. X/*-----------------------------------------------------------------------------
  565. X| Routine   :   OpenCfg() --- Open the ASCII text file that contains the
  566. X|               configuration data.
  567. X-----------------------------------------------------------------------------*/
  568. X
  569. Xvoid    OpenCfg(char    *FileNm)
  570. X{
  571. X    extern  FILE    *ErrFile;
  572. X
  573. X    /* Open the program script file.    */
  574. X    if ((PrgFl = fopen(FileNm, TXT_READ)) == NULL)
  575. X    {
  576. X        fprintf(ErrFile,
  577. X                "%s %d : Error - %s\n",
  578. X                __FILE__,
  579. X                __LINE__,
  580. X                sys_errlist[errno]);
  581. X        fprintf(ErrFile,
  582. X                "\tFile Name: '%s'\n",
  583. X                FileNm);
  584. X        exit( 1 );
  585. X    }
  586. X}
  587. X
  588. X/*-----------------------------------------------------------------------------
  589. X| Routine   :   CloseCfg() --- Close the ASCII text file that contains the
  590. X|               configuration data.
  591. X-----------------------------------------------------------------------------*/
  592. X
  593. Xvoid    CloseCfg(void)
  594. X{
  595. X    fclose( PrgFl );
  596. X}
  597. X
  598. X/*-----------------------------------------------------------------------------
  599. X| Routine   :   ParseErr() --- Report a parse error.
  600. X|
  601. X| Inputs    :   ErrStr  - The error string.
  602. X-----------------------------------------------------------------------------*/
  603. X
  604. Xvoid    ParseErr(char   *ErrStr)
  605. X{
  606. X    extern  FILE    *ErrFile;
  607. X
  608. X    fprintf(ErrFile,
  609. X            "%s %d : Error - %s\n",
  610. X            __FILE__,
  611. X            __LINE__,
  612. X            ErrStr);
  613. X    fprintf(ErrFile,
  614. X            "\tLine %d, word '%s'\n",
  615. X            LnNo + 1,
  616. X            word);
  617. X     exit( 1 );
  618. X}
  619. END_OF_FILE
  620.   if test 16470 -ne `wc -c <'lex.c'`; then
  621.     echo shar: \"'lex.c'\" unpacked with wrong size!
  622.   fi
  623.   # end of 'lex.c'
  624. fi
  625. if test -f 'segment.h' -a "${1}" != "-c" ; then 
  626.   echo shar: Will not clobber existing file \"'segment.h'\"
  627. else
  628.   echo shar: Extracting \"'segment.h'\" \(469 characters\)
  629.   sed "s/^X//" >'segment.h' <<'END_OF_FILE'
  630. X/******************************************************************************
  631. X* Module    :   Segmemt header file.
  632. X*
  633. X* Author    :   John W. M. Stevens
  634. X******************************************************************************/
  635. X
  636. X#if ! defined(SEGMENT_HEADER_FILE)
  637. X#define     SEGMENT_HEADER_FILE
  638. X
  639. X/*  Function prototypes.    */
  640. Xextern
  641. Xvoid    Single(char     *FileNm);
  642. Xextern
  643. Xvoid    Multiple(char       *FileNm);
  644. Xextern
  645. Xvoid    UUDecode(char   *FlName);
  646. X
  647. X#endif
  648. END_OF_FILE
  649.   if test 469 -ne `wc -c <'segment.h'`; then
  650.     echo shar: \"'segment.h'\" unpacked with wrong size!
  651.   fi
  652.   # end of 'segment.h'
  653. fi
  654. if test -f 'unpost.doc' -a "${1}" != "-c" ; then 
  655.   echo shar: Will not clobber existing file \"'unpost.doc'\"
  656. else
  657.   echo shar: Extracting \"'unpost.doc'\" \(40962 characters\)
  658.   sed "s/^X//" >'unpost.doc' <<'END_OF_FILE'
  659. XUNPOST
  660. X
  661. XName:
  662. X
  663. X    unpost - Extract binary files from multi-segment uuencoded USENET
  664. X             postings or Email.
  665. X
  666. XSynopsis:
  667. X
  668. X    unpost [-b[-]] [-c <configuration file>] [-d[-]] [-e <error file>]
  669. X           [-f[-]] [-h|-s|-u] [-i <incompletes file>] [-t <text file>]
  670. X           <source file>
  671. X
  672. X    Where everything but the source file is optional.
  673. X
  674. XDescription:
  675. X
  676. X    UNPOST is a tool designed primarily to extract binaries from USENET
  677. X    binaries postings such as those made to alt.binaries.pictures.misc
  678. X    and comp.binaries.ibm.pc.  As well as extracting binaries from USENET
  679. X    postings, UNPOST can extract binaries from multi-segment uuencoded
  680. X    mailings as well, however, to simplify this documentation only
  681. X    USENET article postings will be discussed.  The principles are the
  682. X    same for multi-segment mailings.
  683. X
  684. X    To avoid confusion, this documentation will refer to a single letter
  685. X    OR article as a 'segment'.  For clarification on what a segment means
  686. X    to UNPOST, see Theory of Operations.
  687. X
  688. XFeatures:
  689. X
  690. X1)  PORTABILITY!  UNPOST has been compiled and sucessfully run on
  691. X    MS-DOS, OS/2, Windows, Unix workstations, MacIntoshes, Amiga's
  692. X    and VAX/VMS systems.
  693. X
  694. X    The code is written to be pure ANSI C, within reasonable limits.
  695. X    (some ANSI C capabilities are not used where they would be
  696. X    appropriate due to lagging compliance in most compilers.  Hey,
  697. X    Unix types!  MS-DOS (Borland C++ 3.1) is a MUCH better compiler
  698. X    than anything I've seen on a Unix workstation!  And their debugger
  699. X    is the best I've used, as well).  Unfortunately, there are still
  700. X    a lot of Unix boxes that have only a K&R compiler, so it may
  701. X    not port well to those.  I personally check to make sure that it
  702. X    will compile and run on an MS-DOS box running MS-DOS 5 and Windows
  703. X    3.1, using the Borland 3.1 C++ compiler, as well as a Sun (running
  704. X    SunOs 4.1.1 sun4c) using the gcc compiler (version 2.1).  I know
  705. X    for a fact that the Sun cc compiler will NOT compile UNPOST
  706. X    succesfully.
  707. X
  708. X    K&R compatibility is being considered, but it is a low priority
  709. X    feature.
  710. X
  711. X2)  CONFIGURABILITY!  UNPOST comes with a default set of rules for
  712. X    detecting and parsing a VERY wide range of possible Subject:
  713. X    line formats, but no configuration can be correct for every
  714. X    situation.
  715. X
  716. X    With that in mind, UNPOST can be configured by the user by creating
  717. X    a text file that contains the regular expressions, etc. that
  718. X    UNPOST uses to recognize, parse, etc.  WARNING!  UNPOST depends
  719. X    almost ENTIRELY on the contents of it's configuration file for
  720. X    correct operation.
  721. X
  722. X    Regular expressions are complex, and writing one that works the
  723. X    way you expect it to takes care and, most importantly,
  724. X    experimentation.
  725. X
  726. X    To this end, the standard UNPOST installation creates both the
  727. X    UNPOST executable and a regular expression test program called
  728. X    RETEST.  RETEST is like grep, feed it a regular expression and
  729. X    a file, and RETEST will tell you what it matched and the sub
  730. X    strings that it extracted.
  731. X
  732. X3)  INTELLIGENCE!  UNPOST uses every trick in the book to try to
  733. X    guess what the poster/sender REALLY meant.
  734. X
  735. X    Also, UNPOST is not limited to finding all of it's information
  736. X    on a single line, or even in the header of a posting/letter.
  737. X
  738. X    UNPOST has succesfully extracted binaries from postings that had,
  739. X    as a subject line,
  740. X
  741. X    Subject: aaaa
  742. X
  743. X    because UNPOST recognized the signature placed into the body of
  744. X    the article by a uuencode/split program.
  745. X
  746. X4)  FLEXIBILITY!  UNPOST has switches that allow it to be configured
  747. X    to do different things for different tastes.  For instance, UNPOST
  748. X    will intelligently sort out articles into four different classes:
  749. X
  750. X    1)  Articles that are part of a complete and correct binary in
  751. X        the input file.  These are sorted, concatenated, uudecoded
  752. X        and written out to a file name that is the same as that
  753. X        on the uuencode begin line.
  754. X
  755. X        Depending on the setting of the file name switch, the file
  756. X        name of the binary may be modified.  See below.
  757. X
  758. X    2)  Articles that are pure text (no uuencoded data in them).
  759. X
  760. X        If the -t switch and a file name are specified, these
  761. X        articles will be written out to the file for reading.
  762. X
  763. X        Obviously, these articles should NEVER be encountered in
  764. X        a binaries news group, but not a single day has ever gone
  765. X        by that I did not see non-binary postings to binary news
  766. X        groups.
  767. X
  768. X    3)  Articles that are part of incomplete postings (four parts,
  769. X        but only three have shown up so far), or that comprise
  770. X        a complete binary, but one that had an error in uudecoding,
  771. X        interpretation, etc.
  772. X
  773. X        If the -i flag and a file name are specified, these articles
  774. X        will be written out to the file.  If the -b switch is
  775. X        on, incompletes will be written to separate files.  If
  776. X        both are on, those incompletes that can be guessed at
  777. X        as having a file name will be written to a separate file,
  778. X        all else will be written to the file named by the -i
  779. X        switch.
  780. X
  781. X        In my experience, two types of articles end up in an
  782. X        incompletes file, those that have missing parts, and
  783. X        those that have been misinterpreted by UNPOST as belonging
  784. X        to a different binary than they really do.
  785. X
  786. X    4)  Articles that are pure text that describe a posting
  787. X        (these are usually found only in the pictures groups).
  788. X
  789. X        If the -d flag is set, and the binary to which they
  790. X        belong is correct and complete, this article, as well as
  791. X        the header and body up to the uuencode begin line of the
  792. X        first article, will be written to a file that has the same
  793. X        base name as the binary, but with the extension .inf.
  794. X
  795. X    UNPOST automatically mungles binary file names to be MS-DOS
  796. X    compatible (the lowest common denominator).  This is switch
  797. X    controllable, and can be turned on or off (depending on the
  798. X    default setting selected by the person who compiled UNPOST).
  799. X
  800. X    UNPOST also has two lesser modes, sorted mode and uudecode mode.
  801. X
  802. X    In sorted mode, UNPOST assumes that the articles still have
  803. X    headers, and that there may be un-uuencoded lines in the middle
  804. X    of a uuencoded file that have to be filtered out, but it assumes
  805. X    that all parts are present, and that they are in order.  Header
  806. X    information, however, is ignored.
  807. X
  808. X    If you use the incompletes file capability of UNPOST, you will
  809. X    notice that it writes out the segments that it did interpret
  810. X    correctly in sorted order.
  811. X
  812. X    In uudecode mode, UNPOST acts like a simple uudecoder.  UUencoded
  813. X    files must be complete, with a begin and end line, and no
  814. X    un-uuencoded lines can appear between the begin and end lines.
  815. X
  816. X    However, uudecode mode is the ONLY mode where UNPOST will accept
  817. X    a short line (one that was space terminated, but had the spaces
  818. X    chopped off) as a legal uuencoded line and properly decode it.
  819. X
  820. X5)  INFORMATIVE!  UNPOST is a very talkative program.  It detects
  821. X    and reports many kinds of problems, tells you what it thinks
  822. X    is going on, and tells you what it is doing.  All this information
  823. X    is written to standard error, or if the -e switch and a file
  824. X    name are specified, written to that file.
  825. X
  826. XTheory of Operations:
  827. X
  828. X    UNPOST assumes that the source file that is given to it will have the
  829. X    following format:
  830. X
  831. X    SEGMENT begin line
  832. X    ...
  833. X    HEADER ID line
  834. X    ...
  835. X    BODY ID line
  836. X    ...
  837. X    UUENCODED line
  838. X
  839. X    Where the lines are:
  840. X
  841. X        SEGMENT begin line - Is the line that identifies the begining of a
  842. X                             segment.
  843. X        HEADER ID line     - One or more lines that contain segment number,
  844. X                             total number of segments or the ID string in
  845. X                             the article or mail header.
  846. X        BODY ID line       - One or more lines that contain segment number,
  847. X                             total number of segments or the ID string in
  848. X                             the article or mail message body.
  849. X        UUENCODED line     - Is the first uuencoded line in the file.
  850. X                             UUencoded lines include the begin and end lines.
  851. X        ...                - Indicates zero or more lines that can contain
  852. X                             any information so long as they CANNOT be
  853. X                             misidentified as SEGMENT begin, ID or UUENCODED
  854. X                             lines.
  855. X
  856. X    Notice that the ID information can be spread across multiple lines.  A
  857. X    segment is assumed to end at the begining of the next segment, or at
  858. X    the end of the source file.  An UNPOST source file contains one or more
  859. X    segments.
  860. X
  861. X    UNPOST has three different modes, interpretation mode, concatenation
  862. X    mode and UU decoder mode.  In all three modes, UNPOST can accept one
  863. X    or more input files.
  864. X
  865. X    In the first mode, interpretation mode, UNPOST looks at segment header
  866. X    and body lines before the first UU encoded line, and attempts to extract
  867. X    three pieces of information from them: segment number, total number
  868. X    of segments that the binary was split into, and an ID string that is
  869. X    common to all segments.  If UNPOST finds something that it considers
  870. X    to be an ID string, and a uuencoded line in the segment, but it does
  871. X    not find a segment number and number of segments, UNPOST assumes that
  872. X    the segment is a single segment binary posting (part 1 of 1).
  873. X
  874. X    To aid in finding out what happened, in interpretation mode UNPOST
  875. X    will write a list of all the different ID strings and their respective
  876. X    segment lists to standard error or the file specified as the error
  877. X    file (see Standards section for details of what an ID string is).
  878. X    Any errors or warnings detected during processing will also be
  879. X    written to standard error or error file.
  880. X
  881. X    In interpretation mode three other files can optionally be created.
  882. X    All three of these files will contain segments copied out of the source
  883. X    file, and none of these files will be created unless they are turned
  884. X    on and named by a command line switch.
  885. X
  886. X    The first optional file that UNPOST can create for the user in
  887. X    interpretation mode is the text file (-t switch).  This file will have
  888. X    copied to it all segments from the source file that do not contain
  889. X    uuencoded data.
  890. X
  891. X    Segments that are part 0/# type segments that do not contain uuencoded
  892. X    data will NOT be copied to the text file.  They are considered to be
  893. X    description segments, and they will be copied to the description file
  894. X    only if the -d switch is turned on.  Also, all binary postings that
  895. X    have all of their segments present will have the segment header
  896. X    and body of segment #1 (up to and including the uuencode begin line)
  897. X    copied into the description file.
  898. X
  899. X    The third optional file that can be created in interpretation mode is
  900. X    the incomplete or unused uuencode data segments file.  This file
  901. X    contains all segments that have uuencoded data, that were not used in
  902. X    a succesful uudecoding.  This file will only be created if the -i
  903. X    switch is present.
  904. X
  905. X    The incompletes file allows the user to hand decode those binarys which
  906. X    could not be interpreted or decoded by UNPOST.  Often times, a binary
  907. X    will have all of it's parts, but UNPOST will not be able to put them
  908. X    together because of differences in the ID string between segments, or
  909. X    problems with the part numbering information.  The simplest way to
  910. X    solve these problems is to collect the incompletes, edit the ID
  911. X    lines to correct the problem, and rerun UNPOST on the incompletes
  912. X    file.
  913. X
  914. X    In the second mode, catentation mode, UNPOST assumes that all of the
  915. X    segments in the source file between a uuencode begin and a uuencode
  916. X    end line are part of one binary posting and that the segments are in
  917. X    order.  UNPOST scans from the begining of the file until it finds a
  918. X    uuencode begin line, and decodes from there (skipping over non-
  919. X    uuencoded lines such as segment header lines and signatures) until
  920. X    it finds a uuencode end line.
  921. X
  922. X    In the last mode, UU decoder mode, UNPOST assumes that the source
  923. X    file contains one or more UU encoded files.  Only UU encoded lines
  924. X    are allowed between the uuencode begin line and the uuencode end line
  925. X    of any single uuencoded file.
  926. X
  927. X    Example header:
  928. X
  929. X    (1) Article 2096 of alt.binaries.pictures.misc:
  930. X        Newsgroups: alt.binaries.pictures.misc
  931. X        Path: csn!csn!convex!cs.utexas.edu!
  932. X        From: a43xz@brain.ac.da (Joe User)
  933. X    (2) Subject: ship.gif (1/3)
  934. X        Organization: Somewhere Near The Sea.
  935. X        Date: Fri, 19 Feb 1993 06:43:48 GMT
  936. X        Message-ID: <21128@brain.ac.da>
  937. X        Sender: news@dep.rnsft.ac.da (Usenet)
  938. X        Lines: 761
  939. X
  940. X
  941. X        Picture of a ship in a bottle, full rigged.  How did it get there?
  942. X
  943. X    (3) section 1 of uuencode 5.20 of file ship.gif    by R.E.M.
  944. X
  945. X    (4) begin 644 ship.gif
  946. X        M1TE&.#=A@`+@`9<```0$!`0$!",G,"LG)RLG,"LG.30G,#TG)RLP,"LP.3TG
  947. X
  948. X    In the above example, line (1) is the SEGMENT begin line, line (2) is
  949. X    a HEADER ID line, line (3) is a BODY ID line and line (4) is the first
  950. X    UUENCODED line in the body.
  951. X
  952. XOptions:
  953. X
  954. X    -b[-]       Set this flag to make UNPOST write the incomplete
  955. X                uuencoded segments to separate files.  This defaults
  956. X                to off.
  957. X
  958. X    -c  <file>  To read and use a different configuration than the
  959. X                default configuration.  The default configuration is
  960. X                stored in a file called def.cfg.
  961. X
  962. X    -d[-]       Turns on description capturing and writes descriptions
  963. X                to a file that has the same name as the output but with
  964. X                a .inf extension.  This defaults to on.
  965. X
  966. X    -e  <file>  Redirects error and information output from standard
  967. X                error to <file>.
  968. X
  969. X    -f[-]       Modify file names to be MS-DOS/USENET compatible.  Use
  970. X                of -f turns file name modification on if the default is off,
  971. X                and -f- turns file name modification off if the default
  972. X                is on.  File name modification is currently the default.
  973. X
  974. X    -h          Turns on full interpretation mode.  This is the default.
  975. X
  976. X    -i  <file>  Turns on incomplete binaries capturing and writes the
  977. X                segments to file <file>.
  978. X
  979. X    -s          Switch to ordered segment mode.  This mode ignores segment
  980. X                headers, and assumes that the segments are in order.
  981. X
  982. X    -t  <file>  Turns on text only segment capturing and writes the segments
  983. X                to <file>.
  984. X
  985. X    -u          Switch to uudecoder mode.  Assume only uuencoded data
  986. X                between begin and end lines.  Multiple uuencoded files
  987. X                are allowed.
  988. X
  989. X    -v          Show version number and quit.
  990. X
  991. X    -?          Show a summary of the command line switches.
  992. X
  993. X    It is important to realize that UNPOST parses the command line in
  994. X    parallel with operations, so the order of the switches on the
  995. X    command line is VERY important.  For example:
  996. X
  997. X    unpost -d -e errors -i abpm.inc abpm.uue -c cbip.cfg -d- cbip.uue
  998. X
  999. X    This will use the default configuration to process the file abpm.uue,
  1000. X    writing out description files, writing errors to the file errors,
  1001. X    and writing incompletes to the file abpm.inc.  After UNPOST finishes
  1002. X    processing abpm.uue, it will read in the cbip.cfg configuration,
  1003. X    turn off writing description files and process cbip.uue.
  1004. X
  1005. X    Note that the errors will continue to be written to the file errors,
  1006. X    and that the incomplete binaries will continue to be written to the
  1007. X    file abpm.inc.  Since we are switching configurations, this is
  1008. X    probably not a good idea.
  1009. X
  1010. XStandards:
  1011. X
  1012. X    In all modes, UNPOST recognizes and decodes only uuencoded data.
  1013. X
  1014. X    In interpretation mode UNPOST requires that:
  1015. X
  1016. X        1)  The uuencoded lines be true uuencoded lines.  This means
  1017. X            that if trailing spaces are truncated by a mailer, editor
  1018. X            or news node, UNPOST will not consider those lines to
  1019. X            be uuencoded lines.  Also, the uuencode character set
  1020. X            recognized by UNPOST is ' ' - '`', with no other characters
  1021. X            being legal.
  1022. X
  1023. X        2)  That all segments of the same binary file posting have
  1024. X            the same, recognizable ID string.
  1025. X
  1026. X        3)  Segments have a recognizable SEGMENT begin line as the
  1027. X            first line in the segment (denoting the begining of a
  1028. X            segment).
  1029. X
  1030. X        4)  That all ID lines follow the SEGMENT begin line in the
  1031. X            segment.
  1032. X
  1033. X        5)  That the first UUencoded line of the segment follows the
  1034. X            last ID line.
  1035. X
  1036. X        6)  That the first uuencode line in the first segment be a
  1037. X            begin line.
  1038. X
  1039. X        7)  That the last segment contain a uuencode end line.
  1040. X
  1041. X    In sorted segment mode, UNPOST requires that:
  1042. X
  1043. X        1)  The uuencoded lines be true uuencoded lines.  This means
  1044. X            that if trailing spaces are truncated by a mailer, editor
  1045. X            or news node, UNPOST will not consider those lines to
  1046. X            be uuencoded lines.  Also, the uuencode character set
  1047. X            recognized by UNPOST is ' ' - '`', with no other characters
  1048. X            being legal.
  1049. X
  1050. X        2)  That the segments be stored in the file in order.
  1051. X
  1052. X        3)  That the first uuencode line in the first segment be a
  1053. X            begin line.
  1054. X
  1055. X        4)  That the last segment contain a uuencode end line.
  1056. X
  1057. X    In uudecoder mode, UNPOST requires that:
  1058. X
  1059. X        1)  There be only uuencoded lines between a uuencode begin and
  1060. X            a uuencode end line.  In this mode, UNPOST will recognize
  1061. X            and attempt to repair lines that had trailing spaces
  1062. X            truncated.
  1063. X
  1064. XExamples:
  1065. X
  1066. X    To extract a single binary that had all of it's segments saved in order
  1067. X    to a single file:
  1068. X
  1069. X    unpost -s binary.uue
  1070. X
  1071. X    To extract all binaries that have had all of their segments saved
  1072. X    to a single file:
  1073. X
  1074. X    unpost multiple.uue 2> errors
  1075. X        Or
  1076. X    unpost -e errors multiple.uue
  1077. X
  1078. X    The file errors will contain a list of all the ID strings that UNPOST
  1079. X    found and thought could have been binary files, and any errors
  1080. X    that occurred during processing.
  1081. X
  1082. X    To capture the incomplete or unused segments that have uuencoded
  1083. X    data in them:
  1084. X
  1085. X    unpost -e errors -i multiple.inc multiple.uue
  1086. X
  1087. X    To capture descriptions and text only segments as well:
  1088. X
  1089. X    unpost -d -e errors -t text -i multiple.inc multiple.uue
  1090. X
  1091. X    To process two different files, one in uuencode mode, one in interpretation
  1092. X    mode:
  1093. X
  1094. X    unpost -e errors -u uuencode.uue -h multiple.uue
  1095. X
  1096. X    To process a file that requires a different configuration:
  1097. X
  1098. X    unpost -c -e errors multiple.uue
  1099. X
  1100. XOutput:
  1101. X
  1102. X    UNPOST will write diagnostic and informative messages to either
  1103. X    standard error or the error file.  The error file has three
  1104. X    parts, interpretation errors (duplicate segments, missing
  1105. X    uuencode begin lines, missing ID string, segment number or
  1106. X    number of segments, etc.), a dump of the binaries found, the
  1107. X    number of segments in each binary and the segment number and
  1108. X    offset of each segment in the source file.  The last part
  1109. X    is a mixture of information (the name of the binary that UNPOST
  1110. X    is attempting to decode) and any errors encountered during
  1111. X    decoding.
  1112. X
  1113. X    In the example below, UNPOST found one segment that had uuencoded
  1114. X    data, the Subject: line had barber.gif as the ID string, the
  1115. X    binary has one segment, and in the list of segments below,
  1116. X    we see that segment number 1 starts at offset 583 in the source file.
  1117. X
  1118. X    If there is a missing segment, it's segment number will be zero,
  1119. X    and it's file offset will be zero.
  1120. X
  1121. X    There were no interpretation errors, and there were no decoding
  1122. X    errors.
  1123. X
  1124. X    File ID                         Segments
  1125. X    ----------------------------------------
  1126. X    barber.gif                      1
  1127. X        1  583
  1128. X
  1129. X    Decoding Binary ID: 'barber.gif'
  1130. X
  1131. XNotes:
  1132. X
  1133. X    To use this program to collect all of the binaries posted to, say,
  1134. X    the alt.binaries.misc group on a daily basis, start up rn, go to
  1135. X    the alt.binaries.misc newsgroup, and save all of the unread segments
  1136. X    by using this command:
  1137. X
  1138. X    .-$smisc.uue:j
  1139. X
  1140. X    This will save all segments from the current number to the last to
  1141. X    the file misc.uue, then junk them.  After exiting rn, run UNPOST
  1142. X    on the file misc.uue in interpretation mode (default mode):
  1143. X
  1144. X    unpost -e errors -i misc.1 misc.uue
  1145. X
  1146. X    Make sure to check the errors and/or misc.1 file for segments
  1147. X    that UNPOST couldn't extract.
  1148. X
  1149. XDiagnostics:
  1150. X
  1151. X    Error - file 'filename' already exists.
  1152. X
  1153. X        UNPOST will not overwrite an existing file.  Delete the file or
  1154. X        rename it and try again.
  1155. X
  1156. X    Error - missing begin line.
  1157. X
  1158. X        UNPOST expected to find a uuencode begin line in this segment,
  1159. X        but did not.
  1160. X
  1161. X    Error - missing file name.
  1162. X
  1163. X        The binary that UNPOST was attempting to decode does not
  1164. X        seem to have a uuencode begin line in the first segment,
  1165. X        so UNPOST has no idea what the file name is.
  1166. X
  1167. X    Error - Could not open description file 'filename' for writing.
  1168. X
  1169. X        UNPOST could not open a file of that name for some reason.
  1170. X        Possibly a permission problem, or the file exists and is not
  1171. X        writeable.
  1172. X
  1173. X    Error - Bad write to binary file.
  1174. X
  1175. X        A file write failed for some unknown reason.  Possibly a full
  1176. X        disk?
  1177. X
  1178. X    Error - missing segment #
  1179. X        Binary ID: 'binaryID'
  1180. X
  1181. X        In attempting to decode a file whose ID string is binaryID,
  1182. X        one or more segments are missing.
  1183. X
  1184. X    Error - Missing UU end line.
  1185. X
  1186. X        As this is the last segment, it ought to have a uuencode end
  1187. X        line in it, but UNPOST did not find one.
  1188. X
  1189. X    Warning - Early uuencode end line.
  1190. X
  1191. X        UNPOST found a uuencode end line, but this was not the last
  1192. X        segment, so we found it early.  Did the poster screw up and
  1193. X        misnumber his segments?
  1194. X
  1195. X    Error - Unexpected UU begin line.
  1196. X
  1197. X        We found an unexpected (read: this is not the first line of the
  1198. X        first segment, so what is this doing here?) UU begin line.
  1199. X
  1200. X    Error - cannot identify string '' in line #
  1201. X
  1202. X        In reading in a configuration file, the configuration file
  1203. X        lexical analyzer could not recognize this string.
  1204. X
  1205. X
  1206. X    Error - Out of memory.
  1207. X
  1208. X            Yup.  Out of memory.  Split the source file into smaller
  1209. X            pieces and try again.
  1210. X
  1211. X    Error - Could not modify file name to be MS-DOS conformant.
  1212. X
  1213. X        File name mungling is turned on, and the name of one of the
  1214. X        files cannot be made conformant (probably due to having to
  1215. X        many numbers in it).
  1216. X
  1217. X    Warning - Unexpected end of file in segment:
  1218. X        Segment: 'segment line'
  1219. X
  1220. X         File name mungling is turned on, and UNPOST is attempting to
  1221. X        identify the file type (so it can use the proper extension
  1222. X        when modifying the file name) but the UU begin line was the
  1223. X        last line in the file.
  1224. X
  1225. X    Warning - No UU line after begin.
  1226. X        Segment: 'segment line'
  1227. X
  1228. X        File name mungling is turned on, and UNPOST is attempting to
  1229. X        identify the file type (so it can use the proper extension
  1230. X        when modifying the file name) but the UU begin line was not
  1231. X        followed by a line of UU encoded binary data.
  1232. X
  1233. X    Error - Got number of segments but not segment number.
  1234. X    Error - Got segment number but not number of segments.
  1235. X
  1236. X        UNPOST must have all three pieces of relevant data, but if
  1237. X        UNPOST has at least an ID string, UNPOST will attempt to
  1238. X        assume a one part binary.
  1239. X
  1240. X    Error - Could not get ID string.
  1241. X
  1242. X        Fatal error, with no ID string, there is no way to collect
  1243. X        the pieces together.
  1244. X
  1245. X    Error - No begin line in first segment:
  1246. X        Segment: 'segment line'
  1247. X
  1248. X        UNPOST did not find a UU begin line in the first segment.
  1249. X
  1250. X    Error - missing '}' in regular expression.
  1251. X
  1252. X        In a regular expression of the type abc{1, 2}, the closing curly
  1253. X        brace is missing.
  1254. X
  1255. X    Error - To many sub-expressions.
  1256. X
  1257. X        UNPOST has a limit on the number of sub-expressions it
  1258. X        allows.  This is a compile time option that can be changed
  1259. X        by modifying the value of MAX_SUB_EXPRS in regexp.h.
  1260. X
  1261. X    Error - missing ')' in regular expression.
  1262. X
  1263. X        Mismatched parentheses.
  1264. X
  1265. X    Error - badly formed regular expression.
  1266. X        Unexpected character 'c'
  1267. X
  1268. X        I give up!  What is this character doing at this point in
  1269. X        a regular expression?
  1270. X
  1271. X    Error, can not enumerate a sub expression.
  1272. X
  1273. X        Regular expressions of the type: (...)* are not allowed.
  1274. X
  1275. X    Error - illegal regular expression node type.
  1276. X
  1277. X        Whoops, we have an internal programmers error here.  Let
  1278. X        me know if you see this.
  1279. X
  1280. X    Error - Sub expression # extraction failed.
  1281. X
  1282. X        Another internal error that needs to be brought to my attention.
  1283. X
  1284. X    Error - could not open file 'filename' for reading.
  1285. X
  1286. X         UNPOST could not open file 'filename' for processing.  Did you
  1287. X        spellit right?
  1288. X
  1289. X    Error - Unexpected end of file.
  1290. X
  1291. X    Error - Unexpected UU begin line.
  1292. X
  1293. X    Error - Segment number # greater than number of segments in:
  1294. X        Segment: 'segment line'
  1295. X
  1296. X        Either UNPOST got screwed up somehow or the poster posted
  1297. X        something like (Part 10/9).
  1298. X
  1299. X    Warning - duplicate segment # in:
  1300. X        Binary ID: 'binaryID'
  1301. X
  1302. X        UNPOST found two segments with the same binary ID and the
  1303. X        same segment number.
  1304. X
  1305. X    Error - reading source file.
  1306. X
  1307. X        Could not read a line from the source file.
  1308. X
  1309. X    Error - Could not open file 'filename' for output.
  1310. X
  1311. X        Could not open one of the text, incomplete or error files
  1312. X        for writing.
  1313. X
  1314. XRegular Expressions:
  1315. X
  1316. X    Operands
  1317. X    --------
  1318. X
  1319. X    UNPOST regular expressions have three types of operands, character
  1320. X    strings (one or more characters), character sets and match any
  1321. X    single character.  A character string is any series of adjacent
  1322. X    characters that are not not meta-characters (special characters).
  1323. X    A data set is a string of characters enclosed in square braces with
  1324. X    an optional caret (^) as the first character following the open
  1325. X    square brace.  The match any character operand matches any single
  1326. X    character except the end of line character.
  1327. X
  1328. X    A character string in a regular expression matches the exact string
  1329. X    in the source, including case.
  1330. X
  1331. X    Example of character strings:
  1332. X
  1333. X    AirPlane    - Matches the string 'AirPlane', but not the strings
  1334. X                  'airPlane' or 'Airplane'.
  1335. X
  1336. X    A character set will match any single character in the source if
  1337. X    that character is a member of the set.  If the first character
  1338. X    of the set is the caret, the character set will match any
  1339. X    character that is NOT a member of the set (including control
  1340. X    characters!) except for NUL and LF.
  1341. X
  1342. X    A character set can be described using ranges.
  1343. X
  1344. X    Examples of character sets:
  1345. X
  1346. X    [abcd]      - Matches either a, b, c or d.
  1347. X
  1348. X    [0-9]       - Matches any decimal character.
  1349. X
  1350. X    [^a-z]      - Matches any character that is NOT a lower
  1351. X                  case alphabetic.
  1352. X
  1353. X    The match any character operand does just that, it matches any
  1354. X    character.  But it does not match the case of no character, NUL
  1355. X    or LF.
  1356. X
  1357. X    Example of match any character:
  1358. X
  1359. X    .       - Matches any character.
  1360. X
  1361. X    Operators
  1362. X    ---------
  1363. X
  1364. X    UNPOST regular expressions also contain operators.  The operators that
  1365. X    upost recognizes are the alternation operator, the span operators, the
  1366. X    concatenation operator and the enumeration operators.
  1367. X
  1368. X    The alternation operator has the lowest precedence of all the operators
  1369. X    and its action is to attempt to match one of two alternatives.
  1370. X
  1371. X    Example of alternation:
  1372. X
  1373. X    Airplane|drigible   - Matches either the string Airplane or the string
  1374. X                          drigible.
  1375. X
  1376. X    The next higher precedence operator is the catenation operator.  The
  1377. X    catenation operator specifies that both the left and right hand
  1378. X    regular expressions must match.  The catenation operator does not
  1379. X    have a special character, it is assumed to exist between two
  1380. X    different operands that have no other operator between them.
  1381. X
  1382. X    Example of catenation:
  1383. X
  1384. X    [Aa]irplane - Matches either a 'A' or an 'a' followed by the string
  1385. X                  irplane.  This is a catenation of the two regular
  1386. X                  expressions [Aa] and irplane.
  1387. X
  1388. X    The next higher precedence operator is the enumeration operator.
  1389. X    The enumeration operator specifies how many instances of a regular
  1390. X    expression must be matched.
  1391. X
  1392. X    Examples of Enumeration:
  1393. X
  1394. X    abc*    - Matches zero or more occurences of the string abc.
  1395. X    [A-Z]+  - Matches one or more occurences of an upper case
  1396. X              alphabetic character.
  1397. X    [ ]?    - Matches zero or one occurences of the space character.
  1398. X    very{1} - Matches one or more occurences of the string very.
  1399. X    b{1,3}  - Matches a minimum of one to a maximum of three occurences
  1400. X              of the string b.
  1401. X
  1402. X    An enumeration operator attempts to match the largest source sub-
  1403. X    string possible, except in the case of the . (match any character)
  1404. X    followed by an enumeration operator.  In this case, the smallest
  1405. X    possible sub-string is matched.
  1406. X
  1407. X    The precedence of the operators can be modified with the use of
  1408. X    parentheses.  Parentheses have another meaning as well, described
  1409. X    below.
  1410. X
  1411. X    Example of parenthesis use:
  1412. X
  1413. X    Death( defying|wish)    - Will match either the string 'Death defying'
  1414. X                              or the string 'Deathwish'.  Without the
  1415. X                              parentheses, the regular expression would
  1416. X                              match either the string 'Death defying'
  1417. X                              or the string 'wish'.
  1418. X    Sub Expressions
  1419. X    ---------------
  1420. X
  1421. X    UNPOST regular expressions are used primarily for identifying a
  1422. X    particular line and extracting substrings from that line.  To
  1423. X    this end, UNPOST regular expressions support sub-expression
  1424. X    marking.  Subexpressions are marked by parentheses.
  1425. X
  1426. X    To determine the sub-expression number of a sub-expression, scan
  1427. X    the regular expression from left to right, counting the number
  1428. X    of left parentheses.  Start with one, and whatever the count for
  1429. X    that sub-expression, is it's subexpression number.
  1430. X
  1431. X    Example:
  1432. X
  1433. X    .*((abcd)((0-9)+/(0-9)+))
  1434. X
  1435. X    Sub-expression ((abcd)((0-9)+/(0-9)+)) is sub-expression #1.
  1436. X    Sub-expression (abcd) is #2.  Sub-expression ((0-9)+/(0-9)+) is #3.
  1437. X    Sub-expression (0-9)+ is #4.  Sub-expression (0-9)+ is #5.
  1438. X
  1439. X    Anchoring
  1440. X    ---------
  1441. X
  1442. X    Normally, a regular expression will match a sub-string any where in
  1443. X    the source string.  If you want to specify that the matching sub-string
  1444. X    must start at the begining of the source string, you may use a caret
  1445. X    character as the first character of the regular expression.  This
  1446. X    anchors the regular expression match to the start of the line.
  1447. X
  1448. X    To anchor a regular expression to the end of a line, use the dollar
  1449. X    sign character.  This effectively matches the end of line or end
  1450. X    of string character.
  1451. X
  1452. X    Anchor operators have a higher precedence than alternation, but lower
  1453. X    than catenation.
  1454. X
  1455. XConfiguration:
  1456. X
  1457. X    Ok, here's how to configure UNPOST to work for you.  UNPOST relies
  1458. X    heavily on regular expressions.  These regular expressions may
  1459. X    not be correct for your news reader, or system.
  1460. X
  1461. X    There are five classes of regular expressions:
  1462. X
  1463. X    1)  The SEGMENT begin line regular expression.
  1464. X
  1465. X    2)  The ID line prefix regular expression.
  1466. X
  1467. X    3)  The ID line with part description regular expression list.
  1468. X
  1469. X    4)  The begin line regular expression.
  1470. X
  1471. X    5)  The end line regular expression.
  1472. X
  1473. X    Of these five, I don't expect you to have to modify the regular
  1474. X    expressions for handling begin and end lines, because they should
  1475. X    be correct for all uuencoders that follow the standard format.
  1476. X
  1477. X    Be aware that UNPOST has a hierarchy of regular expressions.
  1478. X    Each SEGMENT begin line regular expression has underneath it two
  1479. X    lists of regular expressions that recognize ID line prefixes,
  1480. X    and each element in the list of ID line prefix regular expressions
  1481. X    has a list under it that attempts to parse the ID line.
  1482. X
  1483. X    The two lists immediately under the SEGMENT begin line regular
  1484. X    expression are for 1) the header and 2) the body.
  1485. X
  1486. X    The ID line prefix regular expression exists for the sake of
  1487. X    efficiency.  It is used to find an ID line before we attempt
  1488. X    to parse it.  Modify or add one of these if you wish to change
  1489. X    whether or not a line is recognized by UNPOST as being an ID line.
  1490. X    If you modify this, you must modify the list of segment description
  1491. X    regular expressions to match.
  1492. X
  1493. X    The SEGMENT begin line regular expressions are used to find the begining
  1494. X    of a SEGMENT, or the end of a previous segment.  Modify these to change
  1495. X    the line or lines that UNPOST recognizes as the begining of a segment.
  1496. X
  1497. X    If you get an error message that indicates that the Subject line
  1498. X    has no identifiable part description, and you see that some bright
  1499. X    boy/girl has come up with a brand new part description format, then
  1500. X    you have two choices, modify the source and hope they don't post
  1501. X    again, or add a new ID line regular expression to the list of
  1502. X    ID line regular expressions in the segment.c source file.
  1503. X
  1504. X    Be aware that the lists of regular expressions are searched in order
  1505. X    from top to bottom to find a match.  This means that less specific
  1506. X    regular expressions should be placed later in the list.  For example:
  1507. X    the regular expression '\((0-9)+/(0-9)+\)' should come before the
  1508. X    regular expression '(0-9)+ (0-9)+' in the part syntax parsing regular
  1509. X    expression list.  This reduces the number of misparses that occur.
  1510. X
  1511. X    Remember that C uses the backslash (\) as an escape character in
  1512. X    strings, so to put a backslash into a regular expression you
  1513. X    need to put two into the C source string.
  1514. X
  1515. X    All regular expressions can be found at the top of the parse.c source
  1516. X    file.  Before you modify the actual source code and recompile, I
  1517. X    strongly suggest that you test your new regular expression using the
  1518. X    regular expression test harness (retest) that was compiled by the
  1519. X    makefile when you compiled UNPOST.  Then, when you are sure that
  1520. X    it is correct, copy the def.cfg file to a new name, make your changes
  1521. X    there and use that configuration file for a while.  If after all this,
  1522. X    you are sure that it works, go in and change the source code in
  1523. X    parse.c.
  1524. X
  1525. X    Before you add or modify a regular expression, you have to know the
  1526. X    syntax of the regular expressions used in this program.  The syntax
  1527. X    is very similiar to that used by UN*X style regular expressions,
  1528. X    but is not exactly the same.  See the section titled Regular
  1529. X    Expressions before attempting to configure UNPOST.
  1530. X
  1531. XConfiguration Files:
  1532. X
  1533. X    If you don't want to make permanent changes to UNPOST's configuration,
  1534. X    you can make a configuration file.  Configuration files are parsed by
  1535. X    UNPOST, the regular expressions compiled, and these regular expressions
  1536. X    control the operation of UNPOST completely.
  1537. X
  1538. X    A configuration file must have the following syntax:
  1539. X
  1540. X    segment "..."
  1541. X    {
  1542. X        header
  1543. X        {
  1544. X            "...."
  1545. X            {
  1546. X                "..."
  1547. X                {
  1548. X                    id #
  1549. X                    segment number #
  1550. X                    segments #
  1551. X                    alternate id #
  1552. X                    case ignore|sensitive
  1553. X                }
  1554. X            }
  1555. X        }
  1556. X        body
  1557. X        {
  1558. X            "...."
  1559. X            {
  1560. X                "..."
  1561. X                {
  1562. X                    id #
  1563. X                    segment number #
  1564. X                    segments #
  1565. X                    alternate id #
  1566. X                    case ignore|sensitive
  1567. X                }
  1568. X            }
  1569. X        }
  1570. X    }
  1571. X
  1572. X    Where "..." is a regular expression string, # is a sub expression
  1573. X    number (See the section on regular expressions), and case is
  1574. X    either ignored in regular expression string matching, or string
  1575. X    matching is case sensitive.
  1576. X
  1577. X    The outer most construct, starting with the segment "..." line
  1578. X    is used to describe how to recognize the begining of a segment.
  1579. X
  1580. X    The two constructs at the first level within the segment construct
  1581. X    are used to identify lines that are expected to contain part # of
  1582. X    # of parts information in the header, or the body of an article.
  1583. X
  1584. X    Within each header or body group are regular expressions that
  1585. X    are used to parse out the part # of # of parts information from
  1586. X    an identified information line.
  1587. X
  1588. X    A very simple example (taken directly out of the MUFUD
  1589. X    documentation):
  1590. X
  1591. X    segment "^Article[:]?"
  1592. X    {
  1593. X        header
  1594. X        {
  1595. X            "^Subject:"
  1596. X            {
  1597. X                "^Subject:(.*)part[ ]+([0-9]+)[ ]*(of|/)[ ]*([0-9]+)(.*)"
  1598. X                {
  1599. X                    id 1
  1600. X                    segment number 2
  1601. X                    segments 4
  1602. X                    alternate id 5
  1603. X                    case ignore
  1604. X                }
  1605. X                "^Subject:(.*)([0-9]+)[ ]*(of|/)[ ]*([0-9]+)(.*)"
  1606. X                {
  1607. X                    id 1
  1608. X                    segment number 2
  1609. X                    segments 4
  1610. X                    alternate id 5
  1611. X                    case ignore
  1612. X                }
  1613. X            }
  1614. X        }
  1615. X        body
  1616. X        {
  1617. X        }
  1618. X    }
  1619. X
  1620. X    Where:
  1621. X
  1622. X    id 1                Specifies the sub expression number of the
  1623. X                        sub expression that is used to extract the
  1624. X                        binary ID string.
  1625. X
  1626. X    segment number 2    Specifies the sub expression number of the
  1627. X                        sub expression that is used to extract the
  1628. X                        segment number.
  1629. X
  1630. X    segments 3          Specifies the sub expression number of the
  1631. X                        sub expression that is used to extract the
  1632. X                        number of segments that this binary was split
  1633. X                        into.
  1634. X
  1635. X    alternate id 4      Specifies the alternate sub expression
  1636. X                        number.  If the first ID sub expression extracts
  1637. X                        only an empty string (or one with all white
  1638. X                        space), the string extracted by this sub expression
  1639. X                        is used to generate the binary ID string.
  1640. X
  1641. X    case ignore         Specifies that the case of alphabetical
  1642. X                        characters is to be ignored in regular
  1643. X                        expression string matching.
  1644. X
  1645. X    See the def.cfg file for another (more complete) example.
  1646. X
  1647. XDefault Binary Switch Settings:
  1648. X
  1649. X    To modify the default values of the binary switches, edit the
  1650. X    file compiler.h, and change the value of the defines.  There
  1651. X    are defines for file name mungling, breaking incompletes
  1652. X    into separate files and for dumping out description files.
  1653. X
  1654. XBugs:
  1655. X
  1656. X    This program has been pretty extensively tested in interpretation mode,
  1657. X    and it appears to be both robust and flexible.
  1658. X
  1659. X    Unfortunately, about once a week, somebody comes up with a new and
  1660. X    unusual way to encode the parts description on the Subject line.
  1661. X
  1662. X    Bugs, after being found, are chased unmercifully and terminated with
  1663. X    extreme prejudice.  If you think you've found one, send all information
  1664. X    opinions, prejudices and  critcisms to me, and the hunt will begin
  1665. X    (just as soon as I can put on my safari hat and grab my debugger. . .).
  1666. X
  1667. XRights, Copyright, Legal stuff, etc:
  1668. X
  1669. X    This program is distributed free of charge, but it has NOT been placed
  1670. X    in the public domain!  I retain copyright.
  1671. X
  1672. X    Why?  Because I am pathologically commited to producing and maintaining
  1673. X    a quality product, and if every Tom, Dick and Susan modifies UNPOST
  1674. X    and redistributes, I will not be able to respond to bug reports or
  1675. X    continue to upgrade the product (branch revision problem, and all
  1676. X    that. . .).
  1677. X
  1678. X    My job isn't done so long as a single bug exists, or even one user
  1679. X    is unhappy (or even one system is uninfected. . . er, that is to
  1680. X    say, supported :-).
  1681. X
  1682. X    However, I am also dedicated to the principle of maximum use.  If
  1683. X    you wish, you may modify anything in this program you want to.  That's
  1684. X    why I distribute source.  BUT, you may NOT distribute your changes,
  1685. X    unless you can be legally sure that you have made so many as to make
  1686. X    what you distribute a new work.
  1687. X
  1688. X    If you learn any bad habits from reading my source code, tough luck.
  1689. X
  1690. X    And if anything in this section is not legally supportable, the
  1691. X    joke's on me.  Don't bother telling me, I'm to busy coding (So THERE!).
  1692. X
  1693. XAuthor:
  1694. X
  1695. X    John W. M. Stevens  -   jstevens@csn.org
  1696. END_OF_FILE
  1697.   if test 40962 -ne `wc -c <'unpost.doc'`; then
  1698.     echo shar: \"'unpost.doc'\" unpacked with wrong size!
  1699.   fi
  1700.   # end of 'unpost.doc'
  1701. fi
  1702. echo shar: End of archive 2 \(of 7\).
  1703. cp /dev/null ark2isdone
  1704. MISSING=""
  1705. for I in 1 2 3 4 5 6 7 ; do
  1706.     if test ! -f ark${I}isdone ; then
  1707.     MISSING="${MISSING} ${I}"
  1708.     fi
  1709. done
  1710. if test "${MISSING}" = "" ; then
  1711.     echo You have unpacked all 7 archives.
  1712.     rm -f ark[1-9]isdone
  1713. else
  1714.     echo You still must unpack the following archives:
  1715.     echo "        " ${MISSING}
  1716. fi
  1717. exit 0
  1718. exit 0 # Just in case...
  1719.