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

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