home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3415 < prev    next >
Internet Message Format  |  1991-05-24  |  42KB

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