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

  1. Newsgroups: comp.sources.misc,alt.binaries.pictures.utilities
  2. From: jstevens@teal.csn.org (John W.M. Stevens)
  3. Subject: v36i117:  unpost - Smart multi-part uudecoder v2.1.2, Part04/07
  4. Message-ID: <1993Apr19.052459.28983@sparky.imd.sterling.com>
  5. X-Md4-Signature: b9e9665f7ef9406c6dab960973771ef6
  6. Date: Mon, 19 Apr 1993 05:24:59 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 117
  11. Archive-name: unpost/part04
  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:  config.c nntp/client.c segment.c
  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 4 (of 7)."'
  23. if test -f 'config.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'config.c'\"
  25. else
  26.   echo shar: Extracting \"'config.c'\" \(14313 characters\)
  27.   sed "s/^X//" >'config.c' <<'END_OF_FILE'
  28. X/******************************************************************************
  29. X* Module    :   Parse Configuration File --- Build the regular expression
  30. X*               hierarchy tree by reading data from a configuration file.
  31. X*
  32. X* Notes     :   Configuration file grammar:
  33. X*
  34. X*   CONFIG_FILE ::= SEGMENT <EOF>
  35. X*                   | SEGMENT CONFIG_FILE
  36. X*
  37. X*   SEGMENT     ::= 'segment' STRING '{' ID_LINES '}'
  38. X*
  39. X*   ID_LINES    ::= 'header' '{' PREFIXES '}'
  40. X*                   'body' '{' PREFIXES '}'
  41. X*
  42. X*   PREFIXES    ::= PREFIX
  43. X*                   | PREFIX PREFIXES
  44. X*
  45. X*   PREFIX      ::= STRING '{' ID_PARTS '}'
  46. X*
  47. X*   ID_PARTS    ::= ID_PART_RE
  48. X*                   | ID_PART_RE ID_PARTS
  49. X*
  50. X*   ID_PART_RE  :=  STRING '{'
  51. X*                   'id' NUMBER
  52. X*                   'segment' 'number' NUMBER
  53. X*                   'segments' NUMBER
  54. X*                   'alternate' 'id' NUMBER
  55. X*                   'case' CASE_TYPE
  56. X*                   '}'
  57. X*
  58. X*   CASE_TYPE   ::= 'sensitive'
  59. X*                   | 'ignore'
  60. X*
  61. X*   STRING      ::= '"' [ -~]* '"'
  62. X*
  63. X*   NUMBER      ::= [0-9]+
  64. X*
  65. X* Author    :   John W. M. Stevens
  66. X******************************************************************************/
  67. X
  68. X#include    "compiler.h"
  69. X
  70. X#include    "unpost.h"
  71. X#include    "lex.h"
  72. X#include    "list.h"
  73. X#include    "parse.h"
  74. X#include    "regexp.h"
  75. X#include    "config.h"
  76. X#include    "utils.h"
  77. X
  78. Xtypedef enum    {
  79. X    ID_SUB_EXPR,
  80. X    SEG_NO_SUB_EXPR,
  81. X    NO_SEGS_SUB_EXPR,
  82. X    ALT_ID_SUB_EXPR,
  83. X    CASE_SENSITIVITY
  84. X} ID_PARTS_IDX;
  85. X
  86. Xstatic  char    ReStr[512];
  87. X
  88. X/*-----------------------------------------------------------------------------
  89. X| Routine   :   ParseParts() --- Parse the ID line part number blocks.
  90. X|
  91. X| Returns   :   A pointer to the root of the ID part regular expression tree.
  92. X-----------------------------------------------------------------------------*/
  93. X
  94. Xstatic
  95. XPART_RE *ParseParts(void)
  96. X{
  97. X    register    int     i;
  98. X    auto        TOKEN   sym;
  99. X    auto        int     tkn;
  100. X    auto        int     Elements[5];
  101. X    auto        char    *tp;
  102. X    auto        PART_RE NewPart;
  103. X    auto        LIST    *PartList;
  104. X
  105. X    /*  Create ID list. */
  106. X    PartList = CrtList( sizeof( PART_RE ) );
  107. X
  108. X    /*  Get list of part extraction regular expressions.    */
  109. X    while ((tkn = Lex( &sym )) == T_DBL_QUOTE)
  110. X    {
  111. X        /*  Initialize new part re structure.   */
  112. X        NewPart.IDStr    = 0;
  113. X        NewPart.SegNo    = 0;
  114. X        NewPart.NoSegs   = 0;
  115. X        NewPart.AltIDStr = 0;
  116. X        NewPart.Case     = IGN_CASE;
  117. X
  118. X        /*  Get IDENT line part regular expression string.  */
  119. X        for (tp = ReStr; ; tp = ReStr + strlen( ReStr ))
  120. X        {
  121. X            /*  Copy string from token structure to buffer. */
  122. X            strcpy(tp, sym.str);
  123. X
  124. X            /*  Get next token. */
  125. X            if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
  126. X                break;
  127. X        }
  128. X
  129. X        /*  Create ID prefix regular expression string. */
  130. X        NewPart.ReExpStr = StrDup( ReStr );
  131. X
  132. X        /*  Check for opening curly brace.  */
  133. X        if (tkn != T_L_BRACE)
  134. X        {
  135. X            ParseErr("expecting '{' to open ID part block.");
  136. X            exit( 1 );
  137. X        }
  138. X
  139. X        /*  Process components in ANY order.    */
  140. X        for (i = ID_SUB_EXPR; i <= CASE_SENSITIVITY; i++)
  141. X            Elements[i] = 0;
  142. X
  143. X        for (i = ID_SUB_EXPR; i <= CASE_SENSITIVITY; i++)
  144. X        {
  145. X            /*  Get a token.    */
  146. X            if ((tkn = Lex( &sym )) == T_R_BRACE)
  147. X                break;
  148. X
  149. X            /*  Select parse action based on token. */
  150. X            switch ( tkn )
  151. X            {
  152. X            case T_ID:
  153. X                /*  Check for duplication.  */
  154. X                if (Elements[ID_SUB_EXPR] != 0)
  155. X                {
  156. X                    ParseErr("duplicate sub-expression numbers.");
  157. X                    exit( 1 );
  158. X                }
  159. X
  160. X                /*  Get the sub-expression number for the ID sub-string.    */
  161. X                if ((tkn = Lex( &sym )) != T_INT_NO)
  162. X                {
  163. X                    ParseErr("missing sub-expression number.");
  164. X                    exit( 1 );
  165. X                }
  166. X                NewPart.IDStr = sym.no;
  167. X                Elements[ID_SUB_EXPR] = 1;
  168. X                break;
  169. X            case T_SEGMENT:
  170. X                /*  Check for duplication.  */
  171. X                if (Elements[SEG_NO_SUB_EXPR] != 0)
  172. X                {
  173. X                    ParseErr("duplicate sub-expression numbers.");
  174. X                    exit( 1 );
  175. X                }
  176. X
  177. X                /*  Get next token. */
  178. X                if ((tkn = Lex( &sym )) != T_NUMBER)
  179. X                {
  180. X                    ParseErr("missing 'number' after 'segment'.");
  181. X                    exit( 1 );
  182. X                }
  183. X
  184. X                /*  Get sub-expression number for the segment number
  185. X                *   sub-string.
  186. X                */
  187. X                if ((tkn = Lex( &sym )) != T_INT_NO)
  188. X                {
  189. X                    ParseErr("missing sub-expression number.");
  190. X                    exit( 1 );
  191. X                }
  192. X                NewPart.SegNo = sym.no;
  193. X                Elements[SEG_NO_SUB_EXPR] = 1;
  194. X                break;
  195. X            case T_SEGMENTS:
  196. X                /*  Check for duplication.  */
  197. X                if (Elements[NO_SEGS_SUB_EXPR] != 0)
  198. X                {
  199. X                    ParseErr("duplicate sub-expression numbers.");
  200. X                    exit( 1 );
  201. X                }
  202. X
  203. X                /*  Get number of segments sub-expression number.   */
  204. X                if ((tkn = Lex( &sym )) != T_INT_NO)
  205. X                {
  206. X                    ParseErr("missing sub-expression number.");
  207. X                    exit( 1 );
  208. X                }
  209. X                NewPart.NoSegs = sym.no;
  210. X                Elements[NO_SEGS_SUB_EXPR] = 1;
  211. X                break;
  212. X            case T_ALTERNATE:
  213. X                /*  Check for duplication.  */
  214. X                if (Elements[ALT_ID_SUB_EXPR] != 0)
  215. X                {
  216. X                    ParseErr("duplicate sub-expression numbers.");
  217. X                    exit( 1 );
  218. X                }
  219. X
  220. X                /*  Get next token. */
  221. X                if ((tkn = Lex( &sym )) != T_ID)
  222. X                {
  223. X                    ParseErr("missing 'id' after 'alternate'.");
  224. X                    exit( 1 );
  225. X                 }
  226. X
  227. X                /*  Get alternate ID string sub-expression number.  */
  228. X                if ((tkn = Lex( &sym )) != T_INT_NO)
  229. X                {
  230. X                    ParseErr("missing sub-expression number.");
  231. X                    exit( 1 );
  232. X                }
  233. X                NewPart.AltIDStr = sym.no;
  234. X                Elements[ALT_ID_SUB_EXPR] = 1;
  235. X                break;
  236. X            case T_CASE:
  237. X                /*  Check for duplication.  */
  238. X                if (Elements[CASE_SENSITIVITY] != 0)
  239. X                {
  240. X                    ParseErr("duplicate sub-expression numbers.");
  241. X                    exit( 1 );
  242. X                }
  243. X
  244. X                /*  Get case sensitivity type.  */
  245. X                if ((tkn = Lex( &sym )) == T_SENSITIVE)
  246. X                    NewPart.Case = CASE_SENSITIVE;
  247. X                else if (tkn == T_IGNORE)
  248. X                    NewPart.Case = IGN_CASE;
  249. X                else
  250. X                {
  251. X                    ParseErr("expected case sensitivity type after 'case'.");
  252. X                    exit( 1 );
  253. X                }
  254. X                Elements[CASE_SENSITIVITY] = 1;
  255. X                break;
  256. X            default:
  257. X                ParseErr( "Unexpected token in ID part block" );
  258. X                break;
  259. X            }
  260. X        }
  261. X
  262. X        /*  Compile string and save pointer to expression tree in
  263. X        *   structure, then save structure in segment list.
  264. X        */
  265. X        NewPart.ReExpr = ReCompile( NewPart.ReExpStr );
  266. X        PartList = AppList(PartList, &NewPart);
  267. X
  268. X        /*  Get closing token.  */
  269. X        if (tkn != T_R_BRACE)
  270. X        {
  271. X            /*  Get and discard the right brace.    */
  272. X            if ((tkn = Lex( &sym )) != T_R_BRACE)
  273. X            {
  274. X                ParseErr("expecting '}' to close ID part block.");
  275. X                exit( 1 );
  276. X            }
  277. X        }
  278. X    }
  279. X
  280. X    /*  Check closing token.    */
  281. X    if (tkn != T_R_BRACE)
  282. X    {
  283. X        ParseErr("expecting '}' to close ID prefix block.");
  284. X        exit( 1 );
  285. X    }
  286. X
  287. X    /*  Append a null record.   */
  288. X    memset(&NewPart, 0, sizeof( PART_RE ));
  289. X    PartList = AppList(PartList, &NewPart);
  290. X
  291. X     /*  Return pointer to list. */
  292. X    MemCopy(PartList,
  293. X            PartList->List,
  294. X            sizeof( PART_RE ) * PartList->NoElems);
  295. X
  296. X    /*  Return pointer to list. */
  297. X    return( (PART_RE *) PartList );
  298. X}
  299. X
  300. X/*-----------------------------------------------------------------------------
  301. X| Routine   :   ParseIDs() --- Parse the ID blocks.
  302. X|
  303. X| Returns   :   A pointer to the root of the ID regular expression tree.
  304. X-----------------------------------------------------------------------------*/
  305. X
  306. Xstatic
  307. XIDENT   *ParseIDs(void)
  308. X{
  309. X    auto        TOKEN       sym;
  310. X    auto        int         tkn;
  311. X    auto        char        *tp;
  312. X    auto        IDENT       NewID;
  313. X    auto        LIST        *PreFixList;
  314. X
  315. X    /*  Create ID list. */
  316. X    PreFixList = CrtList( sizeof( IDENT ) );
  317. X
  318. X    /*  Get regular expression source string.   */
  319. X    while ((tkn = Lex( &sym )) == T_DBL_QUOTE)
  320. X    {
  321. X        /*  Get IDENT line regular expression string.   */
  322. X        for (tp = ReStr; ; tp = ReStr + strlen( ReStr ))
  323. X        {
  324. X            /*  Copy string from token structure to buffer. */
  325. X            strcpy(tp, sym.str);
  326. X
  327. X            /*  Get next token. */
  328. X            if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
  329. X                break;
  330. X        }
  331. X
  332. X        /*  Check for opening curly brace.  */
  333. X        if (tkn != T_L_BRACE)
  334. X        {
  335. X            ParseErr("expecting '{' after ID prefix regular expression.");
  336. X            exit( 1 );
  337. X        }
  338. X
  339. X        /*  Create ID prefix regular expression string. */
  340. X        NewID.ReExprStr = StrDup( ReStr );
  341. X
  342. X        /*  Parse header regular expression configuration block.    */
  343. X        NewID.IdParts = ParseParts();
  344. X
  345. X        /*  Compile string and save pointer to expression tree in
  346. X        *   structure, then save structure in segment list.
  347. X        */
  348. X        NewID.ReExpr = ReCompile( NewID.ReExprStr );
  349. X        PreFixList = AppList(PreFixList, &NewID);
  350. X    }
  351. X
  352. X    /*  Check closing token.    */
  353. X    if (tkn != T_R_BRACE)
  354. X    {
  355. X        ParseErr("expecting '}' to close ID block.");
  356. X        exit( 1 );
  357. X     }
  358. X
  359. X    /*  Append a null record.   */
  360. X    memset(&NewID, 0, sizeof( IDENT ));
  361. X    PreFixList = AppList(PreFixList, &NewID);
  362. X
  363. X    /*  Return pointer to list. */
  364. X    MemCopy(PreFixList,
  365. X            PreFixList->List,
  366. X            sizeof( IDENT ) * PreFixList->NoElems);
  367. X
  368. X    /*  Return pointer to list. */
  369. X    return( (IDENT *) PreFixList );
  370. X}
  371. X
  372. X/*-----------------------------------------------------------------------------
  373. X| Routine   :   ReadConfig() --- Read the configuration file.
  374. X|
  375. X| Inputs    :   CfgFlNm - Name of configuration file name.
  376. X|
  377. X| Returns   :   A pointer to the root of the SEGMENT regular expression tree.
  378. X-----------------------------------------------------------------------------*/
  379. X
  380. XSEGMENT *ReadConfig(char    *CfgFlNm)
  381. X{
  382. X    auto        TOKEN       sym;
  383. X    auto        int         tkn;
  384. X    auto        char        *tp;
  385. X    auto        SEGMENT     NewSeg;
  386. X    auto        LIST        *SegList;
  387. X
  388. X    /*  Open the configuration file.    */
  389. X    OpenCfg( CfgFlNm );
  390. X
  391. X    /*  Get token.  */
  392. X    if ((tkn = Lex( &sym )) != T_SEGMENT)
  393. X    {
  394. X        ParseErr("expecting SEGMENT token.");
  395. X        exit( 1 );
  396. X    }
  397. X
  398. X    /*  Create segment list.    */
  399. X    SegList = CrtList( sizeof( SEGMENT ) );
  400. X
  401. X    /*  Process multiple SEGMENT begin line blocks. */
  402. X    while (tkn == T_SEGMENT)
  403. X    {
  404. X        /*  Get regular expression source string.   */
  405. X        if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
  406. X        {
  407. X            ParseErr("expecting regular expression source string.");
  408. X            exit( 1 );
  409. X        }
  410. X
  411. X        /*  Get SEGMENT begin line regular expression string.   */
  412. X        for (tp = ReStr; ; tp = ReStr + strlen( ReStr ))
  413. X        {
  414. X            /*  Copy string from token structure to buffer. */
  415. X            strcpy(tp, sym.str);
  416. X
  417. X            /*  Get next token. */
  418. X            if ((tkn = Lex( &sym )) != T_DBL_QUOTE)
  419. X                break;
  420. X        }
  421. X
  422. X        /*  Check for opening curly brace.  */
  423. X         if (tkn != T_L_BRACE)
  424. X        {
  425. X            ParseErr("expecting '{' to open SEGMENT block.");
  426. X            exit( 1 );
  427. X        }
  428. X
  429. X        /*  Create SEGMENT regular expression string.   */
  430. X        NewSeg.ReExprStr = StrDup( ReStr );
  431. X
  432. X        /*  Get header block prefix.    */
  433. X        if ((tkn = Lex( &sym )) != T_HEADER)
  434. X        {
  435. X            ParseErr("expecting 'header' in SEGMENT block.");
  436. X            exit( 1 );
  437. X        }
  438. X
  439. X        /*  Get open curly brace.   */
  440. X        if ((tkn = Lex( &sym )) != T_L_BRACE)
  441. X        {
  442. X            ParseErr("expecting '{' to open HEADER block.");
  443. X            exit( 1 );
  444. X        }
  445. X
  446. X        /*  Get header block.   */
  447. X        NewSeg.Header = ParseIDs();
  448. X
  449. X        /*  Get body block prefix.  */
  450. X        if ((tkn = Lex( &sym )) != T_BODY)
  451. X        {
  452. X            ParseErr("expecting 'body' in SEGMENT block.");
  453. X            exit( 1 );
  454. X        }
  455. X
  456. X        /*  Get open curly brace.   */
  457. X        if ((tkn = Lex( &sym )) != T_L_BRACE)
  458. X        {
  459. X            ParseErr("expecting '{' to open BODY block.");
  460. X            exit( 1 );
  461. X        }
  462. X
  463. X        /*  Parse body ID block.    */
  464. X        NewSeg.Body = ParseIDs();
  465. X
  466. X        /*  Compile string and save pointer to expression tree in
  467. X        *   structure, then save structure in SEGMENT begin line list.
  468. X        */
  469. X        NewSeg.ReExpr = ReCompile( NewSeg.ReExprStr );
  470. X        SegList = AppList(SegList, &NewSeg);
  471. X
  472. X        /*  Get closing token.  */
  473. X        if ((tkn = Lex( &sym )) != T_R_BRACE)
  474. X        {
  475. X            ParseErr("expecting '}' to close SEGMENT block.");
  476. X            exit( 1 );
  477. X        }
  478. X
  479. X        /*  Get next token. */
  480. X        if ((tkn = Lex( &sym )) == EOF)
  481. X            break;
  482. X    }
  483. X
  484. X    /*  Append a null record.   */
  485. X    memset(&NewSeg, 0, sizeof( SEGMENT ));
  486. X    SegList = AppList(SegList, &NewSeg);
  487. X
  488. X    /*  Return pointer to list. */
  489. X    MemCopy(SegList,
  490. X            SegList->List,
  491. X            sizeof( SEGMENT ) * SegList->NoElems);
  492. X
  493. X    /*  Close the configuration file and return a pointer to the new
  494. X    *   configuration tree.
  495. X    */
  496. X    CloseCfg();
  497. X    return( (SEGMENT *) SegList );
  498. X}
  499. END_OF_FILE
  500.   if test 14313 -ne `wc -c <'config.c'`; then
  501.     echo shar: \"'config.c'\" unpacked with wrong size!
  502.   fi
  503.   # end of 'config.c'
  504. fi
  505. if test -f 'nntp/client.c' -a "${1}" != "-c" ; then 
  506.   echo shar: Will not clobber existing file \"'nntp/client.c'\"
  507. else
  508.   echo shar: Extracting \"'nntp/client.c'\" \(18750 characters\)
  509.   sed "s/^X//" >'nntp/client.c' <<'END_OF_FILE'
  510. X/******************************************************************************
  511. X* Module    :   NNTP Client for the automatic extraction of all news articles
  512. X*               from a news group without the use of a news reader.
  513. X*
  514. X* Author    :   John W. M. Stevens
  515. X******************************************************************************/
  516. X
  517. X#include    <stdio.h>
  518. X#include    <stdlib.h>
  519. X#include    <fcntl.h>
  520. X#include    <string.h>
  521. X#include    <time.h>
  522. X
  523. X#include    <sys/errno.h>
  524. X#include    <sys/param.h>
  525. X#include    <sys/file.h>
  526. X#include    <sys/ioctl.h>
  527. X#include    <sys/socket.h>
  528. X#include    <sys/un.h>
  529. X#include    <netinet/in.h>
  530. X#include    <netdb.h>
  531. X
  532. X#define MAX_BFR     513
  533. X
  534. Xtypedef enum    {
  535. X    ST_EXIT,
  536. X    ST_BEGIN,
  537. X    ST_NORM,
  538. X    ST_CR,
  539. X    ST_END_ART,
  540. X    ST_CHK_EXIT
  541. X} STATES;
  542. X
  543. Xextern int  errno;
  544. Xextern char *sys_errlist[];
  545. X
  546. X/*-----------------------------------------------------------------------------
  547. X| Routine   :   MkTmpFl() --- Make a temporary file, and return the name.
  548. X|
  549. X| Outputs   :   FileName    - Returns the name of the temporary file.
  550. X-----------------------------------------------------------------------------*/
  551. X
  552. XFILE    *MkTmpFl(char   *FileName)
  553. X{
  554. X    register    int     i;
  555. X    auto        int     ret;
  556. X    auto        char    TmBfr[10];
  557. X
  558. X    /*  Use the time value to create a temporary file name. */
  559. X    sprintf(TmBfr, "%08x", time( (time_t *) 0 ));
  560. X
  561. X    /*  Make sure that the file does not already exist. */
  562. X    for (i = 0; i < 1000; i++)
  563. X    {
  564. X        /*  Create the file name.   */
  565. X        sprintf(FileName,
  566. X                "%03d%.5s.%.3s",
  567. X                i,
  568. X                TmBfr,
  569. X                TmBfr + 5);
  570. X
  571. X        /*  Check to see if the file exists.    */
  572. X        if ((ret = access(FileName, 0)) != 0)
  573. X        {
  574. X            if (errno == ENOENT)
  575. X                break;
  576. X        }
  577. X    }
  578. X
  579. X    /*  Check to see if we failed utterly.  */
  580. X    if (i == 1000)
  581. X        return( NULL );
  582. X
  583. X    /*  Open the file whose name we just constructed.   */
  584. X    return( fopen(FileName, "w") );
  585. X}
  586. X
  587. X/*-----------------------------------------------------------------------------
  588. X| Routine   :   WrtSrvr() --- Write a buffer to the server.
  589. X|
  590. X| Inputs    :   SockDesc    - Socket descriptor.
  591. X|               Bfr         - Buffer to read into.
  592. X|               Len         - Length of message in buffer.
  593. X-----------------------------------------------------------------------------*/
  594. X
  595. Xvoid    WrtSrvr(int     SockDesc,
  596. X                char    *Bfr,
  597. X                int     Len)
  598. X{
  599. X    auto    int     ret;
  600. X
  601. X    /*  Write buffer to server. */
  602. X    if ((ret = write(SockDesc, Bfr, Len)) <= 0)
  603. X    {
  604. X        fprintf(stderr,
  605. X                "%s %d - Error in writing to news server.\n",
  606. X                __FILE__,
  607. X                __LINE__);
  608. X        fprintf(stderr,
  609. X                "\tReturn = %d, Error number = %d\n",
  610. X                ret,
  611. X                errno);
  612. X        exit( 1 );
  613. X    }
  614. X}
  615. X
  616. X/*-----------------------------------------------------------------------------
  617. X| Routine   :   RdSrvr() --- Read a buffer from the server.
  618. X|
  619. X| Inputs    :   SockDesc    - Socket descriptor.
  620. X|               Bfr         - Buffer to read into.
  621. X|               MaxLen      - Maximum length of buffer.
  622. X-----------------------------------------------------------------------------*/
  623. X
  624. Xint     RdSrvr(int  SockDesc,
  625. X               char *Bfr,
  626. X               int  MaxLen)
  627. X{
  628. X    auto        int     ret;
  629. X
  630. X    /*  Get the buffer full.    */
  631. X    if ((ret = read(SockDesc, Bfr, MaxLen - 1)) < 0)
  632. X    {
  633. X        fprintf(stderr,
  634. X                "%s %d - Error in reading from news server.\n",
  635. X                __FILE__,
  636. X                __LINE__);
  637. X        fprintf(stderr,
  638. X                "\tReturn = %d, Error number = %d\n",
  639. X                ret,
  640. X                errno);
  641. X        exit( 1 );
  642. X    }
  643. X    Bfr[ret] = '\0';
  644. X    return( ret );
  645. X}
  646. X
  647. X/*-----------------------------------------------------------------------------
  648. X| Routine   :   RdArt() --- Read an article from the server.
  649. X|
  650. X| Inputs    :   SockDesc    - Socket descriptor.
  651. X|               OutFp       - Pointer to output file.
  652. X-----------------------------------------------------------------------------*/
  653. X
  654. Xvoid    RdArt(int   SockDesc,
  655. X              long  ArtNo,
  656. X              char  *NewsGroup,
  657. X              FILE  *OutFp)
  658. X{
  659. X    register    int     i;
  660. X    auto        int     State;
  661. X    auto        int     Size;
  662. X    auto        int     Status;
  663. X
  664. X    /*  Read buffer.    */
  665. X    static      char    Bfr[MAX_BFR];
  666. X
  667. X    /*  Get article.    */
  668. X    sprintf(Bfr, "ARTICLE %ld\r\n", ArtNo);
  669. X    WrtSrvr(SockDesc, Bfr, strlen( Bfr ));
  670. X
  671. X    /*  Get reply.  */
  672. X    Size = RdSrvr(SockDesc, Bfr, MAX_BFR);
  673. X
  674. X    /*  Get status, etc.    */
  675. X    sscanf(Bfr,
  676. X           "%d %ld",
  677. X           &Status,
  678. X           &ArtNo);
  679. X
  680. X    /*  Execute the command.    */
  681. X    switch ( Status )
  682. X    {
  683. X    case 220:
  684. X        /*  Get all text that follows, write it to
  685. X        *   the output file.
  686. X        */
  687. X        fprintf(OutFp,
  688. X                "Article: %ld of %s\n",
  689. X                ArtNo,
  690. X                NewsGroup);
  691. X        break;
  692. X    case 221:
  693. X    case 222:
  694. X    case 223:
  695. X        fprintf(stderr,
  696. X                "%s %d : Error, response to ARTICLE = %d.\n",
  697. X                __FILE__,
  698. X                __LINE__,
  699. X                Status);
  700. X        return;
  701. X    case 412:
  702. X        fprintf(stderr,
  703. X                "%s %d : Error, no news group selected.\n",
  704. X                __FILE__,
  705. X                __LINE__);
  706. X        return;
  707. X    case 420:
  708. X        fprintf(stderr,
  709. X                "%s %d : Error, no current article selected.\n",
  710. X                __FILE__,
  711. X                __LINE__);
  712. X        return;
  713. X    case 423:
  714. X        return;
  715. X    case 430:
  716. X        return;
  717. X    }
  718. X
  719. X    /*  Throw away the first line, and continue.    */
  720. X    for (i = 0; i < Size; i++)
  721. X    {
  722. X        /*  Skip carriage return.   */
  723. X        if (Bfr[i] == '\r')
  724. X        {
  725. X            i += 2;
  726. X            break;
  727. X        }
  728. X    }
  729. X    fputc('.', stderr);
  730. X
  731. X    /*  Get and put characters from buffer to output file.  */
  732. X    State = ST_BEGIN;
  733. X    while (State != ST_EXIT && Size)
  734. X    {
  735. X        /*  Determine operation based on state. */
  736. X        switch ( State )
  737. X        {
  738. X        case ST_BEGIN:
  739. X            if (Bfr[i] == '.')
  740. X            {
  741. X                State = ST_END_ART;
  742. X                break;
  743. X            }
  744. X            State = ST_NORM;
  745. X        case ST_NORM:
  746. X            if (Bfr[i] == '\n')
  747. X            {
  748. X                fprintf(stderr,
  749. X                        "%s %d : Warning - saw '\\n' before '\\r'.\n",
  750. X                        __FILE__,
  751. X                        __LINE__);
  752. X                fputc(Bfr[i], OutFp);
  753. X                State = ST_BEGIN;
  754. X            }
  755. X            else if (Bfr[i] == '\r')
  756. X                State = ST_CR;
  757. X            else
  758. X                fputc(Bfr[i], OutFp);
  759. X            break;
  760. X        case ST_CR:
  761. X            if (Bfr[i] == '\n')
  762. X                fputc(Bfr[i], OutFp);
  763. X            else if (Bfr[i] == '\r')
  764. X                break;
  765. X            else
  766. X            {
  767. X                /*  Report warning. */
  768. X                fprintf(stderr,
  769. X                        "%s %d : Warning - saw '.\\r' but no '\\n'.\n",
  770. X                        __FILE__,
  771. X                        __LINE__);
  772. X            }
  773. X            State = ST_BEGIN;
  774. X            break;
  775. X        case ST_END_ART:
  776. X            if (Bfr[i] == '\r')
  777. X                State = ST_CHK_EXIT;
  778. X            else
  779. X            {
  780. X                fputc(Bfr[i], OutFp);
  781. X                State = ST_NORM;
  782. X            }
  783. X            break;
  784. X        case ST_CHK_EXIT:
  785. X            /*  Set state to exit.  */
  786. X            State = ST_EXIT;
  787. X            if (Bfr[i] != '\n')
  788. X            {
  789. X                /*  Issue warning.  */
  790. X                fprintf(stderr,
  791. X                        "%s %d : Warning - saw '.\\r' but no '\\n'.\n",
  792. X                        __FILE__,
  793. X                        __LINE__);
  794. X            }
  795. X            break;
  796. X        }
  797. X
  798. X        /*  Next character, get new buffer if empty.    */
  799. X        if (++i >= Size && State != ST_EXIT)
  800. X        {
  801. X            /*  Read a buffer full. */
  802. X            Size = RdSrvr(SockDesc, Bfr, MAX_BFR);
  803. X            i = 0;
  804. X        }
  805. X    }
  806. X
  807. X    /*  Check exit conditions.  */
  808. X    if (i < Size)
  809. X    {
  810. X        fprintf(stderr,
  811. X                "%s %d : Warning - did not use all of article.\n",
  812. X                __FILE__,
  813. X                __LINE__);
  814. X    }
  815. X    fprintf(OutFp, "\n");
  816. X}
  817. X
  818. X/*-----------------------------------------------------------------------------
  819. X| Routine   :   GetPortNo() --- This routine converts a character string
  820. X|               to a port number.  It looks up the service by name, and if
  821. X|               there is none, then it converts the string to a number with
  822. X|               scanf.
  823. X|
  824. X| Inputs    :   PortName    - Name of port to convert.
  825. X|
  826. X| Returns   :   Returns the TCP port number for this server.
  827. X-----------------------------------------------------------------------------*/
  828. X
  829. Xint GetPortNo(char  *PortName)
  830. X{
  831. X    auto    int     PortNo;
  832. X    struct  servent *Service;
  833. X
  834. X    /*  If no port name string, return no port number.  */
  835. X    if (PortName == NULL)
  836. X        return 0;
  837. X
  838. X    /*  Get server by name and make sure that the protocol
  839. X    *   matches as well.
  840. X    */
  841. X    Service = getservbyname(PortName, "tcp");
  842. X
  843. X    /*  Return either the port number, or 0 for no port number. */
  844. X    if (Service != NULL)
  845. X        return( Service->s_port );
  846. X    else if (sscanf(PortName, "%i", &PortNo) != 1)
  847. X        return 0;
  848. X    else
  849. X        return( htons( PortNo ) );
  850. X}
  851. X
  852. X/*-----------------------------------------------------------------------------
  853. X| Routine   :   GetHostAddr() --- Convert the host name to an address.
  854. X|
  855. X| Inputs    :   HostName    - Host name to convert.
  856. X|               Addr        - Host address.
  857. X|
  858. X| Returns   :   Returns 0 for error, 1 for address being returned.
  859. X-----------------------------------------------------------------------------*/
  860. X
  861. Xint GetHostAddr(char            *HostName,
  862. X                struct  in_addr *Addr)
  863. X{
  864. X    auto        int     len;
  865. X    struct      hostent *Host;
  866. X    auto        int     count;
  867. X    unsigned    int     a1, a2, a3, a4;
  868. X
  869. X    /*  Get a pointer to the host name data.    */
  870. X    Host = gethostbyname( HostName );
  871. X    if (Host != NULL)
  872. X        bcopy(Host->h_addr, Addr, Host->h_length);
  873. X    else
  874. X    {
  875. X        /*  Convert the string representation of the internet
  876. X        *   address into bytes.
  877. X        */
  878. X        count = sscanf(HostName,
  879. X                       "%i.%i.%i.%i%n",
  880. X                       &a1, &a2, &a3, &a4, &len);
  881. X        if (count != 4 || HostName[len] != 0)
  882. X            return( 0 );
  883. X
  884. X        /*  Insert the bytes of the internet address into the
  885. X        *   return address structure.  I suspect that this is highly
  886. X        *   machine specific code.
  887. X        */
  888. X        Addr->S_un.S_un_b.s_b1 = a1;
  889. X        Addr->S_un.S_un_b.s_b2 = a2;
  890. X        Addr->S_un.S_un_b.s_b3 = a3;
  891. X        Addr->S_un.S_un_b.s_b4 = a4;
  892. X    }
  893. X
  894. X    /*  Return no errors occurred.  */
  895. X    return( 1 );
  896. X}
  897. X
  898. X/*-----------------------------------------------------------------------------
  899. X| Routine   :   SetupSocket() --- Set up the socket.
  900. X|
  901. X| Inputs    :   HostName    - Name of host.
  902. X|               PortName    - Name of port.
  903. X-----------------------------------------------------------------------------*/
  904. X
  905. Xint SetupSocket(char    *HostName,
  906. X                char    *PortName)
  907. X{
  908. X    auto    int         SockDesc;   /*  Socket handle (descriptor).     */
  909. X    struct  sockaddr    SockAddr;   /*  Socket address structure.       */
  910. X    struct  sockaddr_in *InAddr;    /*  Internet address structure.     */
  911. X    struct  in_addr     *AdrPtr;
  912. X
  913. X    /*  Get the address of the server.  */
  914. X    InAddr=(struct sockaddr_in *) &SockAddr;
  915. X    InAddr->sin_family = AF_INET;
  916. X    if (! GetHostAddr(HostName, &InAddr->sin_addr))
  917. X    {
  918. X        fprintf(stderr,
  919. X                "%s %d : Error - Could not convert ",
  920. X                __FILE__,
  921. X                __LINE__);
  922. X        fprintf(stderr,
  923. X                "'%s' to a host address.\n",
  924. X                HostName);
  925. X        exit( 1 );
  926. X    }
  927. X    AdrPtr = (struct in_addr *) (&InAddr->sin_addr);
  928. X    fprintf(stderr,
  929. X            "Host '%s', address = %u.%u.%u.%u\n",
  930. X            HostName,
  931. X            AdrPtr->S_un.S_un_b.s_b1,
  932. X            AdrPtr->S_un.S_un_b.s_b2,
  933. X            AdrPtr->S_un.S_un_b.s_b3,
  934. X            AdrPtr->S_un.S_un_b.s_b4);
  935. X
  936. X    /*  Convert a service name to a port number.    */
  937. X    InAddr->sin_port = GetPortNo( PortName );
  938. X    if (InAddr->sin_port == 0)
  939. X    {
  940. X        fprintf(stderr,
  941. X                "%s %d : Error - bogus port number '%s'.\n",
  942. X                __FILE__,
  943. X                __LINE__,
  944. X                PortName);
  945. X        exit( 1 );
  946. X    }
  947. X    fprintf(stderr,
  948. X            "NNTP port number = %d\n",
  949. X            InAddr->sin_port);
  950. X
  951. X    /*  Attempt to get a socket descriptor. */
  952. X    SockDesc = socket(AF_INET, SOCK_STREAM, 0);
  953. X    if (SockDesc < 0)
  954. X    {
  955. X        perror("opening stream socket");
  956. X        exit( 1 );
  957. X    }
  958. X
  959. X    /*  Connect to the server.  */
  960. X    if (connect(SockDesc , &SockAddr, sizeof( SockAddr )) < 0)
  961. X    {
  962. X        /*  Close the old socket descriptor.    */
  963. X        perror("connecting");
  964. X        fprintf(stderr,
  965. X                "%s %d : Error - could not connect to news server.\n",
  966. X                __FILE__,
  967. X                __LINE__);
  968. X        exit( 1 );
  969. X    }
  970. X
  971. X    /*  Return the socket descriptor.   */
  972. X    return( SockDesc );
  973. X}
  974. X
  975. X/*-----------------------------------------------------------------------------
  976. X| Routine   :   RdConfig() --- Open and read the configuration file.
  977. X|
  978. X| Inputs    :   CfgFlNm     - Name of configuration file.
  979. X|               SockDesc    - Socket description.
  980. X-----------------------------------------------------------------------------*/
  981. X
  982. Xvoid    RdConfig(char   *CfgFlNm,
  983. X                 int    SockDesc)
  984. X{
  985. X    register    long    i;
  986. X    auto        FILE    *CfgFp;
  987. X    auto        FILE    *NewFp;
  988. X    auto        FILE    *OutFp;
  989. X    auto        int     ret;
  990. X
  991. X    auto        int     Status;
  992. X    auto        long    Number;
  993. X    auto        long    LastRd;
  994. X    auto        long    Start;
  995. X    auto        long    End;
  996. X
  997. X    static      char    TmpFlNm[MAX_BFR];
  998. X    static      char    OutFlNm[MAX_BFR];
  999. X    static      char    Bfr[MAX_BFR];
  1000. X    static      char    Cmd[MAX_BFR];
  1001. X    static      char    GroupName[MAX_BFR];
  1002. X
  1003. X    /*  Open configuration file.    */
  1004. X    if ((CfgFp = fopen(CfgFlNm, "r")) == NULL)
  1005. X    {
  1006. X        fprintf(stderr,
  1007. X                "%s %d : Error, could not open configuration file.\n",
  1008. X                __FILE__,
  1009. X                __LINE__);
  1010. X        return;
  1011. X    }
  1012. X
  1013. X    /*  Open new configuration file.    */
  1014. X    if ((NewFp = MkTmpFl( TmpFlNm )) == NULL)
  1015. X    {
  1016. X        fprintf(stderr,
  1017. X                "%s %d : Error, could not open new configuration file.\n",
  1018. X                __FILE__,
  1019. X                __LINE__);
  1020. X        return;
  1021. X    }
  1022. X
  1023. X    /*  Read the file a line at a time. */
  1024. X    while (! feof( CfgFp ))
  1025. X    {
  1026. X        /*  Get a line. */
  1027. X        if (fgets(Bfr, MAX_BFR, CfgFp) == NULL)
  1028. X            break;
  1029. X
  1030. X        /*  Parse configuration file line.  */
  1031. X        ret = sscanf(Bfr,
  1032. X                     "group %s %s %ld",
  1033. X                     GroupName,
  1034. X                     OutFlNm,
  1035. X                     &LastRd);
  1036. X        if (ret != 3)
  1037. X        {
  1038. X            fprintf(stderr,
  1039. X                    "%s %d : Error - bad configuration file line.\n",
  1040. X                    __FILE__,
  1041. X                    __LINE__);
  1042. X            fprintf(stderr,
  1043. X                    "\t'%s'\n",
  1044. X                    Bfr);
  1045. X            continue;
  1046. X        }
  1047. X
  1048. X        /*  Switch to appropriate group.    */
  1049. X        sprintf(Cmd, "GROUP %s\r\n", GroupName);
  1050. X        WrtSrvr(SockDesc, Cmd, strlen( Cmd ));
  1051. X        RdSrvr(SockDesc, Bfr, MAX_BFR);
  1052. X        fprintf(stderr, "%s", Bfr);
  1053. X
  1054. X        /*  Check return status and article number range.   */
  1055. X        ret = sscanf(Bfr,
  1056. X                     "%d %ld %ld %ld %s",
  1057. X                     &Status,
  1058. X                     &Number,
  1059. X                     &Start,
  1060. X                     &End,
  1061. X                     Cmd);
  1062. X
  1063. X        /*  Check for non-existant news group.  */
  1064. X        if (Status == 411)
  1065. X        {
  1066. X            fprintf(stderr,
  1067. X                    "%s %d : Error, no such news group '%s'.\n",
  1068. X                    __FILE__,
  1069. X                    __LINE__,
  1070. X                    GroupName);
  1071. X            continue;
  1072. X        }
  1073. X
  1074. X        /*  Check for no articles in news group.    */
  1075. X        if (Number == 0L || Start > End)
  1076. X        {
  1077. X            fprintf(stderr,
  1078. X                    "%s %d : No news in group '%s'.\n",
  1079. X                    __FILE__,
  1080. X                    __LINE__,
  1081. X                    GroupName);
  1082. X            continue;
  1083. X        }
  1084. X
  1085. X        /*  Open output file, get all articles. */
  1086. X        if ((OutFp = fopen(OutFlNm, "a")) == NULL)
  1087. X        {
  1088. X            fprintf(stderr,
  1089. X                    "%s %d : Error, could not open file '%s' for writing.\n",
  1090. X                    __FILE__,
  1091. X                    __LINE__,
  1092. X                    OutFlNm);
  1093. X            continue;
  1094. X        }
  1095. X
  1096. X        /*  Get all articles, write to file.    */
  1097. X        if (LastRd <= End)
  1098. X        {
  1099. X            /*  Get all articles.   */
  1100. X            for (i = (LastRd > Start) ? LastRd : Start;
  1101. X                 i <= End;
  1102. X                 i++)
  1103. X                RdArt(SockDesc, i, GroupName, OutFp);
  1104. X        }
  1105. X        fputc('\n', stderr);
  1106. X
  1107. X        /*  Close the output file pointer.  */
  1108. X        fclose( OutFp );
  1109. X
  1110. X        /*  Write the new value for the configuration file. */
  1111. X        fprintf(NewFp,
  1112. X                "group %s %s %ld\n",
  1113. X                GroupName,
  1114. X                OutFlNm,
  1115. X                End + 1L);
  1116. X    }
  1117. X
  1118. X    /*  Close the configuration files.  */
  1119. X    fclose( CfgFp );
  1120. X    fclose( NewFp );
  1121. X
  1122. X    /*  Delete the old configuration file, and rename the new to
  1123. X    *   be the same as the old.
  1124. X    */
  1125. X    remove( CfgFlNm );
  1126. X    rename(TmpFlNm, CfgFlNm);
  1127. X}
  1128. X
  1129. Xvoid    main(int    argc,
  1130. X             char   **argv)
  1131. X{
  1132. X    auto        int     SockDesc;
  1133. X    static      char    Bfr[MAX_BFR];
  1134. X
  1135. X    /*  Check the argument count.   */
  1136. X    if (argc < 3)
  1137. X    {
  1138. X        /*  Bad argument count, give synopsis.  */
  1139. X        fprintf(stderr,
  1140. X                "Usage : %s <server> <config>\n",
  1141. X                argv[0]);
  1142. X        exit( 1 );
  1143. X    }
  1144. X
  1145. X    /*  Attempt to set up the socket.   */
  1146. X    SockDesc = SetupSocket(argv[1], "nntp");
  1147. X
  1148. X    /*  Read the sign on message and print it.  */
  1149. X    RdSrvr(SockDesc, Bfr, MAX_BFR);
  1150. X    fprintf(stderr, "%s", Bfr);
  1151. X
  1152. X    /*  Read and execute the commands out of the configuration file.    */
  1153. X    RdConfig(argv[2], SockDesc);
  1154. X
  1155. X    /*  Quit server.    */
  1156. X    sprintf(Bfr, "QUIT\r\n");
  1157. X    WrtSrvr(SockDesc, Bfr, strlen( Bfr ));
  1158. X    RdSrvr(SockDesc, Bfr, MAX_BFR);
  1159. X    fprintf(stderr, "%s", Bfr);
  1160. X
  1161. X    /*  Close the socket descriptor and exit with no errors.    */
  1162. X    close( SockDesc );
  1163. X    exit( 0 );
  1164. X}
  1165. END_OF_FILE
  1166.   if test 18750 -ne `wc -c <'nntp/client.c'`; then
  1167.     echo shar: \"'nntp/client.c'\" unpacked with wrong size!
  1168.   fi
  1169.   # end of 'nntp/client.c'
  1170. fi
  1171. if test -f 'segment.c' -a "${1}" != "-c" ; then 
  1172.   echo shar: Will not clobber existing file \"'segment.c'\"
  1173. else
  1174.   echo shar: Extracting \"'segment.c'\" \(23846 characters\)
  1175.   sed "s/^X//" >'segment.c' <<'END_OF_FILE'
  1176. X/******************************************************************************
  1177. X* Module    :   Segment --- Find the segments of the posted file.
  1178. X*
  1179. X* Author    :   John W. M. Stevens
  1180. X******************************************************************************/
  1181. X
  1182. X#include    "compiler.h"
  1183. X
  1184. X#include    "unpost.h"
  1185. X#include    "list.h"
  1186. X#include    "modflnm.h"
  1187. X#include    "parse.h"
  1188. X#include    "decode.h"
  1189. X#include    "uudec.h"
  1190. X#include    "segment.h"
  1191. X#include    "utils.h"
  1192. X
  1193. X/*  Segment types.  */
  1194. Xtypedef enum    {
  1195. X    SEG_USED,           /*  Used in succesful decoding.                     */
  1196. X    SEG_TEXT,           /*  Pure text segment.                              */
  1197. X    SEG_INCOMP,         /*  Segment that is part of incomplete posting.     */
  1198. X    SEG_DESC            /*  Segment is a description.                       */
  1199. X} SEG_TYPE;
  1200. X
  1201. X/*  Segment list structure. */
  1202. Xtypedef struct  {
  1203. X    long    LnOfs;          /*  Byte offset to start of SEGMENT.        */
  1204. X    int     CopyFlag;       /*  Copy out flag.                          */
  1205. X} SEG_LIST;
  1206. X
  1207. X/*  Line and string buffers.    */
  1208. Xchar    SegLine[BFR_SIZE];
  1209. Xchar    IDLine[BFR_SIZE];
  1210. Xchar    UULine[BFR_SIZE];
  1211. Xchar    InBfr[BFR_SIZE];
  1212. XBYTE    OutBfr[BFR_SIZE];
  1213. X
  1214. X/*-----------------------------------------------------------------------------
  1215. X| Routine   :   UUDecode() --- Decode a UU encoded file.
  1216. X|
  1217. X| Inputs    :   FlName  - Name of input file.
  1218. X-----------------------------------------------------------------------------*/
  1219. X
  1220. Xvoid    UUDecode(char   *InFlNm)
  1221. X{
  1222. X    auto        FILE    *InFlPtr;
  1223. X    auto        FILE    *OutFlPtr;
  1224. X    auto        int     OutLen;
  1225. X    auto        char    **RetStrs;
  1226. X    auto        char    FlName[FL_NM_SZ];
  1227. X
  1228. X    /*  Externals used by this function.    */
  1229. X    extern      FILE            *ErrFile;
  1230. X
  1231. X    /*  Open file.  */
  1232. X    if ((InFlPtr = fopen(InFlNm, BIN_READ)) == NULL)
  1233. X    {
  1234. X        fprintf(ErrFile,
  1235. X                "%s %d : Error - could not open file '%s' for reading.\n",
  1236. X                __FILE__,
  1237. X                __LINE__,
  1238. X                InFlNm);
  1239. X        return;
  1240. X    }
  1241. X
  1242. X    /*  Get all uuencoded files from single file.   */
  1243. X    while (! feof( InFlPtr ))
  1244. X    {
  1245. X        /*  Search forwards through the file for the first
  1246. X        *   UU encoded line.
  1247. X        */
  1248. X        do
  1249. X        {
  1250. X            /*  Get a line from the file.   */
  1251. X            if (ReadLine(InFlPtr, InBfr, BFR_SIZE) == EOF)
  1252. X            {
  1253. X                fclose( InFlPtr );
  1254. X                return;
  1255. X            }
  1256. X        } while (! MatchBegin(InBfr, &RetStrs));
  1257. X
  1258. X        /*  Get the binary file name.   */
  1259. X        GetBinFlNm(InFlPtr, RetStrs, FlName);
  1260. X
  1261. X        /*  Check to make sure that file does not already exist.    */
  1262. X        if ( FileExists( FlName ) )
  1263. X        {
  1264. X            fprintf(ErrFile,
  1265. X                    "%s %d : Error - file '%s' already exists.\n",
  1266. X                    __FILE__,
  1267. X                    __LINE__,
  1268. X                    FlName);
  1269. X            fclose( InFlPtr );
  1270. X            return;
  1271. X        }
  1272. X
  1273. X        /*  Open the file.  */
  1274. X        if ((OutFlPtr = fopen(FlName, BIN_WRITE)) == NULL)
  1275. X        {
  1276. X            fprintf(ErrFile,
  1277. X                    "%s %d : Error - %s\n\t'%s'\n",
  1278. X                    __FILE__,
  1279. X                    __LINE__,
  1280. X                    sys_errlist[errno],
  1281. X                    FlName);
  1282. X            fclose( InFlPtr );
  1283. X            return;
  1284. X        }
  1285. X
  1286. X        /*  It exists, is open, and ready to roll.  Now decode to
  1287. X        *   end line.
  1288. X        */
  1289. X        while (ReadLine(InFlPtr, InBfr, BFR_SIZE) != EOF)
  1290. X        {
  1291. X            /*  Test for end line.  */
  1292. X            if ( MatchEnd( InBfr ) )
  1293. X                break;
  1294. X
  1295. X            /*  Space pad line, if necesary.    */
  1296. X            DecTruncUULn(InBfr, &OutLen, OutBfr);
  1297. X
  1298. X            /*  Are there any bytes to write?   */
  1299. X            if (OutLen < 1)
  1300. X                continue;
  1301. X
  1302. X            /*  Write the buffer to the output file.    */
  1303. X            if (fwrite(OutBfr, 1, OutLen, OutFlPtr) != OutLen)
  1304. X            {
  1305. X                fprintf(ErrFile,
  1306. X                        "\t%s %d : Error - Bad write to binary file.\n",
  1307. X                        __FILE__,
  1308. X                        __LINE__);
  1309. X                exit( 1 );
  1310. X            }
  1311. X        }
  1312. X
  1313. X        /*  Close output file.  */
  1314. X        fclose( OutFlPtr );
  1315. X    }
  1316. X
  1317. X    /*  Close input file.   */
  1318. X    fclose( InFlPtr );
  1319. X}
  1320. X
  1321. X/*-----------------------------------------------------------------------------
  1322. X| Routine   :   Single() --- Decode binarys, assumed to be in sorted order.
  1323. X|               already.
  1324. X|
  1325. X| Inputs    :   FileNm  - Name of file that contains single binary.
  1326. X-----------------------------------------------------------------------------*/
  1327. X
  1328. Xvoid    Single(char     *FileNm)
  1329. X{
  1330. X    auto        long            LnOfs;
  1331. X    auto        CHK_UU_ENC      UULnType;
  1332. X    auto        char            **RetStrs;
  1333. X    auto        int             OutLen;
  1334. X    auto        FILE            *InFlPtr;
  1335. X    auto        FILE            *OutFlPtr;
  1336. X    auto        char            FlName[FL_NM_SZ];
  1337. X
  1338. X    /*  Externals used by this function.    */
  1339. X    extern      FILE            *ErrFile;
  1340. X
  1341. X    /*  Open file.  */
  1342. X    if ((InFlPtr = fopen(FileNm, BIN_READ)) == NULL)
  1343. X    {
  1344. X        fprintf(ErrFile,
  1345. X                "%s %d : Error - could not open file '%s' for reading.\n",
  1346. X                __FILE__,
  1347. X                __LINE__,
  1348. X                FileNm);
  1349. X        return;
  1350. X    }
  1351. X
  1352. X
  1353. X    /*  Get all uuencoded files from single file.   */
  1354. X    while (! feof( InFlPtr ))
  1355. X    {
  1356. X        /*  Search forwards through the file for the first UU encoded line. */
  1357. X        do
  1358. X        {
  1359. X            /*  Get the current file offset.    */
  1360. X            LnOfs = ftell( InFlPtr );
  1361. X
  1362. X            /*  Get a line from the file.   */
  1363. X            if (ReadLine(InFlPtr, InBfr, BFR_SIZE) == EOF)
  1364. X             {
  1365. X                fclose( InFlPtr );
  1366. X                return;
  1367. X            }
  1368. X
  1369. X            /*  Check to see if this is a UUencoded line.   */
  1370. X            UULnType = ChkUULine(InBfr, &RetStrs, &OutLen);
  1371. X
  1372. X        } while (UULnType != UU_BEGIN);
  1373. X
  1374. X        /*  Get the binary file name.   */
  1375. XUnExpectedBegin:
  1376. X        GetBinFlNm(InFlPtr, RetStrs, FlName);
  1377. X
  1378. X        /*  Check to make sure that file does not already exist.    */
  1379. X        if ( FileExists( FlName ) )
  1380. X        {
  1381. X            fprintf(ErrFile,
  1382. X                    "%s %d : Error - file '%s' already exists.\n",
  1383. X                    __FILE__,
  1384. X                    __LINE__,
  1385. X                    FlName);
  1386. X            continue;
  1387. X        }
  1388. X
  1389. X        /*  Open the file.  */
  1390. X        if ((OutFlPtr = fopen(FlName, BIN_WRITE)) == NULL)
  1391. X        {
  1392. X            fprintf(ErrFile,
  1393. X                    "%s %d : Error - %s\n\t'%s'\n",
  1394. X                    __FILE__,
  1395. X                    __LINE__,
  1396. X                    sys_errlist[errno],
  1397. X                    FlName);
  1398. X            continue;
  1399. X        }
  1400. X
  1401. X        /*  Now munch and crunch until done with file.  */
  1402. X        do
  1403. X        {
  1404. X            /*  Decode a segment.   */
  1405. X            DecSeg(InFlPtr, OutFlPtr, &UULnType);
  1406. X
  1407. X            /*  Check for proper exit conditions.   */
  1408. X            if (UULnType == UU_BEGIN ||
  1409. X                UULnType == UU_END)
  1410. X                break;
  1411. X
  1412. X            /*  Scan to next UU encoded line.   */
  1413. X            do
  1414. X            {
  1415. X                /*  Get the current file offset.    */
  1416. X                LnOfs = ftell( InFlPtr );
  1417. X
  1418. X                /*  Get next line.  */
  1419. X                if (ReadLine(InFlPtr, InBfr, BFR_SIZE) == EOF)
  1420. X                {
  1421. X                    fprintf(ErrFile,
  1422. X                            "%s %d : Error - Unexpected end of file.\n",
  1423. X                            __FILE__,
  1424. X                            __LINE__);
  1425. X                    fclose( InFlPtr );
  1426. X                    fclose( OutFlPtr );
  1427. X                    return;
  1428. X                }
  1429. X
  1430. X                 /*  Check to see if this is a UUencoded line.   */
  1431. X                UULnType = ChkUULine(InBfr, &RetStrs, &OutLen);
  1432. X
  1433. X            } while (UULnType == NOT_UU_LINE || UULnType == UU_SPACE);
  1434. X
  1435. X            /*  Reset file pointer to begining of UU line.  */
  1436. X            if (fseek(InFlPtr, LnOfs, SEEK_SET) != 0)
  1437. X            {
  1438. X                fprintf(ErrFile,
  1439. X                        "%s %d : Error - %s\n",
  1440. X                        __FILE__,
  1441. X                        __LINE__,
  1442. X                        sys_errlist[errno]);
  1443. X                exit( 1 );
  1444. X            }
  1445. X
  1446. X        } while (UULnType == IS_UU_LINE);
  1447. X
  1448. X        /*  Close the output file pointer.  */
  1449. X        fclose( OutFlPtr );
  1450. X
  1451. X        /*  Check the various types.    */
  1452. X        if (UULnType == UU_BEGIN)
  1453. X        {
  1454. X            fprintf(ErrFile,
  1455. X                    "%s %d : Error - Unexpected UU begin line.\n",
  1456. X                    __FILE__,
  1457. X                    __LINE__);
  1458. X            goto UnExpectedBegin;
  1459. X        }
  1460. X    }
  1461. X
  1462. X    /*  Close the files.    */
  1463. X    fclose( InFlPtr );
  1464. X}
  1465. X
  1466. X/*-----------------------------------------------------------------------------
  1467. X| Routine   :   CmpFl() --- Compare two file list entries.
  1468. X|
  1469. X| Inputs    :   File1   - File entry one.
  1470. X|               File2   - File entry two.
  1471. X-----------------------------------------------------------------------------*/
  1472. X
  1473. Xstatic
  1474. Xint     CmpFl(void  *File1,
  1475. X              void  *File2)
  1476. X{
  1477. X    return( strcmp(((FL_LIST *) File1)->IDString,
  1478. X                   ((FL_LIST *) File2)->IDString) );
  1479. X}
  1480. X
  1481. X/*-----------------------------------------------------------------------------
  1482. X| Routine   :   DumpSeg() --- Dump a segment to a file.
  1483. X|
  1484. X| Inputs    :   InFlPtr     - File to read segment from (source file).
  1485. X|               OutFlPtr    - File to write segment to.
  1486. X|               NextSeg     - Start of next segment.
  1487. X-----------------------------------------------------------------------------*/
  1488. X
  1489. Xstatic
  1490. Xvoid    DumpSeg(FILE    *InFlPtr,
  1491. X                FILE    *OutFlPtr,
  1492. X                long    NextSeg)
  1493. X{
  1494. X    /*  Dump segment to output file.    */
  1495. X    while (ReadLine(InFlPtr, SegLine, BFR_SIZE) != EOF)
  1496. X    {
  1497. X        /*  Print line. */
  1498. X        fprintf(OutFlPtr, "%s\n", SegLine);
  1499. X
  1500. X        /*  Get next line offset.   */
  1501. X        if (ftell( InFlPtr ) == NextSeg)
  1502. X            break;
  1503. X    }
  1504. X}
  1505. X
  1506. X/*-----------------------------------------------------------------------------
  1507. X| Routine   :   Multiple() --- Extract multiple postings from one file.
  1508. X|
  1509. X| Inputs    :   FileNm  - Name of file to unpost.
  1510. X-----------------------------------------------------------------------------*/
  1511. X
  1512. Xvoid    Multiple(char       *FileNm)
  1513. X{
  1514. X    register    int             i;
  1515. X    register    int             j;
  1516. X    auto        FILE            *InFlPtr;
  1517. X    auto        FILE            *OutFlPtr;
  1518. X    auto        long            LnOfs;
  1519. X    auto        int             InsPt;
  1520. X    auto        SEG_INFO        SegInfo;
  1521. X    auto        FL_LIST         *FlPtr;
  1522. X    auto        FL_LIST         NewFile;
  1523. X    auto        SEG_LIST        *SegPtr;
  1524. X    auto        SEG_LIST        NewSeg;
  1525. X
  1526. X    /*  Buffers for input and output.   */
  1527. X    static      LIST            *FileList;
  1528. X    static      LIST            *SegList;
  1529. X    extern      int             MsDosFileNms;
  1530. X    extern      int             DumpDesc;
  1531. X    extern      int             SepIncomps;
  1532. X    extern      FILE            *ErrFile;
  1533. X    extern      FILE            *TextFile;
  1534. X    extern      FILE            *IncompFile;
  1535. X
  1536. X    /*  Open file.  */
  1537. X    if ((InFlPtr = fopen(FileNm, BIN_READ)) == NULL)
  1538. X    {
  1539. X        fprintf(ErrFile,
  1540. X                "%s %d : Error - could not open file '%s' for reading.\n",
  1541. X                __FILE__,
  1542. X                __LINE__,
  1543. X                FileNm);
  1544. X        return;
  1545. X    }
  1546. X
  1547. X    /*  Allocate a file and a segment list.    */
  1548. X    FileList = CrtList( sizeof( FL_LIST ) );
  1549. X    SegList = CrtList( sizeof( SEG_LIST ) );
  1550. X
  1551. X    /*  Search for all ID lines, building a list of all
  1552. X    *   files and their segments as we go.
  1553. X    */
  1554. X    while (! feof( InFlPtr ))
  1555. X    {
  1556. X        /*  Parse article information out of the file.  */
  1557. X        memset(&SegInfo, 0, sizeof( SEG_INFO ));
  1558. X        LnOfs = Parse(InFlPtr,
  1559. X                      SegLine,
  1560. X                      IDLine,
  1561. X                      &SegInfo);
  1562. X
  1563. X#if defined(UNPOST_DEBUG)
  1564. Xprintf("\n\tSegInfo:\n");
  1565. Xprintf("\t--------\n");
  1566. Xprintf("\tNumber of Segments: %d\n", SegInfo.NoSegs);
  1567. Xprintf("\tSegment Number    : %d\n", SegInfo.SegNo);
  1568. Xprintf("\tSegment Offset    : %ld\n", SegInfo.SegOfs);
  1569. Xprintf("\tUUencode Offset   : %ld\n", SegInfo.UUOfs);
  1570. Xprintf("\tBinary ID String  : '%s'\n",
  1571. X       (SegInfo.IDString == NULL) ? "NULL POINTER"
  1572. X                                  : SegInfo.IDString);
  1573. Xprintf("\tBinary File Name  : '%s'\n\n",
  1574. X       (SegInfo.FlName == NULL) ? "NULL POINTER"
  1575. X                                : SegInfo.FlName);
  1576. X
  1577. Xswitch ( LnOfs )
  1578. X{
  1579. Xcase -1L:
  1580. X    printf("\tPRS_NO_SEGMENT\n");
  1581. X    break;
  1582. Xcase -2L:
  1583. X    printf("\tPRS_NO_ID_STR\n");
  1584. X    break;
  1585. Xcase -3L:
  1586. X    printf("\tPRS_NO_UU_LN\n");
  1587. X    break;
  1588. Xcase -4L:
  1589. X    printf("\tPRS_NO_BEGIN\n");
  1590. X    break;
  1591. Xcase -5L:
  1592. X    printf("\tPRS_NO_SEG_NUM\n");
  1593. X    break;
  1594. Xcase -6L:
  1595. X    printf("\tPRS_NO_NUM_SEGS\n");
  1596. X    break;
  1597. Xcase -7L:
  1598. X    printf("\tPRS_UNX_END_SEG\n");
  1599. X    break;
  1600. X}
  1601. X#endif
  1602. X
  1603. X        /*  Save the segment data.  */
  1604. X        NewSeg.LnOfs = SegInfo.SegOfs;
  1605. X
  1606. X        /*  Check for errors.   */
  1607. X        if (LnOfs == PRS_NO_SEGMENT)
  1608. X            break;
  1609. X        else if (LnOfs == PRS_NO_UU_LN)
  1610. X        {
  1611. X            /*  Check to see if this is a description segment.  */
  1612. X            if (SegInfo.IDString &&
  1613. X                *SegInfo.IDString  &&
  1614. X                SegInfo.SegNo == 0 &&
  1615. X                SegInfo.NoSegs > 0)
  1616. X            {
  1617. X                /*  This has part numbering info, and the part number
  1618. X                *   is zero, but it has no uuencoded data, so this
  1619. X                *   must be a description segement.
  1620. X                */
  1621. X                NewSeg.CopyFlag = SEG_DESC;
  1622. X            }
  1623. X            else
  1624. X            {
  1625. X                /*  Save as text segment.   */
  1626. X                NewSeg.CopyFlag = SEG_TEXT;
  1627. X                SegList = AppList(SegList, &NewSeg);
  1628. X
  1629. X                /*  If the file name or ID string exist, deallocate.    */
  1630. X                if ( SegInfo.IDString )
  1631. X                    free( SegInfo.IDString );
  1632. X                continue;
  1633. X            }
  1634. X        }
  1635. X        else if (LnOfs == PRS_NO_SEG_NUM  ||
  1636. X                 LnOfs == PRS_NO_NUM_SEGS ||
  1637. X                 SegInfo.IDString == NULL ||
  1638. X                 *SegInfo.IDString == '\0')
  1639. X        {
  1640. X            /*  Something important is missing.  Do NOT attempt to
  1641. X            *   put one of these in the file list.
  1642. X            */
  1643. X            NewSeg.CopyFlag = SEG_INCOMP;
  1644. X            SegList = AppList(SegList, &NewSeg);
  1645. X
  1646. X            /*  If the file name or ID string exist, deallocate.    */
  1647. X            if ( SegInfo.IDString )
  1648. X                free( SegInfo.IDString );
  1649. X            continue;
  1650. X        }
  1651. X        else
  1652. X            NewSeg.CopyFlag = SEG_INCOMP;
  1653. X
  1654. X        /*  Add segment to list.  */
  1655. X        SegList = AppList(SegList, &NewSeg);
  1656. X
  1657. X        /*  Search file list for ID string. */
  1658. X        NewFile.IDString = SegInfo.IDString;
  1659. X        if (SrchList(FileList, &NewFile, CmpFl, &InsPt) == FALSE)
  1660. X        {
  1661. X            /*  Did not find file in list, add a new file.  First,
  1662. X            *   allocate segments buffer.
  1663. X            */
  1664. X            if ((NewFile.Segs = (SEGS *)
  1665. X                 calloc(SegInfo.NoSegs + 1, sizeof( SEGS ))) == NULL)
  1666. X            {
  1667. X                fprintf(ErrFile,
  1668. X                        "%s %d : Error - out of memory.\n",
  1669. X                        __FILE__,
  1670. X                        __LINE__);
  1671. X                exit( 1 );
  1672. X            }
  1673. X
  1674. X            /*  We have a valid ID line, and at least one UUencoded
  1675. X            *   line, so add this segment to the list.
  1676. X            */
  1677. X            NewFile.NoSegs = SegInfo.NoSegs;
  1678. X            NewFile.FlName = NULL;
  1679. X            NewFile.Success = 0;
  1680. X            FileList = AddList(FileList, &NewFile, InsPt);
  1681. X        }
  1682. X        else
  1683. X            free( SegInfo.IDString );
  1684. X        FlPtr = ListIdx(FileList, InsPt);
  1685. X
  1686. X        /*  Check for irreconcilable differences.   */
  1687. X        if (FlPtr->NoSegs < SegInfo.SegNo)
  1688. X        {
  1689. X            fprintf(ErrFile,
  1690. X                    "%s %d : Error - Segment number #%d greater than number",
  1691. X                    __FILE__,
  1692. X                    __LINE__,
  1693. X                    SegInfo.SegNo);
  1694. X            fprintf(ErrFile,
  1695. X                    " of segments in:\n\tSegment: '%s'\n",
  1696. X                    SegLine);
  1697. X        }
  1698. X        else
  1699. X        {
  1700. X            /*  Save the offset in the proper segment location. */
  1701. X            if (FlPtr->Segs[SegInfo.SegNo].SegNo != 0)
  1702. X            {
  1703. X                fprintf(ErrFile,
  1704. X                        "%s %d : Warning - duplicate segment #%d in:\n",
  1705. X                        __FILE__,
  1706. X                        __LINE__,
  1707. X                        SegInfo.SegNo);
  1708. X                fprintf(ErrFile,
  1709. X                        "\tBinary ID: '%s'\n",
  1710. X                        FlPtr->IDString);
  1711. X            }
  1712. X
  1713. X            /*  Set up file descriptor segment. */
  1714. X            FlPtr->Segs[SegInfo.SegNo].Exists = 1;
  1715. X            FlPtr->Segs[SegInfo.SegNo].SegNo = SegInfo.SegNo;
  1716. X            FlPtr->Segs[SegInfo.SegNo].SegOfs = SegInfo.SegOfs;
  1717. X            FlPtr->Segs[SegInfo.SegNo].UUOfs  = SegInfo.UUOfs;
  1718. X            FlPtr->Segs[SegInfo.SegNo].SegLstOrd = SegList->NoElems - 1;
  1719. X        }
  1720. X
  1721. X        /*  Add the file name string, if it isn't already present.  */
  1722. X        if ( FlPtr->FlName )
  1723. X            free( SegInfo.FlName );
  1724. X        else if ( SegInfo.FlName )
  1725. X            FlPtr->FlName = SegInfo.FlName;
  1726. X    }
  1727. X
  1728. X    /*  Dump Table. */
  1729. X    fprintf(ErrFile, "File ID                         Segments\n");
  1730. X    fprintf(ErrFile, "----------------------------------------\n");
  1731. X    for (i = 0; i < FileList->NoElems; i++)
  1732. X    {
  1733. X        FlPtr = ListIdx(FileList, i);
  1734. X        fprintf(ErrFile,
  1735. X                "%-30.30s  %d\n",
  1736. X                FlPtr->IDString,
  1737. X                FlPtr->NoSegs);
  1738. X        for (j = 1; j <= FlPtr->NoSegs; j++)
  1739. X            fprintf(ErrFile, "\t%d  %ld\n",
  1740. X                    FlPtr->Segs[j].SegNo,
  1741. X                    FlPtr->Segs[j].SegOfs);
  1742. X    }
  1743. X    fprintf(ErrFile, "\n");
  1744. X
  1745. X    /*  Decode the files.   */
  1746. X    for (i = 0; i < FileList->NoElems; i++)
  1747. X    {
  1748. X        /*  Get pointer to file list entry. */
  1749. X        FlPtr = ListIdx(FileList, i);
  1750. X
  1751. X        /*  Report binary id you are attempting to decode.  */
  1752. X        fprintf(ErrFile,
  1753. X                "Decoding Binary ID: '%s'\n",
  1754. X                FlPtr->IDString);
  1755. X
  1756. X        /*  Attempt to decode the file. */
  1757. X        if (DeCode(InFlPtr, FlPtr) == OK)
  1758. X        {
  1759. X            /*  Scan segment list, marking all segments as having been
  1760. X            *   successfully used.
  1761. X            */
  1762. X            FlPtr->Success = 1;
  1763. X            for (j = 1; j <= FlPtr->NoSegs; j++)
  1764. X            {
  1765. X                SegPtr = ListIdx(SegList, FlPtr->Segs[j].SegLstOrd);
  1766. X                SegPtr->CopyFlag = SEG_USED;
  1767. X            }
  1768. X        }
  1769. X    }
  1770. X
  1771. X    /*  Do we want to save incomplete pieces?   */
  1772. X    if (IncompFile || SepIncomps)
  1773. X    {
  1774. X        /*  Write incomplete binaries to uuencoded file in sorted
  1775. X        *   order.
  1776. X        */
  1777. X        for (i = 0; i < FileList->NoElems; i++)
  1778. X        {
  1779. X            auto    long    EndOfs;
  1780. X
  1781. X            /*  Get pointer to file.    */
  1782. X            FlPtr = ListIdx(FileList, i);
  1783. X            if ( FlPtr->Success )
  1784. X                continue;
  1785. X
  1786. X            /*  Open file to write segments to, or use incompletes
  1787. X            *   file.
  1788. X            */
  1789. X            if (SepIncomps && FlPtr->IDString && *FlPtr->IDString)
  1790. X            {
  1791. X                /*  Use the binary ID string to create a .uue file name.
  1792. X                */
  1793. X                if ( MsDosFileNms )
  1794. X                    ModifyFlNm(FlPtr->IDString, ".uue", InBfr);
  1795. X                else
  1796. X                    ModExten(FlPtr->IDString, ".uue", InBfr);
  1797. X
  1798. X                /*  Open incompletes file.  */
  1799. X                if ((OutFlPtr = fopen(InBfr, TXT_APPEND)) == NULL)
  1800. X                {
  1801. X                    fprintf(ErrFile,
  1802. X                            "%s %d : Error - File '%s' cannot be opened ",
  1803. X                            __FILE__,
  1804. X                            __LINE__,
  1805. X                            InBfr);
  1806. X                    fprintf(ErrFile,
  1807. X                            "for appending.\n");
  1808. X                    continue;
  1809. X                }
  1810. X            }
  1811. X            else
  1812. X                OutFlPtr = IncompFile;
  1813. X
  1814. X            /*  This file was NOT successfully converted, write it's
  1815. X            *   segments out to the incomplete file.
  1816. X            */
  1817. X            for (j = 0; j <= FlPtr->NoSegs; j++)
  1818. X            {
  1819. X                /*  If this segment does not exist, do not copy it. */
  1820. X                if (! FlPtr->Segs[j].Exists)
  1821. X                    continue;
  1822. X                else if (j == 0 && ! DumpDesc)
  1823. X                    continue;
  1824. X
  1825. X                /*  Position file pointer to first line of segment. */
  1826. X                if (fseek(InFlPtr, FlPtr->Segs[j].SegOfs, SEEK_SET) != 0)
  1827. X                {
  1828. X                    fprintf(ErrFile,
  1829. X                            "%s %d : Error - %s\n",
  1830. X                            __FILE__,
  1831. X                            __LINE__,
  1832. X                            sys_errlist[errno]);
  1833. X                    exit( 1 );
  1834. X                }
  1835. X
  1836. X                /*  Mark this segment as having been dumped out.    */
  1837. X                SegPtr = ListIdx(SegList, FlPtr->Segs[j].SegLstOrd);
  1838. X                SegPtr->CopyFlag = SEG_USED;
  1839. X
  1840. X                /*  Get offset for end of segment.  */
  1841. X                if (FlPtr->Segs[j].SegLstOrd + 1 < SegList->NoElems)
  1842. X                    EndOfs = SegPtr[1].LnOfs;
  1843. X                else
  1844. X                    EndOfs = -1L;
  1845. X
  1846. X                /*  Write all of segment to file.   */
  1847. X                DumpSeg(InFlPtr, OutFlPtr, EndOfs);
  1848. X            }
  1849. X
  1850. X            /*  Check to see if we need to close the file.  */
  1851. X            if (OutFlPtr != IncompFile)
  1852. X                fclose( OutFlPtr );
  1853. X        }
  1854. X    }
  1855. X
  1856. X    /*  Check to make sure that the user has requested that unused
  1857. X    *   segments be dumped out to ANY file.
  1858. X    */
  1859. X    if (TextFile || IncompFile)
  1860. X    {
  1861. X        /*  Dump unused segments to file.   */
  1862. X        for (i = 0, SegPtr = ListIdx(SegList, 0);
  1863. X             i < SegList->NoElems;
  1864. X             i++, SegPtr++)
  1865. X        {
  1866. X            /*  If this segment was successfully converted, do not
  1867. X            *   copy it.
  1868. X            */
  1869. X            if (SegPtr->CopyFlag == SEG_USED)
  1870. X                continue;
  1871. X
  1872. X            /*  Position file pointer to first UUencoded
  1873. X            *   line of segment.
  1874. X            */
  1875. X            if (fseek(InFlPtr, SegPtr->LnOfs, SEEK_SET) != 0)
  1876. X            {
  1877. X                fprintf(ErrFile,
  1878. X                        "%s %d : Error - %s\n",
  1879. X                        __FILE__,
  1880. X                        __LINE__,
  1881. X                        sys_errlist[errno]);
  1882. X                exit( 1 );
  1883. X            }
  1884. X
  1885. X            /*  Read and write lines.   */
  1886. X            if (SegPtr->CopyFlag == SEG_TEXT && TextFile)
  1887. X            {
  1888. X                /*  Dump the segment out to the text file.  */
  1889. X                DumpSeg(InFlPtr,
  1890. X                        TextFile,
  1891. X                        (i < SegList->NoElems - 1)
  1892. X                            ? SegPtr[1].LnOfs
  1893. X                            : -1L);
  1894. X            }
  1895. X            else if (SegPtr->CopyFlag == SEG_INCOMP && IncompFile)
  1896. X            {
  1897. X                /*  Dump the segment out to the text file.  */
  1898. X                DumpSeg(InFlPtr,
  1899. X                        IncompFile,
  1900. X                        (i < SegList->NoElems - 1)
  1901. X                            ? SegPtr[1].LnOfs
  1902. X                            : -1L);
  1903. X            }
  1904. X        }
  1905. X    }
  1906. X
  1907. X    /*  Deallocate file descriptor list.    */
  1908. X    for (i = 0; i < FileList->NoElems; i++)
  1909. X    {
  1910. X        /*  Get pointer to file list entry. */
  1911. X        FlPtr = ListIdx(FileList, i);
  1912. X
  1913. X        /*  Deallocate the heap memory. */
  1914. X        free( FlPtr->Segs );
  1915. X        free( FlPtr->FlName );
  1916. X        free( FlPtr->IDString );
  1917. X    }
  1918. X
  1919. X    /*  Free the list.  */
  1920. X    free( FileList );
  1921. X    free( SegList );
  1922. X}
  1923. END_OF_FILE
  1924.   if test 23846 -ne `wc -c <'segment.c'`; then
  1925.     echo shar: \"'segment.c'\" unpacked with wrong size!
  1926.   fi
  1927.   # end of 'segment.c'
  1928. fi
  1929. echo shar: End of archive 4 \(of 7\).
  1930. cp /dev/null ark4isdone
  1931. MISSING=""
  1932. for I in 1 2 3 4 5 6 7 ; do
  1933.     if test ! -f ark${I}isdone ; then
  1934.     MISSING="${MISSING} ${I}"
  1935.     fi
  1936. done
  1937. if test "${MISSING}" = "" ; then
  1938.     echo You have unpacked all 7 archives.
  1939.     rm -f ark[1-9]isdone
  1940. else
  1941.     echo You still must unpack the following archives:
  1942.     echo "        " ${MISSING}
  1943. fi
  1944. exit 0
  1945. exit 0 # Just in case...
  1946.