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

  1. From: mj@dfv.rwth-aachen.de (Martin Junius)
  2. Newsgroups: alt.sources
  3. Subject: FIDOGATE 04/06
  4. Message-ID: <mj.675078457@suntex>
  5. Date: 24 May 91 09:47:37 GMT
  6.  
  7. ---- Cut Here and feed the following to sh ----
  8. #!/bin/sh
  9. # This is part 04 of a multipart archive
  10. # ============= funcs.c ==============
  11. if test -f 'funcs.c' -a X"$1" != X"-c"; then
  12.     echo 'x - skipping funcs.c (File already exists)'
  13. else
  14. echo 'x - extracting funcs.c (Text)'
  15. sed 's/^X//' << 'SHAR_EOF' > 'funcs.c' &&
  16. /*:ts=4*/
  17. /*****************************************************************************
  18. X * FIDOGATE --- Gateway software UNIX <-> FIDO
  19. X *
  20. X * $Id: funcs.c,v 1.8 91/05/21 08:48:10 mj Exp $
  21. X *
  22. X * Miscancelleus functions, logging, sequence numberic etc.
  23. X *
  24. X * $Log:   funcs.c,v $
  25. X * Revision 1.8  91/05/21  08:48:10  mj
  26. X * Less verbose log().
  27. X * 
  28. X * Revision 1.7  90/12/02  21:21:57  mj
  29. X * Changed program header to mention both authors of the original
  30. X * software posted to alt.sources.
  31. X * 
  32. X * Revision 1.6  90/11/05  20:49:53  mj
  33. X * Changed my signature in all program headers.
  34. X * 
  35. X * Revision 1.5  90/11/01  14:33:39  mj
  36. X * Added function xtol()
  37. X * 
  38. X * Revision 1.4  90/10/29  21:19:14  mj
  39. X * Added functions strnicmp() and stricmp().
  40. X * 
  41. X * Revision 1.3  90/09/08  18:45:54  mj
  42. X * Some changes.
  43. X * 
  44. X * Revision 1.2  90/08/12  14:14:09  mj
  45. X * Removed unused code.
  46. X * 
  47. X * Revision 1.1  90/06/28  22:04:15  mj
  48. X * Much rework of the sources, no more hsu.h and other clean up.
  49. X * rmail improved, now handles special XENIX quirks.
  50. X * 
  51. X * Revision 1.0  90/06/21  19:01:04  mj
  52. X * Initial revision
  53. X * 
  54. X *
  55. X *****************************************************************************
  56. X * This version hacked and maintained by:
  57. X *    _____ _____
  58. X *   |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
  59. X *   | | | |   | |   Republikplatz 3   DOMAIN:  mju@dfv.rwth-aachen.de
  60. X *   |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
  61. X *
  62. X * Original version of these programs and files:
  63. X *
  64. X *   Teemu Torma
  65. X *   Heikki Suonsivu   FIDO: 2:504/1   UUCP: ...!mcsun!santra!hsu
  66. X *
  67. X *****************************************************************************/
  68. X
  69. #include "fidogate.h"
  70. X
  71. #include <varargs.h>
  72. #include <unistd.h>
  73. X
  74. #include "shuffle.h"
  75. X
  76. X
  77. /*
  78. X * We supply our own version of the toupper()/tolower()
  79. X * macros, because the exact behaviour of those in
  80. X * <ctype.h> varies among systems.
  81. X */
  82. X
  83. #undef _toupper
  84. #undef _tolower
  85. #undef toupper
  86. #undef tolower
  87. X
  88. #define _toupper(c) ((c)-'a'+'A')
  89. #define _tolower(c) ((c)-'A'+'a')
  90. #define toupper(c)  (islower(c) ? _toupper(c) : (c))
  91. #define tolower(c)  (isupper(c) ? _tolower(c) : (c))
  92. X
  93. X
  94. X
  95. #define labs(n) (((n) < 0l) ? (-(n)) : (n))
  96. X
  97. extern void exit(), perror();
  98. extern long atol();
  99. extern time_t time();
  100. X
  101. X
  102. /***** strnicmp() --- compare n chars of strings ignoring case ***************/
  103. X
  104. int strnicmp(sa, sb, len)
  105. register char *sa, *sb;
  106. int len;
  107. {
  108. X   while(len--)
  109. X       if(tolower(*sa) == tolower(*sb)) {
  110. X           sa++;
  111. X           sb++;
  112. X       }
  113. X       else if(tolower(*sa) < tolower(*sb))
  114. X           return(-1);
  115. X       else
  116. X           return(1);
  117. X   return(0);
  118. }
  119. X
  120. X
  121. X
  122. /***** stricmp() --- compare strings ignoring case ***************************/
  123. X
  124. int stricmp(sa, sb)
  125. register char *sa, *sb;
  126. {
  127. X   while(tolower(*sa) == tolower(*sb)) {
  128. X       if(!*sa)
  129. X           return(0);
  130. X       sa++;
  131. X       sb++;
  132. X   }
  133. X   return(tolower(*sa) - tolower(*sb));
  134. }
  135. X
  136. X
  137. X
  138. /***** xtol() --- convert hex string to long *********************************/
  139. X
  140. long xtol(s)
  141. char *s;
  142. {
  143. long val = 0;
  144. int n;
  145. X
  146. X   while(*s) {
  147. X       n = toupper(*s) - (isalpha(*s) ? 'A'-10 : '0');
  148. X       val = val*16 + n;
  149. X       s++;
  150. X   }
  151. X   return(val);
  152. }
  153. X
  154. X
  155. X
  156. FILE *logfp = NULL;
  157. X
  158. /* Lock file descriptor up to the end. If yur system doesn't have lockf()
  159. X   (also known as locking()), or other region or file locking function
  160. X   or system call, this should be done with lock-files. */
  161. X
  162. int
  163. lock(fd)
  164. X     int fd;
  165. {
  166. #ifdef LOCK_LOCKF
  167. X  return lockf(fd, F_LOCK, 0l);
  168. #else
  169. X  return locking(fd, F_LOCK, 0l);
  170. #endif
  171. }
  172. X
  173. /* Unlock file descriptor up to the end. Routine which calls this should
  174. X   first seek to original position. */
  175. X
  176. int
  177. unlock(fd)
  178. X     int fd;
  179. {
  180. #ifdef LOCK_LOCKF
  181. X  return lockf(fd, F_ULOCK, 0l);
  182. #else
  183. X  return locking(fd, F_ULOCK, 0l);
  184. #endif
  185. }
  186. X
  187. /* Return ascii-date in specified format. If format string is null, return
  188. X   date as date(1) returns it. Format is same than date(1) has, in addition
  189. X   %z, which means timezone name. Clock is the time to convert, if NULL,
  190. X   we'll use current time. */
  191. X
  192. char *
  193. date(fmt, clock)
  194. X     char *fmt;
  195. X     time_t *clock;
  196. {
  197. X  /* names for weekdays */
  198. X  static char *weekdays[] = {
  199. X    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
  200. X  };
  201. X
  202. X  /* names for months */
  203. X  static char *months[] = {
  204. X    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  205. X    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  206. X  };
  207. X
  208. X  static char buffer[80];
  209. X  char *bp = buffer;
  210. X  time_t _clock;
  211. X  struct tm *tm;
  212. X
  213. X  if (!clock)
  214. X    _clock = time((long *) 0);
  215. X  tm = localtime(clock ? clock : &_clock);
  216. X
  217. X  /* if no format string, this is default */
  218. X  if (!fmt)
  219. X    fmt = "%a %h %d %T %z 19%y";
  220. X
  221. X  for (*bp = 0; *fmt; fmt++)
  222. X    switch (*fmt)
  223. X      {
  224. X      case '%':
  225. X        switch (*++fmt)
  226. X          {
  227. X            /* newline */
  228. X          case 'n':
  229. X            *bp++ = '\n';
  230. X            break;
  231. X            /* tabulator */
  232. X          case 't':
  233. X            *bp++ = '\t';
  234. X            break;
  235. X            /* month number 1-12 */
  236. X          case 'm':
  237. X            (void) sprintf(bp, "%02d", tm->tm_mon + 1);
  238. X            while (*bp)
  239. X              bp++;
  240. X            break;
  241. X            /* day of month 1-31 */
  242. X          case 'd':
  243. X            (void) sprintf(bp, "%2d", tm->tm_mday);
  244. X            while (*bp)
  245. X              bp++;
  246. X            break;
  247. X          case 'q':
  248. X            (void) sprintf(bp, "%02d", tm->tm_mday);
  249. X            while (*bp)
  250. X              bp++;
  251. X            break;
  252. X            /* year 00-99 */
  253. X          case 'y':
  254. X            (void) sprintf(bp, "%02d", tm->tm_year);
  255. X            while (*bp)
  256. X              bp++;
  257. X            break;
  258. X            /* date in format YY/MM/DD */
  259. X          case 'D':
  260. X            (void) sprintf(bp, "%02d/%02d/%02d", tm->tm_year,
  261. X                           tm->tm_mon + 1, tm->tm_mday);
  262. X            while (*bp)
  263. X              bp++;
  264. X            break;
  265. X            /* hour 0-23 */
  266. X          case 'H':
  267. X            (void) sprintf(bp, "%02d", tm->tm_hour);
  268. X            while (*bp)
  269. X              bp++;
  270. X            break;
  271. X            /* minutes 0-59 */
  272. X          case 'M':
  273. X            (void) sprintf(bp, "%02d", tm->tm_min);
  274. X            while (*bp)
  275. X              bp++;
  276. X            break;
  277. X            /* seconds 0-59 */
  278. X          case 'S':
  279. X            (void) sprintf(bp, "%02d", tm->tm_sec);
  280. X            while (*bp)
  281. X              bp++;
  282. X            break;
  283. X            /* time in format HH:MM:SS */
  284. X          case 'T':
  285. X            (void) sprintf(bp, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
  286. X                           tm->tm_sec);
  287. X            while (*bp)
  288. X              bp++;
  289. X            break;
  290. X            /* day of year 1-356 */
  291. X          case 'j':
  292. X            (void) sprintf(bp, "%03d", tm->tm_yday + 1);
  293. X            while (*bp)
  294. X              bp++;
  295. X            break;
  296. X            /* weekday 0-6 */
  297. X          case 'w':
  298. X            (void) sprintf(bp, "%d", tm->tm_wday);
  299. X            while (*bp)
  300. X              bp++;
  301. X            break;
  302. X            /* name of weekday 'Mon', 'Tue', ... , 'Sun' */
  303. X          case 'a':
  304. X            (void) strcpy(bp, weekdays[tm->tm_wday]);
  305. X            while (*bp)
  306. X              bp++;
  307. X            break;
  308. X            /* name of month 'Jan', 'Feb', ... , 'Dec' */
  309. X          case 'h':
  310. X            (void) strcpy(bp, months[tm->tm_mon]);
  311. X            while (*bp)
  312. X              bp++;
  313. X            break;
  314. X            /* name of timezone, e.g. EST */
  315. X          case 'z':
  316. X            (void) strcpy(bp, *tzname);
  317. X            while (*bp)
  318. X              bp++;
  319. X            break;
  320. X            /* numeric time zone, e.g. +0200 */
  321. X          case 'o':
  322. X            (void) sprintf(bp, "%c%02ld%02ld", (timezone <= 0l) ? '+' : '-',
  323. X                           (labs(timezone) / (60l * 60l)),
  324. X                           (labs(timezone) % (60l * 60l)));
  325. X            while (*bp)
  326. X              bp++;
  327. X            break;
  328. X          case 'l':
  329. X            /* military time zone, Z = UT, A = -1, M = -12, (J not used),
  330. X               N = +1, Y = +12.. */
  331. X            *bp = (timezone == 0l) ? 'Z' : ((int) (labs(timezone) /
  332. X                                                   (60l * 60l)) +
  333. X                                            ((timezone < 0l) ? 'M' : '@'));
  334. X            if (timezone > 0l && *bp >= 'J')
  335. X              (*bp)++;
  336. X            *++bp = 0;
  337. X            break;
  338. X          default:
  339. X            *bp++ = *fmt;
  340. X            break;
  341. X          }
  342. X        break;
  343. X      default:
  344. X        *bp++ = *fmt;
  345. X        break;
  346. X      }
  347. X
  348. X  *bp = 0;
  349. X  return buffer;
  350. }
  351. X
  352. X
  353. X
  354. /*
  355. X * strerror()  ---  get string from sys_errlist[]
  356. X */
  357. X
  358. char *
  359. strerror(errnum)
  360. int errnum;
  361. {
  362. extern int sys_nerr;
  363. extern char *sys_errlist[];
  364. X
  365. X   if (errnum > 0 && errnum < sys_nerr)
  366. X       return sys_errlist[errnum];
  367. X   return "";
  368. }
  369. X
  370. X
  371. X
  372. /*
  373. X * Log to logfile. If logfile is not open, open it.
  374. X *
  375. X * If first character in format string is '$', print also errno. If external
  376. X * variable verbose is set, logging will be done also to stderr.
  377. X */
  378. X
  379. /**VARARGS**/
  380. void
  381. log(va_alist)
  382. va_dcl
  383. {
  384. va_list args;
  385. char *fmt;
  386. X
  387. X   va_start(args);
  388. X
  389. X   fmt = va_arg(args, char *);
  390. X
  391. X   if(!logfp)
  392. X       if ((logfp = fopen(LOGFILE, "a")) == NULL) {
  393. X           perror("Cannot open log file");
  394. X           return;
  395. X       }
  396. X
  397. X   (void) fprintf(logfp, "%s: ", date("%d %h %y %H:%M", (long *) 0));
  398. X   (void) vfprintf(logfp, *fmt == '$' ? fmt + 1 : fmt, args);
  399. X   if (*fmt == '$')
  400. X       (void) fprintf(logfp, "\n\t\terrno = %d (%s)\n", errno, strerror(errno));
  401. X   else
  402. X       (void) fprintf(logfp, "\n");
  403. X   (void) fflush(logfp);
  404. X
  405. X   /*
  406. X    * if verbose is set, print also to stderr (without date)
  407. X    */
  408. X   if (verbose) {
  409. X       (void) vfprintf(stderr, *fmt == '$' ? fmt + 1 : fmt, args);
  410. X       if (*fmt == '$')
  411. X           (void) fprintf(stderr, "\n\t\terrno = %d (%s)\n", errno, strerror(errno));
  412. X       else
  413. X           (void) fprintf(stderr, "\n");
  414. X       (void) fflush(stderr);
  415. X   }
  416. X
  417. X   va_end(args);
  418. }
  419. X
  420. X
  421. X
  422. /*
  423. X * Debug output. First argument should be number, rest are used arguments
  424. X * for vfprintf(3S). If external variable verbose has equal or greater
  425. X * value than first number, vfprintf(3S) will be used to print other
  426. X * arguments to stderr.
  427. X */
  428. X
  429. /**VARARGS**/
  430. void
  431. debug(va_alist)
  432. va_dcl
  433. {
  434. va_list args;
  435. char *fmt;
  436. int debug_level;
  437. X
  438. X   va_start(args);
  439. X
  440. X   debug_level = va_arg(args, int);
  441. X   fmt = va_arg(args, char *);
  442. X
  443. X   if (debug_level <= verbose) {
  444. X       if (*fmt != '>' && *fmt != '<')
  445. X       (void) vfprintf(stderr, fmt, args);
  446. X       (void) fprintf(stderr, "\n");
  447. X   }
  448. X
  449. X   va_end(args);
  450. }
  451. X
  452. X
  453. X
  454. /* Get next job number. New sequemnt number will be taken from file
  455. X   LIBDIR/seq, which is in ascii-format and new number will be saved
  456. X   back there. */
  457. X
  458. long
  459. job_number()
  460. {
  461. X   return sequencer(JOBSEQ);
  462. }
  463. X
  464. /* General sequencer */
  465. X
  466. long
  467. sequencer(filename)
  468. X     char *filename;
  469. {
  470. X  char seqfile[128], buffer[14];
  471. X  FILE *fp;
  472. X  long seqn = 0;
  473. X
  474. X  (void) sprintf(seqfile, "%s", filename);
  475. X  if ((fp = fopen(seqfile, "r+")) == NULL)
  476. X    {
  477. X      if (errno == ENOENT)
  478. X    {
  479. X      if ((fp = fopen(seqfile, "w+")) == NULL)
  480. X        {
  481. X          log("$Can not create seq-file %s", seqfile);
  482. X          exit(EX_OSFILE);
  483. X        }
  484. X      fputs("1", fp);
  485. X      fclose(fp);
  486. X      if ((fp = fopen(seqfile, "r+")) == NULL)
  487. X        {
  488. X          log("$Can not open new seq-file %s", seqfile);
  489. X          exit(EX_OSFILE);
  490. X        }
  491. X    }
  492. X      else
  493. X    {
  494. X      log("$Can not open seq-file %s", seqfile);
  495. X      exit(EX_OSFILE);
  496. X    }
  497. X    }
  498. X
  499. X  (void) lock(fileno(fp));
  500. X  if (fgets(buffer, 14, fp))
  501. X    seqn = atol(buffer);
  502. X  else
  503. X    seqn = 0; /* This can theoretically fail */
  504. X
  505. X  seqn++;
  506. X  (void) rewind(fp);
  507. X  (void) fprintf(fp, "%ld\n", seqn);
  508. X  (void) unlock(fileno(fp));
  509. X  (void) fclose(fp);
  510. X  return seqn;
  511. }
  512. X
  513. /* Returns current last sequence number */
  514. long
  515. getsequencer(filename)
  516. X     char *filename;
  517. {
  518. X  char seqfile[128], buffer[14];
  519. X  FILE *fp;
  520. X  long seqn = 0;
  521. X
  522. X  (void) sprintf(seqfile, "%s", filename);
  523. X  if ((fp = fopen(seqfile, "r+")) == NULL)
  524. X    {
  525. X      if (errno == ENOENT)
  526. X    {
  527. X      if ((fp = fopen(seqfile, "w+")) == NULL)
  528. X        {
  529. X          log("$Can not create seq-file %s", seqfile);
  530. X          exit(EX_OSFILE);
  531. X        }
  532. X      fputs("1", fp);
  533. X      fclose(fp);
  534. X      if ((fp = fopen(seqfile, "r+")) == NULL)
  535. X        {
  536. X          log("$Can not open new seq-file %s", seqfile);
  537. X          exit(EX_OSFILE);
  538. X        }
  539. X    }
  540. X      else
  541. X    {
  542. X      log("$Can not open seq-file %s", seqfile);
  543. X      exit(EX_OSFILE);
  544. X    }
  545. X    }
  546. X
  547. X  (void) lock(fileno(fp));
  548. X  if (fgets(buffer, 14, fp))
  549. X    seqn = atol(buffer);
  550. X  else
  551. X    seqn = 0; /* This can theoretically fail */
  552. X
  553. X  (void) unlock(fileno(fp));
  554. X  (void) fclose(fp);
  555. X  return seqn;
  556. }
  557. X
  558. /* Get full pathname for spoolfile with new job number. File is in
  559. X   spool directory and contains prefix followed by four digit
  560. X   job number. */
  561. X
  562. char *
  563. spoolfile(prefix)
  564. X     char *prefix;
  565. {
  566. X  static char file[BUFLEN];
  567. X
  568. X  (void) sprintf(file, "%s/%s%08ld", SPOOL, prefix, job_number());
  569. X  return file;
  570. }
  571. X
  572. /* Return basename of s */
  573. X
  574. char *
  575. basename(s)
  576. X     register char *s;
  577. {
  578. X  register char *p = s;
  579. X
  580. X  while (*s)
  581. X    if (*s++ == '/')
  582. X      p = s;
  583. X  return p;
  584. }
  585. X
  586. /* Open file with directory name and filename. */
  587. X
  588. FILE *
  589. pfopen(dir, name, mode)
  590. X     char *dir, *name, *mode;
  591. {
  592. X  char filename[128];
  593. X
  594. X  (void) strcpy(filename, dir);
  595. X  (void) strcat(filename, "/");
  596. X  (void) strcat(filename, name);
  597. X
  598. X  return fopen(filename, mode);
  599. }
  600. X
  601. char *baseit(n)
  602. X     long n;
  603. {
  604. X  static char tab[] =
  605. X    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  606. X  int count = 0;
  607. X
  608. X  SHUFFLEBUFFERS;
  609. X
  610. X  while (n)
  611. X    {
  612. X      tcharp[count] = tab[n % strlen(tab)];
  613. X      n = n / strlen(tab);
  614. X      count++;
  615. X    }
  616. X
  617. X  tcharp[count] = 0;
  618. X  return tcharp;
  619. }
  620. X
  621. /* Create packet name for node given */
  622. X
  623. sprintpacketname(s, node)
  624. X     char *s;
  625. X     Node node;
  626. {
  627. X  sprintf(s, "%s%s.%s.%s", node.point ?
  628. X      sprintfs("%s.", baseit( (long) node.point)) : "",
  629. X      baseit( (long) node.node), baseit( (long) node.net),
  630. X      baseit( (long) node.zone));
  631. }
  632. X
  633. /* Create packet name for inbound xx.xx.xx.xx.num. If point
  634. X   number is 0, don't include it. All numbers are in ~63-base to squeeze
  635. X   them to as small space as possible. It could be more sensible solution
  636. X   to make them directory trees but I would need more time for that. This
  637. X   trick makes finding packets difficult.
  638. X   */
  639. X
  640. sprintipacketname(s, node)
  641. X     char *s;
  642. X     Node node;
  643. {
  644. X  sprintf(s, "%s%s.%s.%s.%s", node.point ?
  645. X      sprintfs("%s.", baseit( (long) node.point)) : "",
  646. X      baseit( (long) node.node), baseit( (long) node.net),
  647. X      baseit( (long) node.zone), baseit(sequencer(IPACKETSEQUENCE)));
  648. }
  649. X
  650. X
  651. X
  652. /*
  653. X * Get line from config file. If *-character is in first column, report
  654. X * EOF, and otherwise return line with comments stripped. This causes
  655. X * effect, that each section in configuration file looks like it's own
  656. X * file. Arguments and return value are the same than with fgets(3S).
  657. X */
  658. X
  659. char *
  660. getcl(buffer, len, fp)
  661. char *buffer;
  662. int len;
  663. FILE *fp;
  664. {
  665. char *cp;
  666. X
  667. X   while (fgets(buffer, len, fp)) {
  668. X       buffer[strlen(buffer) - 1] = 0;
  669. X       if (*buffer == '*')
  670. X           return (char *) NULL;
  671. X       /* everything after #-sign is comment */
  672. X       if (cp = strchr(buffer, '#'))
  673. X           *cp = 0;
  674. X       /* if there's something left, return it */
  675. X       if (*buffer)
  676. X           return buffer;
  677. X   }
  678. X   return (char *) NULL;
  679. }
  680. X
  681. X
  682. X
  683. /* Scan config file to specified section. This mechanism is not very
  684. X   effective, but otherwise it would get too complicated. */
  685. X
  686. void
  687. section(number, config)
  688. X     int number;
  689. X     FILE *config;
  690. {
  691. X  char buffer[BUFLEN];
  692. X
  693. X  (void) rewind(config);
  694. X  while (--number)
  695. X    while (getcl(buffer, BUFLEN, config))
  696. X      /* skip section */;
  697. }
  698. X
  699. /* Get header field from file. */
  700. X
  701. #define MAX_HEADER_LEN 256
  702. X
  703. char *mheader(fp, headername)
  704. X     FILE *fp;
  705. X     char *headername;
  706. {
  707. X  static char header[MAX_HEADER_LEN];
  708. X  long position;
  709. X
  710. X  position = ftell(fp);
  711. X
  712. X  rewind(fp);
  713. X
  714. X  /* Blank line terminates also, there shouldn't be any headers
  715. X     after it any more */
  716. X
  717. X  while (fgets(header, MAX_HEADER_LEN, fp) && *header != '\n')
  718. X    if (!strncmp(header, headername, strlen(headername)))
  719. X      {
  720. X    /* Remove \n at end */
  721. X    header[strlen(header) - 1] = 0;
  722. X    fseek(fp, position, 0);
  723. X    return header + strlen(headername);
  724. X      }
  725. X
  726. X  /* Not found, return empty string */
  727. X
  728. X  fseek(fp, position, 0);
  729. X  return "";
  730. }
  731. SHAR_EOF
  732. chmod 0644 funcs.c ||
  733. echo 'restore of funcs.c failed'
  734. Wc_c="`wc -c < 'funcs.c'`"
  735. test 15896 -eq "$Wc_c" ||
  736.     echo 'funcs.c: original size 15896, current size' "$Wc_c"
  737. fi
  738. # ============= rmail.c ==============
  739. if test -f 'rmail.c' -a X"$1" != X"-c"; then
  740.     echo 'x - skipping rmail.c (File already exists)'
  741. else
  742. echo 'x - extracting rmail.c (Text)'
  743. sed 's/^X//' << 'SHAR_EOF' > 'rmail.c' &&
  744. /*:ts=4*/
  745. /*****************************************************************************
  746. X * FIDOGATE --- Gateway software UNIX <-> FIDO
  747. X *
  748. X * $Id: rmail.c,v 1.12 91/05/07 23:59:33 mj Exp $
  749. X *
  750. X * Replacement for rmail.
  751. X * This program performs two functions:
  752. X * - it checks for mail addressed to the FIDO domain (.fidonet.org)
  753. X *   and passes these messages to rfmail
  754. X * - It does some rudimentary transforming for domain style addresses
  755. X *
  756. X * This is just a small hack. For real mail processing use
  757. X * sendmail or smail, which are much better at those things.
  758. X *
  759. X * $Log:   rmail.c,v $
  760. X * Revision 1.12  91/05/07  23:59:33  mj
  761. X * Uses new function isfido() to determine wheter address is for FIDO or
  762. X * not. Also supports rerouting of UUCP bang addresses to UUCP feed.
  763. X * 
  764. X * Revision 1.11  91/04/28  21:40:55  mj
  765. X * Reroute mail to .uucp also via UUCPFEED.
  766. X * 
  767. X * Revision 1.10  91/03/29  18:13:50  mj
  768. X * Improved routing for new Reply-To: adresses.
  769. X * 
  770. X * Revision 1.9  91/01/05  13:08:58  mj
  771. X * Recognize MY_HOSTNAME.MY_DOMAIN as local address.
  772. X * 
  773. X * Revision 1.8  90/12/09  17:35:50  mj
  774. X * Readdress mail to UUCPFEED. Removed unnessary `GATEWAY' code.
  775. X * 
  776. X * Revision 1.7  90/12/02  21:22:32  mj
  777. X * Changed program header to mention both authors of the original
  778. X * software posted to alt.sources.
  779. X * 
  780. X * Revision 1.6  90/11/05  20:51:06  mj
  781. X * Changed my signature in all program headers.
  782. X * 
  783. X * Revision 1.5  90/07/11  17:57:50  mj
  784. X * Removed an obscure bug while feeding letter to mail receiving
  785. X * process. Once in a while the result was garbage. The cause was
  786. X * that the temporary file was opened by both the parent and the
  787. X * child process. Even if the child never ever does something to
  788. X * this file, this seems to confuse the operating system.
  789. X * 
  790. X * Revision 1.4  90/07/07  17:54:47  mj
  791. X * Improved version. Now rmail is able to get destination address
  792. X * from message header, `To: ...' line. This has been implemented
  793. X * to make rmail work with nn, 'cause this news reader doesn't pass
  794. X * the address as a command line argument to rmail.
  795. X * 
  796. X * Revision 1.3  90/07/01  15:20:37  mj
  797. X * Fixed some bugs in funpack caused by the removal of alloca().
  798. X * No more core dumps, but heaven knows, why it works now. Strange.
  799. X * 
  800. X * Revision 1.2  90/07/01  13:46:12  mj
  801. X * Removed all calls to alloca(). All unsave malloc()'s without
  802. X * checking the returned pointer are now done via xmalloc().
  803. X * Fixed a malloc() error in rmail.
  804. X * 
  805. X * Revision 1.1  90/06/28  22:04:56  mj
  806. X * Much rework of the sources, no more hsu.h and other clean up.
  807. X * rmail improved, now handles special XENIX quirks.
  808. X * 
  809. X * Revision 1.0  90/06/19  18:34:10  mj
  810. X * Initial revision
  811. X * 
  812. X *
  813. X *****************************************************************************
  814. X * This version hacked and maintained by:
  815. X *    _____ _____
  816. X *   |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
  817. X *   | | | |   | |   Republikplatz 3   DOMAIN:  mju@dfv.rwth-aachen.de
  818. X *   |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
  819. X *
  820. X * Original version of these programs and files:
  821. X *
  822. X *   Teemu Torma
  823. X *   Heikki Suonsivu   FIDO: 2:504/1   UUCP: ...!mcsun!santra!hsu
  824. X *
  825. X *****************************************************************************/
  826. X
  827. #include "fidogate.h"
  828. X
  829. X
  830. X
  831. #define PROGRAMNAME "rmail $Revision: 1.12 $"
  832. X
  833. X
  834. X
  835. /*
  836. X * This is special to XENIX:
  837. X * On XENIX, one can't use rmail for sending mail, 'cause this
  838. X * program doesn't generate a correct `From user ...' line for
  839. X * locally created mail. One has to execute /usr/lib/mail/execmail
  840. X * instead. But execmail *always* generates it's own `From ...'
  841. X * line, even if there is already one in the mail. So for mail
  842. X * of remote origin, e.g. those messages created by funpack, one
  843. X * must instruct execmail to handle this right. This can be done
  844. X * with the `-f' flags of execmail, whose argument replaces user
  845. X * in `From user ...' line.
  846. X */
  847. #ifdef M_XENIX
  848. # define EXECMAIL                           /* Use -f from, if neccessary */
  849. # undef  RECVMAIL
  850. # define RECVMAIL "/usr/lib/mail/execmail"  /* Force use of execmail */
  851. #endif
  852. X
  853. X
  854. /* verbosity */
  855. /* int verbose = 3; /**/
  856. int verbose = INIT_VERBOSE; /**/
  857. X
  858. X
  859. X
  860. /*
  861. X * For domain type addresses (name@system):
  862. X *
  863. X * Local adress converting:
  864. X *     user@localhost.localdomain  ->  user
  865. X * [.uucp domain to bang converting:                ]
  866. X * [    user@system.uucp            ->  system!user ] disabled
  867. X * [    user@system                 ->  system!user ]
  868. X * Forward other messages to UUCP feed
  869. X *     user@system.domain          ->  uucpfeed!domain!user
  870. X * UUCP rerouting via UUCP feed
  871. X *     system!user                 ->  uucpfeed!system!user
  872. X */
  873. X
  874. char *process_address(addr)
  875. char *addr;
  876. {
  877. static char hostname[256];
  878. static char address[256];
  879. static char newaddress[256];
  880. char *p;
  881. int len;
  882. int not_uucp = FALSE;
  883. X
  884. X   gethostname(hostname, 20);
  885. X   strcpy(address, addr);
  886. X   debug(3, "Address to process: %s", addr);
  887. X
  888. X   if(p = strchr(address, '@')) {
  889. X       /*
  890. X        * Domain address: name@system.domain
  891. X        *
  892. X        * Isolate user name, p points to system.domain
  893. X        */
  894. X       *p++ = 0;
  895. X       /*
  896. X        * Remove suffix ".uucp"
  897. X        */
  898. X       len = strlen(p);
  899. #if 0
  900. X       if(len>5 && (!strcmp(p+len-5, ".uucp") || !strcmp(p+len-5, ".UUCP")))
  901. X           p[len - 5] = 0;
  902. X       else if(strchr(p, '.'))
  903. #endif
  904. X           not_uucp = TRUE;
  905. X       /*
  906. X        * If addressed to our hostname or full domain name,
  907. X        * just send to user name
  908. X        */
  909. X       if(!strcmp(p, hostname))
  910. X           *p = 0;
  911. X       else {
  912. X           strcat(hostname, MY_DOMAIN);
  913. X           if(!strcmp(p, hostname))
  914. X               *p = 0;
  915. X       }
  916. X       /*
  917. X        * Construct converted address
  918. X        */
  919. X       if(!*p)                             /* Local address */
  920. X           strcpy(newaddress, address);
  921. X       else if(not_uucp)                   /* Address domain via UUCPFEED */
  922. X           sprintf(newaddress, "%s!%s!%s", UUCPFEED, p, address);
  923. X       else                                /* UUCP address */
  924. X           sprintf(newaddress, "%s!%s", p, address);
  925. X       debug(2, "Renamed %s to %s", addr, newaddress);
  926. X       return strsave(newaddress);
  927. X   }
  928. X   else if(strchr(address, '!')) {
  929. X       /*
  930. X        * Bang address: system!user
  931. X        */
  932. X       sprintf(newaddress, "%s!%s", UUCPFEED, address);
  933. X       return strsave(newaddress);
  934. X   }
  935. X   else
  936. X       return strsave(address); 
  937. }
  938. X
  939. X
  940. X
  941. /*
  942. X * Get name from `From user ...' line.
  943. X * Understood format of From line is:
  944. X *     `From USER day mon dd hh:mm:ss [zone] yyyy [remote from SYSTEM]'
  945. X * Destroys contents of buf!
  946. X */
  947. X
  948. char *get_from_name(buf)
  949. char *buf;
  950. {
  951. char *name, *system;
  952. static char from[64];
  953. X
  954. X   name   = "anonymous";                   /* Defaults */
  955. X   system = "";
  956. X
  957. X   buf += 5;                               /* Skip `From ' */
  958. X   if(*buf) {
  959. X       name = buf;
  960. X       while(*buf && *buf!=' ' && *buf!='\t')
  961. X           buf++;
  962. X       if(*buf) {
  963. X           *buf++ = 0;
  964. X           /* Scan for `remote from ' */
  965. X           while(strlen(buf) >= 12)        /* 12 = strlen("remote from") */
  966. X               if(!strncmp(buf, "remote from ", 12)) {     /* gefunden! */
  967. X                   buf += 12;
  968. X                   system = buf;
  969. X                   while(*buf && *buf!=' ' && *buf!='\t' && *buf!='\n')
  970. X                       buf++;
  971. X                   *buf = 0;
  972. X                   break;
  973. X               }
  974. X               else
  975. X                   buf++;
  976. X       }
  977. X   }
  978. X   
  979. X   if(*system) {
  980. X       strcpy(from, system);
  981. X       strcat(from, "!");
  982. X   }
  983. X   else
  984. X       *from = 0;
  985. X   strcat(from, name);
  986. X       
  987. X   return(from);
  988. }
  989. X
  990. X
  991. X
  992. /*
  993. X * get_to_name() --- Get destination address from `To: ...' line
  994. X */
  995. X
  996. char *get_to_name(buffer)
  997. char *buffer;
  998. {
  999. register char *cp, *np;
  1000. register int cnt;
  1001. static char to[64];
  1002. X
  1003. X   buffer += strlen("To: ");
  1004. X   *to = 0;
  1005. X
  1006. X   /*
  1007. X    * Parse the name from `To: ...' line. There are basically
  1008. X    * two formats:
  1009. X    *     `User Name <address>'    or
  1010. X    *     `address (User Name)'
  1011. X    * We'll try to figure it out which format sender uses.
  1012. X    */
  1013. X   if ((cp = strchr(buffer, '<')) && (np = strchr(cp, '>'))) {
  1014. X       /*
  1015. X        * Format is 'From: Name <address>'
  1016. X        */
  1017. X       for(np=cp+1, cnt=0; *np && *np!='>'; np++, cnt++)
  1018. X           to[cnt] = *np;
  1019. X       to[cnt] = 0;
  1020. X   }
  1021. X   else if ((cp = strchr(buffer, '(')) && (np = strchr(cp, ')'))) {
  1022. X       /*
  1023. X        * Format is 'From: address (Name)'
  1024. X        */
  1025. X       for(np=buffer, cnt=0; *np && *np!='(' && !isspace(*np); np++, cnt++)
  1026. X           to[cnt] = *np;
  1027. X       to[cnt] = 0;
  1028. X   }
  1029. X   else {
  1030. X       /*
  1031. X        * Not a recognized format, just copy
  1032. X        */
  1033. X       strncpy(to, buffer, 64);
  1034. X       to[63] = 0;
  1035. X       cnt = strlen(to);
  1036. X       if(to[cnt - 1] == '\n')
  1037. X           to[cnt - 1] = 0;
  1038. X   }
  1039. X   
  1040. X   return( *to ? to : NULL);
  1041. }
  1042. X
  1043. X   
  1044. X
  1045. /*
  1046. X * Open stream associated with programs standard input. Program is invoked
  1047. X * with given argument list. Popen(3S) would invoke mailer thru sh(1),
  1048. X * so this uses less memory and is faster.
  1049. X */
  1050. X
  1051. FILE *
  1052. open_mailer(program, args, pid)
  1053. char *program, **args;
  1054. int *pid;
  1055. {
  1056. FILE *fp;
  1057. int fd[2];
  1058. X
  1059. X   /* create pipe */
  1060. X   if (pipe(fd) == -1) {
  1061. X       perror("rmail: pipe");
  1062. X       exit(EX_OSERR);
  1063. X   }
  1064. X
  1065. X   switch (*pid = fork()) {
  1066. X       case -1:                                /* Error */
  1067. X           perror("rmail: fork failed");
  1068. X           exit(EX_OSERR);
  1069. X       case 0:                                 /* Child */
  1070. X           (void) close(0);
  1071. X           if (dup(fd[0]) == 0) {
  1072. X               (void) close(fd[0]);
  1073. X               (void) close(fd[1]);
  1074. X               (void) execvp(program, args);
  1075. X               perror(program);
  1076. X           }
  1077. X           else
  1078. X               perror("rmail: dup");
  1079. X           exit(EX_OSERR);
  1080. X       default:                                /* Parent */
  1081. X           (void) close(fd[0]);
  1082. X           if ((fp = fdopen(fd[1], "w")) == NULL) {
  1083. X               perror("rmail: fdopen");
  1084. X               exit(EX_OSERR);
  1085. X           }
  1086. X   }
  1087. X   return fp;
  1088. }
  1089. X
  1090. X
  1091. X
  1092. int main(argc, argv)
  1093. int argc;
  1094. char *argv[];
  1095. {
  1096. int cnt;
  1097. char **rargs, **fargs;
  1098. int rrec = 0, frec = 0, rargc = 1, fargc = 1;
  1099. int status = EX_OK;
  1100. FILE *mailer;
  1101. static char buffer[BUFSIZ];
  1102. int stat_loc, pid;
  1103. char *from;
  1104. char *to;
  1105. static char tempname[64];
  1106. FILE *temp;
  1107. int in_header_flag;
  1108. char *addr;
  1109. X
  1110. X   /*
  1111. X    * Allocate memory for argument lists of RECVMAIL and RFMAIL.
  1112. X    * 2 extra pointers are needed, 'cause we eventually insert
  1113. X    * `-f user' for XENIX execmail. 1 more extra pointer for
  1114. X    * address from `To: ...' line.
  1115. X    */
  1116. X   rargs = (char **)xmalloc( (argc + 4) * sizeof(char *) );
  1117. X   fargs = (char **)xmalloc( (argc + 4) * sizeof(char *) );
  1118. X
  1119. X   rargs[0] = RECVMAIL;
  1120. X   fargs[0] = RFMAIL;
  1121. X
  1122. X   /*
  1123. X    * Scan thru receiver list and put all receivers in fidonet in fido-
  1124. X    * mailer's receiver-list and all others in real rmails one. No
  1125. X    * options can be passed to fidomailer thru this, because it would
  1126. X    * be too difficult to determine which one goes to which one and
  1127. X    * there might be same options also. Somehow it's good that fidomailer
  1128. X    * is well hidden under this...
  1129. X    */
  1130. X   for (cnt = 1; cnt < argc; cnt++)
  1131. X       if (*argv[cnt] == '-')
  1132. X           rargs[rargc++] = strsave(argv[cnt]);
  1133. X       else {
  1134. X           if(isfido(argv[cnt])) {
  1135. X               /*
  1136. X                * Mail for FIDO.
  1137. X                */
  1138. X               debug(2, "Argument %d (receiver %d) in fidomailer: %s",
  1139. X                               fargc, frec + 1, argv[cnt]);
  1140. X               fargs[fargc++] = strsave(argv[cnt]);
  1141. X               frec++;
  1142. X           }
  1143. X           else {
  1144. X               /*
  1145. X                * Not a valid FIDO address, so this must be for UUCP.
  1146. X                * In this case process address further to convert
  1147. X                * internet domain address name@system.domain to
  1148. X                * UUCP bang address system!name.
  1149. X                * Beware: result of process_address() may be a FIDO
  1150. X                * address again, so another check is necessary.
  1151. X                */
  1152. X               addr = process_address(argv[cnt]);
  1153. X               if(isfido(addr)) {
  1154. X                   debug(2, "Argument %d (receiver %d) in fidomailer: %s",
  1155. X                                   fargc, frec + 1, addr);
  1156. X                   fargs[fargc++] = addr;
  1157. X                   frec++;
  1158. X               }
  1159. X               else {
  1160. X                   debug(2, "Argument %d (receiver %d) in rmail: %s",
  1161. X                                   rargc, rrec + 1, addr);
  1162. X                   rargs[rargc++] = addr;
  1163. X                   rrec++;
  1164. X               }
  1165. X           }
  1166. X       }
  1167. X
  1168. X   /*
  1169. X    * Open temporary file and copy mail from stdin to there
  1170. X    */
  1171. X   tmpnam(tempname);
  1172. X   temp = fopen(tempname, "w");
  1173. X   if(!temp) {
  1174. X       log("$Can't create temporary file %s", tempname);
  1175. X       exit(1);
  1176. X   }
  1177. X   *buffer = 0;
  1178. X   from = to = NULL;
  1179. X   in_header_flag = TRUE;
  1180. #ifdef EXECMAIL
  1181. X   /*
  1182. X    * Look form `From user ...' line
  1183. X    */
  1184. X   *buffer = 0;
  1185. X   fgets(buffer, BUFSIZ, stdin);
  1186. X   if(!strncmp(buffer, "From ", 5)) {
  1187. X       from = get_from_name(buffer);
  1188. X       debug(3, "from = %s", from);
  1189. X       *buffer = 0;
  1190. X   }
  1191. X   else {
  1192. X       from = NULL;
  1193. X       goto test_header;
  1194. X   }
  1195. #endif
  1196. X   while(fgets(buffer, BUFSIZ, stdin)) {
  1197. test_header:
  1198. X       if(in_header_flag) {
  1199. X           if(*buffer == '\n')
  1200. X               in_header_flag = FALSE;
  1201. X           else if(!strncmp(buffer, "To: ", 4)) {
  1202. X               to = get_to_name(buffer);
  1203. X               debug(3, "to = %s", to);
  1204. X           }
  1205. X       }
  1206. X       fputs(buffer, temp);
  1207. X   }
  1208. X   fclose(temp);
  1209. X
  1210. X   /*
  1211. X    * If no address on command line, then use the one from
  1212. X    * get_to_name()
  1213. X    */
  1214. X   if(!frec && !rrec && to) {
  1215. X       if(isfido(to)) {
  1216. X           debug(2, "Argument %d (receiver %d) in fidomailer: %s",
  1217. X                           fargc, frec + 1, to);
  1218. X           fargs[fargc++] = strsave(to);
  1219. X           frec++;
  1220. X       }
  1221. X       else {
  1222. X           addr = process_address(to);
  1223. X           if(isfido(addr)) {
  1224. X               debug(2, "Argument %d (receiver %d) in fidomailer: %s",
  1225. X                               fargc, frec + 1, addr);
  1226. X               fargs[fargc++] = addr;
  1227. X               frec++;
  1228. X           }
  1229. X           else {
  1230. X               debug(2, "Argument %d (receiver %d) in rmail: %s",
  1231. X                               rargc, rrec + 1, addr);
  1232. X               rargs[rargc++] = addr;
  1233. X               rrec++;
  1234. X           }
  1235. X       }
  1236. X   }
  1237. X
  1238. X   /*
  1239. X    * NULL terminate arument lists
  1240. X    */
  1241. X   rargs[rargc] = NULL;
  1242. X   fargs[fargc] = NULL;
  1243. X
  1244. X
  1245. X   if (rrec) {
  1246. X       /*
  1247. X        * Mail to UUCP, use rmail (or XENIX special: execmail)
  1248. X        */
  1249. X       debug(1, "Mail to UUCP, executing %s", RECVMAIL);
  1250. #ifdef EXECMAIL
  1251. X       /*
  1252. X        * Insert `-f FROM' into argument list of execmail (rargs[])
  1253. X        */
  1254. X       if(from) {
  1255. X           for(cnt=rargc; cnt>=1; cnt--)
  1256. X               rargs[cnt + 2] = rargs[cnt];
  1257. X           rargs[1] = "-f";
  1258. X           rargs[2] = from;
  1259. X           rargc += 2;
  1260. X       }
  1261. #endif /**EXECMAIL**/
  1262. X       /*
  1263. X        * Open mailer and feed letter to it
  1264. X        */
  1265. X        mailer = open_mailer(RECVMAIL, rargs, &pid);
  1266. X        temp = fopen(tempname, "r");
  1267. X        if(!temp) {
  1268. X           log("$Can't open %s again", tempname);
  1269. X           unlink(tempname);
  1270. X           exit(1);
  1271. X        }
  1272. X       while (fgets(buffer, BUFSIZ, temp))
  1273. X           fputs(buffer, mailer);
  1274. X        fclose(mailer);
  1275. X        /*
  1276. X         * Wait for rmail to exit
  1277. X         */
  1278. X       wait(&stat_loc);
  1279. X       if(!status)
  1280. X           status = (stat_loc & 0xff) == 0 ? (stat_loc >> 8) & 0xff : 1;
  1281. X   }
  1282. X
  1283. X   if (frec) {
  1284. X       /*
  1285. X        * Mail to FIDO, use rfmail
  1286. X        */
  1287. X       debug(1, "Mail to FIDO, executing %s", RFMAIL);
  1288. X       /*
  1289. X        * Open mailer and feed letter to it
  1290. X        */
  1291. X        mailer = open_mailer(RFMAIL, fargs, &pid);
  1292. X        temp = fopen(tempname, "r");
  1293. X        if(!temp) {
  1294. X           log("$Can't open %s again", tempname);
  1295. X           unlink(tempname);
  1296. X           exit(1);
  1297. X        }
  1298. X       while (fgets(buffer, BUFSIZ, temp))
  1299. X           fputs(buffer, mailer);
  1300. X        fclose(mailer);
  1301. X        /*
  1302. X         * Wait for rfmail to exit
  1303. X         */
  1304. X       wait(&stat_loc);
  1305. X       if(!status)
  1306. X           status = (stat_loc & 0xff) == 0 ? (stat_loc >> 8) & 0xff : 1;
  1307. X   }
  1308. X   
  1309. X   /*
  1310. X    * Remove temporary file
  1311. X    */
  1312. X   unlink(tempname);
  1313. X
  1314. X   exit(status);
  1315. }
  1316. SHAR_EOF
  1317. chmod 0644 rmail.c ||
  1318. echo 'restore of rmail.c failed'
  1319. Wc_c="`wc -c < 'rmail.c'`"
  1320. test 14095 -eq "$Wc_c" ||
  1321.     echo 'rmail.c: original size 14095, current size' "$Wc_c"
  1322. fi
  1323. # ============= fpack.c ==============
  1324. if test -f 'fpack.c' -a X"$1" != X"-c"; then
  1325.     echo 'x - skipping fpack.c (File already exists)'
  1326. else
  1327. echo 'x - extracting fpack.c (Text)'
  1328. sed 's/^X//' << 'SHAR_EOF' > 'fpack.c' &&
  1329. /*:ts=4*/
  1330. /*****************************************************************************
  1331. X * FIDOGATE --- Gateway software UNIX <-> FIDO
  1332. X *
  1333. X * $Id: fpack.c,v 2.4 91/05/21 08:47:41 mj Exp $
  1334. X *
  1335. X * Create and update fidomail packets. Read mail messages from
  1336. X * spool directory and append them to packet. If packet doesn't
  1337. X * exist already, it will be created.
  1338. X *
  1339. X * $Log:   fpack.c,v $
  1340. X * Revision 2.4  91/05/21  08:47:41  mj
  1341. X * Moved log entry for NetMail to rfmail.
  1342. X * 
  1343. X * Revision 2.3  91/03/29  18:10:14  mj
  1344. X * No log entries for news.
  1345. X * 
  1346. X * Revision 2.2  90/12/09  18:35:27  mj
  1347. X * Rewrote some more code. Now support `X' header line and crash mail.
  1348. X * 
  1349. X * Revision 2.1  90/12/02  21:21:53  mj
  1350. X * Changed program header to mention both authors of the original
  1351. X * software posted to alt.sources.
  1352. X * 
  1353. X * Revision 2.0  90/11/23  21:49:24  mj
  1354. X * Major rewrite of fpack started: no more ugly messing around with
  1355. X * byte order, use machine independent function write_int() instead.
  1356. X * Removed some functions and macros.
  1357. X * 
  1358. X * Revision 1.3  90/11/05  20:49:38  mj
  1359. X * Changed my signature in all program headers.
  1360. X * 
  1361. X * Revision 1.2  90/07/29  18:10:52  mj
  1362. X * Place real net/node in message header for FIDO netmail. Also
  1363. X * a `^AFMPT x' kludge is generated in this case. Recipient of
  1364. X * our mail now gets real address from message, which should
  1365. X * make replying much easier.
  1366. X * 
  1367. X * Revision 1.1  90/06/28  22:04:07  mj
  1368. X * Much rework of the sources, no more hsu.h and other clean up.
  1369. X * rmail improved, now handles special XENIX quirks.
  1370. X * 
  1371. X * Revision 1.0  90/06/19  18:32:01  mj
  1372. X * Initial revision
  1373. X * 
  1374. X *
  1375. X *****************************************************************************
  1376. X * This version hacked and maintained by:
  1377. X *    _____ _____
  1378. X *   |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
  1379. X *   | | | |   | |   Republikplatz 3   DOMAIN:  mju@dfv.rwth-aachen.de
  1380. X *   |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
  1381. X *
  1382. X * Original version of these programs and files:
  1383. X *
  1384. X *   Teemu Torma
  1385. X *   Heikki Suonsivu   FIDO: 2:504/1   UUCP: ...!mcsun!santra!hsu
  1386. X *
  1387. X *****************************************************************************/
  1388. X
  1389. #include "fidogate.h"
  1390. /*
  1391. #include <fcntl.h>
  1392. #include <sys/stat.h>
  1393. */
  1394. X
  1395. X
  1396. #define PROGRAMNAME "fpack $Revision: 2.4 $"
  1397. X
  1398. X
  1399. X
  1400. extern time_t time();
  1401. extern int getopt();
  1402. extern int optind;
  1403. extern char *optarg;
  1404. extern unsigned sleep();
  1405. extern void exit();
  1406. extern void swab();
  1407. X
  1408. Node node;
  1409. int verbose = INIT_VERBOSE;
  1410. X
  1411. X
  1412. X
  1413. /*
  1414. X * Put string to file in null-terminated format.
  1415. X */
  1416. X
  1417. int put_string(fp, s)
  1418. FILE *fp;
  1419. char *s;
  1420. {
  1421. X   while (*s) {
  1422. X       putc(*s, fp);
  1423. X       s++;
  1424. X   }
  1425. X   putc(0, fp);
  1426. }
  1427. X
  1428. X
  1429. X
  1430. /*
  1431. X * Write 16-bit integer in 80x86 format, i.e. low byte first,
  1432. X * then high byte. Machine independent function.
  1433. X */
  1434. X
  1435. int write_int(value, fp)
  1436. int value;
  1437. FILE *fp;
  1438. {
  1439. X   putc(value & 0xff, fp);
  1440. X   putc((value >> 8) & 0xff, fp);
  1441. }
  1442. X
  1443. X
  1444. /*
  1445. X * Copy n-char String, force trailing `\0'
  1446. X */
  1447. X
  1448. char *strncpy0(d, s, n)
  1449. char *d, *s;
  1450. int n;
  1451. {
  1452. char *p;
  1453. X
  1454. X   p = strncpy(d, s, n);
  1455. X   d[n - 1] = 0;
  1456. X   return(p);
  1457. }
  1458. X   
  1459. X
  1460. X
  1461. /*
  1462. X * Write FIDO message header to mail packet. Information is taken
  1463. X * from input message header:
  1464. X *
  1465. X *     N node         Address to send to
  1466. X *     T name         Name of recipient
  1467. X *     F name         Name of sender
  1468. X *     S subject      Subject of message
  1469. X *     D date         Date of message (FTS-0001 format)
  1470. X *     X flags        Message flags: P=private, C=crash
  1471. X */
  1472. X
  1473. int write_hdr(source, packet)
  1474. FILE *source, *packet;
  1475. {
  1476. int private_flag = FALSE;
  1477. char buffer[BUFSIZ];
  1478. char from[SIZE_FROM],
  1479. X    to[SIZE_TO],
  1480. X    subject[SIZE_SUBJECT],
  1481. X    date[SIZE_DATE];
  1482. Node msg_node;
  1483. int attr = 0;
  1484. char *p;
  1485. X
  1486. X   msg_node.zone = msg_node.net = msg_node.node = msg_node.point = -1;
  1487. X
  1488. X   /* clean up from, to and subject */
  1489. X   *from    = 0;
  1490. X   *to      = 0;
  1491. X   *subject = 0;
  1492. X   *date    = 0;
  1493. X
  1494. X   while (fgets(buffer, BUFSIZ, source) && *buffer != '\n') {
  1495. X       buffer[strlen(buffer) - 1] = 0; /* strip newline */
  1496. X       switch(*buffer) {
  1497. X           case 'N':
  1498. X               if (parsefnetaddress(buffer, &msg_node)) {
  1499. X                   log("Invalid destination: %s", buffer);
  1500. X                   return FALSE;
  1501. X               }
  1502. X               break;
  1503. X           case 'F':
  1504. X               strncpy0(from, buffer + 2, SIZE_FROM);
  1505. X               break;
  1506. X           case 'T':
  1507. X               strncpy0(to,   buffer + 2, SIZE_TO);
  1508. X               break;
  1509. X           case 'S':
  1510. X               strncpy0(subject, buffer + 2, SIZE_SUBJECT);
  1511. X               break;
  1512. X           case 'D':
  1513. X               strncpy0(date, buffer + 2, SIZE_DATE);
  1514. X               break;
  1515. X           case 'P':                       /* Old `private' header */
  1516. X               attr |= ATTR_PRIVATE;
  1517. X               private_flag = TRUE;
  1518. X               break;
  1519. X           case 'X':                       /* New flags header */
  1520. X               for(p=buffer+2; *p; p++)
  1521. X                   switch(*p) {
  1522. X                       case 'P':
  1523. X                           attr |= ATTR_PRIVATE;
  1524. X                           private_flag = TRUE;
  1525. X                           break;
  1526. X                       case 'C':
  1527. X                           attr |= ATTR_CRASH;
  1528. X                           break;
  1529. X                   }
  1530. X               break;
  1531. X       }
  1532. X   }
  1533. X
  1534. X   /* Save all header values */
  1535. X   write_int(MSGTYPE, packet);                         /* save msg type */
  1536. X   write_int(private_flag ? REAL_NODE : MY_NODE, packet);/* save our node */
  1537. X   write_int(msg_node.node, packet);                   /* save messages node */
  1538. X   write_int(private_flag ? REAL_NET : MY_NET, packet);/* save our net */
  1539. X   write_int(msg_node.net, packet);                    /* save messages net */
  1540. X   write_int(attr, packet);                            /* save attributes */
  1541. X   write_int(0, packet);                               /* cost, not used by us */
  1542. X   put_string(packet, date);                           /* save time of mail */
  1543. X   put_string(packet, to);                             /* save receiver */
  1544. X   put_string(packet, from);                           /* save sender */
  1545. X   put_string(packet, subject);                        /* save subject */
  1546. X
  1547. X   /* done with this header */
  1548. X   return TRUE;
  1549. }
  1550. X
  1551. X
  1552. X
  1553. /*
  1554. X *  Write packet header for new packet.
  1555. X */
  1556. X
  1557. int write_pkthdr(packet)
  1558. FILE *packet;
  1559. {
  1560. Packet header;
  1561. int count;
  1562. struct tm *tm;
  1563. time_t clock = time((long *) 0);
  1564. X
  1565. X   tm = localtime(&clock);
  1566. X
  1567. X   /* create packet structure */
  1568. X   header.orig_node = MY_NODE;
  1569. X   header.dest_node = node.node;
  1570. X   header.orig_net  = MY_NET;
  1571. X   header.dest_net  = node.net;
  1572. X
  1573. X   /* save time for header (why all these fields?) */
  1574. X   header.year      = tm->tm_year + 1900;
  1575. X   header.month     = tm->tm_mon;
  1576. X   header.day       = tm->tm_mday;
  1577. X   header.hour      = tm->tm_hour + 1;
  1578. X   header.minute    = tm->tm_min;
  1579. X   header.second    = tm->tm_sec;
  1580. X
  1581. X   header.rate      = MAXBAUD;
  1582. X   header.ver       = HDRVER;
  1583. X   header.product   = 0;
  1584. X   header.x1        = 0;
  1585. #ifdef FIDO_V11w
  1586. X   for(count = 0; count < 16; count++)
  1587. X       header.fill[count] = 0;
  1588. #else
  1589. X   for(count = 0; count < 8; count++)
  1590. X       header.pwd_kludge[count] = 0;
  1591. X   header.orig_zone = MY_ZONE;
  1592. X   header.dest_zone = node.zone;
  1593. X   for (count = 0; count < 16; count++)
  1594. X       header.B_fill2[count] = 0;
  1595. X   header.B_fill3 = 0;
  1596. #endif
  1597. X   /* write header to file */
  1598. X   write_int(header.orig_node, packet);
  1599. X   write_int(header.dest_node, packet);
  1600. X   write_int(header.year     , packet);
  1601. X   write_int(header.month    , packet);
  1602. X   write_int(header.day      , packet);
  1603. X   write_int(header.hour     , packet);
  1604. X   write_int(header.minute   , packet);
  1605. X   write_int(header.second   , packet);
  1606. X   write_int(header.rate     , packet);
  1607. X   write_int(header.ver      , packet);
  1608. X   write_int(header.orig_net , packet);
  1609. X   write_int(header.dest_net , packet);
  1610. X   putc(     header.product  , packet);
  1611. X   putc(     header.x1       , packet);
  1612. X   for(count = 0; count < 8; count++)
  1613. X       putc(header.pwd_kludge[count], packet);
  1614. X   write_int(header.orig_zone, packet);
  1615. X   write_int(header.dest_zone, packet);
  1616. X   for(count = 0; count < 16; count++)
  1617. X       putc(header.B_fill2[count], packet);
  1618. X   for(count = 0; count < 4; count++)
  1619. X       putc(header.B_fill3 << (8 * count), packet); /* pc long = 4 bytes! */
  1620. X
  1621. X   if(ferror(packet) || feof(packet)) {
  1622. X       log("$Write error on packet header");
  1623. X       return FALSE;
  1624. X   }
  1625. X
  1626. X   debug(1, "New packet created");
  1627. X
  1628. X   return TRUE;
  1629. }
  1630. X
  1631. X
  1632. X
  1633. int main(argc, argv)
  1634. int argc;
  1635. char *argv[];
  1636. {
  1637. DIR *dp;
  1638. struct dirent *dir;
  1639. FILE *msg, *packet;
  1640. char packet_name[16];
  1641. int c;
  1642. Node np;
  1643. char *error;
  1644. X
  1645. X   node.net = node.zone = -1;
  1646. X  
  1647. X   /* get options */
  1648. X   while ((c = getopt(argc, argv, "vf:")) != EOF)
  1649. X       switch (c) {
  1650. X           case 'f':
  1651. X               if (parsefnetaddress(optarg, &np)) exit(1);
  1652. X               node = np;
  1653. X               break;
  1654. X           case 'v':
  1655. X               verbose++;
  1656. X               break;
  1657. X           default:
  1658. X               fprintf(stderr, "%s\n\n", PROGRAMNAME);
  1659. X               fprintf(stderr, "Usage: fpack [-v] [-f Z:N/N.P]\n\n");
  1660. X               exit(EX_USAGE);
  1661. X       }
  1662. X
  1663. X   /* make sure that we got net/node */
  1664. X   if (node.net == -1 || node.node == -1) {
  1665. X       node.zone  = REM_ZONE;
  1666. X       node.net   = REM_NET;
  1667. X       node.node  = REM_NODE;
  1668. X       node.point = REM_POINT;
  1669. X       strcpy(node.name, REM_NAME);
  1670. X   }
  1671. X
  1672. #if 0
  1673. X  /* try to update nodelist-index */
  1674. X  if (error = update_index())
  1675. X    {
  1676. X      if (*error == '$')
  1677. X        log("$Cannot update nodelist-index: %s", error + 1);
  1678. X      else
  1679. X        log("Cannot update nodelist-index: %s", error);
  1680. X      exit(EX_OSERR);
  1681. X    }
  1682. #endif
  1683. X
  1684. X  /* goto spool directory, everything exiting happens there... */
  1685. X   if (chdir(SPOOL) == -1) {
  1686. X       log("$Can't chdir to %s", SPOOL);
  1687. X       exit(1);
  1688. X   }
  1689. X
  1690. #if 0
  1691. X   /* create packet name */
  1692. X   sprintpacketname(packet_name, node);
  1693. #else
  1694. X   /* MSDOS compatible packet names */
  1695. X   sprintf(packet_name, "%04x%04x.out", node.net, node.node);
  1696. #endif
  1697. X
  1698. X   if (access(sprintfs("out/%s", packet_name), 0) == 0) {
  1699. X       debug(1, "Packet out/%s exists, append to it", packet_name);
  1700. X       if ((packet = fopen(sprintfs("out/%s", packet_name), "r+")) == NULL) {
  1701. X           log("$Can't open out/%s for update", packet_name);
  1702. X           exit(1);
  1703. X       }
  1704. X       fseek(packet, -2L, 2);
  1705. X   }
  1706. X   else {
  1707. X       debug(1, "New packet out/%s", packet_name);
  1708. X       if ((packet = fopen(sprintfs("out/%s", packet_name), "w")) == NULL) {
  1709. X           log("$Can't open out/%s for writing", packet_name);
  1710. X           exit(1);
  1711. X       }
  1712. X       /* protect packet from users...*/
  1713. X       chmod(sprintfs("out/%s", packet_name), 0600);
  1714. X       /* write packet-header, if it fails, exit */
  1715. X       if (!write_pkthdr(packet)) {
  1716. X           unlink(sprintfs("out/%s", packet_name));
  1717. X           exit(1);
  1718. X       }
  1719. X   }
  1720. X
  1721. X   /* lock packet, wait if it's alredy locked */
  1722. X   while (lock(fileno(packet)) == -1 && errno == EAGAIN)
  1723. X       sleep(5);
  1724. X
  1725. X   /* open spool directory */
  1726. X   dp = opendir(".");
  1727. X   if(!dp) {
  1728. X       log("$Can't open spool directory %s", SPOOL);
  1729. X       exit(1);
  1730. X    }
  1731. X   while (dir = readdir(dp)) {
  1732. X       /* check that file is for us */
  1733. X       if(dir->d_name[0]=='M' && dir->d_name[1]=='.') {
  1734. X           msg = fopen(dir->d_name, "r");
  1735. X           if(!msg) {
  1736. X               log("$Can't open mail %s for reading", dir->d_name);
  1737. X               continue;
  1738. X           }
  1739. X           debug(1, "Adding mailfile %s", dir->d_name);
  1740. X
  1741. X           /* save header */
  1742. X           if(write_hdr(msg, packet)) {
  1743. X               /* copy mail text, replace newlines with <cr> <lf> */
  1744. X               while ((c = getc(msg)) && c != EOF) {
  1745. X                   if (c == '\n')
  1746. X                       putc('\r', packet);
  1747. X                   putc(c, packet);
  1748. X               }
  1749. X               /* null-terminate msg text */
  1750. X               putc(0, packet);
  1751. X           }
  1752. X           fclose(msg);
  1753. X           if(unlink(dir->d_name) == -1)
  1754. X               log("$Unable to unlink %s", dir->d_name);
  1755. X       }
  1756. X   }
  1757. X   closedir(dp);
  1758. X
  1759. X   /* msg type 0 indicates end of packet */
  1760. X   write_int(0, packet);
  1761. X
  1762. X   fclose(packet);
  1763. X
  1764. X   exit(0);
  1765. }
  1766. SHAR_EOF
  1767. chmod 0644 fpack.c ||
  1768. echo 'restore of fpack.c failed'
  1769. Wc_c="`wc -c < 'fpack.c'`"
  1770. test 10575 -eq "$Wc_c" ||
  1771.     echo 'fpack.c: original size 10575, current size' "$Wc_c"
  1772. fi
  1773. true || echo 'restore of funpack.c failed'
  1774. echo End of part 4, continue with part 5
  1775. exit 0
  1776.  
  1777. --
  1778.  _____ _____
  1779. |     |___  |   Martin Junius     FIDO:    2:242/6.1   2:242/6.0
  1780. | | | |   | |   Republikplatz 3   DOMAIN:  mj@dfv.rwth-aachen.de
  1781. |_|_|_|_____|   D-5100 Aachen     Tel. (Voice) 0241-86931
  1782.