home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff319.lzh / CNewsSrc / cnews.src.lzh / input / newsspool.c < prev    next >
C/C++ Source or Header  |  1989-07-06  |  7KB  |  318 lines

  1. /*
  2.  * newsspool - copy incoming news into incoming directory
  3.  *
  4.  * The -i option relies on the parent setting (and exporting) $PATH.
  5.  *
  6.  * $Log$
  7.  */
  8.  
  9. #ifdef AMIGA
  10.     /*
  11.      *    If being compiled for an Amiga, then this code should be linked into
  12.      *    the executable for UUPC to replace the built-in "rnews" command.
  13.      *    Note that this bypasses the "rnews.{batch,immed}" script.
  14.      */
  15. #  define MAIN        RNews
  16. #  define LOCAL        static
  17. #else
  18. #  define MAIN        main
  19. #  define LOCAL
  20. #endif
  21.  
  22. #include <stdio.h>
  23. #include <sys/types.h>
  24.  
  25. #ifndef AMIGA
  26. #  include <sys/stat.h>
  27. #else
  28. #  include <libraries/dos.h>
  29. #  define stat        FileInfoBlock
  30. #  define st_mode    fib_DirEntryType
  31. extern int *Lock();
  32. #endif /* AMIGA */
  33.  
  34. #include <string.h>
  35. #include <errno.h>
  36. #include "libc.h"
  37. #include "news.h"
  38. #include "config.h"
  39.  
  40. #ifndef lint
  41. static char RCSid[] = "$Header$";
  42. #endif
  43.  
  44. #ifndef MAXTRIES
  45. #define    MAXTRIES    100    /* limit on attempts to make links */
  46. #endif
  47.  
  48. int debug = 0;
  49. char *progname;
  50.  
  51. extern void error(), exit();
  52. #ifdef UTZOOERR
  53. extern char *mkprogname();
  54. #else
  55. #define    mkprogname(a)    (a)
  56. #endif
  57.  
  58. char buf[BUFSIZ*16];    /* try to get a batch in a few gulps */
  59. int immed = 0;        /* try an immediate newsrun? */
  60.  
  61. void process();
  62. FILE *outopen();
  63. void outclose();
  64. extern time_t time();
  65. char *outname();
  66.  
  67. /*
  68.  * main - parse arguments and handle options
  69.  */
  70. MAIN (argc, argv)
  71. int argc;
  72. char *argv[];
  73. {
  74.     int c;
  75.     int errflg = 0;
  76.     FILE *in;
  77.     struct stat statbuf;
  78.     extern int optind;
  79.     extern char *optarg;
  80.     extern FILE *efopen();
  81.     void process();
  82.  
  83.     progname = mkprogname(argv[0]);
  84.  
  85.     while ((c = getopt(argc, argv, "id")) != EOF)
  86.         switch (c) {
  87.         case 'i':    /* try immediate newsrun */
  88.             immed++;
  89.             break;
  90.         case 'd':    /* Debugging. */
  91.             debug++;
  92.             setbuf(stderr, (char *)NULL);
  93.             break;
  94.         case '?':
  95.         default:
  96.             errflg++;
  97.             break;
  98.         }
  99.     if (errflg) {
  100.         fprintf(stderr, "Usage:  %s [file] ...\n", progname);
  101.         exit(2);
  102.     }
  103.     /* probe to get unprivileged() called if necessary */
  104.     (void) ctlfile((char *)NULL);
  105.  
  106.     /* mktemp() uses access(2) [ARGH!] so minimize chances of trouble */
  107.     (void) setgid(getegid());
  108.     (void) setuid(geteuid());
  109.  
  110.     (void) umask(newsumask());
  111.  
  112.     if (optind >= argc)
  113.         process(stdin, "stdin");
  114.     else
  115.         for (; optind < argc; optind++)
  116.             if (STREQ(argv[optind], "-"))
  117.                 process(stdin, "-");
  118.             else {
  119. #ifdef AMIGA
  120.                 int *lock;
  121.  
  122.                 if (lock = Lock(argv[optind], ACCESS_READ)) {
  123.                     Examine(lock, &statbuf);
  124.                     UnLock(lock);
  125.                 } else
  126.                     statbuf.st_mode = -1;
  127.                 in = efopen(argv[optind], "r");
  128.                 if (statbuf.st_mode > 0)            /* AmigaDOS directory */
  129.                     error("`%s' is directory!", argv[optind]);
  130. #else
  131.                 in = efopen(argv[optind], "r");
  132.                 if (fstat(fileno(in), &statbuf) < 0)
  133.                     error("can't fstat `%s'", argv[optind]);
  134.                 if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
  135.                     error("`%s' is directory!", argv[optind]);
  136. #endif /* AMIGA */
  137.                 process(in, argv[optind]);
  138.                 (void) fclose(in);
  139.             }
  140. #ifndef AMIGA
  141.     if (immed) {
  142.         execlp("newsrun", "newsrun", (char *)NULL);
  143.         error("attempt to run newsrun failed!", "");
  144.     }
  145. #endif /* AMIGA */
  146.     exit(0);
  147. }
  148.  
  149. /*
  150.  * process - process input file
  151.  */
  152.  
  153. /* ARGSUSED */
  154. LOCAL void process(in, inname)
  155. FILE *in;
  156. char *inname;
  157. {
  158.     register int count;
  159.     register int firstblock;
  160.     FILE *out;
  161.     register char *p;
  162.     register int n;
  163.     char *name;
  164.  
  165.     name = outname();
  166.     out = outopen(name);
  167.  
  168.     /* do the copying */
  169.     firstblock = 1;
  170.     while ((count = fread(buf, sizeof(char), sizeof(buf), in)) > 0) {
  171.         if (firstblock) {
  172.             n = cunskip(buf, count);
  173.             p = buf + n;
  174.             count -= n;
  175.             firstblock = 0;
  176.         } else
  177.             p = buf;
  178.         n = fwrite(p, sizeof(char), count, out);
  179.         if (n != count)
  180.             error("write error in output to `%s'", name);
  181.     }
  182.     outclose(out, name);
  183. }
  184.  
  185. /*
  186.  * outname - construct name for the temporary output file
  187.  */
  188. LOCAL char *outname()
  189. {
  190.     register char *p;
  191.  
  192.     p = strsave(fullartfile("in.coming/nspool.XXXXXX"));
  193.     mktemp(p);
  194.     return(p);
  195. }
  196.  
  197. /*
  198.  * outopen - acquire an output file
  199.  */
  200. LOCAL FILE *outopen(name)
  201. char *name;
  202. {
  203.     FILE *f;
  204.  
  205.     f = fopen(name, "w");
  206.     if (f == NULL)
  207.         error("unable to create temporary `%s'", name);
  208.     if (debug)
  209.         fprintf(stderr, "output into %s\n", name);
  210.  
  211.     return(f);
  212. }
  213.  
  214. /*
  215.  * outclose - close output file, moving it to the right place
  216.  *
  217.  * Names are based on the current time in hopes of keeping input in order.
  218.  */
  219. LOCAL void outclose(f, tmpname)
  220. FILE *f;
  221. char *tmpname;
  222. {
  223.     register char *p;
  224.     register char *name;
  225.     register int ntries;
  226.     time_t now;
  227.     extern int errno;
  228.  
  229.     if (fclose(f) == EOF)
  230.         error("fclose error on file `%s'", tmpname);
  231.  
  232.     p = fullartfile("in.coming/");
  233.     name = emalloc(strlen(p) + 20);    /* plenty for a number */
  234.     (void) strcpy(name, p);
  235.     p = name + strlen(name);
  236.  
  237.     ntries = 0;
  238.     for (;;) {
  239.         now = time((time_t *)NULL);
  240.         sprintf(p, "%ld", now);
  241.         if (debug)
  242.             fprintf(stderr, "trying renaming to %s\n", name);
  243.         if (link(tmpname, name) >= 0)
  244.             break;                /* NOTE BREAK OUT */
  245.         if (errno != EEXIST)    /* something strange is wrong */
  246.             error("unable to link `%s'", tmpname);
  247.         errno = 0;
  248.         if (ntries > MAXTRIES)    /* sanity check */
  249.             error("too many attempts to link `%s'", tmpname);
  250.         if (debug)
  251.             fprintf(stderr, "failed\n");
  252.         sleep(2);    /* avoid rumored race in 1-sec sleep */
  253.         ntries++;
  254.     }
  255.     if (debug)
  256.         fprintf(stderr, "succeeded\n");
  257.     (void) unlink(tmpname);
  258. }
  259.  
  260. /*
  261.  * cunskip - inspect block for silly #! cunbatch headers
  262.  *
  263.  * number of chars at start to skip
  264.  */
  265. LOCAL int cunskip(bufp, count)
  266. char *bufp;
  267. int count;
  268. {
  269.     static char goop[] = "cunbatch";
  270. #    define    GOOPLEN    (sizeof(goop)-1)    /* strlen(goop) */
  271.     static char goop2[] = "c7unbatch";
  272. #    define    GOOP2LEN    (sizeof(goop2)-1)    /* strlen(goop2) */
  273.     register char *p;
  274.     register int nleft;
  275.  
  276.     nleft = count;
  277.     p = bufp;
  278.  
  279.     if (nleft < 2)                /* no room for a header */
  280.         return(0);
  281.     if (*p++ != '#' || *p++ != '!')        /* doesn't start with #! */
  282.         return(0);
  283.     nleft -= 2;
  284.  
  285.     /* skip space */
  286.     while (nleft > 0 && (*p == ' ' || *p == '\t')) {
  287.         p++;
  288.         nleft--;
  289.     }
  290.     /* recognize headers (the +1s ensure room for the newline) */
  291.     if (nleft >= GOOPLEN+1 && STREQN(p, goop, GOOPLEN)) {
  292.         p += GOOPLEN;
  293.         nleft -= GOOPLEN;
  294.     } else if (nleft >= GOOP2LEN+1 && STREQN(p, goop2, GOOP2LEN)) {
  295.         p += GOOP2LEN;
  296.         nleft -= GOOP2LEN;
  297.     } else                    /* no header */
  298.         return(0);
  299.  
  300.     /* skip more space */
  301.     while (nleft > 0 && (*p == ' ' || *p == '\t')) {
  302.         p++;
  303.         nleft--;
  304.     }
  305.     if (nleft == 0 || *p++ != '\n')        /* didn't end properly */
  306.         return(0);
  307.     return(p - bufp);
  308. }
  309.  
  310. /*
  311.  * unprivileged - drop setuid-ness if configuration is overridden
  312.  */
  313. void unprivileged()
  314. {
  315.     setgid(getgid());
  316.     setuid(getuid());
  317. }
  318.