home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / uuxqt22.lha / uuxqt.c next >
Encoding:
C/C++ Source or Header  |  1995-10-23  |  9.1 KB  |  576 lines

  1. /*
  2. **  UUXQT.C
  3. **    by William Loftus
  4. **
  5. **    Copyright 1988 by William Loftus, All Rights Reserved.
  6. **    Changes Copyright 1990 - 1991 by Matthew Dillon, All Rights Reserved.
  7. **    Changes Copyright 1993 - 1995 by Michael B. Smith, All Rights Reserved.
  8. */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <log.h>
  14. #include <errno.h>
  15. #include "version.h"
  16. #include "protos.h"
  17. #include <owndevunit.h>
  18. #ifdef __SASC
  19. #include <dos.h>
  20. #endif
  21.  
  22. IDENT (".22");
  23.  
  24. /* #define PROCDEBUG */
  25. /* PROCDEBUG also affects the LogLevel assignment below */
  26.  
  27. #ifdef PROCDEBUG
  28. #define D(x)        printf x
  29. #else
  30. #define D(x)
  31. #endif
  32.  
  33. static const char
  34.     ProgName [] = "UUXQT",
  35.     odu_name [] = { ODU_NAME };
  36. struct Library
  37.     *OwnDevUnitBase;
  38. int
  39.     UseSubDirs,
  40.     numFiles,
  41.     file_pointer,
  42.     LoError,
  43.     GloError;
  44. char
  45.     *command,
  46.     *config,
  47.     *sys,
  48.     *name,
  49.     *uuspool,
  50.     names [MAXFILES * 16],
  51.     *pointers [MAXFILES],
  52.     *xfile,
  53.     dfile [128],
  54.     cmd [2048 + 1024],
  55.     ccmd [256],
  56.     ccmd_args [2048],
  57.     buf [2048];
  58.  
  59. #define DELIM " \t\n\r"
  60.  
  61. char *xstrtok (char *, const char *);
  62. void myexit (void);
  63.  
  64. #ifdef __GNUC__
  65. #define __aligned
  66. #endif
  67.  
  68. int
  69. brk (void)
  70. {
  71.     return 0;
  72. }
  73.  
  74. int
  75. bp_strcmp (const void *s1, const void *s2)
  76. {
  77.     return strcmp (* ((char **) s1), * ((char **) s2));
  78. }
  79.  
  80. int
  81. work_scan (const char *which)
  82. {
  83.     int
  84.         count;
  85.  
  86.     file_pointer = 0;
  87.  
  88.     /* we are already in the correct directory so don't change it */
  89.     count = getfnl ("X.#?", names, sizeof (names), 0);
  90.  
  91.     if (count > 0)
  92.     {
  93.         printf ("New files have arrived (%s).\n", which);
  94.  
  95.         if (strbpl (pointers, MAXFILES, names) != count)
  96.         {
  97.             fprintf (stderr, "Too many execute files\n");
  98.             return 0;
  99.         }
  100.     }
  101.     else
  102.     {
  103.         if (numFiles == 0)
  104.             printf ("No files to process (%s).\n", which);
  105.         return 0;
  106.     }
  107.  
  108.     qsort (pointers, count, sizeof (char *), bp_strcmp);
  109.  
  110.     return 1;
  111. }
  112.  
  113. char *
  114. work_next (void)
  115. {
  116.     char
  117.         *ptr;
  118.  
  119.     if (ptr = pointers [file_pointer])
  120.         ++file_pointer;
  121.     return ptr;
  122. }
  123.  
  124. int
  125. parse (char *x)
  126. {
  127.     BPTR
  128.         lock;
  129.     FILE
  130.         *fp;
  131.     char
  132.         *tmp;
  133.  
  134.     fp = fopen (x, "r");
  135.     if (!fp)
  136.     {
  137.         ulog (-1, "Can't open %s", x);
  138.         fprintf (stderr, "Can't open %s\n", x);
  139.         return 0;
  140.     }
  141.  
  142.     while (fgets (buf, sizeof (buf), fp))
  143.     {
  144.         if (buf [0] == 'F')
  145.         {
  146.             strcpy (dfile, xstrtok (&buf [1], DELIM));
  147.             continue;
  148.         }
  149.  
  150.         if (buf [0] == 'C')
  151.         {
  152.             strcpy (ccmd, xstrtok (&buf[1], DELIM));
  153.             strcpy (ccmd_args, xstrtok (NULL, DELIM));
  154.             while (tmp = strtok (NULL, DELIM))
  155.             {
  156.                 strcat (ccmd_args, " ");
  157.                 strcat (ccmd_args, tmp);
  158.             }
  159.             continue;
  160.         }
  161.  
  162.         if (buf [0] == '\n')
  163.             continue;
  164.  
  165.         if (buf [0] == '#')
  166.         {
  167.             ulog (10, "Ignored: %s", buf);
  168.             continue;
  169.         }
  170.  
  171.         if (tmp = strchr (buf, '\n'))
  172.             *tmp = '\0';
  173.         ulog (5, "Ignored: %s", buf);
  174.     }
  175.  
  176.     /*
  177.     **  If unable to find file it could be munge-cased
  178.     */
  179.     if (lock = Lock (dfile, SHARED_LOCK))
  180.         UnLock (lock);
  181.     else
  182.         mungecase_filename (dfile, dfile);
  183.  
  184.     ulog (5, "Command '%s', file '%s', args '%s'", ccmd, dfile, ccmd_args);
  185.  
  186.     if (command && strcmp (ccmd, command))
  187.     {
  188.         fclose (fp);
  189.         D (("ignored '%s' while looking for '%s'\n", ccmd, command));
  190.         return 0;
  191.     }
  192.     /*
  193.     **  FIXME:
  194.     **    Why do we ignore the arguments for everything except
  195.     **    RMAIL and CUNBATCH?
  196.     **
  197.     **    Why do we even HAVE a cunbatch when such a thing doesn't
  198.     **    exist?
  199.     **
  200.     **    Why don't we have a L.Cmds file approach?
  201.     */
  202.  
  203.     if (strncmp (ccmd, "rmail", 5) == 0)
  204.     {
  205.         sprintf (cmd, "%s <%s %s", GetConfigProgram (RMAIL), dfile, ccmd_args);
  206.     }
  207.     else
  208.     if (strncmp (ccmd, "cunbatch", 8) == 0)
  209.     {
  210.         sprintf (cmd, "%s <%s %s", GetConfigProgram (CUNBATCH), dfile, ccmd_args);
  211.     }
  212.     else
  213.     if (strncmp (ccmd, "rnews", 5) == 0)
  214.     {
  215.         /* RNEWS likes it better when input isn't stdin */
  216.         sprintf (cmd, "%s %s", GetConfigProgram (RNEWS), dfile);
  217.     }
  218.     else
  219.     if (strncmp (ccmd, "rsmtp", 5) == 0)
  220.     {
  221.         sprintf (cmd, "%s <%s", GetConfigProgram (RSMTP), dfile);
  222.     }
  223.     else
  224.     if (strncmp (ccmd, "rcsmtp", 5) == 0)
  225.     {
  226.         sprintf (cmd, "%s <%s", GetConfigProgram (RCSMTP), dfile);
  227.     }
  228.     else
  229.     if (strncmp (ccmd, "rgsmtp", 5) == 0)
  230.     {
  231.         sprintf (cmd, "%s <%s", GetConfigProgram ("RGSMTP"), dfile);
  232.     }
  233.     else
  234.     if (strnicmp (ccmd, "rlharc", 6) == 0)
  235.     {
  236.         sprintf (cmd, "%s %s", GetConfigProgram ("RLharc"), dfile);
  237.     }
  238.     else
  239.     {
  240.         fprintf (stderr, "Unknown command request %s  - Operation Aborted -\n", ccmd);
  241.         LoError = 1;
  242.         fclose (fp);
  243.         return 0;
  244.     }
  245.  
  246.     fclose (fp);
  247.     return 1;
  248. }
  249.  
  250. int
  251. rename_xfile (void)
  252. {
  253.     char
  254.         *p = strdup (xfile);
  255.     int
  256.         i;
  257.  
  258.     if (!p)
  259.     {
  260.         ulog (-1, "Ran out of memory trying to rename %s", xfile);
  261.         return 30;
  262.     }
  263.  
  264.     for (i = strlen (p); i >= 0; --i)
  265.     {
  266.         if (p [i] == '/' || p [i] ==':')
  267.             break;
  268.     }
  269.     ++i;
  270.  
  271.     if ((p [i] == 'X') || (p [i] == 'x'))
  272.     {
  273.         p [i] = 'E';
  274.         if (rename (xfile, p) == 0)
  275.             ulog (-1, "Renamed %s to %s", xfile, p);
  276.         else
  277.             ulog (-1, "Unable to rename %s to %s (Errno=%d, IoErr()=%ld)", xfile, p, errno, IoErr ());
  278.     }
  279.     else
  280.     {
  281.         ulog (-1, "Didn't try to rename '%s'", p);
  282.     }
  283.  
  284.     free (p);
  285.  
  286.     return 0;
  287. }
  288.  
  289. int
  290. process_cmd (const char *cmd)
  291. {
  292.     int
  293.         i,
  294.         syserr;
  295.  
  296.     syserr = system (cmd);
  297.  
  298.     if (syserr == 0)
  299.     {
  300.         /* no problems */
  301.         return 0;
  302.     }
  303.  
  304.     ulog (-1, "Execute Error: rc=%d cmd=%s", syserr, cmd);
  305.  
  306.     LoError = 1;
  307.  
  308.     if (i = rename_xfile ())
  309.     {
  310.         return i;
  311.     }
  312.  
  313.     return syserr;
  314. }
  315.  
  316. void
  317. process_directory (const char *which)
  318. {
  319.     if (UseSubDirs && strchr (which, ':') == 0 && strchr (which, '/') == 0)
  320.     {
  321.         static char
  322.             path [256];
  323.         int
  324.             i;
  325.  
  326.         i = strlen (uuspool);
  327.         if (uuspool [i - 1] == ':' || uuspool [i - 1] == '/')
  328.             i = 1;
  329.         else
  330.             i = 0;
  331.  
  332.         sprintf (path, "%s%s%s", uuspool, i ? "" : "/", which);
  333.         D (("dir (built) %s\n", path));
  334.         safe_chdir (path);
  335.     }
  336.     else
  337.     {
  338.         D (("dir (arg) %s\n", which));
  339.         safe_chdir (which);
  340.     }
  341.  
  342.     while (work_scan (which))
  343.     {
  344.         while (xfile = work_next ())
  345.         {
  346.             LoError = 0;
  347.             ++numFiles;
  348.             LockFile (xfile);
  349.             if (parse (xfile) && LoError == 0)
  350.             {
  351.                 if (process_cmd (cmd) == 0)
  352.                 {
  353.                     remove (xfile);
  354.                     remove (dfile);
  355.                 }
  356.             }
  357.             else
  358.             {
  359.                 rename_xfile ();
  360.             }
  361.             UnLockFile (xfile);
  362.             if (LoError)
  363.                 GloError++;
  364.         }
  365.     }
  366.  
  367.     return;
  368. }
  369.  
  370. void
  371. usage (void)
  372. {
  373.     fprintf (stderr, "usage: %s [-c command] [-s system]\n", name);
  374.     exit (30);
  375. }
  376.  
  377. int
  378. main (int ac, char **av)
  379. {
  380.     char
  381.         *tmp;
  382.  
  383.     if (ac == 0)
  384.         exit (10);
  385.  
  386.     LogProgram = ProgName;
  387.     name = av [0];
  388.  
  389. #ifdef PROCDEBUG
  390.     /* normally zero */
  391.     LogLevel = 99;
  392. #endif
  393.  
  394.     if (ac == 2 && *av [1] != '-')
  395.         sys = av [1];
  396.     else
  397.     {
  398.         int
  399.             i;
  400.         char
  401.             *debug;
  402.  
  403.         for (i = 1; i < ac; i++)
  404.         {
  405.             tmp = av [i];
  406.             if (*tmp != '-')
  407.                 usage ();
  408.             tmp++;
  409.  
  410.             switch (*tmp)
  411.             {
  412.                 case 'c':
  413.                     if (command)
  414.                     {
  415.                         fprintf (stderr, "You may only specify -c once\n");
  416.                         exit (20);
  417.                     }
  418.  
  419.                     tmp++;
  420.                     if (*tmp)
  421.                         command = tmp;
  422.                     else
  423.                         command = av [++i];
  424.                     D (("set command '%s'\n", command));
  425.                     break;
  426.  
  427.                 case 'I':
  428.                     if (config)
  429.                     {
  430.                         fprintf (stderr, "You may only specify -I once\n");
  431.                         exit (20);
  432.                     }
  433.  
  434.                     tmp++;
  435.                     if (*tmp)
  436.                         config = tmp;
  437.                     else
  438.                         config = av [++i];
  439.                     D (("set config '%s'\b", config));
  440.                     /* FIXME: support alternate configuration files */
  441.                     fprintf (stderr, "Warning: The alternate configuration file you specified will be ignored\n");
  442.                     break;
  443.  
  444.                 case 's':
  445.                     if (sys)
  446.                     {
  447.                         fprintf (stderr, "You may only specify -s once\n");
  448.                         exit (20);
  449.                     }
  450.  
  451.                     tmp++;
  452.                     if (*tmp)
  453.                         sys = tmp;
  454.                     else
  455.                         sys = av [++i];
  456.                     D (("set sys '%s'\n", sys));
  457.                     break;
  458.  
  459.                 case 'x':
  460.                     tmp++;
  461.                     if (*tmp)
  462.                         debug = tmp;
  463.                     else
  464.                         debug = av [++i];
  465.                     D (("ignored debug '%s'\n", debug));
  466.                     LogLevel = 5;
  467.                     /* FIXME: implement debug per Taylor? Maybe, but probably not. */
  468.                     fprintf (stderr, "Warning: your '-x %s' is being ignored\n", debug);
  469.                     break;
  470.  
  471.                 default:
  472.                     usage ();
  473.             }
  474.         }
  475.     }
  476.  
  477.     onbreak (brk);
  478.     atexit (myexit);
  479.  
  480.     if ((OwnDevUnitBase = OpenLibrary (odu_name, 0)) == NULL)
  481.     {
  482.         fprintf (stderr, "Unable to open %s\n", odu_name);
  483.         exit (20);
  484.     }
  485.  
  486.     if (FileIsLocked (ProgName))
  487.     {
  488.         ulog (-1, "%s already running!", ProgName);
  489.         exit (0);
  490.     }
  491.     LockFile (ProgName);
  492.  
  493.     tmp = GetConfig (USESUBDIRS, "0");
  494.     if (*tmp == 'y' || *tmp == 'Y' || *tmp == '1')
  495.         UseSubDirs = 1;
  496.  
  497.     uuspool = GetConfigDir (UUSPOOL);
  498.  
  499.     if (sys && UseSubDirs == 0)
  500.         fprintf (stderr, "WARNING: system specification ignored\n");
  501.  
  502.     if (UseSubDirs == 0)
  503.     {
  504.         process_directory (uuspool);
  505.     }
  506.     else
  507.     {
  508.         if (sys)
  509.         {
  510.             process_directory (sys);
  511.         }
  512.         else
  513.         {
  514.             BPTR
  515.                 lock;
  516.             __aligned struct FileInfoBlock
  517.                 fib;
  518.  
  519.             /* check normal UUSPOOL first, and get into   */
  520.             /* the correct directory for the Lock() below */
  521.             process_directory (uuspool);
  522.  
  523.             /* process files in all subdirectories */
  524.             lock = Lock ("", ACCESS_READ);
  525.             if (lock && Examine (lock, &fib))
  526.             {
  527.                 while (ExNext (lock, &fib))
  528.                 {
  529.                     if (fib.fib_DirEntryType < 0)
  530.                         continue;
  531.                     process_directory (fib.fib_FileName);
  532.                 }
  533.             }
  534.             if (lock)
  535.                 UnLock (lock);
  536.         }
  537.     }
  538.  
  539.     UnLockFile (ProgName);
  540.  
  541.     if (sys)
  542.         ulog (-1, "Processed %d files for %s", numFiles, sys);
  543.     else
  544.         ulog (-1, "Processed %d files", numFiles);
  545.     if (GloError)
  546.         ulog (-1, "%d files had errors", GloError);
  547.  
  548.     exit (0);
  549. }
  550.  
  551. char *
  552. xstrtok (char *s, const char *toks)
  553. {
  554.     char
  555.         *r;
  556.  
  557.     if (r = strtok (s, toks))
  558.         return r;
  559.  
  560.     return "";
  561. }
  562.  
  563. void
  564. myexit (void)
  565. {
  566.     UnLockFiles ();
  567.  
  568.     if (OwnDevUnitBase)
  569.     {
  570.         CloseLibrary (OwnDevUnitBase);
  571.         OwnDevUnitBase = NULL;
  572.     }
  573.  
  574.     return;
  575. }
  576.