home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / listserv5.31 / part03 < prev    next >
Encoding:
Internet Message Format  |  1991-12-12  |  39.3 KB

  1. Subject: v25i037: listserv5.31 - mailing list management system, Part03/06
  2. Newsgroups: comp.sources.unix
  3. Approved: vixie@pa.dec.com
  4.  
  5. Submitted-By: tasos@cs.bu.edu
  6. Posting-Number: Volume 25, Issue 37
  7. Archive-Name: listserv5.31/part03
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 3 (of 6)."
  16. # Contents:  src/farch.c src/misc.c
  17. # Wrapped by vixie@cognition.pa.dec.com on Fri Dec 13 18:31:09 1991
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'src/farch.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'src/farch.c'\"
  21. else
  22. echo shar: Extracting \"'src/farch.c'\" \(14750 characters\)
  23. sed "s/^X//" >'src/farch.c' <<'END_OF_FILE'
  24. X/*
  25. X  ----------------------------------------------------------------------------
  26. X  |                        FILE ARCHIVING UTILITY                 |
  27. X  |                                                                          |
  28. X  |                              Version 1.0                                 |
  29. X  |                                                                          |
  30. X  |                (or, when Computer Science gets to you)                   |
  31. X  |                                                                          |
  32. X  |                    Written by Anastasios Kotsikonas                      |
  33. X  |                           (tasos@cs.bu.edu)                              |
  34. X  |                                                                          |
  35. X  | AGREEMENT: This software can be used and distributed freely as long      |
  36. X  | as you do not remove or alter the Copyright notice in the file defs.h;   |
  37. X  | this notice is #define'd in the symbol VERSION. Although you may alter   |
  38. X  | the code provided, you may not alter the functions create_header()       |
  39. X  | and create_multi_recipient_header() in list.c and listserv.c.            |
  40. X  | By using this software you are bound by this agreement.                  |
  41. X  | This software comes with no warranties and cannot be sold for profit.    |
  42. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  43. X  | files when distributing this software.                                   |
  44. X  | COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas                  |
  45. X  ----------------------------------------------------------------------------
  46. X
  47. X  farch archives files into the specified directories, possibly splitting
  48. X  them into smaller parts. It then updates the DIR file of the appropriate
  49. X  archive. Split files have numbers appended to their original names;
  50. X  non-split files have their names intact. Binary files are uuencoded before
  51. X  processed, and all output files are compressed.
  52. X
  53. X  COMMAND LINE OPTIONS:
  54. X    -n: Do not split input files.
  55. X    -t: Tar all input files.
  56. X    -b: Input files are binary; uuencode.
  57. X    -s: Set the maximum size of each of the split subparts in kilobytes.
  58. X    -a: Specify the archive where the input files will be archived.
  59. X    -d: Specify the actual directory that the archived files will reside.
  60. X
  61. X  WARNING: The program can also archive directory files, if these can be
  62. X  of any use.
  63. X
  64. X  Algorithm:
  65. X  {
  66. X    Process command line arguments; allocate buffer_size
  67. X    Open master archive; get path to specified archive
  68. X    Verify existsence of target directory -- create it if necessary
  69. X    Tar files, if so requested
  70. X    for (each input file) {
  71. X      open
  72. X      get filesize
  73. X      if (-b)
  74. X    uuencode file
  75. X      if (-n or filesize <= buffer_size) { -- Do not split --
  76. X    if (-b)
  77. X      copy uuencoded file into target directory
  78. X    else if (file does not exist in target directory)
  79. X      copy it to target directory
  80. X      compress it
  81. X    update (archive's directory)
  82. X      }
  83. X      else split file {
  84. X    while (not eof) {
  85. X      get unique output filename
  86. X      fwrite (leftover bytes from previous chunk)
  87. X      fread (new chunk)
  88. X      if (! -b) {
  89. X        locate nearest newline from the end of the buffer
  90. X        copy those skipped bytes to leftover
  91. X      }
  92. X      fwrite (new modified chunk)
  93. X      compress it
  94. X    }
  95. X    fwrite (any leftovers)
  96. X    compress part
  97. X    update (archive's directory)
  98. X      }
  99. X    }
  100. X  }
  101. X*/
  102. X
  103. X#include <stdio.h>
  104. X#include <malloc.h>
  105. X#include <sys/types.h>
  106. X#include <sys/stat.h>
  107. X#include "defs.h"
  108. X#include "struct.h"
  109. X#include "listserv.h"
  110. X
  111. X#define DEFAULT_SIZE    64 * 1024
  112. X#define UUE_FILE    "/tmp/uue"
  113. X
  114. extern char *extract_filename (char *);
  115. extern char *locase (char *);
  116. void   main (int , char **);
  117. void   uuencode (FILE **, char *, char *, struct stat *, BOOLEAN);
  118. void   update (char *, char *, int, char *);
  119. void   usage (void);
  120. void   do_archive (int, int, char **, char *, char *, char *, char *, long int,
  121. X                   BOOLEAN, BOOLEAN, BOOLEAN);
  122. int    get_archive (char **, char *);
  123. int    get_dir (char *, char **, char *);
  124. int    tar_files (int, int, char **, char *);
  125. X
  126. SYS sys; /* Bogus */
  127. COMMANDS commands [MAX_COMMANDS]; /* Bogus */
  128. X
  129. void main (int argc, char **argv)
  130. X{
  131. X  long int size = DEFAULT_SIZE;
  132. X  char *buf, *arch = NULL, *newdir = NULL, *dir, fullpath[256],
  133. X       *tarf, *options = "nbs:a:d:t:u";
  134. X  int c;
  135. X  BOOLEAN bin = FALSE, tar = FALSE, split = TRUE;
  136. X  extern char *optarg;
  137. X  extern int optopt, optind;
  138. X
  139. X  buf = (char *) malloc (size * sizeof (char));
  140. X  dir = (char *) malloc (sizeof (char));
  141. X  while ((c = getopt (argc, argv, options)) != EOF)
  142. X    switch ((char) c) {
  143. X    case 'n': split = 0; break;
  144. X    case 't': tar = TRUE; tarf = optarg;
  145. X    case 'b': bin = TRUE; break;
  146. X    case 's': size = (long) atol (optarg) * 1024;
  147. X                if (size <= 0)
  148. X                fprintf (stderr, "How am I supposed to allocate %ld bytes?\n",
  149. X                         size),
  150. X                exit (2);
  151. X              free ((char *) buf);
  152. X              if ((buf = (char *) malloc (size * sizeof (char))) == NULL)
  153. X                fprintf (stderr, "Size too big; not enough memory.\n"),
  154. X                exit (1);
  155. X              break;
  156. X    case 'a': arch = locase (optarg); break;
  157. X    case 'd': newdir = optarg;
  158. X              if (*newdir != '/')
  159. X                fprintf (stderr, "Must specify full path for the directory.\n"),
  160. X                exit (1);
  161. X              break;
  162. X    case 'u': usage ();
  163. X    case ':': fprintf (stderr, "Option '%c' requires an argument.\n", optopt);
  164. X              exit (2);
  165. X    case '?':
  166. X    default:
  167. X      fprintf (stderr, "Unrecognized option '%c'.\n", optopt);
  168. X      usage ();
  169. X    }
  170. X
  171. X  if (optind == argc)
  172. X    goto abort;
  173. X  if (get_archive (&arch, fullpath) && get_dir (newdir, &dir, fullpath)) {
  174. X    if (tar)
  175. X      if (tar_files (optind, argc, argv, tarf))
  176. X        argc = optind + 1;
  177. X      else 
  178. X    goto abort;
  179. X    do_archive (optind, argc, argv, buf, fullpath, arch, dir, size, bin,
  180. X        split, tar);
  181. X    if (tar)
  182. X      unlink (tarf);
  183. X  }
  184. X  abort:
  185. X  free ((char *) dir);
  186. X  free ((char *) buf);
  187. X}
  188. X
  189. X/*
  190. X  uuencode a file.
  191. X*/
  192. X
  193. void uuencode (FILE **fin, char *file, char *infile, struct stat *finbuf,
  194. X           BOOLEAN tar)
  195. X{
  196. X  fclose (*fin);
  197. X  printf ("\t- uuencoding...\n");
  198. X  syscom ("uuencode %s %s%s > %s", file, infile, (tar ? ".tar" : ""),
  199. X      UUE_FILE);
  200. X  *fin = fopen (UUE_FILE, "r");
  201. X  stat (UUE_FILE, finbuf);
  202. X}
  203. X
  204. X/*
  205. X  tar all input files into 'tarf'.
  206. X*/
  207. X
  208. int tar_files (int optind, int argc, char **argv, char *tarf)
  209. X{
  210. X  FILE *fin, *fout;
  211. X  char files[10000];
  212. X  int original = optind;
  213. X
  214. X  if ((fout = fopen (tarf, "w")) == NULL) {
  215. X    fprintf (stderr, "Cannot write to tar file %s\n", tarf);
  216. X    return 0;
  217. X  }
  218. X  unlink (tarf);
  219. X  printf ("tarring...\n");
  220. X  RESET (files);
  221. X  while (optind < argc) {
  222. X    if ((fin = fopen (argv[optind], "r")) == NULL) {
  223. X      fprintf (stderr, "Unable to open %s for reading.\n", argv[optind]);
  224. X      return 0;
  225. X    }
  226. X    fclose (fin);
  227. X    sprintf (files + strlen (files), "%s ", argv[optind++]);
  228. X  }
  229. X  syscom ("tar cf %s %s", tarf, files);
  230. X  argv[original] = tarf;
  231. X  return 1;
  232. X}
  233. X
  234. X/*
  235. X  Update the archive's directory.
  236. X*/
  237. X
  238. void update (char *path, char *file, int count, char *dir)
  239. X{
  240. X  char dirf[256];
  241. X  FILE *fout;
  242. X
  243. X  dirf[0] = EOS;
  244. X  sprintf (dirf, "%s/%s", path, DIR);
  245. X  if ((fout = fopen (dirf, "a")) == NULL) {
  246. X    fprintf (stderr, "Unable to open index %s for update.\nFile %s \
  247. not archived. Remove output file(s) from %s\n", dirf, file, dir);
  248. X    exit (1);
  249. X  }
  250. X  fprintf (fout, "%s %d %s\n", file, count, dir);
  251. X  fclose (fout);
  252. X}
  253. X
  254. void usage ()
  255. X{
  256. X  fprintf (stderr, "farch [-n] [-b] [-s size] [-a archive] [-d dir] \
  257. X[-t file] filename(s)\n");
  258. X  fprintf (stderr, "-n: do not split input file(s)\n\
  259. X-b: input files are binary: uuencode (on if -t specified)\n\
  260. X-s: maximum size of each output file (in kilobytes) -- default %ld\n\
  261. X-a: which archive index to update (subdir of %s)\n    -- \
  262. default %s\n\
  263. X-d: actual directory to put output file(s)\n    -- default %s/%s\n\
  264. X-t: tar all input files into 'file' and archive that\n",
  265. X(long) DEFAULT_SIZE / 1024, ARCHIVE_DIR, DEFAULT_ARCHIVE, ARCHIVE_DIR,
  266. DEFAULT_ARCHIVE);
  267. X  exit (2);
  268. X}
  269. X
  270. X/*
  271. X  Archive all files given in 'argv'.
  272. X*/
  273. X
  274. void do_archive (int optind, int argc, char **argv, char *buf, char *fullpath,
  275. X             char *archive, char *dir, long int size, BOOLEAN bin,
  276. X         BOOLEAN split, BOOLEAN tar)
  277. X{
  278. X  FILE *fin, *fout, *flast;
  279. X  long int count, nread, nchars, total;
  280. X  char *leftovers = NULL, *s, *infile = NULL, filename[256], compressed[256];
  281. X  struct stat sbuf, finbuf;
  282. X
  283. X  while (optind < argc) { /* Split and archive each file */
  284. X
  285. X    s = argv[optind] + strlen (argv[optind]) - 1;
  286. X    while (s != argv[optind] && *s == '/')  /* Remove trailing / */
  287. X      *(s--) = EOS;
  288. X
  289. X    if ((fin = fopen (argv[optind], "r")) == NULL) { /* Open file */
  290. X      fprintf (stderr, "Cannot open file %s for reading.\n", argv[optind]);
  291. X      goto abort;
  292. X    }
  293. X
  294. X    printf ("%s:\n", argv[optind]);
  295. X    count = 1;
  296. X    nchars = 0;
  297. X    stat (argv[optind], &finbuf); /* Get size of input file */
  298. X
  299. X    if (infile) /* free previous allocation */
  300. X      free ((char *) infile);
  301. X    infile = extract_filename (argv[optind]); /* get filename from path */
  302. X    locase (infile);
  303. X
  304. X    if (bin) /* uuencode */
  305. X      uuencode (&fin, argv[optind], infile, &finbuf, tar);
  306. X
  307. X    if (!split || finbuf.st_size <= size) { /* Not splitting;may have to copy */
  308. X      fclose (fin);
  309. X      sprintf (filename, "%s%s%s", (strcmp (dir, "/") ? dir : ""),
  310. X               ((strcmp (dir, infile) && strcmp (infile, "/")) ? "/" : ""),
  311. X               infile);
  312. X
  313. X      if (bin) { /* Copy UUE_FILE to target directory */
  314. X        if ((fout = fopen (filename, "w")) == NULL) { /* Test */
  315. X          fprintf (stderr, "Cannot write to directory %s; cannot \
  316. proceed with %s\n",
  317. X                   dir, argv[optind]);
  318. X          goto abort;
  319. X        }
  320. X        fclose (fout);
  321. X        syscom ("mv %s %s > /dev/null 2>&1", UUE_FILE, filename);
  322. X      }
  323. X      else if (stat (filename, &sbuf)) { /* File does not exist in target dir */
  324. X        if ((fout = fopen (filename, "w")) == NULL) {
  325. X          fprintf (stderr, "Cannot write to directory %s; cannot \
  326. proceed with %s\n",
  327. X                   dir, argv[optind]);
  328. X          goto abort;
  329. X        }
  330. X        fclose (fout);
  331. X        syscom ("cp %s %s > /dev/null 2>&1", argv[optind], filename);
  332. X      }
  333. X
  334. X      sprintf (compressed, "%s.Z", filename);
  335. X      if (!stat (compressed, &sbuf)) {
  336. X    fprintf (stderr, "Output file %s exists; cannot proceed with %s\n",
  337. X         compressed, argv[optind]);
  338. X    goto abort;
  339. X      }
  340. X
  341. X      syscom ("compress %s > /dev/null 2>&1", filename);
  342. X      update (fullpath, infile, 1, dir);
  343. X      printf ("\t- file not split\n\t- archived in %s\n\t- directory: %s\n",
  344. X              archive, dir);
  345. X    }
  346. X    else { /* Split file */
  347. X      while (!feof (fin)) {
  348. X        sprintf (filename, "%s%s%s%d", (strcmp (dir, "/") ? dir : ""),
  349. X                 ((strcmp (dir, infile) && strcmp (infile, "/")) ? "/" : ""),
  350. X                 infile, count);
  351. X
  352. X        if (!stat (filename, &sbuf)) {
  353. X          fprintf (stderr, "Output file %s exists; cannot proceed with %s\n",
  354. X                   filename, argv[optind]);
  355. X          fout = (FILE *) -1;
  356. X          break;
  357. X        }
  358. X        if ((fout = fopen (filename, "w")) == NULL) {
  359. X          fprintf (stderr, "Cannot write to directory %s; cannot proceed \
  360. with %s\n",
  361. X                   dir, argv[optind]);
  362. X          fout = (FILE *) -1;
  363. X          break;
  364. X        }
  365. X
  366. X        total = 0;  /* Do the actual splitting */
  367. X        total += fwrite (leftovers, sizeof (char), nchars, fout);
  368. X        nread = fread (buf, sizeof (char), size - nchars, fin);
  369. X        if (nchars)
  370. X          free ((char *) leftovers);
  371. X        s = buf + nread - (nread > 0 ? 1 : 0);
  372. X        nchars = 0;
  373. X        while (s != buf && *s != '\n') /* Look for first \n from the end */
  374. X          ++nchars,
  375. X          --s;
  376. X        if (s == buf) /* No new line found; write as is */
  377. X          nchars = 0;
  378. X        nread -= nchars;
  379. X        leftovers = (char *) malloc (nchars * sizeof (char));
  380. X        strncpy (leftovers, ++s, nchars); /* Copy anything after \n */
  381. X        total += fwrite (buf, sizeof (char), nread, fout);
  382. X        fclose (fout);
  383. X
  384. X        if (total == 0)
  385. X          unlink (filename);
  386. X        else { /* OK, compress */
  387. X          sprintf (compressed, "%s.Z", filename);
  388. X          if (!stat (compressed, &sbuf)) {
  389. X            fprintf (stderr, "Output file %s exists; cannot proceed with %s\n",
  390. X                     compressed, argv[optind]);
  391. X        unlink (filename);
  392. X            goto abort;
  393. X          }
  394. X          syscom ("compress %s > /dev/null 2>&1", filename),
  395. X          ++count;
  396. X    }
  397. X      }
  398. X
  399. X      fclose (fin);
  400. X      if (bin)
  401. X        unlink (UUE_FILE);
  402. X      if (nchars) /* write any leftovers */
  403. X        flast = fopen (filename, "a"),
  404. X        fwrite (leftovers, sizeof (char), nchars, flast),
  405. X        fclose (flast),
  406. X        free ((char *) leftovers);
  407. X
  408. X      if (fout != (FILE *) -1) { /* Splitting successful, update DIR file */
  409. X        update (fullpath, infile, count - 1, dir);
  410. X        printf ("\t- file split in %ld parts\n\t- archived in %s\n\t\
  411. X- directory: %s\n",
  412. X                (long) count - 1, archive, dir);
  413. X      }
  414. X    }
  415. X    abort:
  416. X    ++optind;
  417. X  }
  418. X}
  419. X
  420. X/*
  421. X  Get archive to update.
  422. X*/
  423. X
  424. int get_archive (char **arch, char *fullpath)
  425. X{
  426. X  FILE *master;
  427. X  char indexf[256], archiv[256], line[256];
  428. X  BOOLEAN found = FALSE;
  429. X
  430. X  if (!*arch)
  431. X    *arch = DEFAULT_ARCHIVE;
  432. X  sprintf (indexf, "%s/%s/%s", ARCHIVE_DIR, DEFAULT_ARCHIVE, INDEX);
  433. X  if ((master = fopen (indexf, "r")) == NULL) {
  434. X    fprintf (stderr, "Sorry, no master index found.\n");
  435. X    return 0;
  436. X  }
  437. X  while (!feof (master)) { /* Look at the master index for fullpath */
  438. X    fullpath[0] = archiv[0] = RESET (line);
  439. X    fgets (line, MAX_LINE - 2, master);
  440. X    if (line[0] != EOS) {
  441. X      sscanf (line, "%s %s\n", archiv, fullpath);
  442. X      locase (archiv);
  443. X      if (!strcmp (*arch, archiv)) {
  444. X        found = TRUE;
  445. X        break;
  446. X      }
  447. X    }
  448. X  }
  449. X  fclose (master);
  450. X  if (!found) {
  451. X    fprintf (stderr, "Archive %s not found.\n", *arch);
  452. X    return 0;
  453. X  }
  454. X  return 1;
  455. X}
  456. X
  457. X/*
  458. X  Get output directory.
  459. X*/
  460. X
  461. int get_dir (char *newdir, char **dir, char *fullpath)
  462. X{
  463. X  char *s;
  464. X  struct stat sbuf;
  465. X
  466. X  free ((char *) *dir);
  467. X  if (!newdir)
  468. X    *dir = (char *) malloc ((strlen (fullpath) + 1) * sizeof (char)),
  469. X    sprintf (*dir, "%s", fullpath);
  470. X  else {
  471. X    *dir = (char *) malloc ((strlen (newdir) + 1) * sizeof (char));
  472. X    sprintf (*dir, "%s", newdir);
  473. X    s = *dir + strlen (*dir) - 1;
  474. X    while (s != *dir && *s == '/')
  475. X      *(s--) = EOS;
  476. X  }
  477. X  if (stat (*dir, &sbuf)) {
  478. X    if (mkdir (*dir, 448)) {
  479. X      fprintf (stderr, "Unable to create new directory %s\n", *dir);
  480. X      return 0;
  481. X    }
  482. X    printf ("Creating new directory %s\n", *dir);
  483. X  }
  484. X  return 1;
  485. X}
  486. END_OF_FILE
  487. if test 14750 -ne `wc -c <'src/farch.c'`; then
  488.     echo shar: \"'src/farch.c'\" unpacked with wrong size!
  489. fi
  490. # end of 'src/farch.c'
  491. fi
  492. if test -f 'src/misc.c' -a "${1}" != "-c" ; then 
  493.   echo shar: Will not clobber existing file \"'src/misc.c'\"
  494. else
  495. echo shar: Extracting \"'src/misc.c'\" \(22380 characters\)
  496. sed "s/^X//" >'src/misc.c' <<'END_OF_FILE'
  497. X/*
  498. X  ----------------------------------------------------------------------------
  499. X  |                      GENERAL PURPOSE FUNCTIONS                           |
  500. X  |                                                                          |
  501. X  |                              Version 2.0                                 |
  502. X  |                                                                          |
  503. X  |                (or, when Computer Science gets to you)                   |
  504. X  |                                                                          |
  505. X  |                    Written by Anastasios Kotsikonas                      |
  506. X  |                           (tasos@cs.bu.edu)                              |
  507. X  |                                                                          |
  508. X  | AGREEMENT: This software can be used and distributed freely as long      |
  509. X  | as you do not remove or alter the Copyright notice in the file defs.h;   |
  510. X  | this notice is #define'd in the symbol VERSION. Although you may alter   |
  511. X  | the code provided, you may not alter the functions create_header()       |
  512. X  | and create_multi_recipient_header() in list.c and listserv.c.            |
  513. X  | By using this software you are bound by this agreement.                  |
  514. X  | This software comes with no warranties and cannot be sold for profit.    |
  515. X  | The AGREEMENT and COPYRIGHT notices should be included in all source     |
  516. X  | files when distributing this software.                                   |
  517. X  | COPYRIGHT: Copyright (c) 1991, Anastasios C. Kotsikonas                  |
  518. X  ----------------------------------------------------------------------------
  519. X*/
  520. X
  521. X#include <stdio.h>
  522. X#include <malloc.h>
  523. X#include <time.h>
  524. X#include <string.h>
  525. X#include <ctype.h>
  526. X#include <signal.h>
  527. X#include "defs.h"
  528. X#include "struct.h"
  529. X
  530. extern  COMMANDS commands[MAX_COMMANDS];
  531. X
  532. extern  int atoi (char *);
  533. extern  BOOLEAN subscribed (FILE *, char *, char *, char *, char *, char *);
  534. extern  void process_message (char *, char *, BOOLEAN);
  535. X#ifdef __STDC__
  536. X#include <stdarg.h>
  537. int     syscom (char *, ...);
  538. X#else
  539. X#include <varargs.h>
  540. int     syscom ();
  541. X#endif
  542. int    sys_config (FILE *, SYS *);
  543. char    *locase (char *);
  544. char    *upcase (char *);
  545. void    report_progress (FILE *, char *, int);
  546. void    distribute (FILE *mail, void (*)(), FILE *, char *, char *, char *,
  547. X            char *);
  548. BOOLEAN strinstr (char *, char *, char *);
  549. char    *extract_filename (char *);
  550. int     getopt (int, char **, char *);
  551. char    *cleanup_name (char *);
  552. void    cleanup_request (char *);
  553. void    get_list_name (char *, char *);
  554. int    get_list_id (char *, SYS *, int nlists);
  555. void    setup_string (char *, char *, char *);
  556. char    *_strstr (char *, char *);
  557. void    shrink (char *);
  558. BOOLEAN requested_part (char *, int);
  559. int    my_system (char *);
  560. X
  561. X/*
  562. X  Execute a system request.
  563. X*/
  564. X
  565. X#ifdef __STDC__
  566. int syscom (char *control, ...)
  567. X#else
  568. int syscom (control, va_alist)
  569. char *control;
  570. va_dcl
  571. X#endif
  572. X{
  573. X  char command [10240];
  574. X  extern SYS sys;
  575. X  extern BOOLEAN tty_echo;
  576. X  va_list ap;
  577. X  int status;
  578. X  FILE *f;
  579. X  long int time_is = 0;
  580. X  struct tm *t;
  581. X
  582. X#ifdef __STDC__
  583. X  va_start (ap, control);
  584. X#else
  585. X  va_start (ap);
  586. X#endif
  587. X  RESET (command);
  588. X  vsprintf (command, control, ap);
  589. X  va_end (ap);
  590. X  if ((sys.options & USE_MY_SYSTEM) == 0)
  591. X    status = system (command);
  592. X  else
  593. X    status = my_system (command);
  594. X  if (status) {
  595. X    if ((f = fopen (WARNING, "a")) != NULL)
  596. X      fprintf (f, "\nWARNING: System call exit status %d: %s\n",
  597. X           status / 256, command),
  598. X      time (&time_is),
  599. X      t = localtime (&time_is),
  600. X      fprintf (f, "Time/Date: %2d:%.2d:%.2d, %2d/%.2d/%2d\n",
  601. X               t->tm_hour, t->tm_min, t->tm_sec, t->tm_mon + 1, t->tm_mday,
  602. X               t->tm_year),
  603. X      fclose (f);
  604. X    if (tty_echo)
  605. X      printf ("\nWARNING: System call exit status %d: %s\n", status / 256,
  606. X          command);
  607. X  }
  608. X  return status;
  609. X}
  610. X
  611. X/*
  612. X  Initialize the 'sys' structure from the CONFIG file. It returns the number
  613. X  of lists in the system.
  614. X*/
  615. X
  616. int sys_config (FILE *report, SYS *sys)
  617. X{
  618. X  FILE *config;
  619. X  char cmd [MAX_LINE];
  620. X  char args [MAX_LINE];
  621. X  char error [MAX_LINE];
  622. X  char mail_prog [MAX_LINE];
  623. X  char env_var [MAX_LINE];
  624. X  char *comment, *cmdarg;
  625. X  int nlists = 0, i, j, k, id;
  626. X  BOOLEAN notok;
  627. X
  628. X  for (i = 0; i < MAX_LISTS; i++)
  629. X    sys->lists[i].disabled_commands = 0,
  630. X    RESET (sys->lists[i].alias),
  631. X    RESET (sys->lists[i].address),
  632. X    RESET (sys->lists[i].comment),
  633. X    RESET (sys->lists[i].cmdoptions);
  634. X  RESET (sys->server.address), RESET (sys->server.cmdoptions),
  635. X  RESET (sys->server.comment), RESET (sys->serverd_cmdoptions),
  636. X  RESET (sys->server.password), RESET (sys->arg), RESET (sys->manager),
  637. X  RESET (sys->organization), RESET (error);
  638. X  strcpy (sys->server.address, DEFAULT_SERVER_ADDRESS);
  639. X  strcpy (sys->server.cmdoptions, DEFAULT_SERVER_CMDOPTIONS);
  640. X  strcpy (sys->server.comment, DEFAULT_SERVER_COMMENT);
  641. X  strcpy (sys->manager, DEFAULT_MANAGER);
  642. X  sys->mail.method = BINMAIL;
  643. X  sys->options = 0;
  644. X  sys->users = 100;
  645. X  sys->frequency = 0;
  646. X  if ((config = fopen (CONFIG, "r")) == NULL)
  647. X    sprintf (error, "\nsys_config(): Could not open %s", CONFIG),
  648. X    report_progress (report, error, TRUE),
  649. X    exit (1);
  650. X  chmod (CONFIG, 384);
  651. X  while (! feof (config)) {
  652. X    args [0] = RESET (cmd);
  653. X    fscanf (config, "%s", cmd);
  654. X    if (cmd[0] == EOS)
  655. X      continue;
  656. X    fgets (args, MAX_LINE - 2, config);
  657. X    args [strlen (args) - 1] = EOS;
  658. X    if (cmd[0] == '#')
  659. X      continue;
  660. X    if (!strcmp (locase (cmd), "list")) {
  661. X      if (nlists >= MAX_LISTS) {
  662. X    sprintf (error, "\nsys_config(): List %s ignored: too many lists\n",
  663. X         args);
  664. X    report_progress (report, error, FALSE);
  665. X    continue;
  666. X      }
  667. X      comment = strchr (args, '#');
  668. X      if (comment)
  669. X    *comment = EOS;
  670. X      sscanf (args, "%s%s", sys->lists [nlists].alias,
  671. X          sys->lists [nlists].address);
  672. X      if (get_list_id (sys->lists [nlists].alias, sys, nlists) >= 0 &&
  673. X      nlists > 0)
  674. X    sprintf (error, "\nsys_config(): Duplicate list %s in %s",
  675. X         sys->lists [nlists].alias, CONFIG),
  676. X    report_progress (report, error, TRUE),
  677. X    exit (4);
  678. X      cmdarg = _strstr (args, " -");
  679. X      if (!cmdarg)
  680. X    cmdarg = _strstr (args, "\t-");
  681. X      if (cmdarg)
  682. X    strcat (sys->lists [nlists].cmdoptions, cmdarg);
  683. X      upcase (sys->lists [nlists].alias);
  684. X      locase (sys->lists [nlists].address);
  685. X      ++nlists;
  686. X    }
  687. X    else if (!strcmp (cmd, "server")) {
  688. X      comment = strchr (args, '#');
  689. X      if (comment)
  690. X        *comment = EOS;
  691. X      sscanf (args, "%s", sys->server.address);
  692. X      cmdarg = _strstr (args, " -");
  693. X      if (!cmdarg)
  694. X    cmdarg = _strstr (args, "\t-");
  695. X      if (cmdarg)
  696. X    strcat (sys->server.cmdoptions, cmdarg);
  697. X      locase (sys->server.address);
  698. X    }
  699. X    else if (!strcmp (cmd, "frequency")) {
  700. X      sscanf (args, "%d", &sys->frequency);
  701. X      if (sys->frequency < 0)
  702. X    sprintf (error, "\nsys_config(): Invalid 'frequency' argument %d in %s",
  703. X         sys->frequency, CONFIG),
  704. X    report_progress (report, error, TRUE),
  705. X    exit (4);
  706. X    }
  707. X    else if (!strcmp (cmd, "limit")) {
  708. X      sscanf (args, "%s", sys->arg);
  709. X      if (!strcmp (locase (sys->arg), "message"))
  710. X    sys->options |= LIMIT_MSG,
  711. X        sscanf (args, "%s %ld", sys->arg, &sys->limits.msg);
  712. X      else
  713. X        sprintf (error, "\nsys_config(): Invalid argument %s to 'limit' in %s",
  714. X              sys->arg, CONFIG),
  715. X     report_progress (report, error, TRUE),
  716. X    exit (4);
  717. X    }
  718. X    else if (!strcmp (cmd, "option")) {
  719. X      sscanf (args, "%s", sys->arg);
  720. X      if (!strcmp (locase (sys->arg), "bsd_ps"))
  721. X    sys->options |= BSD_PS;
  722. X      else if (!strcmp (sys->arg, "sysv_ps"))
  723. X    sys->options |= SYSV_PS;
  724. X      else if (!strcmp (sys->arg, "bsd_mail"))
  725. X    sys->options |= BSD_MAIL;
  726. X      else if (!strcmp (sys->arg, "bad_telnet"))
  727. X    sys->options |= USE_MY_SYSTEM;
  728. X      else if (!strcmp (sys->arg, "post_mail"))
  729. X    sys->options |= POST_MAIL;
  730. X      else if (!strcmp (sys->arg, "gate_mail"))
  731. X    sys->options |= GATE_MAIL;
  732. X      else
  733. X    sprintf (error, "\nsys_config(): Invalid argument %s to 'option' in %s",
  734. X         sys->arg, CONFIG),
  735. X    report_progress (report, error, TRUE),
  736. X    exit (4);
  737. X    }
  738. X    else if (!strcmp (cmd, "serverd")) {
  739. X      comment = strchr (args, '#');
  740. X      if (comment)
  741. X        *comment = EOS;
  742. X      cmdarg = strchr (args, '-');
  743. X      if (cmdarg)
  744. X    strcat (sys->serverd_cmdoptions, cmdarg);
  745. X    }
  746. X    else if (!strcmp (cmd, "organization")) {
  747. X      comment = strchr (args, '#');
  748. X      if (comment)
  749. X        *comment = EOS;
  750. X      strcpy (sys->organization, args + 1);
  751. X    }
  752. X    else if (!strcmp (cmd, "restriction"))
  753. X      sscanf (args, "%d", &sys->users);
  754. X    else if (!strcmp (cmd, "manager"))
  755. X      sscanf (args, "%s", sys->manager);
  756. X    else if (!strcmp (cmd, "password"))
  757. X      sscanf (args, "%s", sys->server.password),
  758. X      upcase (sys->server.password);
  759. X    else if (!strcmp (cmd, "disable")) {
  760. X      if (commands[0].name == NULL)  /* Array not initialized */
  761. X    continue;
  762. X      sscanf (args, "%s", sys->arg);
  763. X      upcase (sys->arg);
  764. X      id = get_list_id (sys->arg, sys, nlists);
  765. X      if (id < 0)
  766. X    sprintf (error, "sys_config(): Unrecognized list name %s for \
  767. X'disable' in %s", sys->arg, CONFIG),
  768. X      report_progress (report, error, TRUE),
  769. X      exit (4);
  770. X      sscanf (args, "%s %s", sys->arg, sys->arg); /* Get request to disable */
  771. X      upcase (sys->arg);
  772. X      notok = FALSE;
  773. X      k = 0;
  774. X      for (i = 0; i < MAX_COMMANDS; ++i) {
  775. X    notok &= (((j = strncmp (sys->arg, commands[i].name, strlen (sys->arg)))
  776. X           != 0) ? 1 : 0);
  777. X    if (!j)
  778. X      ++k,
  779. X      sys->lists[id].disabled_commands |= commands[i].mask;
  780. X      }
  781. X      if (notok)
  782. X    sprintf (error, "sys_config(): Unrecognized request %s to 'disable' \
  783. for list %s in %s", sys->arg, sys->lists[id].alias, CONFIG),
  784. X    report_progress (report, error, TRUE),
  785. X    exit (4);
  786. X      if (k > 1)
  787. X    sprintf (error, "sys_config(): Ambiguous request %s to 'disable' \
  788. for list %s in %s", sys->arg, sys->lists[id].alias, CONFIG),
  789. X    report_progress (report, error, TRUE),
  790. X    exit (4);
  791. X    }
  792. X    else if (!strcmp (cmd, "comment")) {
  793. X      sscanf (args, "%s", sys->arg);
  794. X      if (!strcmp (locase (sys->arg), "server")) {
  795. X    comment = strchr (args, '#');
  796. X    if (comment == NULL)
  797. X      sprintf (error, "\nsys_config(): Missing # for comment in %s",CONFIG),
  798. X          report_progress (report, error, TRUE),
  799. X          exit (4);
  800. X    RESET (sys->server.comment);
  801. X    strcat (sys->server.comment, comment + 1);
  802. X      }
  803. X      else {  /* Some list name was specified */
  804. X    upcase (sys->arg);
  805. X    id = get_list_id (sys->arg, sys, nlists);
  806. X    if (id < 0)
  807. X      sprintf (error, "sys_config(): Unrecognized list name %s for \
  808. X'comment' in %s", sys->arg, CONFIG),
  809. X      report_progress (report, error, TRUE),
  810. X      exit (4);
  811. X    comment = strchr (args, '#');
  812. X    if (comment == NULL)
  813. X      sprintf (error, "\nsys_config(): Missing # for comment in %s", CONFIG),
  814. X      report_progress (report, error, TRUE),
  815. X      exit (4);
  816. X    RESET (sys->lists[id].comment);
  817. X    strcat (sys->lists[id].comment, comment + 1);
  818. X      }
  819. X    }
  820. X    else if (!strcmp (cmd, "mailmethod")) {
  821. X      sscanf (args, "%s", sys->arg);
  822. X      if (!strcmp (locase (sys->arg), "telnet"))
  823. X    sys->mail.method = TELNET,
  824. X     sys->options |= USE_TELNET;
  825. X      else if (!strcmp (locase (sys->arg), "system"))
  826. X    sys->options |= (USE_TELNET | USE_SYSMAIL);
  827. X      else if (!strcmp (sys->arg, "sendmail") || !strcmp (sys->arg, "rmail"))
  828. X    sys->mail.method = (char *) malloc (256 * sizeof (char)),
  829. X    sscanf (args, "%s %s", sys->arg, sys->mail.method),
  830. X    locase (sys->mail.method),
  831. X    strcat (sys->mail.method, " > /dev/null 2>&1");
  832. X      else if (!strcmp (sys->arg, "binmail"))
  833. X    sys->mail.method = BINMAIL;
  834. X      else if (!strcmp (sys->arg, "env_var"))
  835. X    sys->options |= USE_ENV_VAR,
  836. X    sscanf (args, "%s %s %s", sys->arg, sys->mail.env_var,
  837. X            sys->mail.mail_prog),
  838. X    locase (sys->mail.mail_prog),
  839. X    upcase (sys->mail.env_var);
  840. X      else
  841. X    sprintf (error, "\nsys_config(): Unrecognized mail method %s in %s",
  842. X         sys->arg, CONFIG),
  843. X    report_progress (report, error, TRUE),
  844. X    exit (4);
  845. X    }
  846. X    else
  847. X      sprintf (error, "\nUnrecognized command %s in %s", cmd, CONFIG),
  848. X      report_progress (report, error, TRUE),
  849. X      exit (4);
  850. X  }
  851. X  fclose (config);
  852. X  return nlists;
  853. X}
  854. X
  855. X/*
  856. X  Convert a string to lower case.
  857. X*/
  858. X
  859. char *locase (char *s)
  860. X{
  861. X  char *r = s;
  862. X  while (*s != EOS) {
  863. X    if (isupper (*s))
  864. X      *s = tolower (*s);
  865. X    ++s;
  866. X  }
  867. X  return r;
  868. X}
  869. X
  870. X/*
  871. X  Convert a string to upper case.
  872. X*/
  873. X
  874. char *upcase (char *s)
  875. X{
  876. X  char *r = s;
  877. X
  878. X  while (*s != EOS) {
  879. X    if (islower (*s))
  880. X      *s = toupper (*s);
  881. X    ++s;
  882. X  }
  883. X  return r;
  884. X}
  885. X
  886. X/*
  887. X  Write messages and times to REPORT_LIST and stdout. If 'report_time'
  888. X  is set to a negative value no leading newline is printed to 'report'.
  889. X  NOTE: Use strftime(), if possible.
  890. X*/
  891. X
  892. void report_progress (FILE *report, char *s, int report_time)
  893. X{
  894. X  extern BOOLEAN tty_echo;
  895. X  long int time_is = 0;
  896. X  struct tm *t;
  897. X
  898. X  fprintf (report, "%s", s);
  899. X  if (report_time) {
  900. X    time (&time_is);
  901. X    t = localtime (&time_is);
  902. X    if (report_time > 0)
  903. X      fprintf (report, "\n");
  904. X    fprintf (report, "Time/Date: %2d:%.2d:%.2d, %2d/%.2d/%2d\n",
  905. X             t->tm_hour, t->tm_min, t->tm_sec, t->tm_mon + 1, t->tm_mday,
  906. X             t->tm_year);
  907. X  }
  908. X  fflush (report);
  909. X  if (tty_echo) {
  910. X    printf ("%s", s);
  911. X    if (report_time)
  912. X      printf ("\n");
  913. X    fflush (stdout);
  914. X  }
  915. X}
  916. X
  917. X/*
  918. X  Start distribution. Call lower level routines; the algorithm is such that
  919. X  this routine always looks at the beginning of each message when reading
  920. X  into 'first_line', i.e. 'first_line' is always assigned a string of the form:
  921. X        'From emailaddress Date Time'
  922. X  which is the universal convention for the start of every message. It calls
  923. X  subscribed() to find out if the sender is subscribed and passes the
  924. X  result to process_message(). Since the call to extract_sender() alters
  925. X  'first_line' to contain only the sender's email address a 'linecopy' is used.
  926. X  When returning from process_message() we have already advanced to the
  927. X  beginning of the next message, and 'linecopy' contains a string of the 
  928. X  above form; therefore we need to copy that back to 'first_line'.
  929. X*/
  930. X
  931. void distribute (FILE *mail, void (*process_message)(), FILE *report,
  932. X         char *subscribersf, char *newsf, char *peersf, char *aliasesf)
  933. X{
  934. X  char first_line[MAX_LINE], linecopy[MAX_LINE];
  935. X
  936. X  first_line[0] = RESET (linecopy);
  937. X  while (!feof (mail))
  938. X    if (first_line[0] != EOS)
  939. X      extract_sender (first_line),
  940. X      process_message ((char *) first_line, (char *) linecopy, (BOOLEAN)
  941. X               subscribed (report, first_line, subscribersf, newsf,
  942. X                   peersf, aliasesf)),
  943. X      strcpy (first_line, linecopy);
  944. X    else /* Read the first line of the very first message */
  945. X      fgets (first_line, MAX_LINE - 2, mail), /* 'From email Date Time' */
  946. X      strcpy (linecopy, first_line);
  947. X}
  948. X
  949. X/*
  950. X  Look for occurence of 'string' in 'substr' and return either TRUE or FALSE.
  951. X  Look at the comments for defs.h for the syntax of 'substr'. A 'substr' of
  952. X  "*" matches everything.
  953. X*/
  954. X
  955. BOOLEAN strinstr (char *substr, char *string, char *sep)
  956. X{
  957. X  char *origstr = string, *tok, *substrcopy;
  958. X  int l;
  959. X
  960. X  if (*substr == '*')
  961. X    return TRUE;
  962. X  substrcopy = (char *) malloc ((strlen (substr) + 1) * sizeof (char));
  963. X  strcpy (substrcopy, substr);
  964. X  tok = strtok (substrcopy, sep); /* Get first token */
  965. X  while (tok) { /* For every token in substr, check if it's in 'string' */
  966. X    string = origstr;
  967. X    l = strlen (tok);
  968. X    if (strlen (string) < l) {
  969. X      tok = strtok (NULL, sep);  /* get next token */
  970. X      continue;
  971. X    }
  972. X    while (strlen (string) >= l)
  973. X      if (! strncmp (tok, string, l)) {
  974. X        free (substrcopy);
  975. X        return TRUE;
  976. X      }
  977. X      else
  978. X        ++string;
  979. X    tok = strtok (NULL, sep); /* failed with this token; get the next one */
  980. X  }
  981. X  free (substrcopy);
  982. X  return FALSE;
  983. X}
  984. X
  985. X/*
  986. X  Given a file path, extract the file name. In the process, any command line
  987. X  options or any characters separated from the filename are discarded.
  988. X*/
  989. X
  990. char *extract_filename (char *s)
  991. X{
  992. X  char *p, *r, *t = s, nchar = 0;
  993. X
  994. X  while (*t != EOS && *t != ' ' && *t != '\t') /* Get to delimiting char */
  995. X    ++t;
  996. X  while (t != s && *t != '/') /* Go back till / or the beginning of s */
  997. X    ++nchar,
  998. X    --t;
  999. X  if (t != s || (*t == '/' && *(t + 1) != EOS))
  1000. X    --nchar,
  1001. X    ++t;
  1002. X  r = p = (char *) malloc ((nchar + 1) * sizeof (char));
  1003. X  *p = EOS;
  1004. X  while (*t != EOS && *t != ' ' && *t != '\t')
  1005. X    *(p++) = *(t++);
  1006. X  *p = EOS;
  1007. X  return r;
  1008. X}
  1009. X
  1010. X/*
  1011. X  Recognize the command line parameters. It returns '?' on an unrecognized
  1012. X  option, ':' if an option requires an argument and the argument is missing,
  1013. X  or the recognized character itself. This code is a copyright of AT&T.
  1014. X*/
  1015. X
  1016. X# define ERR(str, ch) if (opterr) \
  1017. X                        fprintf (stderr, "%s%s%c\n", argv[0], str, ch);
  1018. X
  1019. int opterr = 0;
  1020. int optind = 1;
  1021. int optopt;
  1022. char *optarg;
  1023. X
  1024. int getopt (int argc, char **argv, char *opts)
  1025. X{
  1026. X  static int sp = 1;
  1027. X  register int c;
  1028. X  register char *cp;
  1029. X
  1030. X  if (sp == 1)
  1031. X    if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
  1032. X      return EOF;
  1033. X    else if (strcmp (argv[optind], "--") == NULL) {
  1034. X      optind++;
  1035. X      return EOF;
  1036. X    }
  1037. X    optopt = c = argv[optind][sp];
  1038. X    if (c == ':' || (cp = strchr (opts, c)) == NULL) {
  1039. X      ERR (": unknown option, -", c);
  1040. X      if (argv[optind][++sp] == '\0')
  1041. X        optind++,
  1042. X        sp = 1;
  1043. X      return '?';
  1044. X    }
  1045. X    if (*++cp == ':') {
  1046. X      if (argv[optind][sp+1] != '\0')
  1047. X        optarg = &argv[optind++][sp+1];
  1048. X      else if (++optind >= argc) {
  1049. X        ERR(": argument missing for -", c);
  1050. X        sp = 1;
  1051. X        return ':';
  1052. X      }
  1053. X      else
  1054. X        optarg = argv[optind++];
  1055. X      sp = 1;
  1056. X    }
  1057. X    else {
  1058. X      if (argv[optind][++sp] == '\0')
  1059. X        sp = 1,
  1060. X        optind++;
  1061. X      optarg = NULL;
  1062. X    }
  1063. X    return c;
  1064. X}
  1065. X
  1066. X/*
  1067. X  Remove any extraneous characters from a name and convert it to lower
  1068. X  case with the first character of each word capitalized.
  1069. X*/
  1070. X
  1071. char *cleanup_name (char *s)
  1072. X{
  1073. X  char *tok, *copy, *sep = " ", *line;
  1074. X  int j, l;
  1075. X
  1076. X  if (s [strlen (s) - 1] == '\n')
  1077. X    s [strlen (s) - 1] = EOS;
  1078. X  line = (char *) malloc ((strlen (s) + 1) * sizeof (char));
  1079. X  strcpy (line, s);
  1080. X  *s = EOS;
  1081. X  tok = strtok (line, sep);
  1082. X  while (tok) {
  1083. X    copy = tok;
  1084. X    while (*copy != EOS) {  /* Remove extraneous characters */
  1085. X      if (! isalpha (*copy) && ! isspace (*copy)) {
  1086. X        for (j = 0, l = strlen (copy); j < l; copy[j] = copy[j+1], ++j);
  1087. X        continue;
  1088. X      }
  1089. X      ++copy;
  1090. X    }
  1091. X    locase (tok);
  1092. X    *tok = toupper (*tok);
  1093. X    sprintf (s + strlen (s), " %s", tok);
  1094. X    tok = strtok (NULL, sep);
  1095. X  }
  1096. X  free (line);
  1097. X  return s;
  1098. X}
  1099. X
  1100. X/*
  1101. X  Remove leading blanks from a request.
  1102. X*/
  1103. X
  1104. void cleanup_request (char *s)
  1105. X{
  1106. X  while (isspace (*s))
  1107. X    sprintf (s, "%s", s + 1);
  1108. X}
  1109. X
  1110. X/*
  1111. X  Identify the list that the request refers to. Before doing so, remove
  1112. X  any unnecessary blanks from the parameters. Also, check each parameter
  1113. X  for proper syntax.
  1114. X*/
  1115. X
  1116. void get_list_name (char *params, char *list_name)
  1117. X{
  1118. X  int i;
  1119. X  char *s, *r, *t;
  1120. X  char param [MAX_LINE];
  1121. X
  1122. X  r = s = (char *) malloc ((strlen (params) + 1) * sizeof (char));
  1123. X  strcpy (s, params);
  1124. X  RESET (params);
  1125. X  RESET (param);
  1126. X  for (i = 0; s[i] != EOS;)
  1127. X    if (isspace (s[i]) && isspace (s[i + 1]))
  1128. X      sprintf (s + i, "%s", s + i + 1);
  1129. X    else
  1130. X      i++;
  1131. X  do {
  1132. X    RESET (param);
  1133. X    sscanf (s, "%s", param);
  1134. X    s = s + strlen (param) + 1; /* Skip over space */
  1135. X    t = strpbrk (param, "*?/");
  1136. X    if (t != NULL) {
  1137. X      if (t == param || (t != param && ! isalpha (*(t - 1)))) /* Invalid *,? */
  1138. X    *t = '+';
  1139. X      if (*t == '/') /* Invalid / */
  1140. X    *t = '%';
  1141. X    }
  1142. X    sprintf (params + strlen (params), " %s", param);
  1143. X  } while (param[0] != EOS);
  1144. X  strcat (params, "\n");
  1145. X  free (r);
  1146. X  RESET (list_name);
  1147. X  sscanf (params, "%s", list_name);
  1148. X  upcase (list_name);
  1149. X  sprintf (params, "%s", params + strlen (list_name) + 1);
  1150. X}
  1151. X
  1152. X/*
  1153. X  Given a list name, return its index in the array of known lists.
  1154. X*/
  1155. X
  1156. int get_list_id (char *list_name, SYS *sys, int nlists)
  1157. X{
  1158. X  int i;
  1159. X
  1160. X  for (i = 0; i < nlists; i++)
  1161. X    if (!strcmp (list_name, sys->lists[i].alias))
  1162. X      return i;
  1163. X  return -1;
  1164. X}
  1165. X
  1166. void setup_string (char *s, char *alias, char *filename)
  1167. X{
  1168. X  RESET (s);
  1169. X  sprintf (s, "%s/lists/%s/%s", PATH", alias, filename);
  1170. X}
  1171. X
  1172. X/*
  1173. X  Return the first occurence of 'sub' in 'src', or NULL if not found.
  1174. X*/
  1175. X
  1176. char *_strstr (char *src, char *sub)
  1177. X{
  1178. X  if (src == NULL || sub == NULL)
  1179. X    return NULL;
  1180. X  while (*src != EOS) {
  1181. X    if (!strncmp (src, sub, strlen (sub)))
  1182. X      return src;
  1183. X    ++src;
  1184. X  }
  1185. X  return NULL;
  1186. X}
  1187. X
  1188. X/*
  1189. X  Shrink a message-id file so that it contains a maximum of KEEP_MESSAGE_IDS
  1190. X  entries in it.
  1191. X*/
  1192. X
  1193. void shrink (char *s)
  1194. X{
  1195. X  syscom ("tail -%d %s > /tmp/.msg", KEEP_MESSAGE_IDS, s);
  1196. X  syscom ("mv /tmp/.msg %s", s);
  1197. X}
  1198. X
  1199. X/*
  1200. X  Verify that 'i' is in 's'.
  1201. X*/
  1202. X
  1203. BOOLEAN requested_part (char *s, int i)
  1204. X{
  1205. X  char buf [80];
  1206. X  char copy [MAX_LINE];
  1207. X
  1208. X  strncpy (copy, s, MAX_LINE - 1);
  1209. X  do {
  1210. X    RESET (buf);
  1211. X    sscanf (copy, "%s", buf);
  1212. X    sprintf (copy, "%s", strchr (copy, buf[0]) + strlen (buf));
  1213. X    if (atoi (buf) == i)
  1214. X      return TRUE;
  1215. X  } while (buf[0] != EOS);
  1216. X  return FALSE;
  1217. X}
  1218. X
  1219. X/*
  1220. X  Use my_system() when either list and listserv use TELNET and there is
  1221. X  an indication that the sessions do not exit.
  1222. X*/
  1223. X
  1224. int my_system (char *s)
  1225. X{
  1226. X  FILE *f;
  1227. X  int pid, status;
  1228. X  char line [MAX_LINE], *r;
  1229. X  extern SYS sys;
  1230. X
  1231. X  if (strcmp ((r = extract_filename (s)), "telnet")) {
  1232. X    status = system (s);
  1233. X    free ((char *) r);
  1234. X    return status;
  1235. X  }
  1236. X  free ((char *) r);
  1237. X  strcat (s, " &"); /* Only telnet runs in the background */
  1238. X  status = system (s);
  1239. X  if (status > 127)
  1240. X    return status;
  1241. X  sleep (5);
  1242. X  if (sys.options & BSD_PS)
  1243. X    system ("ps -gx | grep telnet | grep -v \"grep telnet\" \
  1244. X        | grep -v telnetd > ./telnet");
  1245. X  else if (sys.options & SYSV_PS)
  1246. X    system ("ps -ef | grep telnet | grep -v \"grep telnet\" \
  1247. X        | grep -v telnetd > ./telnet");
  1248. X  if ((f = fopen ("./telnet", "r")) == NULL)
  1249. X    return -1;
  1250. X  while (! feof (f)) {
  1251. X    RESET (line);
  1252. X    fgets (line, MAX_LINE - 2, f);
  1253. X    if (line[0] != EOS)
  1254. X      sscanf (line, "%d", &pid),
  1255. X      sleep (15),
  1256. X      kill (pid, SIGHUP);
  1257. X  }
  1258. X  fclose (f);
  1259. X  unlink ("./telnet");
  1260. X  return status;
  1261. X}
  1262. X
  1263. X/* Change history (by Bob Boyd)
  1264. X21-Aug-1991   RLB     change parameter scanning for "list" lines in the
  1265. X                      config file so that "-" characters in the list-alias
  1266. X                      are ignored when looking for the beginning of the
  1267. X                      list parameters [tasos: I defined my own strstr()]
  1268. X*/
  1269. END_OF_FILE
  1270. if test 22380 -ne `wc -c <'src/misc.c'`; then
  1271.     echo shar: \"'src/misc.c'\" unpacked with wrong size!
  1272. fi
  1273. # end of 'src/misc.c'
  1274. fi
  1275. echo shar: End of archive 3 \(of 6\).
  1276. cp /dev/null ark3isdone
  1277. MISSING=""
  1278. for I in 1 2 3 4 5 6 ; do
  1279.     if test ! -f ark${I}isdone ; then
  1280.     MISSING="${MISSING} ${I}"
  1281.     fi
  1282. done
  1283. if test "${MISSING}" = "" ; then
  1284.     echo You have unpacked all 6 archives.
  1285.     rm -f ark[1-9]isdone
  1286. else
  1287.     echo You still need to unpack the following archives:
  1288.     echo "        " ${MISSING}
  1289. fi
  1290. ##  End of shell archive.
  1291. exit 0
  1292.