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

  1. From: mj@dfv.rwth-aachen.de (Martin Junius)
  2. Newsgroups: alt.sources
  3. Subject: FIDOGATE Part 3/6
  4. Message-ID: <mj.665055268@suntex>
  5. Date: 28 Jan 91 09:34:28 GMT
  6.  
  7. ---- Cut Here and feed the following to sh ----
  8. #!/bin/sh
  9. # This is part 03 of a multipart archive
  10. # ============= rfmail.c ==============
  11. if test -f 'rfmail.c' -a X"$1" != X"-c"; then
  12.     echo 'x - skipping rfmail.c (File already exists)'
  13. else
  14. echo 'x - extracting rfmail.c (Text)'
  15. sed 's/^X//' << 'SHAR_EOF' > 'rfmail.c' &&
  16. /*:ts=4*/
  17. /*****************************************************************************
  18. X * FIDOGATE --- Gateway software UNIX <-> FIDO
  19. X *
  20. X * $Id: rfmail.c,v 2.18 91/01/05 13:07:34 mj Exp $
  21. X *
  22. X * Read mail or news from standard input and put it into spool-directory.
  23. X * rfmail is called by the included version of rmail (mail receiver)
  24. X * and by relaynews from the CNews software.
  25. X *
  26. X * $Log:    rfmail.c,v $
  27. X * Revision 2.18  91/01/05  13:07:34  mj
  28. X * Improved generation of FIDO `^AREPLY', use `References:' or `In-Reply-To:'
  29. X * even if no `Message-ID:' present. Fixed function get_header().
  30. X * 
  31. X * Revision 2.17  90/12/09  18:36:48  mj
  32. X * Support for new `X' header in intermediate file taken from X-F[D[D[DRFC `X-Flags:'.
  33. X * Crash mail is now possible via `X-Flags: C'.
  34. X * 
  35. X * Revision 2.16  90/12/09  17:35:13  mj
  36. X * Fixed a small bug in subject handling.
  37. X * 
  38. X * Revision 2.15  90/12/02  21:22:25  mj
  39. X * Changed program header to mention both authors of the original
  40. X * software posted to alt.sources.
  41. X * 
  42. X * Revision 2.14  90/12/01  17:49:49  mj
  43. X * Major new feature: rfmail is now able to handle news articles posted
  44. X * to several newsgroup. For each newsgroup in the Newsgroups header a
  45. X * seperate spool file for the corresponding FIDO EchoMail area is created.
  46. X * 
  47. X * Revision 2.13  90/11/23  21:52:14  mj
  48. X * Changed date output to be compliant with FTS-0001: `DD MON YY  HH:MM:SS',
  49. X * so QMail hopefully won't mess around with rfmail's dates any more.
  50. X * 
  51. X * Revision 2.12  90/11/23  20:42:36  mj
  52. X * Output of ^AREPLY no longer depends on real versus fake net address.
  53. X * 
  54. X * Revision 2.11  90/11/20  21:09:35  mj
  55. X * Added support for ^AINTL kludge.
  56. X * 
  57. X * Revision 2.10  90/11/05  20:50:55  mj
  58. X * Changed my signature in all program headers.
  59. X * 
  60. X * Revision 2.9  90/11/01  14:53:43  mj
  61. X * Take last message id from RFC822 Message-ID/References header.
  62. X * 
  63. X * Revision 2.8  90/11/01  14:35:05  mj
  64. X * Enabled generation of ^AREPLY kludge.
  65. X * 
  66. X * Revision 2.7  90/10/29  21:20:15  mj
  67. X * Enabled generation of ^AMSGID kludge.
  68. X * 
  69. X * Revision 2.6  90/09/16  17:36:25  mj
  70. X * Some changes. (what?)
  71. X * 
  72. X * Revision 2.5  90/09/15  14:22:54  mj
  73. X * Bug in newsgroup<->area conversion removed.
  74. X * 
  75. X * Revision 2.4  90/09/13  21:58:38  mj
  76. X * Two major changes:
  77. X * Improved handling of user names in addresses and real names.
  78. X * Normally we use real name from header lines, but in case of
  79. X * special addressing via '%', e.g. "... % MAUS AC", we must use
  80. X * name in address, because "% ..." is not in real name.
  81. X * rfmail now handles news messages too. `-n' option implemented for
  82. X * this purpose. Look up newsgroup<->area conversion in Areas file
  83. X * and generate tear, origin, seen-by and path line. No more need
  84. X * for the rfnews program.
  85. X * 
  86. X * Revision 2.3  90/09/08  18:49:03  mj
  87. X * Move strsaveline() to xalloc.c
  88. X * 
  89. X * Revision 2.2  90/09/03  17:57:44  mj
  90. X * Some changes. Generation of ^AMSGID and ^AREPLY not active
  91. X * at this point.
  92. X * 
  93. X * Revision 2.1  90/08/12  14:16:05  mj
  94. X * Added output of FIDO `^AMSGID:' and `^AREPLY:' kludges to the
  95. X * spool file for fpack. These lines are generated from RFC 822
  96. X * header lines `Message-ID:' and `References:'.
  97. X * 
  98. X * Revision 2.0  90/08/12  11:58:33  mj
  99. X * Rewrote much of the code of rfmail.c: Parsing of header is now
  100. X * much cleaner, changed the names of some functions, introduced
  101. X * other ones. Sending of mail to more than one user now really
  102. X * works.
  103. X * 
  104. X * Revision 1.6  90/08/09  19:18:05  mj
  105. X * `Comment-To:' header line no longer makes it's way into the FIDO
  106. X * message.
  107. X * 
  108. X * Revision 1.5  90/07/29  18:12:23  mj
  109. X * Place real net/node in message header for FIDO netmail. Also
  110. X * a `^AFMPT x' kludge is generated in this case. Recipient of
  111. X * our mail now gets real address from message, which should
  112. X * make replying much easier.
  113. X * 
  114. X * Revision 1.4  90/07/07  18:23:53  mj
  115. X * Support for point addressing and the IFNA `^ATOPT x' kludge
  116. X * added to rfmail.
  117. X * 
  118. X * Revision 1.3  90/07/01  13:46:04  mj
  119. X * Removed all calls to alloca(). All unsave malloc()'s without
  120. X * checking the returned pointer are now done via xmalloc().
  121. X * Fixed a malloc() error in rmail.
  122. X * 
  123. X * Revision 1.2  90/06/28  22:04:43  mj
  124. X * Much rework of the sources, no more hsu.h and other clean up.
  125. X * rmail improved, now handles special XENIX quirks.
  126. X * 
  127. X * Revision 1.1  90/06/21  21:09:34  mj
  128. X * Everything seems to work, so this delta was made.
  129. X * 
  130. X * Revision 1.0  90/06/19  18:33:19  mj
  131. X * Initial revision
  132. X * 
  133. X *
  134. X *****************************************************************************
  135. X * This version hacked and maintained by:
  136. X *    _____ _____
  137. X *   |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
  138. X *   | | | |   | |   Republikplatz 3   DOMAIN:  mju@dfv.rwth-aachen.de
  139. X *   |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
  140. X *
  141. X * Original version of these programs and files:
  142. X *
  143. X *   Teemu Torma
  144. X *   Heikki Suonsivu   FIDO: 2:504/1   UUCP: ...!mcsun!santra!hsu
  145. X *
  146. X *****************************************************************************/
  147. X
  148. #include "fidogate.h"
  149. X
  150. #include <varargs.h>
  151. #include <pwd.h>
  152. X
  153. X
  154. X
  155. #define PROGRAMNAME        "rfmail $Revision: 2.18 $"
  156. X
  157. X
  158. X
  159. #define ORIGIN            "Link to news/mail at hippo.uucp"
  160. X
  161. X
  162. extern struct passwd *getpwuid();
  163. extern int getopt();
  164. extern char *optarg;
  165. extern int optind;
  166. extern void exit();
  167. extern char *spoolfile(), *basename();
  168. extern char *regex();
  169. extern time_t time();
  170. extern FILE *popen();
  171. X
  172. X
  173. /* Verbosity */
  174. int verbose = INIT_VERBOSE;
  175. X
  176. /* Private mail (default) */
  177. bool private = TRUE;
  178. X
  179. /* News-article */
  180. int newsmode = FALSE;
  181. X
  182. /* Our net/node information */
  183. Node this;
  184. X
  185. /*
  186. X * Global array to save message header
  187. X */
  188. #define MAXHEADERS 50
  189. X
  190. char *headers[MAXHEADERS];
  191. X
  192. X
  193. X
  194. /*
  195. X * get_header() --- Get specific message header from headers[]
  196. X *
  197. X * Example:
  198. X *   To: mj@hippo.uucp (Martin Junius)
  199. X * Use:
  200. X *   get_header("To") -> "mj@hippo.uucp (Martin Junius)"
  201. X */
  202. X
  203. char *get_header(name)
  204. char *name;
  205. {
  206. register int i, len;
  207. X
  208. X    len = strlen(name);
  209. X    for(i=0; i<MAXHEADERS && headers[i]; i++)
  210. X        if(!strncmp(headers[i], name, len) && headers[i][len]==':')
  211. X            return(headers[i] + strlen(name) + 2);        /* +2 for ": " */
  212. X    return(NULL);
  213. }
  214. X
  215. X
  216. X
  217. /*
  218. X * Extract address/name from `From:', `Reply-To:' or `To:' field.
  219. X * Understood formats:
  220. X *     full name <address>
  221. X *     address (full name)
  222. X *     address
  223. X */
  224. X
  225. void get_address(field, address)
  226. char *field, *address;
  227. {
  228. register char *cp, *np;
  229. X
  230. X    if ((cp = strchr(field, '(')) && strchr(cp + 1, ')')) {
  231. X        /* format is 'address (full name)' */
  232. X        for (np = field; np < cp - 1; np++)
  233. X            *address++ = *np;
  234. X        *address = 0;
  235. X    }
  236. X    else if ((cp = strchr(field, '<')) && (np = strchr(cp + 1, '>'))) {
  237. X        /* format is 'full name <address>' */
  238. X        cp++;
  239. X        while (cp < np)
  240. X            *address++ = *cp++;
  241. X        *address = 0;
  242. X    }
  243. X    else
  244. X        /* line contains only address */
  245. X        strcpy(address, field);
  246. }
  247. X
  248. void get_name(field, name)
  249. char *field;
  250. char *name;
  251. {
  252. register char *cp, *np;
  253. X
  254. X    if ((cp = strchr(field, '(')) && (np = strchr(cp + 1, ')'))) {
  255. X        /* format is 'address (full name)' */
  256. X        for(cp++; *cp && cp<np; cp++)
  257. X            *name++ = *cp;
  258. X        *name= 0;
  259. X    }
  260. X    else if ((cp = strchr(field, '<')) && (np = strchr(cp + 1, '>'))) {
  261. X        /* format is 'full name <address>' */
  262. X        for(cp=field; *cp && *cp!='<' && *(cp+1)!='<'; cp++)
  263. X            *name++ = *cp;
  264. X        *name = 0;
  265. X    }
  266. X    else
  267. X        /* line contains only address */
  268. X        *name = 0;
  269. }
  270. X
  271. X
  272. X
  273. /*
  274. X * Get return address for returning undeliverable mail to sender.
  275. X * Extract it from Reply-To: or From: fields.
  276. X */
  277. X
  278. void
  279. get_return_address(address)
  280. char *address;
  281. {
  282. char buffer[BUFSIZ];
  283. char *field;
  284. X
  285. X    *address = 0;
  286. X
  287. X    /* check is there is Reply-To: field */
  288. X    if(field = get_header("Reply-To")) {
  289. X        get_address(field, address);
  290. X        return;
  291. X    }
  292. X
  293. X    /* no Reply-To:, check for From: */
  294. X    if(field = get_header("From")) {
  295. X        get_address(field, address);
  296. X        return;
  297. X    }
  298. X
  299. X    /* not found, send it to root */
  300. X    strcpy(address, "root");
  301. }
  302. X
  303. X
  304. X
  305. /*
  306. X * Open stream associated with programs standard input. Program is invoked
  307. X * with given argument list. Popen(3S) would invoke mailer thru sh(1),
  308. X * so this uses less memory and is faster.
  309. X */
  310. X
  311. FILE *open_mailer(program, args, pid)
  312. char *program, **args;
  313. int *pid;
  314. {
  315. FILE *fp;
  316. int fd[2];
  317. X
  318. X    /* create pipe */
  319. X    if (pipe(fd) == -1) {
  320. X        perror("rfmail: pipe");
  321. X        exit(EX_OSERR);
  322. X    }
  323. X
  324. X    switch (*pid = fork()) {
  325. X        case -1:                                /* Error */
  326. X            perror("rfmail: fork failed");
  327. X            exit(EX_OSERR);
  328. X        case 0:                                    /* Child */
  329. X            (void) close(0);
  330. X            if (dup(fd[0]) == 0) {
  331. X                (void) close(fd[0]);
  332. X                (void) close(fd[1]);
  333. X                (void) execvp(program, args);
  334. X                perror(program);
  335. X            }
  336. X            else
  337. X                perror("rfmail: dup");
  338. X            exit(EX_OSERR);
  339. X        default:                                /* Parent */
  340. X            (void) close(fd[0]);
  341. X            if ((fp = fdopen(fd[1], "w")) == NULL) {
  342. X                perror("rfmail: fdopen");
  343. X                exit(EX_OSERR);
  344. X            }
  345. X    }
  346. X    return fp;
  347. }
  348. X
  349. X
  350. X
  351. /*
  352. X * In case of error send mail back to sender.
  353. X * First argument is file pointer for mail file, the following
  354. X * are format string and args for printf().
  355. X */
  356. X
  357. /**VARARGS**/
  358. void sendback(va_alist)
  359. va_dcl
  360. {
  361. va_list args;
  362. FILE *mail;
  363. char *fmt;
  364. X
  365. #ifdef RETURN_FAILED_MAIL
  366. FILE *mailer;
  367. char to[128];
  368. char *argv[3];
  369. int pid;
  370. char buffer[BUFSIZ];
  371. int i;
  372. #endif /* RETURN_FAILED_MAIL */
  373. X
  374. X    va_start(args);
  375. X    mail = va_arg(args, FILE *);
  376. X    fmt = va_arg(args, char *);
  377. X
  378. #ifdef RETURN_FAILED_MAIL
  379. X    get_return_address(to);
  380. X    log("Mail failed, return to %s", to);
  381. X
  382. X    argv[0] = RMAIL;
  383. X    argv[1] = to;
  384. X    argv[2] = NULL;
  385. X    mailer = open_mailer(RMAIL, argv, &pid);
  386. X    if(!mailer) {
  387. X        log("$Unable to invoke mailer for returned mail");
  388. X        va_end(args);
  389. X        return;
  390. X    }
  391. X
  392. X    /* print correct header for mailer */
  393. X    fprintf(mailer, "From rfmail %s\n", date("%a %h %d %T 19%y", (long *) 0));
  394. X    fprintf(mailer, "Received: by %s (%s/%s)\n",
  395. X                    internode(this), PROGRAMNAME, this.name);
  396. X    fprintf(mailer, "\tid AA%05d; %s\n", getpid(),
  397. X                    date("%a, %d %h %y %T %o (%z)", (long *) 0));
  398. X    fprintf(mailer, "Date: %s\n", date("%a, %d %h %y %T %o", (long *) 0));
  399. X    fprintf(mailer, "From: Gateway to FIDONet <%s@%s>\n",
  400. X                    "rfmail", internode(this));
  401. X    fprintf(mailer, "Subject: Returned mail: Unable to deliver mail to FIDONet\n");
  402. X    fprintf(mailer, "Message-Id: <%s.AA%05d@%s>\n",
  403. X                    date("%y%m%q%H%M", (long *) 0), getpid(),
  404. X                    internode(this));
  405. X    fprintf(mailer, "To: %s\n", to);
  406. X    fprintf(mailer, "\n");
  407. X    fprintf(mailer, "  ----- Transcript of session follows -----\n");
  408. X    vfprintf(mailer, fmt, args);
  409. X    fprintf(mailer, "\n\n");
  410. X    fprintf(mailer, "  ----- Unsent message follows -----\n");
  411. X
  412. X    /* Copy removed header line */
  413. X    for(i=0; i<MAXHEADERS && headers[i]; i++)
  414. X        fprintf(mailer, "%s\n", headers[i]);
  415. X    fprintf(mailer, "\n");
  416. X
  417. X    /* now copy the message to mailer */
  418. X    rewind(mail);
  419. X    while (fgets(buffer, BUFSIZ, mail))
  420. X        fputs(buffer, mailer);
  421. X
  422. X    /* mail is now sent, close mailer */
  423. X    fclose(mailer);
  424. X
  425. #else /**!RETURN_FAILED_MAIL**/
  426. X    mail = va_arg(args, FILE*);
  427. X    fmt = va_arg(args, char *);
  428. X
  429. X    vfprintf(stderr, fmt, args);
  430. #endif /* not RETURN_FAILED_MAIL */
  431. X
  432. X    va_end(args);
  433. }
  434. X
  435. X
  436. X
  437. /* Check that net/node exists and mail can be send to there (ie. it
  438. X   is not down or in hold). Also be will replace name with sysop's name,
  439. X   if mail is for sysop (note that alias will override this sysop-name).
  440. X   Mail will be send back to sender, if this checking fails. */
  441. X
  442. int
  443. valid_netnode(name, node, mail)
  444. X     char *name;
  445. X     Node node;
  446. X     FILE *mail;
  447. {
  448. #ifdef NODELIST_SUPPORT
  449. X  Node *entry;
  450. X
  451. X  if (entry = node_entry(node))
  452. X    switch (entry->type)
  453. X      {
  454. X      case HOLD:
  455. X        /* node is in hold */
  456. X        sendback(mail, "Node %s is in hold", ascnode(node));
  457. X        return EX_NOHOST;
  458. X      case DOWN:
  459. X        /* node is down */
  460. X        sendback(mail, "Node %s is currently down", ascnode(node));
  461. X        return EX_NOHOST;
  462. X      default:
  463. X        /* everything was fine */
  464. X        if (!strcmp(name, "sysop") || !strcmp(name, "Sysop"))
  465. X          (void) strcpy(name, entry->sysop);
  466. X        return EX_OK;
  467. X      }
  468. X
  469. X  /* we didn't find node */
  470. X  sendback(mail, "Node %s does not exist", ascnode(node));
  471. X  return EX_NOHOST;
  472. #else
  473. X    return EX_OK;
  474. #endif
  475. }
  476. X
  477. X
  478. X
  479. /*
  480. X * Return sender of mail. Figure it out from From: field or from
  481. X * our uid if it's not administrative uid (e.g. uucp or nuucp).
  482. X * If not there, try $HOME/.fullname, then
  483. X * $HOME/.realname, then
  484. X * environment string NAME.
  485. X * If neither method works, return NULL.
  486. X * If $HOME is not defined, skip both .fullname and .realname
  487. X */
  488. X
  489. char *mail_sender()
  490. {
  491. struct passwd *pwd;
  492. static char name[36];
  493. char buffer[BUFSIZ];
  494. register char *cp, *np;
  495. register int cnt;
  496. Node dummynode;
  497. FILE *fp;
  498. char *from;
  499. X
  500. X    name[35] = 0;
  501. X    buffer[0] = 0;
  502. X    
  503. X    if(from = get_header("From"))
  504. X        strcpy(buffer, from);
  505. X        
  506. X    if(*buffer) {
  507. X        debug(2, "Checking From: field");
  508. X        /*
  509. X         * Parse the name out from From: field. there are basically
  510. X         * two kinds of formats: 'User Name <address>' or
  511. X         * 'address (User Name)'. We'll try to figure it out
  512. X         * which format sender uses.
  513. X         */
  514. X        if ((cp = strchr(buffer, '<')) && (np = strchr(cp, '>'))) {
  515. X            /* Format is 'From: Name <address>' */
  516. X            for(np = buffer,
  517. X                cnt = 0; np < cp - 1 && cnt < 35;
  518. X                np++, cnt++)
  519. X                name[cnt] = *np;
  520. X            name[cnt] = 0;
  521. X            debug(2, "Got name %s, fmt name <address>", name);
  522. X        }
  523. X        else if ((cp = strchr(buffer, '(')) && (np = strchr(cp, ')'))) {
  524. X            /* Format is 'From: address (Name)' */
  525. X            for (cnt = 0, cp++; cp < np && cnt < 35; cp++, cnt++)
  526. X                name[cnt] = *cp;
  527. X            name[cnt] = 0;
  528. X            debug(2, "Got name %s, fmt address (name)", name);
  529. X        }
  530. X        else {
  531. X            debug(5, "Could no find realname in <> or ()");
  532. X            /* Try parse it with parse_address */
  533. X            if (parse_address(buffer, name, &dummynode)) {
  534. X                (void) strncpy(name, buffer, 35);
  535. X                name[35] = 0;
  536. X                debug(2, "No format in From: line, name %s", name);
  537. X            }
  538. X            else {
  539. X                name[35] = 0;
  540. X                debug(2, "Name %s parsed from address", name);
  541. X            }
  542. X        }
  543. X        return name;
  544. X    }
  545. X
  546. X  /* hmm.. no From: field in mail. let's try to figure this problem
  547. X     out some other way. If our uid is some user's uid, we'll use
  548. X     that uid to show user's name, otherwise we'll return NULL. */
  549. X
  550. X  if (getuid() >= USERUID && (pwd = getpwuid( (int) getuid())))
  551. X    {
  552. X      /* There are two commonly used gecos-formats: So called USG
  553. X         format used by System III and System V machines and BSD
  554. X         format used by BSD machines. In USG format name is
  555. X         sandwitched between '-' and '(' characters and in BSD
  556. X         format name is first this in gecos-field up to first comma
  557. X         in it. In many machines there's only name in gecos. */
  558. X
  559. X      if ((cp = strchr(pwd->pw_gecos, '-')) && (np = strchr(cp, '(')))
  560. X        {
  561. X          /* USG format 'stuff-name(stuff)' */
  562. X          for (cnt = 0, cp++; cnt < 35 && cp < np; cp++, cnt++)
  563. X            name[cnt] = *cp;
  564. X          name[cnt] = 0;
  565. X          debug(3, "Got name from USG fmt, name %s", name);
  566. X        }
  567. X      else
  568. X        if (cp = strchr(pwd->pw_gecos, ','))
  569. X          {
  570. X            /* BSD format 'name,stuff...' */
  571. X            for (cp = buffer, cnt = 0; cnt < 35 && *cp != ','; cp++, cnt++)
  572. X              name[cnt] = *cp;
  573. X            name[cnt] = 0;
  574. X            debug(3, "Got name from BSD format, name %s", name);
  575. X          }
  576. X        else
  577. X          if (*pwd->pw_gecos)
  578. X            {
  579. X              /* non-empty gecos, assume that there's only name */
  580. X              (void) strncpy(name, pwd->pw_gecos, 35);
  581. X              name[35] = 0;
  582. X              debug(3, "No fmt in gecos, name %s", name);
  583. X            }
  584. X          else
  585. X            {
  586. X              /* Lazy administrator or user who want's to be anonymous
  587. X                 (or this is some administrative uid with no explanation
  588. X                 which)... We'll use only the username. */
  589. X
  590. X              (void) strncpy(name, pwd->pw_name, 35);
  591. X              /* never heard over 35 char usernames???? I haven't but... */
  592. X              name[35] = 0;
  593. X              debug(3, "No gecos, name = %s");
  594. X            }
  595. X      return name;
  596. X    }
  597. X
  598. X  *buffer = 0;
  599. X  if (cp = getenv("HOME"))
  600. X    {
  601. X      debug(5, "Try .fullname");
  602. X      if (fp = fopen(sprintfs("%s/%s", cp, ".fullname"), "r"))
  603. X    {
  604. X      if (!fgets(buffer, BUFSIZ, fp)) *buffer = 0;
  605. X      fclose(fp);
  606. X      strncpy(name, buffer, 35);
  607. X      if (!strempty(name))
  608. X        {
  609. X          strclean(name);
  610. X          debug(2, "Got name %s from .fullname", name);
  611. X          return name;
  612. X        }
  613. X      else
  614. X        debug(1, "Empty name '%s' in .fullname", name);
  615. X    }
  616. X      debug(5, "Try .realname");
  617. X      if (fp = fopen(sprintfs("%s/%s", cp, ".realname"), "r"))
  618. X    {
  619. X      if (!fgets(buffer, BUFSIZ, fp)) *buffer = 0;
  620. X      fclose(fp);
  621. X      strncpy(name, buffer, 35);
  622. X      if (!strempty(name))
  623. X        {
  624. X          strclean(name);
  625. X          debug(2, "Got name %s from .realname", name);
  626. X          return name;
  627. X        }
  628. X      else
  629. X        debug(1, "Empty name '%s' in .realname", name);
  630. X    }
  631. X    }
  632. X
  633. X  if (cp = getenv("NAME"))
  634. X    {
  635. X      debug(5, "Name defined, use it");
  636. X      strncpy(name, buffer, 35);
  637. X      if (!strempty(name))
  638. X    {
  639. X      strclean(name);
  640. X      debug(2, "Got name %s from environment NAME", name);
  641. X      return name;
  642. X    }
  643. X    }
  644. X
  645. X    debug(2, "No name, uid = %d", getuid());
  646. X
  647. X    return (char *) 0;
  648. }
  649. X
  650. X
  651. X
  652. /* Get net/node information from info. If zone, net, or point are missing,
  653. X   they will be returned as -1TRUE is returned, if
  654. X   everything went fine, otherwise FALSE. */
  655. X
  656. bool
  657. getnode(info, node)
  658. X     char *info;
  659. X     Node *node;
  660. {
  661. X  /* Extract zone information */
  662. X  if (strchr(info, ':'))
  663. X    {
  664. X      for (node->zone = 0; *info != ':'; info++)
  665. X    if (isdigit(*info))
  666. X      node->zone = node->zone * 10 + *info - '0';
  667. X    else
  668. X      {
  669. X        debug(1, "Invalid character in zone '%c' %02x", *info, *info);
  670. X        return FALSE;
  671. X      }
  672. X      info++;
  673. X    }
  674. X  else
  675. X    node->zone = -1;
  676. X
  677. X  /* Extract net information if net is present, otherwise
  678. X     set net to -1. */
  679. X
  680. X  if (strchr(info, '/'))
  681. X    {
  682. X      for (node->net = 0; *info != '/'; info++)
  683. X        if (isdigit(*info))
  684. X          node->net = node->net * 10 + *info - '0';
  685. X        else
  686. X          {
  687. X            debug(1, "Invalid character in net '%c' %02x", *info, *info);
  688. X            return FALSE;
  689. X          }
  690. X      info++;
  691. X    }
  692. X  else
  693. X    node->net = -1;
  694. X
  695. X  /* Exract node information, set to -1 if empty. */
  696. X
  697. X  if (*info)
  698. X    for (node->node = 0; *info && *info != '.'; info++)
  699. X      if (isdigit(*info))
  700. X        node->node = node->node * 10 + *info - '0';
  701. X      else
  702. X        {
  703. X          debug(1, "Invalid characer in node '%c' %02x", *info, *info);
  704. X          return FALSE;
  705. X        }
  706. X  else
  707. X    node->node = -1;
  708. X
  709. X  /* Exract point information, set to -1 if empty. */
  710. X
  711. X  if (*info)
  712. X    for (node->point = 0; *info; info++)
  713. X      if (isdigit(*info))
  714. X        node->point = node->point * 10 + *info - '0';
  715. X      else
  716. X        {
  717. X          debug(1, "Invalid characer in node '%c' %02x", *info, *info);
  718. X          return FALSE;
  719. X        }
  720. X  else
  721. X    node->point = -1;
  722. X
  723. X  debug(2, "Got alias %s", ascnode(*node));
  724. X  return TRUE;
  725. }
  726. X
  727. /* Compare receiver and user in aliasfile. Each line in aliasfile contains
  728. X   alias, optional net/node information separated by commas zero or
  729. X   more times, white space(s) and rest of the line literally to whom
  730. X   mail should be send. Net and node information is format 'net/node'.
  731. X   if net is omitted then every net is counted, if node is omitted,
  732. X   then all nodes in that net. If net is omitted, slash may be left off.
  733. X
  734. X   E.g following are valid aliases:
  735. X
  736. X   tot,504/ Teemu Torma
  737. X   foo Foo Bar
  738. X   sysop,504/1,504/9 System Operator */
  739. X
  740. bool aliascmp(alias, to, node)
  741. char *alias, *to;
  742. Node *node;
  743. {
  744. char buffer[BUFSIZ];
  745. char *cp;
  746. Node anode;
  747. X
  748. X    while (*alias && *alias != ',' && !isspace(*alias) && *to)
  749. X        if (*alias++ != *to++)
  750. X            return FALSE;
  751. X
  752. X    if (isspace(*alias)) /* match */
  753. X        return TRUE;
  754. X
  755. X    if (*alias == ',') {
  756. X        /* copy alias to buffer and terminate the it after first space */
  757. X        strcpy(buffer, alias + 1);
  758. X        for (cp = buffer; *cp; cp++)
  759. X            if (isspace(*cp)) {
  760. X                *cp = 0;
  761. X                break;
  762. X            }
  763. X
  764. X        /* get net/node information from buffer one at the time */
  765. X        for (cp = strtok(buffer, ","); cp; cp = strtok((char *) 0, ",")) {
  766. X            debug(2, "Got node '%s'", cp);
  767. X            if (getnode(cp, &anode)) {
  768. X                if ((anode.zone  == -1 || anode.zone  == node->zone ) &&
  769. X                    (anode.net   == -1 || anode.net   == node->net  ) &&
  770. X                    (anode.node  == -1 || anode.node  == node->node ) &&
  771. X                    (anode.point == -1 || anode.point == node->point)   )
  772. X                    return TRUE;
  773. X                }
  774. X            else
  775. X                return FALSE;
  776. X        }
  777. X    }
  778. X    else
  779. X        debug(1, "Invalid alias, %c is not ',' or white space", *alias);
  780. X
  781. X    return FALSE;
  782. }
  783. X
  784. X
  785. X
  786. /* Return receiver's name. If name is aliased, return it, otherwise
  787. X   return receiver's name. */
  788. X
  789. char *receiver(to, node)
  790. char *to;
  791. Node *node;
  792. {
  793. static char name[36];
  794. char buffer[BUFSIZ];
  795. register int cnt;
  796. register char *cp;
  797. FILE *fp;
  798. int i, c, convert_flag;
  799. X
  800. X    debug(3, "Name for alias checking: %s", to);
  801. X
  802. X    if (fp = fopen(ALIAS, "r")) {
  803. X        while (fgets(buffer, BUFSIZ, fp)) {
  804. X            buffer[strlen(buffer) - 1] = 0;
  805. X            if (*buffer != '#')
  806. X                debug(3, "Checking for alias %s", buffer);
  807. X            if (*buffer != '#' && aliascmp(buffer, to, node)) {
  808. X                /* match, save the alias. */
  809. X                for (cp = buffer; *cp && !isspace(*cp); cp++)
  810. X                    /* skip alias itself */;
  811. X                while (isspace(*cp))
  812. X                    cp++;
  813. X                if (*cp) {
  814. X                    for (cnt = 0; *cp && cnt < 35; cnt++, cp++)
  815. X                        name[cnt] = *cp;
  816. X                    name[cnt] = 0;
  817. X                    debug(2, "Got alias %s", name);
  818. X                    fclose(fp);
  819. X                    return name;
  820. X                }
  821. X                else
  822. X                    debug(1, "Missing alias");
  823. X            }
  824. X        }
  825. X        fclose(fp);
  826. X    }
  827. X    else
  828. X        log("$Unable to open aliasfile %s", ALIAS);
  829. X
  830. X    /*
  831. X     * Alias not found. Return the the original receiver with all
  832. X     * '_' characters replaced by space and all words capitalized.
  833. X     */
  834. X    convert_flag = isupper(*to) ? -1 : 1;
  835. X    for(i=0; *to && i<35; i++, to++) {
  836. X        c = *to;
  837. X        switch(c) {
  838. X            case '_':
  839. X                name[i] = ' ';
  840. X                if(!convert_flag)
  841. X                    convert_flag = 1;
  842. X                break;
  843. X            case '%':
  844. X                if(convert_flag != -1)
  845. X                    convert_flag = 2;
  846. X                /**Fall thru**/
  847. X            default:
  848. X                if(convert_flag > 0) {
  849. X                    name[i] = islower(c) ? toupper(c) : c;
  850. X                    if(convert_flag == 1)
  851. X                        convert_flag = 0;
  852. X                }
  853. X                else
  854. X                    name[i] = c;
  855. X                break;
  856. X        }
  857. X    }
  858. X    name[i] = 0;
  859. X
  860. X    debug(2, "No alias, name %s", name);
  861. X    return name;
  862. }
  863. X
  864. X
  865. X
  866. /*
  867. X * Return from field for FIDO message.
  868. X * Alias checking is done via receiver().
  869. X */
  870. X
  871. char *mail_receiver(address, node)
  872. char *address;
  873. Node *node;
  874. {
  875. char *cp;
  876. int found = 0;
  877. char name[36];
  878. char realname[36];
  879. char addr[128];
  880. char *to;
  881. Node dummy;
  882. X
  883. X    realname[0] = 0;
  884. X
  885. X    if(address) {
  886. X        /*
  887. X         * Address is argument
  888. X         */
  889. X        debug(2, "Address to parse: %s", address);
  890. X        if(cp = parse_address(address, name, node)) {
  891. X            log("Parse failed: %s", cp);
  892. X            return NULL;
  893. X        }
  894. X    }
  895. X    else {
  896. X        /*
  897. X         * Address is echo feed
  898. X         */
  899. X        node->zone  = MY_ZONE;
  900. X        node->net   = ECHOFEED_NET;
  901. X        node->node  = ECHOFEED_NODE;
  902. X        node->point = 0;
  903. X        strcpy(name, "All");
  904. X    }
  905. X        
  906. X    /*
  907. X     * Try to look up a better real name in header fields
  908. X     *
  909. X     * Standard RFC822 header line
  910. X     */
  911. X    if(to = get_header("To")) {
  912. X        debug(2, "Checking To: field");
  913. X        get_address(to, addr);
  914. X        if(!address || !strcmp(address, addr)) {
  915. X            get_name(to, realname);
  916. X            found = 1;
  917. X        }
  918. X    }
  919. X
  920. X    /*
  921. X     * User-defined header line for gateway software
  922. X     * (can be patched into news reader)
  923. X     */
  924. X    if(!found && (to = get_header("Comment-To"))) {
  925. X        debug(2, "Checking Comment-To: field");
  926. X        get_address(to, addr);
  927. X        if(!address || !strcmp(address, addr)) {
  928. X            get_name(to, realname);
  929. X            found = 1;
  930. X        }
  931. X    }
  932. X    
  933. X    /*
  934. X     * Header generated by nn's `r' command
  935. X     */
  936. X    if(!found && (to = get_header("Orig-To"))) {
  937. X        debug(2, "Checking Orig-To: field");
  938. X        get_address(to, addr);
  939. X        if(!address || !strcmp(address, addr)) {
  940. X            get_name(to, realname);
  941. X            found = 1;
  942. X        }
  943. X    }
  944. X    
  945. X    /*
  946. X     * News message: get name from address taken out of header line
  947. X     */
  948. X    if(found && !address)
  949. X        parse_address(addr, name, &dummy);
  950. X        
  951. X    /*
  952. X     * Use real name from header line, if no special addressing with '%'
  953. X     */
  954. X    if(found && !strchr(name, '%') && *realname)
  955. X        strcpy(name, realname);
  956. X    
  957. X    return receiver(name, node);
  958. }
  959. X
  960. X
  961. X
  962. /*
  963. X * Get date field for FIDO message. Look for `Date:' header or use
  964. X * current time.
  965. X */
  966. X
  967. char *fido_date()
  968. {
  969. time_t timevar;
  970. struct tm *localtime();
  971. struct tm *mtime;
  972. static char timebuf[20];
  973. /* literal months */
  974. static char *months[] = {
  975. X    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  976. X    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  977. X    (char *) 0,
  978. };
  979. /* Literal weekdays */
  980. static char *wkdays[] = {
  981. X    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", (char *) 0,
  982. };
  983. char *header_date;
  984. X
  985. X    if(header_date = get_header("Date")) {
  986. X        /* try to extract date and other information from it */
  987. X        debug(2, "Found date: '%s'", header_date);
  988. X        timevar = getdate(header_date, NULL);
  989. X    }
  990. X    else
  991. X        timevar = time(0);
  992. X
  993. X    debug(2, "timevar %ld", timevar);
  994. X    mtime = localtime(&timevar);
  995. X    /* Save date in FTS-0001 format ! */
  996. X    sprintf(timebuf, "%02d %3s %02d  %02d:%02d:%02d",
  997. X                     mtime->tm_mday, months[mtime->tm_mon], mtime->tm_year,
  998. X                     mtime->tm_hour, mtime->tm_min, mtime->tm_sec            );
  999. X    debug(1, "Returning %s", timebuf);
  1000. X    return timebuf;
  1001. }
  1002. X
  1003. X
  1004. X
  1005. char *estrtok(s, sep)
  1006. char *s, *sep;
  1007. {
  1008. X    char *p;
  1009. X
  1010. X    if (p = strtok(s, sep))
  1011. X        return p;
  1012. X    return "";
  1013. }
  1014. X
  1015. X
  1016. X
  1017. /*
  1018. X * Output mail/news messages into spool file(s) for fpack
  1019. X */
  1020. X
  1021. #define NGROUPS            10
  1022. #define NFIDO            6
  1023. X
  1024. #define FIDO_NODE        0
  1025. #define FIDO_TO            1
  1026. #define FIDO_FROM        2
  1027. #define FIDO_SUBJECT    3
  1028. #define FIDO_DATE        4
  1029. #define FIDO_FLAGS        5
  1030. X
  1031. int send_mail(fp, to)
  1032. FILE *fp;                                /* Temporary file message body */
  1033. char *to;                                /* Adress to send to (news = NULL) */
  1034. {
  1035. char buffer[BUFSIZ];
  1036. char groups[BUFSIZ];
  1037. char *group[NGROUPS];
  1038. Node node;
  1039. char *p;
  1040. char *fido_header[NFIDO];
  1041. char *area;
  1042. char *newsgroup;
  1043. FILE *fpareas;
  1044. int status;
  1045. int i;
  1046. X
  1047. X    if(to)
  1048. X        debug(1, "Sending mail to %s", to);
  1049. X    else
  1050. X        debug(1, "Sending news");
  1051. X
  1052. X    /*
  1053. X     * Get to/from/node/subject/date
  1054. X     */
  1055. X    fido_header[FIDO_TO]      = mail_receiver(to, &node);
  1056. X    if(!fido_header[FIDO_TO]) {
  1057. X        sendback(fp, "Illegal address %s", to);
  1058. X        return(EX_NOHOST);
  1059. X    }
  1060. X
  1061. X    fido_header[FIDO_FROM]    = mail_sender();
  1062. X    if(!fido_header[FIDO_FROM])
  1063. X        fido_header[FIDO_FROM] = "Gateway to FIDONET";
  1064. X
  1065. X    fido_header[FIDO_NODE]    = ascnode(node);
  1066. X
  1067. X    fido_header[FIDO_SUBJECT] = get_header("Subject");
  1068. X    if(!fido_header[FIDO_SUBJECT])
  1069. X        fido_header[FIDO_SUBJECT] = "Mail from Gateway to FIDONET";
  1070. X    
  1071. X    fido_header[FIDO_DATE]    = fido_date();
  1072. X    
  1073. X    fido_header[FIDO_FLAGS]   = get_header("X-Flags");
  1074. X    if(!fido_header[FIDO_FLAGS])
  1075. X        fido_header[FIDO_FLAGS] = "";
  1076. X
  1077. X    debug(2, "FIDO Node:    %s", fido_header[FIDO_NODE]);
  1078. X    debug(2, "FIDO To:      %s", fido_header[FIDO_TO]);
  1079. X    debug(2, "FIDO From:    %s", fido_header[FIDO_FROM]);
  1080. X    debug(2, "FIDO Subject: %s", fido_header[FIDO_SUBJECT]);
  1081. X    debug(2, "FIDO Date:    %s", fido_header[FIDO_DATE]);
  1082. X    debug(2, "FIDO Flags:   %s", fido_header[FIDO_DATE]);
  1083. X
  1084. X    if(newsmode) {
  1085. X        /*
  1086. X         * News message: get newsgroups and convert to FIDO areas
  1087. X         */
  1088. X        p = get_header("Newsgroups");
  1089. X        if(!p) {
  1090. X            sendback(fp, "No Newsgroups header in news message");
  1091. X            return(EX_DATAERR);
  1092. X        }
  1093. X        strcpy(groups, p);
  1094. X        debug(3, "Newsgroups '%s'", groups);
  1095. X
  1096. X        for(i=0, p=strtok(groups, ","); p && i<NGROUPS; p=strtok(NULL, ","), i++)
  1097. X            group[i] = p;
  1098. X        for(; i<NGROUPS; i++)
  1099. X            group[i] = NULL;
  1100. X
  1101. X        fpareas = pfopen(LIBDIR, "Areas", "r");
  1102. X        if(!fpareas) {
  1103. X            log("$Can't open areas file");
  1104. X            sendback(fp, "Internal error: can't open file");
  1105. X            return(EX_IOERR);
  1106. X        }
  1107. X
  1108. X        for(i=0; i<NGROUPS && group[i]; i++) {
  1109. X            p = group[i];
  1110. X            debug(3, "Look up newsgroup %s", p);
  1111. X            rewind(fpareas);
  1112. X            while(getcl(buffer, BUFSIZ, fpareas)) {
  1113. X                area      = estrtok(buffer, " \t");
  1114. X                newsgroup = estrtok(NULL,   " \t");
  1115. X                debug(4, "Checking newsgroup %s", newsgroup);
  1116. X                if(!strcmp(newsgroup, p)) {        /* Found */
  1117. X                    debug(4, "Found area %s", area);
  1118. X                    break;
  1119. X                }
  1120. X                area = NULL;
  1121. X            }
  1122. X            if(!area) {
  1123. X                log("No EchoMail area found for newsgroup '%s'", p);
  1124. /*                area = "JUNK"; /**/
  1125. X            }
  1126. X            if(area) {
  1127. X                debug(3, "Sending message to area '%s'", area);
  1128. X                status = send_message(fp, node, fido_header, area);
  1129. X                if(status)
  1130. X                    return(status);
  1131. X            }
  1132. X        }
  1133. X    }
  1134. X    else {
  1135. X        /*
  1136. X         * NetMail message
  1137. X         */
  1138. X        return(send_message(fp, node, fido_header, NULL));
  1139. X    }
  1140. X    
  1141. X    return EX_OK;
  1142. }
  1143. X
  1144. X
  1145. int send_message(fp, node, fido_header, area)
  1146. FILE *fp;
  1147. Node node;
  1148. char *fido_header[];
  1149. char *area;
  1150. {
  1151. char buffer[BUFSIZ];
  1152. FILE *sf;
  1153. char *sfile;
  1154. char *header;
  1155. X
  1156. X    /*
  1157. X     * Open spool file for output
  1158. X     */
  1159. X    sf = fopen(sfile = spoolfile("M."), "w");
  1160. X    if(!sf) {
  1161. X        log("$Unable to open spoolfile %s", sfile);
  1162. X        return(EX_CANTCREAT);
  1163. X    }
  1164. X    
  1165. X    /* set correct permissions for spoolfile and lock it */
  1166. X    chmod(sfile, 0600);
  1167. X    lock(fileno(sf));
  1168. X
  1169. X    /*
  1170. X     * Header for fpack
  1171. X     *     N destination node
  1172. X     *     T destination name
  1173. X     *     F from name
  1174. X     *     S subject
  1175. X     *     D date
  1176. X     *     X flags            (P=private, C=crash)
  1177. X     */
  1178. X    fprintf(sf, "N %s\n", fido_header[FIDO_NODE]);
  1179. X    fprintf(sf, "T %s\n", fido_header[FIDO_TO]);
  1180. X    fprintf(sf, "F %s\n", fido_header[FIDO_FROM]);
  1181. X    fprintf(sf, "S %s\n", fido_header[FIDO_SUBJECT]);
  1182. X    fprintf(sf, "D %s\n", fido_header[FIDO_DATE]);
  1183. X    fprintf(sf, "X %s%s\n", private ? "P" : "", fido_header[FIDO_FLAGS]);
  1184. X    fprintf(sf, "\n");
  1185. X
  1186. X
  1187. X    if(newsmode) {
  1188. X        /*
  1189. X         * Add AREA:... line for echo mail
  1190. X         */
  1191. X        fprintf(sf, "AREA:%s\n", area);
  1192. X    }
  1193. X    else {
  1194. X        /*
  1195. X         * Add IFNA kludges for zone/point addressing
  1196. X         */
  1197. X        if(private && (node.zone != MY_ZONE))
  1198. X            fprintf(sf, "\001INTL %s %s\n", ascnoden(node), ascnoden(this));
  1199. X        if(private && REAL_POINT)
  1200. X            fprintf(sf, "\001FMPT %d\n", REAL_POINT);
  1201. X        if(node.point)
  1202. X            fprintf(sf, "\001TOPT %d\n", node.point);
  1203. X    }
  1204. X    
  1205. X    /*
  1206. X     * Add kludge for MSGID / REPLY
  1207. X     */
  1208. X    if(header = get_header("Message-ID")) {
  1209. X        if(print_msgid(sf, "MSGID", header))
  1210. X            print_local_msgid(sf);
  1211. X        if(header = get_header("References"))
  1212. X            print_msgid(sf, "REPLY", header);
  1213. X        else if(header = get_header("In-Reply-To"))
  1214. X            print_msgid(sf, "REPLY", header);
  1215. X    }
  1216. X    else {
  1217. X        print_local_msgid(sf);
  1218. X        if(header = get_header("In-Reply-To"))
  1219. X            print_msgid(sf, "REPLY", header);
  1220. X    }
  1221. X
  1222. X    /*
  1223. X     * Add some header lines
  1224. X     */
  1225. X    if(header = get_header("From"))
  1226. X        fprintf(sf, "From: %s\n", header);
  1227. X    if(header = get_header("Reply-To"))
  1228. X        fprintf(sf, "Reply-To: %s\n", header);
  1229. X    if(header = get_header("To"))
  1230. X        fprintf(sf, "To: %s\n", header);
  1231. X    if(header = get_header("Cc"))
  1232. X        fprintf(sf, "Cc: %s\n", header);
  1233. X    if(header = get_header("Newsgroups"))
  1234. X        if(strchr(header, ','))                /* Posted to multiple groups */
  1235. X            fprintf(sf, "Newsgroups: %s\n", header);
  1236. X    fprintf(sf, "\n");
  1237. X
  1238. X    /*
  1239. X     * Copy mail file
  1240. X     */
  1241. X    debug(3, "Copying mail");
  1242. X    rewind(fp);
  1243. X    while(fgets(buffer, BUFSIZ, fp))
  1244. X        fputs(buffer, sf);
  1245. X    /*
  1246. X     * Done
  1247. X     */
  1248. X    fclose(sf);
  1249. X    return EX_OK;
  1250. }
  1251. X
  1252. X
  1253. X
  1254. /*
  1255. X * Generate new FIDO kludge: `^AMSGID:' and `^AREPLY:'
  1256. X */
  1257. X
  1258. int print_msgid(fp, name, message_id)
  1259. FILE *fp;
  1260. char *name;
  1261. char *message_id;
  1262. {
  1263. char *id, *host, *p;
  1264. char *savep;
  1265. Node node;
  1266. long atol();
  1267. X
  1268. X    savep = message_id = strsave(message_id);
  1269. X    /*
  1270. X     * Format of message_id is "<identification@host.domain> ..."
  1271. X     * We want the the last one in the chain, which is the message id
  1272. X     * of the article replied to.
  1273. X     */
  1274. X    message_id = strrchr(message_id, '<');
  1275. X    if(!message_id)
  1276. X        goto error;
  1277. X    id   = message_id+1;
  1278. X    host = strchr(message_id, '@');
  1279. X    if(!host)
  1280. X        goto error;
  1281. X    *host++ = 0;
  1282. X    p = strchr(host, '>');
  1283. X    if(!p)
  1284. X        goto error;
  1285. X    *p = 0;
  1286. X    
  1287. X    /*
  1288. X     * First let's test id. If it is entirely numeric, we can use
  1289. X     * it for the 32-bit number in ^AMSGID, else give up.
  1290. X     */
  1291. X    for(p=id; *p; p++)
  1292. X        if(!isdigit(*p))
  1293. X            goto error;
  1294. X    
  1295. X    /*
  1296. X     * Try to interprete host as a FIDO node. If this succeedes
  1297. X     * print out host as <zone>:<net>/<node>[.<point>], else
  1298. X     * print host as we got it from message_id.
  1299. X     */
  1300. X    if(!parseinternode(host, &node))
  1301. X        host = ascnode(node);
  1302. X    fprintf(fp, "\001%s: %s %08lx\n", name, host, atol(id));
  1303. X
  1304. X    free(savep);
  1305. X    return(0);
  1306. X
  1307. error:
  1308. X    free(savep);
  1309. X    return(-1);
  1310. }
  1311. X
  1312. X
  1313. X
  1314. /*
  1315. X * Generate local `^AMSGID:' if none is found in message header
  1316. X */
  1317. X
  1318. print_local_msgid(fp)
  1319. FILE *fp;
  1320. {
  1321. long msgid;
  1322. X
  1323. X    msgid = sequencer(MSGIDSEQ);
  1324. X    fprintf(fp, "\001MSGID: %s %08lx\n", ascnode(this), msgid);
  1325. }
  1326. X
  1327. X
  1328. X
  1329. main(argc, argv)
  1330. int argc;
  1331. char *argv[];
  1332. {
  1333. int cnt, c;
  1334. FILE *mail;
  1335. char buffer[BUFSIZ], tmpfile[L_tmpnam];
  1336. int status = EX_OK;
  1337. char *error;
  1338. Node *node, mynode;
  1339. int header_count;
  1340. X
  1341. X    newsmode = FALSE;
  1342. X
  1343. X    while ((c = getopt(argc, argv, "npvV:")) != EOF)
  1344. X        switch (c) {
  1345. X            case 'n':
  1346. X                /* Set news-mode */
  1347. X                newsmode = TRUE;
  1348. X                private  = FALSE;
  1349. X                break;
  1350. X            case 'v':
  1351. X                /* set more verbosity */
  1352. X                verbose++;
  1353. X                break;
  1354. X            case 'V':
  1355. X                verbose = atoi(optarg);
  1356. X                break;
  1357. X            case 'p':
  1358. X                /* this is not private message */
  1359. X                private  = FALSE;
  1360. X                break;
  1361. X            default:
  1362. X                fprintf(stderr, "%s\n\n", PROGRAMNAME);
  1363. X                fprintf(stderr, "usage: rfmail [-npv] [-V verbose_level] user ...\n\n");
  1364. X                exit(EX_USAGE);
  1365. X                break;
  1366. X        }
  1367. X
  1368. X    /*
  1369. X     * Create temp file for saving standard input and open it
  1370. X     */
  1371. X    tmpnam(tmpfile);
  1372. X    if((mail = fopen(tmpfile, "w+")) == NULL) {
  1373. X        log("$Can not open %s for writing", tmpfile);
  1374. X        exit(EX_CANTCREAT);
  1375. X    }
  1376. X    /* protect mail file */
  1377. X    chmod(tmpfile, 0600);
  1378. X
  1379. X    /*
  1380. X     * Read headers from stdin
  1381. X     */
  1382. X    header_count = 0;
  1383. X    while(fgets(buffer, BUFSIZ, stdin)) {
  1384. X        if(*buffer == '\n')                    /* End of header lines */
  1385. X            break;
  1386. X        if(header_count < MAXHEADERS)
  1387. X            headers[header_count++] = strsaveline(buffer);
  1388. X    }
  1389. X
  1390. X    /*
  1391. X     * Copy remainder of stdin to temporary file
  1392. X     */
  1393. X    while(fgets(buffer, BUFSIZ, stdin))
  1394. X        fputs(buffer, mail);
  1395. X
  1396. X    /*
  1397. X     * If message is for echo mail (-n flag) then add
  1398. X     * tear, origin, seen-by and path line.
  1399. X     */
  1400. X    if(newsmode) {
  1401. X        fprintf(mail, "\n--- %s\n", PROGRAMNAME);
  1402. X        fprintf(mail, " * Origin: %s (%d:%d/%d.%d)\n", ORIGIN,
  1403. X                      REAL_ZONE, REAL_NET, REAL_NODE, REAL_POINT);
  1404. X        fprintf(mail, "SEEN-BY: %d/%d ", MY_NET, MY_NODE);
  1405. X        if(ECHOFEED_NET != MY_NET)
  1406. X            fprintf(mail, "%d/", ECHOFEED_NET);
  1407. X        fprintf(mail,"%d\n", ECHOFEED_NODE);
  1408. X        fprintf(mail, "\001PATH: %d/%d\n", MY_NET, MY_NODE);
  1409. X    }
  1410. X
  1411. #ifdef NODELIST_SUPPORT
  1412. X    /* update nodelist-index if needed */
  1413. X    if (error = update_index()) {
  1414. X        /* there was error while updating nodelist-index */
  1415. X        if (*error == '$')
  1416. X            sendback(mail, "%s: %s", error + 1, strerror(errno));
  1417. X        else
  1418. X            sendback(mail, "%s", error);
  1419. X        exit(EX_SOFTWARE);
  1420. X    }
  1421. #endif
  1422. X
  1423. X    mynode.zone  = REAL_ZONE;
  1424. X    mynode.net   = REAL_NET;
  1425. X    mynode.node  = REAL_NODE;
  1426. X    mynode.point = REAL_POINT;
  1427. X    strcpy(mynode.name, MY_NAME);
  1428. X
  1429. #ifdef NODELIST_SUPPORT
  1430. X    if ((node = node_entry(mynode)) == NULL) {
  1431. X        (void) fprintf(stderr, "Unable to this node from nodelist\n");
  1432. X        log("No %s in nodelist", ascnode(mynode));
  1433. X        exit(EX_SOFTWARE);
  1434. X    }
  1435. #else
  1436. X    node = &mynode;
  1437. #endif
  1438. X    this = *node;
  1439. X
  1440. X
  1441. X    rewind(mail);
  1442. X
  1443. X    if(newsmode)
  1444. X        /*
  1445. X         * Send mail to echo feed for news messages
  1446. X         */
  1447. X        status = send_mail(mail, NULL);
  1448. X    else
  1449. X        /*
  1450. X         * Send mail to addresses from command line args
  1451. X         */
  1452. X        for(cnt = optind; cnt < argc; cnt++)
  1453. X            if((status = send_mail(mail, argv[cnt])) != EX_OK)
  1454. X                break;
  1455. X
  1456. X    /* remove temporary file */
  1457. X    fclose(mail);
  1458. X    unlink(tmpfile);
  1459. X
  1460. X    exit(status);
  1461. }
  1462. SHAR_EOF
  1463. chmod 0644 rfmail.c ||
  1464. echo 'restore of rfmail.c failed'
  1465. Wc_c="`wc -c < 'rfmail.c'`"
  1466. test 34750 -eq "$Wc_c" ||
  1467.     echo 'rfmail.c: original size 34750, current size' "$Wc_c"
  1468. fi
  1469. true || echo 'restore of funcs.c failed'
  1470. echo End of part 3, continue with part 4
  1471. exit 0
  1472.  
  1473. --
  1474.  _____ _____
  1475. |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
  1476. | | | |   | |   Republikplatz 3   DOMAIN:  mju@dfv.rwth-aachen.de
  1477. |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
  1478.