home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2640 < prev    next >
Encoding:
Internet Message Format  |  1991-01-31  |  33.5 KB

  1. From: mj@dfv.rwth-aachen.de (Martin Junius)
  2. Newsgroups: alt.sources
  3. Subject: FIDOGATE Part 5/6
  4. Message-ID: <mj.665055349@suntex>
  5. Date: 28 Jan 91 09:35:49 GMT
  6.  
  7. ---- Cut Here and feed the following to sh ----
  8. #!/bin/sh
  9. # This is part 05 of a multipart archive
  10. # ============= funpack.c ==============
  11. if test -f 'funpack.c' -a X"$1" != X"-c"; then
  12.     echo 'x - skipping funpack.c (File already exists)'
  13. else
  14. echo 'x - extracting funpack.c (Text)'
  15. sed 's/^X//' << 'SHAR_EOF' > 'funpack.c' &&
  16. /*:ts=4*/
  17. /*****************************************************************************
  18. X * FIDOGATE --- Gateway software UNIX <-> FIDO
  19. X *
  20. X * $Id: funpack.c,v 2.12 91/01/26 13:27:37 mj Exp $
  21. X *
  22. X * Unpack fido mail packets
  23. X *
  24. X * $Log:    funpack.c,v $
  25. X * Revision 2.12  91/01/26  13:27:37  mj
  26. X * Changed generation of `Path' header to include FIDO address of gateway.
  27. X * 
  28. X * Revision 2.11  90/12/09  17:34:26  mj
  29. X * Recognize `To:' header at start of message.
  30. X * 
  31. X * Revision 2.10  90/12/02  21:22:02  mj
  32. X * Changed program header to mention both authors of the original
  33. X * software posted to alt.sources.
  34. X * 
  35. X * Revision 2.9  90/11/23  20:41:10  mj
  36. X * Changed locally generated message ids to <funpackNNN@fN.nN.zN.fidonet.org>,
  37. X * corrected line breaking in ffgets().
  38. X * 
  39. X * Revision 2.8  90/11/20  21:08:44  mj
  40. X * Added support for ^AINTL kludge.
  41. X * 
  42. X * Revision 2.7  90/11/05  20:50:14  mj
  43. X * Changed my signature in all program headers.
  44. X * 
  45. X * Revision 2.6  90/11/04  14:14:48  mj
  46. X * A small change in line wrapping: no more line wrapping at punctuation
  47. X * characters.
  48. X * 
  49. X * Revision 2.5  90/11/01  14:33:56  mj
  50. X * Convert FIDO ^AMSGID and ^AREPLY kludges to RFC822 Message-ID and
  51. X * References headers.
  52. X * 
  53. X * Revision 2.4  90/10/29  21:19:37  mj
  54. X * Ignore case when checking for name alias.
  55. X * 
  56. X * Revision 2.3  90/09/16  17:35:49  mj
  57. X * Also look for "UUCPFROM:" in first lines of message body.
  58. X * 
  59. X * Revision 2.2  90/09/09  10:54:37  mj
  60. X * Fixed a bug in handling of `ReplyTo:' in FIDO message body. Spaces
  61. X * in such an address are now striped off.
  62. X * 
  63. X * Revision 2.1  90/09/08  18:46:32  mj
  64. X * Changed some code for getting real names out of FIDO from and to header
  65. X * fields. (Ignore things after "%" or "Of")
  66. X * Now we look for RFC822 like header lines at the beginning of the
  67. X * message body and use them for the `From:' and `To:' field.
  68. X * 
  69. X * Revision 2.0  90/09/03  17:54:23  mj
  70. X * Rewrote much of the code inside this module.
  71. X * There are now hooks, where support for most of
  72. X * the FIDO ^A kludges (e.g. ^AMSGID) can be installed.
  73. X * Function stripbad() from nodelist.c moved to
  74. X * funpack.c
  75. X * 
  76. X * Revision 1.7  90/08/12  11:56:54  mj
  77. X * Some changes. (what?)
  78. X * 
  79. X * Revision 1.6  90/07/23  12:58:26  mj
  80. X * The FIDO `^AFMPT x' kludge is now recognized by funpack and
  81. X * inserted as the point address in the `From: ...' line.
  82. X * 
  83. X * Revision 1.5  90/07/15  10:26:11  mj
  84. X * Messages for mail: M.xxxx.TO is not used any more. frecv now
  85. X * looks for `To: ...' line is mail file M.xxxx.
  86. X * Messages for news: Address from origin line is only substituted
  87. X * in header `From: ...' line, all others are left unchanged.
  88. X * 
  89. X * Revision 1.4  90/07/01  15:20:18  mj
  90. X * Fixed some bugs in funpack caused by the removal of alloca().
  91. X * No more core dumps, but heaven knows, why it works now. Strange.
  92. X * 
  93. X * Revision 1.3  90/07/01  13:45:50  mj
  94. X * Removed all calls to alloca(). All unsave malloc()'s without
  95. X * checking the returned pointer are now done via xmalloc().
  96. X * Fixed a malloc() error in rmail.
  97. X * 
  98. X * Revision 1.2  90/06/28  22:04:19  mj
  99. X * Much rework of the sources, no more hsu.h and other clean up.
  100. X * rmail improved, now handles special XENIX quirks.
  101. X * 
  102. X * Revision 1.1  90/06/21  21:09:19  mj
  103. X * Everything seems to work, so this delta was made.
  104. X * 
  105. X * Revision 1.0  90/06/19  18:32:29  mj
  106. X * Initial revision
  107. X * 
  108. X *
  109. X *****************************************************************************
  110. X * This version hacked and maintained by:
  111. X *    _____ _____
  112. X *   |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
  113. X *   | | | |   | |   Republikplatz 3   DOMAIN:  mju@dfv.rwth-aachen.de
  114. X *   |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
  115. X *
  116. X * Original version of these programs and files:
  117. X *
  118. X *   Teemu Torma
  119. X *   Heikki Suonsivu   FIDO: 2:504/1   UUCP: ...!mcsun!santra!hsu
  120. X *
  121. X *****************************************************************************/
  122. X
  123. /*
  124. X * Fido mail packets in SPOOL/in are processed and splitted into
  125. X * single messages for either news
  126. X *     N.xxxx
  127. X * or mail
  128. X *     M.xxxx
  129. X * in directory SPOOL/unpacked.
  130. X *
  131. X */
  132. X
  133. #include "fidogate.h"
  134. X
  135. X
  136. X
  137. #define PROGRAMNAME "funpack $Revision: 2.12 $"
  138. X
  139. X
  140. X
  141. #define SEPARATORS " ,;\015\012\011"
  142. #define WHITESPACE " \015\012\011"
  143. X
  144. X
  145. X
  146. extern time_t time();
  147. extern char *tzname[];
  148. extern int getopt();
  149. extern int optind;
  150. extern char *optarg;
  151. extern void exit(), perror();
  152. extern time_t dateconv();
  153. extern void swab();
  154. X
  155. X
  156. int verbose = INIT_VERBOSE;
  157. int acceptprivate = FALSE;
  158. int trashprivate = FALSE;
  159. X
  160. /* Our net/node information */
  161. Node this;
  162. X
  163. X
  164. /*
  165. X * For recognizing `^AINTL', `^AFMPT x', `^AMSGID ...' and `^AREPLY ...'
  166. X */
  167. #define SAVEBUFSIZ 256
  168. X
  169. static int  msgbody_fmpt = 0;
  170. static char msgbody_msgid[SAVEBUFSIZ];
  171. static char msgbody_reply[SAVEBUFSIZ];
  172. static char msgbody_intl[SAVEBUFSIZ];
  173. X
  174. X
  175. /*
  176. X * For grabbing addresses from RFC822 header lines at start of message
  177. X */
  178. X
  179. static char *msgbody_rfc_from;
  180. static char *msgbody_rfc_to;
  181. X
  182. X
  183. X
  184. /*
  185. X * check_origin() --- Analyse ` * Origin: ...' line in FIDO message
  186. X *                    body and parse address in ()s into Node structure
  187. X *
  188. X * Origin line is checked for the rightmost occurence of
  189. X * ([text] z:n/n.p). If origin line get splitted across
  190. X * two lines you're out of luck.
  191. X */
  192. X
  193. check_origin(buffer, node, text)
  194. char *buffer;
  195. Node *node;
  196. char *text;
  197. {
  198. char *left, *right;
  199. char *buf;
  200. X
  201. X    if(!strncmp(" * Origin:", buffer, 10)) {
  202. X        debug(3, "Checking origin line for FIDO address");
  203. X        buf   = strsave(buffer);
  204. X        right = strrchr(buf, ')');
  205. X        if(!right) {
  206. X            free(buf);
  207. X            return(FALSE);
  208. X        }
  209. X        left  = strrchr(buf, '(');
  210. X        if(!left) {
  211. X            free(buf);
  212. X            return(FALSE);
  213. X        }
  214. X        *right = 0;
  215. X        *left++ = 0;
  216. X        /*
  217. X         * Copy info text for Organization: header
  218. X         */
  219. X        strcpy(text, buf + strlen(" * Origin: "));
  220. X        /*
  221. X         * Parse node info
  222. X         */
  223. X        if(parsefnetaddress(left, node)) {
  224. X            /* Not a valid FIDO address */
  225. X            debug(3, "Could not parse %s", left);
  226. X            node->zone = node->net = node->node = node->point = -1;
  227. X            free(buf);
  228. X            return(FALSE);
  229. X        }
  230. X        else {
  231. X            /* Valid FIDO address */
  232. X            debug(3, "Parsed %s to %s", left, ascnode(*node));
  233. X        }
  234. X        free(buf);
  235. X        return(TRUE);
  236. X    }
  237. X    return(FALSE);
  238. }
  239. X
  240. X
  241. X
  242. /*
  243. X * check_ctrl_a() --- Check for various ^A kludges
  244. X */
  245. X
  246. check_ctrl_a(buffer)
  247. char *buffer;
  248. {
  249. register char *p;
  250. X
  251. X    /*
  252. X     * Look for `^AINTL ...'
  253. X     */
  254. X    if(!strncmp(buffer, "^AINTL", 6)) {
  255. X        buffer += 6;
  256. X        while(*buffer==':' || *buffer==' ')
  257. X            buffer++;
  258. X        strcpy(msgbody_intl, buffer);
  259. X    }
  260. X
  261. X    /*
  262. X     * Look for `^AFMPT x'
  263. X     */
  264. X    if(!strncmp(buffer, "^AFMPT", 6)) {
  265. X        for(p=buffer+6; *p && !isdigit(*p); p++);
  266. X        if(*p)
  267. X            msgbody_fmpt = atoi(p);
  268. X    }
  269. X    
  270. X    /*
  271. X     * Look for `^AMSGID ...'
  272. X     */
  273. X    if(!strncmp(buffer, "^AMSGID: ", 9))
  274. X        strcpy(msgbody_msgid, buffer+9);
  275. X    
  276. X    /*
  277. X     * Look for `^AREPLY ...'
  278. X     */
  279. X    if(!strncmp(buffer, "^AREPLY: ", 9))
  280. X        strcpy(msgbody_reply, buffer+9);
  281. X
  282. }
  283. X
  284. X
  285. X
  286. /*
  287. X * check_rfc_header() --- Check for RFC822 like header lines at
  288. X *                        the beginning of the FIDO message body
  289. X */
  290. X
  291. int check_rfc_header(buffer)
  292. char *buffer;
  293. {
  294. X    if(!strncmp(buffer, "From: ", 6)) {
  295. X        msgbody_rfc_from = strsaveline(buffer + 6);
  296. /*        compress_spaces(msgbody_rfc_from); */
  297. X        return(1);
  298. X    }
  299. X    if(!strncmp(buffer, "Reply-To: ", 10)) {
  300. X        msgbody_rfc_from = strsaveline(buffer + 10);
  301. X        compress_spaces(msgbody_rfc_from);
  302. X        return(1);
  303. X    }
  304. X    if(!strncmp(buffer, "UUCPFROM:", 9)) {
  305. X        msgbody_rfc_from = strsaveline(buffer + 9);
  306. /*        compress_spaces(msgbody_rfc_from); */
  307. X        return(1);
  308. X    }
  309. X    if(!strncmp(buffer, "To: ", 4)) {
  310. X        msgbody_rfc_to = strsaveline(buffer + 4);
  311. X        return(1);
  312. X    }
  313. X    return(0);
  314. }
  315. X
  316. X
  317. X
  318. /*
  319. X * compress_spaces()  ---  Strip spaces out of string
  320. X */
  321. X
  322. compress_spaces(string)
  323. char *string;
  324. {
  325. char *p;
  326. X
  327. X    for(p=string; *p; p++)
  328. X        if(*p != ' ')
  329. X            *string++ = *p;
  330. X    *string = 0;
  331. }
  332. X
  333. X
  334. X
  335. /*
  336. X * Generate RFC822 message-id from FIDO ^AMSGID/REPLY kludge
  337. X */
  338. X
  339. int generate_msgid(fp, header, msgid)
  340. FILE *fp;
  341. char *header, *msgid;
  342. {
  343. char *system;
  344. char *id;
  345. Node idnode;
  346. long idnumber, xtol();
  347. X
  348. X    /*
  349. X     * Seperate system string
  350. X     */
  351. X    for(system=msgid; *msgid && !isspace(*msgid); msgid++);
  352. X    if(!*msgid)
  353. X        return(-1);
  354. X    *msgid++ = 0;
  355. X    /*
  356. X     * Seperate id string
  357. X     */
  358. X    for(; *msgid && isspace(*msgid); msgid++);
  359. X    if(!*msgid)
  360. X        return(-1);
  361. X    for(id=msgid; *msgid && isxdigit(*msgid); msgid++);
  362. X    *msgid = 0;
  363. X
  364. X    /*
  365. X     * Try to interprete system as FIDO node
  366. X     */
  367. X    if(!parsefnetaddress(system, &idnode))
  368. X        system = internode(idnode);
  369. X    else
  370. X        stripbad(system);
  371. X    /*
  372. X     * Convert hex id to decimal
  373. X     */
  374. X    idnumber = xtol(id);
  375. X    
  376. X    /*
  377. X     * Output RFC822 style message id
  378. X     */
  379. X    fprintf(fp, "%s <%lu@%s>\n", header, idnumber, system);
  380. X    
  381. X    return(0);
  382. }
  383. X
  384. X
  385. X
  386. /*
  387. X * Replacement for fgets(3S) to understand cr's generated by Fido
  388. X * and 'soft' cr's generated by SEAdog.
  389. X * ie. 0 is got from file.
  390. X */
  391. X
  392. static char *
  393. ffgets(buffer, maxlen, fp)
  394. char *buffer;
  395. int maxlen;
  396. FILE *fp;
  397. {
  398. X    register int c, ch, index;
  399. X    register char *cp;
  400. X    static char wordsave[BUFSIZ];
  401. X
  402. X    /* TRUE if last line was origin line without valid node */
  403. X    static int last_line_was_origin = FALSE;
  404. X
  405. X    /* TRUE if last character caused line wrap */
  406. X    static int last_char_wrapped = FALSE;
  407. X    Node node;
  408. X
  409. X    /* There might be wrapped word lying around */
  410. X    if (*wordsave) {
  411. X        strcpy(buffer, wordsave);
  412. X        strsclean(buffer);
  413. X        debug(20, "Picked up word '%s'", buffer);
  414. X        *wordsave = 0;
  415. X    }
  416. X    else
  417. X        *buffer = 0;
  418. X
  419. X    cp = buffer + strlen(buffer);
  420. X
  421. X    while (--maxlen > 0 && (c = getc(fp)) != EOF && c) {
  422. X        /* Hard carriage return */
  423. X
  424. X        if (c == '\r')
  425. X            c = '\n';
  426. X        else if (c == '\n' || c == 0x8d) {
  427. X            /* Forget about these ! */
  428. X            continue;
  429. X        }
  430. X        else if(c < ' ') {
  431. X            /*
  432. X             * Substitute control chars with '^X'
  433. X             */
  434. X            if(c != '\t') {
  435. X                *cp++ = '^';
  436. X                c = c + '@';
  437. X            }
  438. X        }
  439. X        else if(c & 0x80) {
  440. X            /*
  441. X             * Convert IBM umlaut chars and others above 0x80
  442. X             */
  443. X            switch(c) {
  444. X                case 132:
  445. X                    *cp++ = 'a';    c = 'e';    break;
  446. X                case 148:
  447. X                    *cp++ = 'o';    c = 'e';    break;
  448. X                case 129:
  449. X                    *cp++ = 'u';    c = 'e';    break;
  450. X                case 142:
  451. X                    *cp++ = 'A';    c = 'e';    break;
  452. X                case 153:
  453. X                    *cp++ = 'O';    c = 'e';    break;
  454. X                case 154:
  455. X                    *cp++ = 'U';    c = 'e';    break;
  456. X                case 225:  case 158:
  457. X                    *cp++ = 's';    c = 's';    break;
  458. X                default:
  459. X                    c = '*';                    break;
  460. X            }
  461. X        }
  462. X
  463. X        /*
  464. X         * If last character caused line wrap, and we now got another linefeed,
  465. X         * skip this linefeed to avoid unneeded empty lines.
  466. X         */
  467. X        if (last_char_wrapped) {
  468. X            if (c == '\n') {
  469. X                last_char_wrapped = FALSE;
  470. X                continue;
  471. X            }
  472. X
  473. X            if (isspace(c) && strempty(buffer))
  474. X                continue;
  475. X        }
  476. X
  477. X        *cp++ = c;
  478. X
  479. X        if (c == '\n')
  480. X            break;
  481. X
  482. X        *cp = 0;
  483. X
  484. X        /*
  485. X         * Try to wrap if line is too long and it is not a seen-by, origin or
  486. X         * path line.
  487. X         */
  488. X        if (strlen(buffer) >= MAX_LINELEN &&
  489. X            strncmp(" * Origin:", buffer, 10) &&
  490. X            strncmp("SEEN-BY:", buffer, 8) &&
  491. X            strncmp("^A", buffer, 2) &&
  492. X            strncmp("FSC-Control:", buffer, 12)) {        /* - 1 for \n */
  493. X            last_char_wrapped = TRUE;
  494. X
  495. X            /* Search for place to cut */
  496. X            for (index = strlen(buffer) - 1; index >= 0; index--) {
  497. X                c = buffer[index];
  498. X                if (index <= MAX_LINELEN / 3) {
  499. X                    /* Too long, cut. */
  500. X                    *cp++ = c = '\n';
  501. X                    goto collected;
  502. X                }
  503. X
  504. X                if (isspace(c)) {
  505. X                    /* Wrap here! */
  506. X                    cp = buffer + index + 1;    /* Punctuation left on this
  507. X                                                 * line */
  508. X                    strcpy(wordsave, cp);
  509. X                    debug(20, "saving word '%s'", wordsave);
  510. X                    *cp++ = c = '\n';
  511. X                    goto collected;
  512. X                }
  513. X            }
  514. X        }
  515. X
  516. X        last_char_wrapped = FALSE;
  517. X    }
  518. X
  519. X  collected:
  520. X
  521. X    /* if we got nul, put it back if occurred in the middle of line */
  522. X    if (!c && cp != buffer)
  523. X        (void) ungetc(0, fp);
  524. X
  525. X    *cp = 0;                    /* Cut it here */
  526. X
  527. X
  528. X  out:
  529. X    return ((!c || c == EOF) && cp == buffer) ? (char *) 0 : buffer;
  530. }
  531. X
  532. X
  533. X
  534. static Packet header;
  535. X
  536. read_header(fp)
  537. FILE *fp;
  538. {
  539. X    header.orig_node = read_int(fp);
  540. X    header.dest_node = read_int(fp);
  541. X    header.year      = read_int(fp);
  542. X    header.month     = read_int(fp);
  543. X    header.day       = read_int(fp);
  544. X    header.hour      = read_int(fp);
  545. X    header.minute    = read_int(fp);
  546. X    header.second    = read_int(fp);
  547. X    header.rate      = read_int(fp);
  548. X    header.ver       = read_int(fp);
  549. X    header.orig_net  = read_int(fp);
  550. X    header.dest_net  = read_int(fp);
  551. X    header.product   = getc(fp);
  552. X    header.x1        = getc(fp);
  553. X    fread(header.pwd_kludge, 8, 1, fp);
  554. X    header.orig_zone = read_int(fp);
  555. X    if (header.orig_zone == 0)
  556. X        header.orig_zone = MY_ZONE;
  557. X    header.dest_zone = read_int(fp);
  558. X    if (header.dest_zone == 0)
  559. X        header.dest_zone = MY_ZONE;
  560. X    fread(header.B_fill2, 16, 1, fp);
  561. X    fread((char *) &header.B_fill3, 4, 1, fp);
  562. X    return(ferror(fp) || feof(fp));
  563. }
  564. X
  565. X
  566. X
  567. /*
  568. X * Read 16-bit integer in 80x86 format, i.e. low byte first,
  569. X * then high byte. Machine independent function.
  570. X */
  571. X
  572. int read_int(fp)
  573. FILE *fp;
  574. {
  575. register int c;
  576. register int val;
  577. X
  578. X    if((c = getc(fp)) == EOF) {
  579. X        log("$Can't read file (EOF)");
  580. X        return(0);
  581. X    }
  582. X    val  = c;
  583. X    if((c = getc(fp)) == EOF) {
  584. X        log("$Can't read file (EOF)");
  585. X        return(0);
  586. X    }
  587. X    val |= c << 8;
  588. X    return(val);
  589. }
  590. X
  591. X
  592. X
  593. /* Read null-terminated string from file. Ensure that buffer is also
  594. X   null-terminated. Remove possible \n:s from end, they are generated by
  595. X   some buggy mailers. */
  596. X
  597. void
  598. get_string(buffer, fp, nbytes)
  599. char *buffer;
  600. FILE *fp;
  601. int nbytes;
  602. {
  603. X    register int n;
  604. X    char *p;
  605. X
  606. X    debug(8, "get string start %ld", ftell(fp));
  607. X
  608. X    for (n = 0, *buffer = 0; n < nbytes; n++)
  609. X        if ((buffer[n] = getc(fp)) == 0)
  610. X            break;
  611. X        else
  612. X            debug(8, "<%d %c>", buffer[n], buffer[n]);
  613. X
  614. X    /* If still more chars in buffer, skip them until null char found */
  615. X    if (n >= nbytes) {
  616. X        debug(8, "Skipping rest");
  617. X        while (getc(fp)) ;
  618. X    }
  619. X
  620. X    buffer[nbytes] = 0;
  621. X
  622. X    /* Remove \n from end if its there, its a bug */
  623. X    if (p = strchr(buffer, '\n'))
  624. X        *p = 0;
  625. X
  626. X    debug(8, "Getstring at %ld %s", ftell(fp), buffer);
  627. }
  628. X
  629. #define NGFLAG_ACCEPT_PRIVATE 0
  630. #define NGFLAG_COMMAND 1
  631. #define NGFLAG_TRASH_PRIVATE 2
  632. X
  633. static char distribution[64];
  634. static char *ngflags[] =
  635. {"accept-private", "command", "trash-private", ""};
  636. X
  637. /* Like strtok but returns empty string instead of null if no more thigns
  638. X   found */
  639. X
  640. char *
  641. estrtok(s, sep)
  642. char *s, *sep;
  643. {
  644. X    char *p;
  645. X
  646. X    if (p = strtok(s, sep))
  647. X        return p;
  648. X    return "";
  649. }
  650. X
  651. char *
  652. get_ng(config, echo, distrib)
  653. FILE *config;
  654. char *echo, *distrib;
  655. {
  656. static char conv[BUFLEN];
  657. char *gr, *flag;
  658. X
  659. X    debug(2, "Checking echolist '%s'", echo);
  660. X
  661. /*    section(SECT_AREA_NG, config); /**/
  662. X    trashprivate = FALSE;
  663. X    acceptprivate = FALSE;
  664. X    while (getcl(conv, BUFLEN, config)) {
  665. X        debug(3, "Config line '%s'", conv);
  666. X
  667. X        gr = estrtok(conv, SEPARATORS);
  668. X        if (!strcmp(gr, echo)) {
  669. X            /* Matched, take distribution and return newsgroup */
  670. X
  671. X            gr = estrtok(NULL, SEPARATORS);
  672. X            strcpy(distrib, estrtok(NULL, SEPARATORS));
  673. X            while (flag = strtok(NULL, SEPARATORS))
  674. X                switch (listscan(ngflags, flag)) {
  675. X                    case NGFLAG_ACCEPT_PRIVATE:
  676. X                        acceptprivate = TRUE;
  677. X                        break;
  678. X
  679. X                    case NGFLAG_TRASH_PRIVATE:
  680. X                        trashprivate = TRUE;
  681. X                        break;
  682. X
  683. X                    case -1:
  684. X                    default:
  685. X                        log("Bad flag '%s' for newsgroup %s", flag, gr);
  686. X                        break;
  687. X                }
  688. X
  689. X            debug(3, "Match, return newsgroup '%s', distribution %s",
  690. X                  gr, distrib);
  691. X            return gr;
  692. X        }
  693. X    }
  694. X    log("No newsgroup for '%s' found, return junk, distribution local", echo);
  695. X    strcpy(distrib, "local");
  696. X    return "junk";
  697. }
  698. X
  699. /* Check if message is news-message (currenlty: if first line begins
  700. X   with AREA:). If area is found, we'll return name for that area,
  701. X   otherwise NULL. */
  702. X
  703. char *
  704. news_msg(fp)
  705. FILE *fp;
  706. {
  707. X    FILE *config;
  708. X    long offset = ftell(fp);
  709. X    char *cp;
  710. X    static char area[64];
  711. X
  712. X    if (ffgets(area, 64, fp) && !strncmp(area, "AREA:", 5)) {
  713. X        /* this is echomail-message */
  714. X        area[strlen(area) - 1] = 0;
  715. X
  716. X        /* strip possible spaces */
  717. X        for (cp = area + 5; *cp && isspace(*cp); cp++) ;
  718. X
  719. X        if ((config = pfopen(LIBDIR, "Areas", "r")) == NULL) {
  720. X            log("$Unable to open areas file");
  721. X            exit(1);
  722. X        }
  723. X
  724. X        strcpy(cp, get_ng(config, cp, distribution));
  725. X        fclose(config);
  726. X
  727. X        /* return converted area-name */
  728. X        return cp;
  729. X    }
  730. X    else {
  731. X        /* this is not echomail message, seek back */
  732. X        (void) fseek(fp, offset, 0);
  733. X        return (char *) 0;
  734. X    }
  735. X    /* NOTREACHED */
  736. }
  737. X
  738. X
  739. X
  740. /*
  741. X * Return date of message in UNIX format (secs after the epoche)
  742. X *
  743. X * Understood formats: see getdate.y
  744. X */
  745. X
  746. time_t lgetdate(packet)
  747. FILE *packet;
  748. {
  749. char buffer[20];
  750. int c;
  751. time_t timevar;
  752. int n;
  753. X
  754. X    /* read date from packet */
  755. X    for (n = 0; n < 20; n++)
  756. X        if ((buffer[n] = getc(packet)) == 0)
  757. X            break;
  758. X
  759. X    /*
  760. X     * Some message-packers do mistakes! Date should be 20 bytes but they start
  761. X     * name directly after null terminating 18-char date used in some systems.
  762. X     * Check if following char is null or not, and if not, put it back there as
  763. X     * it probably is first char in recipent name. This seems to be problem in
  764. X     * OMMM, but I'm not sure yet.
  765. X     * 
  766. X     * Wed Nov 16 21:11:34 1988 Seems that the bug is in fsc001, as I constantly
  767. X     * keep receiving messages which 19 byte date?
  768. X     */
  769. X
  770. #ifdef FSC_IS_REALLY_CORRECT
  771. X    for (n++; n < 20; n++)
  772. X        if (c = getc(packet)) {
  773. X            ungetc(c, packet);
  774. X        }
  775. #endif
  776. X
  777. X    buffer[19] = 0;
  778. X    debug(8, "Getdate %s at %ld", buffer, ftell(packet));
  779. X
  780. X    /* try to get date */
  781. X    timevar = getdate(buffer, NULL);
  782. X    return timevar;
  783. }
  784. X
  785. X
  786. X
  787. /* Search alias name which matches with fidonet name, return NULL
  788. X   if no alias specified. */
  789. X
  790. char *
  791. get_alias(name)
  792. char *name;
  793. {
  794. X    char buffer[BUFSIZ];
  795. X    char *cp;
  796. X    FILE *fp;
  797. X    static char unixname[BUFSIZ], fidoname[BUFSIZ];
  798. X
  799. X    if (fp = fopen(ALIAS, "r")) {
  800. X        while (fgets(buffer, BUFSIZ, fp)) {
  801. X            buffer[strlen(buffer) - 1] = 0;
  802. X            if (*buffer != '#') {
  803. X                if ((cp = strchr(buffer, ' ')) ?
  804. X                    cp : (cp = strchr(buffer, '\t'))) {
  805. X                    *cp = 0;    /* Break unixname out */
  806. X                    strcpy(unixname, buffer);    /* And save it */
  807. X                    debug(8, "Unix name %s", unixname);
  808. X                }
  809. X                else {
  810. X                    /* No space or tab found, probably bad line */
  811. X                    debug(1, "Bad alias line %s", buffer);
  812. X                    continue;
  813. X                }
  814. X
  815. X                /* Search for name start, there may be space between */
  816. X                cp++;
  817. X                while (*cp && isspace(*cp))
  818. X                    cp++;
  819. X                if (!*cp) {
  820. X                    debug(1, "Bad alias line %s", buffer);
  821. X                    continue;
  822. X                }
  823. X
  824. X                strcpy(fidoname, cp);    /* Save fidonet name */
  825. X                debug(8, "Fidoname %s", fidoname);
  826. X
  827. X                if (!stricmp(fidoname, name)) {
  828. X                    fclose(fp);
  829. X
  830. X                    /* There may be node specs after name, null them out */
  831. X                    if (cp = strchr(unixname, ','))
  832. X                        *cp = 0;
  833. X
  834. X                    debug(8, "Fidoname %s matched with %s, return %s",
  835. X                          fidoname, name, unixname);
  836. X                    return unixname;
  837. X                }
  838. X            }
  839. X        }
  840. X    }
  841. X
  842. X    fclose(fp);
  843. X    return NULL;
  844. }
  845. X
  846. X
  847. X
  848. /*
  849. X * Strip bad chars from FIDO names, i.e. chars not allowed in
  850. X * RFC822 `atoms'. One execption is ' ' (space), which is converted
  851. X * to '_' later on.
  852. X */
  853. X
  854. stripbad(name)
  855. char *name;
  856. {
  857. char *d;
  858. X
  859. X    for(d=name; *d; d++)
  860. X        if( !iscntrl(*d) && !strchr("()<>@,;:\\\"[]", *d) )
  861. X            *name++ = *d;
  862. X    *name = 0;
  863. }
  864. X
  865. X
  866. X
  867. /*
  868. X * Capitalize string
  869. X */
  870. X
  871. char *strcap(s)
  872. char *s;
  873. {
  874. X    if(!s || !*s)
  875. X        return(s);
  876. X    if(islower(*s))
  877. X        *s = toupper(*s);
  878. X    for(s++; *s; s++)
  879. X        if(isupper(*s))
  880. X            *s = tolower(*s);
  881. X    return(s);
  882. }
  883. X
  884. X
  885. X
  886. /*
  887. X * Convert name in FIDO from or to field to real name
  888. X * for use in () in RFC822 header. Everything after
  889. X * `%' or `Of' is thrown away. The result is capitalized.
  890. X */
  891. X
  892. realname_convert(name, realname)
  893. char *name;
  894. char *realname;
  895. {
  896. char *p, *string;
  897. int cat_flag = 0;
  898. X
  899. X    string = strsave(name);
  900. X    *realname = 0;
  901. X    for(p=strtok(string, " \t"); p; p=strtok(NULL, " \t")) {
  902. X        if(!strcmp(p, "%") || !strcmp(p, "of") || !strcmp(p, "Of") ||
  903. X           !strcmp(p, "-")                                                )
  904. X            break;
  905. X        strcap(p);
  906. X        if(cat_flag)
  907. X            strcat(realname, " ");
  908. X        strcat(realname, p);
  909. X        cat_flag = 1;
  910. X    }
  911. X    free(string);
  912. }
  913. X
  914. X
  915. X
  916. /* Unpack packet and all files in it. Packet's header will be stripped
  917. X   off. For each message check if it is news-msg (First line begins
  918. X   with AREA:). If it is, send it to news-sender sfnews, otherwise
  919. X   send it to rmail. Address is given in to-field, or if it wont
  920. X   fit to it, in the first line of message. In later case to-field
  921. X   must be "Usenet". */
  922. X
  923. void
  924. unpack(packet, packetnode)
  925. FILE *packet;
  926. Node packetnode;
  927. {
  928. /*
  929. X * Variables for header info
  930. X */
  931. Node msg_orignode, msg_destnode;        /* Origin/destination address */
  932. int msg_attributes;                        /* Attributes of message (priv. etc.) */
  933. time_t msg_date;                        /* Date of message */
  934. char msg_to[36];                        /* To name */
  935. char msg_from[36];                        /* From name */
  936. char msg_subject[72];                    /* Subject */
  937. /*
  938. X * Variables for info from FIDO kludges
  939. X */
  940. Node origin_node;                        /* Address in origin line */
  941. char origin_text[128];                    /* Organization taken from * Origin */
  942. X
  943. int lines;                                /* Lines in message body */
  944. X
  945. char *area;                                /* Area / newsgroup (NULL = mail) */
  946. char *p;
  947. int count, messagetype;
  948. char realto[40], realfrom[40];
  949. char searchto[36];
  950. char buffer[BUFSIZ];
  951. int c;
  952. Node *entry, mynode;
  953. Node node;
  954. char hostname[10];
  955. long msgid;                                /* Msg id from sequence file */
  956. char out_name[128];                        /* Name for output msg */
  957. char mail_to[128];                        /* Addressee of mail */
  958. FILE *outtmp, *out;
  959. int rfc_header_flag;
  960. X
  961. X
  962. #ifdef NODELIST_SUPPORT
  963. X    /* get node-entry fo packet-sender */
  964. X    if (node_entry(packetnode) == NULL) {
  965. X        log("Unknown packet sender: %s", ascnode(packetnode));
  966. X        return;
  967. X    }
  968. #endif
  969. X
  970. X    mynode.zone = MY_ZONE;
  971. X    mynode.net = MY_NET;
  972. X    mynode.node = MY_NODE;
  973. X    mynode.point = MY_POINT;
  974. X    strcpy(mynode.name, MY_NAME);
  975. X
  976. #ifdef NODELIST_SUPPORT
  977. X    if ((entry = node_entry(mynode)) == NULL) {
  978. X        log("Unable to find this net/node from nodelist");
  979. X        return;
  980. X    }
  981. #else
  982. X    entry = &mynode;
  983. #endif
  984. X
  985. X    /* get our uucp-nodename */
  986. X    if (gethostname(hostname, 10) == -1) {
  987. X        log("Unable to get hostname");
  988. X        return;
  989. X    }
  990. X
  991. X    while ((messagetype = read_int(packet)) == MSGTYPE) {
  992. X        /*
  993. X         * Clear stuff set by parsing message body
  994. X         */
  995. X        origin_node.zone = -1;
  996. X        origin_text[0] = 0;
  997. X        msgbody_fmpt = 0;
  998. X        msgbody_msgid[0] = 0;
  999. X        msgbody_reply[0] = 0;
  1000. X        msgbody_intl[0]  = 0;
  1001. X        if(msgbody_rfc_from) {
  1002. X            free(msgbody_rfc_from);
  1003. X            msgbody_rfc_from = NULL;
  1004. X        }
  1005. X        if(msgbody_rfc_to) {
  1006. X            free(msgbody_rfc_to);
  1007. X            msgbody_rfc_to = NULL;
  1008. X        }
  1009. X        lines = 1;
  1010. X
  1011. X        /*
  1012. X         * Initialize some stuff
  1013. X         */
  1014. X        msg_orignode.zone  = packetnode.zone;
  1015. X        msg_orignode.point = packetnode.point;
  1016. X        msg_destnode.zone  = packetnode.zone;
  1017. X        msg_destnode.point = packetnode.point;
  1018. X
  1019. X        /*
  1020. X         * Read FIDO message header and save information
  1021. X         */
  1022. X        /***** Origin/destination node *****/
  1023. X        msg_orignode.node = read_int(packet);
  1024. X        msg_destnode.node = read_int(packet);
  1025. X        /***** Origin/destination net *****/
  1026. X        msg_orignode.net = read_int(packet);
  1027. X        msg_destnode.net = read_int(packet);
  1028. X        debug(2, "Origin:      %s", ascnode(msg_orignode));
  1029. X        debug(2, "Destination: %s", ascnode(msg_destnode));
  1030. X        /***** Message attributes *****/
  1031. X        msg_attributes = read_int(packet);
  1032. X        /***** Cost (thrown away) *****/
  1033. X        read_int(packet);
  1034. X        /***** Date *****/
  1035. X        msg_date = lgetdate(packet);
  1036. X        /***** To name *****/
  1037. X        get_string(msg_to, packet, 35);
  1038. X        debug(2, "To:      %s", msg_to);
  1039. X        /***** From name *****/
  1040. X        get_string(msg_from, packet, 35);
  1041. X        debug(2, "From:    %s", msg_from);
  1042. X        /***** Subject *****/
  1043. X        get_string(msg_subject, packet, 71);
  1044. X        /* Remove trailing blanks */
  1045. X        for(count = strlen(msg_subject) - 1;
  1046. X            count >= 0 && isspace(msg_subject[count]);
  1047. X            count--                                    )
  1048. X            msg_subject[count] = 0;
  1049. X        if (!*msg_subject)
  1050. X            strcpy(msg_subject, "(no subject)");
  1051. X        debug(2, "Subject: %s", msg_subject);
  1052. X
  1053. X        /*
  1054. X         * Check that message is addressed to this node
  1055. X         */
  1056. X        if(!samenode(msg_destnode, mynode)) {
  1057. X            log("Msg from %s to %s at %s: wrong node address",
  1058. X                msg_from, msg_to, ascnode(msg_destnode));
  1059. X            goto error;
  1060. X        }
  1061. X        
  1062. X        /*
  1063. X         * Strip bad chars from header fields
  1064. X         */
  1065. X        stripbad(msg_from);
  1066. X        stripbad(msg_to);
  1067. X        strcpy(searchto, msg_to);
  1068. X        /*
  1069. X         * Convert to real names for use in ()
  1070. X         */
  1071. X        realname_convert(msg_from, realfrom);
  1072. X        realname_convert(msg_to, realto);
  1073. X        /*
  1074. X         * Convert spaces to `_'
  1075. X         */
  1076. X        for(p=msg_from; *p; p++)
  1077. X            *p = *p==' ' ? '_' : *p;
  1078. X        for(p=msg_to; *p; p++)
  1079. X            *p = *p==' ' ? '_' : *p;
  1080. X
  1081. X        /*
  1082. X         * Get next message-id
  1083. X         */
  1084. X        msgid = sequencer(IDSEQUENCE);
  1085. X
  1086. X        /*
  1087. X         * Check for mail or news.
  1088. X         * Read first line from FIDO message body. If it starts with
  1089. X         * `AREA:...' then it is news, else it is mail. area is newsgroup
  1090. X         * name or NULL for mail.
  1091. X         */
  1092. X        if ((area = news_msg(packet)) &&
  1093. X            (acceptprivate || !(msg_attributes & ATTR_PRIVATE)))
  1094. X        {
  1095. X            /*
  1096. X             * This is a news article.
  1097. X             */
  1098. X            debug(1, "Message is news-article");
  1099. X            sprintf(out_name, "%s/unpacked/N.%ld", SPOOL, msgid);
  1100. X        }
  1101. X        else {
  1102. X            /*
  1103. X             * This is personal mail
  1104. X             */
  1105. X            debug(1, "Message is for mail");
  1106. X            sprintf(out_name, "%s/unpacked/M.%ld", SPOOL, msgid);
  1107. X
  1108. X            if (area) {
  1109. X                debug(1, "Private message for area %s", area);
  1110. X                if (trashprivate)
  1111. X                    goto error;
  1112. X            }
  1113. X
  1114. X            debug(8, "Searching alias for %s", searchto);
  1115. X            if (p = get_alias(searchto)) {
  1116. X                (void) strcpy(buffer, p);
  1117. X                debug(8, "Got alias %s", buffer);
  1118. X            }
  1119. X            else {
  1120. X                if (area) {
  1121. X                    log("Skipping private echo for %s", msg_to);
  1122. X                    goto error;        /* If private echo message, skip */
  1123. X                }
  1124. X                (void) strcpy(buffer, msg_to);
  1125. X                debug(8, "No alias, using %s", buffer);
  1126. X            }
  1127. X
  1128. X            for(p=buffer; *p; p++)
  1129. X                *p = isupper(*p) ? tolower(*p) : *p;
  1130. X
  1131. X            strcpy(mail_to, buffer);
  1132. X            log("Sending mail from %s at %s to %s", msg_from,
  1133. X                ascnode(msg_orignode), buffer );
  1134. X
  1135. X            area = NULL;
  1136. X        }
  1137. X
  1138. X        /*
  1139. X         * Create files
  1140. X         */
  1141. X        outtmp = tmpfile();
  1142. X        if(!outtmp) {
  1143. X            log("$Can't create temp file");
  1144. X            goto error;
  1145. X        }
  1146. X        out = fopen(out_name, "w");
  1147. X        if(!out) {
  1148. X            log("$Can't create output file %s", out_name);
  1149. X            fclose(outtmp);
  1150. X            goto error;
  1151. X        }
  1152. X
  1153. X        /*
  1154. X         * Read entire FIDO message body and write it
  1155. X         * to temporary file for later use. (Must read
  1156. X         * message body first `cause we need some information
  1157. X         * from it.)
  1158. X         * Some special treatment for origin line and ^A
  1159. X         * kludges is done.
  1160. X         */
  1161. X        rfc_header_flag = 1;
  1162. X        while(ffgets(buffer, BUFSIZ, packet)) {
  1163. X            if(!strncmp(buffer, "^A", 2)) {
  1164. X                check_ctrl_a(buffer);
  1165. X                continue;
  1166. X            }
  1167. X            else if(rfc_header_flag) {
  1168. X                rfc_header_flag = check_rfc_header(buffer);
  1169. X            }
  1170. X            if(!strncmp(" * Origin:", buffer, 10)) {
  1171. X                check_origin(buffer, &origin_node, origin_text);
  1172. X            }
  1173. X            lines++;
  1174. X            fputs(buffer, outtmp);
  1175. X        }
  1176. X
  1177. X        /*
  1178. X         * Construct real from address, using information from
  1179. X         * header, origin line and ^A kludges.
  1180. X         */
  1181. X        if (origin_node.zone != -1) {
  1182. X            debug(1, "Using address from ` * Origin: ...'");
  1183. X            msg_orignode = origin_node;
  1184. X        }
  1185. X        else {
  1186. X            debug(1, "Using address in message header");
  1187. X        }
  1188. X        if(*msgbody_intl) {
  1189. X            p = strtok(msgbody_intl, " \n");        /* Destination */
  1190. X            p = strtok(NULL        , " \n");        /* Source */
  1191. X            if(p)
  1192. X                if(!parsefnetaddress(p, &node)) {
  1193. X                    debug(1, "Using address from ^AINTL");
  1194. X                    msg_orignode = node;
  1195. X                }
  1196. X        }
  1197. X        if(msgbody_fmpt) {
  1198. X            debug(1, "Point address %d", msgbody_fmpt);
  1199. X            msg_orignode.point = msgbody_fmpt;
  1200. X        }
  1201. X        debug(1, "New from address %s", ascnode(msg_orignode));
  1202. X
  1203. X        /*
  1204. X         * Output `From user ...' for mail
  1205. X         */
  1206. X        if(!area) {
  1207. X            fprintf(out, "From %s %s remote from %s\n",
  1208. X                        msg_from, 
  1209. X                        date("%a %h %d %T 19%y", (long *) 0),
  1210. X                        internode(packetnode)                    );
  1211. X        }
  1212. X
  1213. X        /*
  1214. X         * Output RFC822 header for mail/news
  1215. X         */
  1216. X        if(area) 
  1217. X            fprintf(out, "Path: %s!%s!%s\n",
  1218. X                         internode(this), internode(msg_orignode), msg_from);
  1219. X        else {
  1220. X            fprintf(out, "Received: by %s (%s/%s)\n",
  1221. X                    internode(*entry), PROGRAMNAME, entry->name);
  1222. X            fprintf(out, "\tid AA%05d; %s\n",
  1223. X                    getpid(), date("%a, %d %h %y %T %o (%z)", (long *) 0));
  1224. X        }
  1225. X        fprintf(out, "Date: %s\n", date("%a, %d %h %y %T %o", &msg_date));
  1226. X        if(msgbody_rfc_from) {
  1227. X            if(strchr(msgbody_rfc_from, '('))
  1228. X                fprintf(out, "From: %s\n", msgbody_rfc_from);
  1229. X            else
  1230. X                fprintf(out, "From: %s (%s)\n", msgbody_rfc_from, realfrom);
  1231. X        }
  1232. X        else
  1233. X            fprintf(out, "From: %s@%s (%s)\n", msg_from, internode(msg_orignode),
  1234. X                    realfrom);
  1235. X        fprintf(out, "Subject: %s\n", msg_subject);
  1236. X        if(!*msgbody_msgid ||
  1237. X           generate_msgid(out, "Message-ID:", msgbody_msgid) )
  1238. X            fprintf(out, "Message-ID: <funpack%lu@%s>\n", msgid, internode(*entry));
  1239. X        if(*msgbody_reply)
  1240. X            generate_msgid(out, "References:", msgbody_reply);
  1241. X
  1242. X        if (area) {
  1243. X            /*
  1244. X             * News special
  1245. X             */
  1246. X            fprintf(out, "Newsgroups: %s\n", area);
  1247. X            if(*distribution)
  1248. X                fprintf(out, "Distribution: %s\n", distribution);
  1249. X            /***** This is a *USER DEFINED* header, not in RFC822 !!! *****/
  1250. X            fprintf(out, "Comment-To: %s@%s (%s)\n", msg_to,
  1251. X                    internode(msg_destnode), realto);
  1252. X        }
  1253. X        else {
  1254. X            /*
  1255. X             * Mail special
  1256. X             */
  1257. X            if(msgbody_rfc_to) {
  1258. X                if(strchr(msgbody_rfc_to, '('))
  1259. X                    fprintf(out, "To: %s\n", msgbody_rfc_to);
  1260. X                else
  1261. X                    fprintf(out, "To: %s (%s)\n", msgbody_rfc_to, realto);
  1262. X            }
  1263. X            else
  1264. X                fprintf(out, "To: %s\n", mail_to);
  1265. X        }
  1266. X        /*
  1267. X         * Some more headers ...
  1268. X         */
  1269. X        if(*origin_text)
  1270. X            fprintf(out, "Organization: %s\n", origin_text);
  1271. X        fprintf(out, "Lines: %d\n", lines);
  1272. X
  1273. X        /*
  1274. X         * Append message body in temporary file to message
  1275. X         */
  1276. X        fprintf(out, "\n");
  1277. X        
  1278. X        rewind(outtmp);
  1279. X        while(fgets(buffer, BUFSIZ, outtmp))
  1280. X            fputs(buffer, out);
  1281. X
  1282. X        /*
  1283. X         * Dome with this message.
  1284. X         */
  1285. X        fclose(outtmp);
  1286. X        fclose(out);
  1287. X        debug(1, "Done with message");
  1288. X        continue;
  1289. X
  1290. X        /*
  1291. X         * In case of error skip text of message
  1292. X         */
  1293. error:
  1294. X        while((c = getc(packet)) && c != EOF);
  1295. X    }
  1296. X
  1297. X    if (messagetype != MSGTYPE && messagetype != EOF && messagetype != 0)
  1298. X        log("Strange ending: %d", messagetype);
  1299. X
  1300. X    debug(1, "Done with packet");
  1301. }
  1302. X
  1303. X
  1304. X
  1305. main(argc, argv)
  1306. int argc;
  1307. char *argv[];
  1308. {
  1309. struct dirent *dir;
  1310. DIR *dp;
  1311. int c;
  1312. FILE *packet;
  1313. char files[BUFLEN];
  1314. Node node;
  1315. bool nocheck = FALSE;
  1316. char *error, *p;
  1317. Node packetnode;
  1318. X
  1319. X    node.zone = -1;
  1320. X    while ((c = getopt(argc, argv, "if:vV:")) != EOF)
  1321. X        switch (c) {
  1322. X            case 'i':
  1323. X                nocheck = TRUE;
  1324. X                break;
  1325. X            case 'v':
  1326. X                verbose++;
  1327. X                break;
  1328. X            case 'V':
  1329. X                verbose = atoi(optarg);
  1330. X                break;
  1331. X            case 'f':
  1332. X                if (parsefnetaddress(optarg, &node))
  1333. X                    exit(1);
  1334. X                break;
  1335. X            default:
  1336. X                fprintf(stderr, "%s\n\n", PROGRAMNAME);
  1337. X                fprintf(stderr, "usage: funpack [-iv] [-V verbose_level] [-f Z:N/F.P]\n\n");
  1338. X                exit(EX_USAGE);
  1339. X                break;
  1340. X        }
  1341. X
  1342. X    this.zone  = MY_ZONE;
  1343. X    this.net   = MY_NET;
  1344. X    this.node  = MY_NODE;
  1345. X    this.point = MY_POINT;
  1346. X    strcpy(this.name, MY_NAME);
  1347. X
  1348. X    /* create name for unpacking */
  1349. X    if (node.zone == -1)
  1350. X        (void) strcpy(files, "");
  1351. X    else {
  1352. X        sprintipacketname(files, node);
  1353. X        /* Cut sequence number off */
  1354. X        if (p = strrchr(files, "."))
  1355. X            *p = 0;
  1356. X    }
  1357. X
  1358. X    debug(2, "Unpacking packets beginning with %s", files);
  1359. X
  1360. X    /* try to update nodelist-index */
  1361. #ifdef NODELIST_SUPPORT
  1362. X    if (error = update_index()) {
  1363. X        if (*error == '$')
  1364. X            log("$Cannot update nodelist-index: %s", error + 1);
  1365. X        else
  1366. X            log("Cannot update nodelist-index: %s", error);
  1367. X        exit(EX_OSERR);
  1368. X    }
  1369. #endif
  1370. X    if (chdir(sprintfs("%s/in", SPOOL)) == -1) {
  1371. X        log("$Cannot chdir to %s/in", SPOOL);
  1372. X        exit(EX_OSERR);
  1373. X    };
  1374. X    if (dp = opendir(".")) {
  1375. X        while (dir = readdir(dp))
  1376. X            if (!strncmp(dir->d_name, files, strlen(files)) && *dir->d_name != '.') {
  1377. X
  1378. X                /* this packet is right */
  1379. X                debug(1, "Unpacking %s", dir->d_name);
  1380. X
  1381. X                /* open packet */
  1382. X                if (packet = fopen(dir->d_name, "r")) {
  1383. X                    if (read_header(packet)) {
  1384. X                        if (feof(packet))
  1385. X                            log("Missing packet header");
  1386. X                        else
  1387. X                            log("$Error reading header");
  1388. X                    }
  1389. X                    else {
  1390. X                        packetnode.zone  = header.orig_zone;
  1391. X                        packetnode.net   = header.orig_net;
  1392. X                        packetnode.node  = header.orig_node;
  1393. X                        packetnode.point = 0;
  1394. X                        debug(1, "Packet from %s", ascnode(packetnode));
  1395. X                        debug(1, "Time %02d:%02d:%02d %d.%d.%d",
  1396. X                                header.hour, header.minute, header.second,
  1397. X                                header.day, header.month+1, header.year   );
  1398. X                        debug(1, "Max baud rate %d, version %d, product %d, x %d",
  1399. X                                header.rate, header.ver, header.product, header.x1);
  1400. X                        debug(1, "Pwd \"%s\"", header.pwd_kludge);
  1401. X                    }
  1402. X
  1403. X                    if (nocheck || ((header.dest_zone == MY_ZONE ||
  1404. X                                     header.dest_zone == 0) &&
  1405. X                                    header.dest_node == MY_NODE &&
  1406. X                                    header.dest_net == MY_NET))
  1407. X                        unpack(packet, packetnode);
  1408. X                    else
  1409. X                        log("Packet is to %d:%d/%d",
  1410. X                            header.dest_zone,
  1411. X                            header.dest_net,
  1412. X                            header.dest_node);
  1413. X                    (void) fclose(packet);
  1414. X
  1415. X                    if (unlink(dir->d_name))
  1416. X                        log("$Could not unlink packet %s", dir->d_name);
  1417. X                }
  1418. X                else
  1419. X                    log("$Unable open packet %s", dir->d_name);
  1420. X            }
  1421. X        (void) closedir(dp);
  1422. X    }
  1423. X    else {
  1424. X        log("$Unable to open spool directory");
  1425. X        exit(EX_OSERR);
  1426. X    }
  1427. X    exit(EX_OK);
  1428. X    /* NOTREACHED */
  1429. }
  1430. SHAR_EOF
  1431. chmod 0644 funpack.c ||
  1432. echo 'restore of funpack.c failed'
  1433. Wc_c="`wc -c < 'funpack.c'`"
  1434. test 32138 -eq "$Wc_c" ||
  1435.     echo 'funpack.c: original size 32138, current size' "$Wc_c"
  1436. fi
  1437. true || echo 'restore of nodelist.c failed'
  1438. echo End of part 5, continue with part 6
  1439. exit 0
  1440.  
  1441. --
  1442.  _____ _____
  1443. |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
  1444. | | | |   | |   Republikplatz 3   DOMAIN:  mju@dfv.rwth-aachen.de
  1445. |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
  1446.