home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / MISC / MNLDOS.ZIP / src / config.c next >
C/C++ Source or Header  |  2004-07-22  |  29KB  |  917 lines

  1. /* $Id: config.c,v 1.17 2004/07/21 22:57:45 fido Exp $ */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include <time.h>
  8.  
  9. #include "makenl.h"
  10. #include "msg.h"
  11. #include "config.h"
  12. #include "fts5.h"
  13. #include "proc.h"
  14. #include "lsttool.h"
  15. #include "fileutil.h"
  16. #include "credits.h"
  17.  
  18. #ifdef MALLOC_DEBUG
  19. #include "rmalloc.h"
  20. #endif
  21.  
  22. #ifdef DMALLOC
  23. #include "dmalloc.h"
  24. #endif
  25.  
  26. #define MF_EVERYWHERE(x) ((x) | ((x) << MF_SHIFT_ERRORS) | ((x) << MF_SHIFT_SUBMIT))
  27. #define MAIL_CRASH MF_EVERYWHERE(MF_CRASH)
  28. #define MAIL_HOLD MF_EVERYWHERE(MF_HOLD)
  29. #define MAIL_INTL MF_EVERYWHERE(MF_INTL)
  30.  
  31. static int CheckErrors(int mode) /* mode is -1 or 0 or CFG_DATA or
  32.                                     CFG_FILES */
  33. {
  34.     if (mode != -1)             /* This means there already is an error */
  35.     {
  36.         if (MakeType == -1)
  37.         {
  38.             fprintf(stderr, "No MAKE specified -- nothing to make\n");
  39.             mode = -1;
  40.         }
  41.         else
  42.         {
  43.             if (mode == 0 && MakeSourceFile[0] == 0) /* No Source
  44.                                                         specified */
  45.             {
  46.                 fprintf(stderr, "No input file or data specified\n");
  47.                 mode = -1;
  48.             }
  49.             else if (mode == CFG_DATA && MakeSourceFile[0] != 0)
  50.             {
  51.                 fprintf(stderr,
  52.                         "Master input file and DATA stream both specified\n");
  53.                 mode = -1;
  54.             }
  55.             else if (OutFile[0] == 0)
  56.             {
  57.                 fprintf(stderr, "No output file specified\n");
  58.                 mode = -1;
  59.             }
  60.             else
  61.             {
  62.                 if (MasterDir[0] == 0)
  63.                 {
  64.                     fprintf(stderr,
  65.                             "No directory for master files specified -- using \"%s\"\n",
  66.                             CurDir);
  67.                     strcpy(MasterDir, CurDir);
  68.                 }
  69.                 if (OutDir[0] == 0)
  70.                 {
  71.                     fprintf(stderr,
  72.                             "No directory for output file specified -- using \"%s\"\n",
  73.                             MasterDir);
  74.                     strcpy(OutDir, MasterDir);
  75.                 }
  76.                 if (UploadDir[0] != 0 && !strcmp(UploadDir, MasterDir))
  77.                 {
  78.                     fprintf(stderr,
  79.                             "UPLoads and MASter both specify \"%s\"\n",
  80.                             MasterDir);
  81.                     mode = -1;
  82.                 }
  83.                 else if (MailfileDir[0] != 0
  84.                          && !strcmp(MailfileDir, MasterDir))
  85.                 {
  86.                     fprintf(stderr,
  87.                             "MAIlfiles and MASter both specify \"%s\"\n",
  88.                             MasterDir);
  89.                     mode = -1;
  90.                 }
  91.                 else if (UpdateDir[0] != 0
  92.                          && !strcmp(UpdateDir, MasterDir))
  93.                 {
  94.                     fprintf(stderr,
  95.                             "UPDate and MASter both specify \"%s\"\n",
  96.                             MasterDir);
  97.                     mode = -1;
  98.                 }
  99.                 else if (UpdateDir[0] != 0 && UploadDir[0] != 0
  100.                          && !strcmp(UpdateDir, UploadDir))
  101.                 {
  102.                     fprintf(stderr,
  103.                             "UPLoads and UPDate both specify \"%s\"\n",
  104.                             UpdateDir);
  105.                     mode = -1;
  106.                 }
  107.                 else if (UpdateDir[0] != 0 && MailfileDir[0] != 0
  108.                          && !filecmp(UpdateDir, MailfileDir))
  109.                     /* FIXED BUG: The original read "MailfileDir != NULL" */
  110.                 {
  111.                     fprintf(stderr,
  112.                             "UPDate and MAIlfiles both specify \"%s\"\n",
  113.                             UpdateDir);
  114.                     mode = -1;
  115.                 }
  116.                 else if (UploadDir[0] != 0 && MailfileDir[0] != 0
  117.                          && !filecmp(UpdateDir, MailfileDir))
  118.                 {
  119.                     fprintf(stderr,
  120.                             "UPLoads and MAIlfiles both specify \"%s\"\n",
  121.                             UploadDir);
  122.                     mode = -1;
  123.                 }
  124.             }
  125.         }
  126.         if (MakeType == 0 && Levels[LEVEL_TOP][0] == 0)
  127.             fprintf(stderr,
  128.                     "WARNING -- No net NAME given for list header (use /N or NAME verb)\n");
  129.         if (PrivateLevel > 0 && PrivateLevel < MakeType)
  130.         {
  131.             fprintf(stderr,
  132.                     "PRIvate phone numbers referred to too high a level\n");
  133.             mode = -1;
  134.         }
  135.         if (MyAddress[A_NET] == 0
  136.             && (MakeType == LEVEL_REGION || MakeType == LEVEL_HOST))
  137.             MyAddress[A_NET] = MakeNum;
  138.         if (MyAddress[A_ZONE] == 0 && MakeType == LEVEL_ZONE)
  139.             MyAddress[A_ZONE] = MakeNum;
  140.         if (MyAddress[A_NODE] == 0 && MakeType >= LEVEL_HUB)
  141.             MyAddress[A_NODE] = MakeNum;
  142.         if (mode != -1 && MailerFlags != 0)
  143.         {
  144.             if (MessageDir[0] == 0)
  145.             {
  146.                 fprintf(stderr,
  147.                         "No message directory specified for notification\n");
  148.                 mode = -1;
  149.             }
  150.             else if (MyAddress[A_NET] == 0)
  151.             {
  152.                 fprintf(stderr,
  153.                         "No local \"From\" net address for notification messages.\n");
  154.                 mode = -1;
  155.             }
  156.             else if (SubmitAddress[A_NET] != 0
  157.                      && SubmitAddress[A_ZONE] == 0)
  158.                 SubmitAddress[A_ZONE] = MyAddress[A_ZONE];
  159.             if (MailerFlags & MAIL_INTL && MyAddress[A_ZONE] == 0)
  160.             {
  161.                 fprintf(stderr,
  162.                         "Forced \"INTL\" kluge requested, but your zone is unknown.\n");
  163.                 mode = -1;
  164.             }
  165.             if (mode != -1)
  166.                 BuildHeaders();
  167.         }
  168.     }
  169.     return mode;
  170. }
  171.  
  172. static int
  173. getswitch(char *argument, const struct switchstruct *swstrings,
  174.           char **value)
  175. {
  176.     if (argument[0] != '-' && argument[0] != '/')
  177.     {
  178.         *value = argument;
  179.         return -1;
  180.     }
  181.     if ((*value = strchr(argument++, '=')) != NULL)
  182.     {
  183.         (*value)[0] = 0;        /* Kill the '=' sign */
  184.         (*value)++;             /* Point to the value */
  185.     }
  186.     return xlate_switch(strupr(argument), swstrings);
  187. }
  188.  
  189. unsigned int
  190. xlate_switch(const char *swit, const struct switchstruct *desc)
  191. {
  192.     const char *swptr, *nameptr;
  193.  
  194.     while (desc->name)
  195.     {
  196.         swptr = swit;
  197.         nameptr = desc->name;
  198.         while (*swptr && *swptr == *nameptr)
  199.             swptr++, nameptr++;
  200.         if (!*swptr)
  201.             break;              /* Found the switch in the list */
  202.         if (swptr - swit > desc->minlen)
  203.             break;
  204.         desc++;
  205.     }
  206.     return desc->value;
  207. }
  208.  
  209. static const struct switchstruct SwitchXLate[] = {
  210.     {"MERGE", 1, 'M'},
  211.     {"NAME", 1, 'N'},
  212.     {"PROCESS", 1, 'P'},
  213.     {"TEST", 1, 'T'},
  214.     {"ZONE", 1, 'Z'},
  215.     {"DEBUG", 1, 'D'},
  216.     {"CREDITS", 1, 'C'},
  217.     {NULL, 0, 0}
  218. };
  219.  
  220. static char *ProgramName(const char *argv0, char *def)
  221. {
  222.     static char *program = NULL;
  223.     char *p;
  224.  
  225.     /* make a quick exit if we've been here before */
  226.  
  227.     if (program != NULL)
  228.     {
  229.         return program;
  230.     }
  231.     
  232.     /* make a copy of the full filename */
  233.  
  234.     program = malloc(strlen(argv0) + 1);
  235.  
  236.     if (program == NULL)
  237.     {
  238.         /* malloc failed - we may as well return the default */
  239.  
  240.         return def;
  241.     }
  242.  
  243.     strcpy(program, argv0);
  244.     
  245.     /* make program name point to the first character after the last \ */
  246.  
  247.     p = strrchr(program, '\\');
  248.  
  249.     if (p != NULL)
  250.     {
  251.         program = p + 1;
  252.     }
  253.  
  254.     /* make program name point to the first character after the last / */
  255.  
  256.     p = strrchr(program, '/');
  257.  
  258.     if (p != NULL)
  259.     {
  260.         program = p + 1;
  261.     }
  262.  
  263. #if PROGRAMNAME_STRIP_EXTENSION
  264.     /* remove the extension from the filename */
  265.  
  266.     p = strrchr(program, '.');
  267.  
  268.     if (p != NULL)
  269.     {
  270.         *p = '\0'; 
  271.     }
  272. #endif
  273.  
  274.     if (*program == '\0')
  275.     {
  276.         /*
  277.          *  somehow we ended up with an empty string!
  278.          *  return the default instead
  279.          */
  280.  
  281.         return def;
  282.     }
  283.  
  284. #if PROGRAMNAME_LOWERCASE
  285.     p = program;
  286.  
  287.     while (*p != '\0')
  288.     {
  289.         *p = tolower(*p);
  290.         p++;
  291.     }
  292. #endif
  293.  
  294.     return program;
  295. }
  296.  
  297. static void showusage(char *argv0)
  298. {
  299.    die(255, 1,
  300.      "\n"
  301.      "\n"
  302.      "Usage: %s [<config file>] [/P|/T] [/M[=<nodelist>]] [/N=<netname>] [/D]" "\n"
  303.      "\n"
  304.      "  /P (/PROCESS)  Operate in Process mode, overriding Process statement" "\n"
  305.      "                 in makenl.ctl." "\n"
  306.      "\n"
  307.      "  /T (/TEST)     Operate in Test mode even on the normal process day." "\n"
  308.      "\n"
  309.      "  /M (/MERGE)    Merge your updated nodelist segment with an existing" "\n"
  310.      "                 distribution nodelist to produce a temporary nodelist" "\n"
  311.      "                 containing your updates." "\n"
  312.      "\n"
  313.      "  /N (/NAME)     Specialized cosmetic switch. When you make a composite" "\n"
  314.      "                 nodelist, the generated list begins, by default, with the" "\n"
  315.      "                 line \"Nodelist for ...\". The /NAME switch may be used to" "\n"
  316.      "                 insert a network name in front of the first word in that" "\n"
  317.      "                 line. If the specified replacement name contains spaces," "\n"
  318.      "                 the entire parameter must be enclosed in quotes." "\n"
  319.      "\n"
  320.      "  /D (/DEBUG)    Enable debugging output for some functions." "\n",
  321.  
  322.      ProgramName(argv0, "makenl")
  323.    );
  324. }
  325.  
  326. void DoCmdLine(char **argv, char **cfgfilename)
  327. {
  328.     char *argv0, *tmpptr, *valueptr;
  329.  
  330.     argv0 = argv[0];
  331.  
  332.     while (*(++argv) != NULL)
  333.     {
  334.         switch (getswitch(*argv, SwitchXLate, &valueptr))
  335.         {
  336.         default:
  337.             showusage(argv0);
  338.             break;
  339.  
  340.         case 'C':
  341.             die(0, 1, MAKENL_CREDITS);
  342.             break;
  343.  
  344.         case -1:
  345.             *cfgfilename = valueptr;
  346.             break;
  347.  
  348.         case 'M':
  349.             /* Is it "/M" or "/M=BLA.LST"? */
  350.  
  351.             if (valueptr != NULL && *valueptr)
  352.             {
  353.                 tmpptr = valueptr;
  354.             }
  355.             else
  356.             {
  357.                 tmpptr = "nodelist";
  358.             }
  359.             strcpy(MergeFilename, tmpptr);
  360.             break;
  361.  
  362.         case 'N':
  363.             if (valueptr != NULL && *valueptr)
  364.             {
  365.                 Levels[0] = valueptr;
  366.             }
  367.             break;
  368.  
  369.         case 'P':
  370.             ShouldProcess = USUAL_PROCESSING | FORCED_PROCESSING;
  371.             break;
  372.  
  373.         case 'T':
  374.             ShouldProcess = 0;
  375.             JustTest = 1;
  376.             break;
  377.  
  378.         case 'Z':
  379.             Levels[2] = Levels[1];
  380.             break;
  381.  
  382.         case 'D':
  383.             MakenlDebug = 1;
  384.             break;
  385.         }
  386.     }
  387. }
  388.  
  389. static char const cfgspacechars[] = " \t";
  390.  
  391. const struct switchstruct MailFlags[] = {
  392.     {"CRASH", 5, MAIL_CRASH},
  393.     {"HOLD", 4, MAIL_HOLD},
  394.     {"INTL", 4, MAIL_INTL},
  395.     {NULL, 0, -1}
  396. };
  397.  
  398. #define NOTIFY_ERRORS 0xF0
  399. #define NOTIFY_RECEIPT 0x0F
  400. #define NOTIFY_ALL 0xFF
  401. #define NOTIFY_SELF 4096
  402.  
  403. const struct switchstruct NotifyType[] = {
  404.     {"ERRORS", 3, NOTIFY_ERRORS},
  405.     {"RECEIPT", 3, NOTIFY_RECEIPT},
  406.     {"ALL", 3, NOTIFY_ALL},
  407.     {"SELF", 4, NOTIFY_SELF},
  408.     {NULL, 0, -1}
  409. };
  410.  
  411. const struct switchstruct MakeTypes[] = {
  412.     {"MASTER", 3, LEVEL_TOP},
  413.     {"COMPOSITE", 3, LEVEL_TOP},
  414.     {"ZONE", 3, LEVEL_ZONE},
  415.     {"REGION", 3, LEVEL_REGION},
  416.     {"NETWORK", 3, LEVEL_HOST},
  417.     {"HUB", 3, LEVEL_HUB},
  418.     {"NODE", 3, LEVEL_NODE},
  419.     {NULL, 0, -1}
  420. };
  421.  
  422. /* Stupid mistake by BF: the three new verbs must be
  423.    at least 4 characters long to be unique */
  424.  
  425. const struct switchstruct CfgEntries[] = {
  426.     {"ARCCOPY", 4, CFG_ARCCOPY},
  427.     {"ARCMOVE", 4, CFG_ARCMOVE},
  428.     {"ARCOPEN", 4, CFG_ARCOPEN},
  429.     {"BADFILES", 3, CFG_BADFILES},
  430.     {"BATCHFILE", 3, CFG_BATCHFILE},
  431.     {"BAUDRATE", 3, CFG_BAUDRATE},
  432.     {"CALLEDBATCHFILE", 3, CFG_CALLEDBATCHFILE},
  433.     {"CLEANUP", 3, CFG_CLEANUP},
  434.     {"COMMENTS", 3, CFG_COMMENTS},
  435.     {"COPYRIGHT", 3, CFG_COPYRIGHT},
  436.     {"DATA", 4, CFG_DATA},
  437.     {"EPILOG", 3, CFG_EPILOG},
  438.     {"FILES", 5, CFG_FILES},
  439.     {"MAILFILES", 3, CFG_MAILFILES},
  440.     {"MAKE", 3, CFG_MAKE},
  441.     {"MASTER", 3, CFG_MASTER},
  442.     {"MERGE", 3, CFG_MERGE},
  443.     {"MESSAGES", 3, CFG_MESSAGES},
  444.     {"MINPHONE", 3, CFG_MINPHONE},
  445.     {"NAME", 3, CFG_NAME},
  446.     {"NETADRESS", 3, CFG_NETADRESS},
  447.     {"NOTIFY", 3, CFG_NOTIFY},
  448.     {"OUTDIFF", 4, CFG_OUTDIFF},
  449.     {"OUTFILE", 4, CFG_OUTFILE},
  450.     {"OUTPATH", 4, CFG_OUTPATH},
  451.     {"POINTS", 3, CFG_POINTS},
  452.     {"PRIVATE", 3, CFG_PRIVATE},
  453.     {"PROCESS", 4, CFG_PROCESS},
  454.     {"PROLOG", 4, CFG_PROLOG},
  455.     {"PUBLISH", 3, CFG_PUBLISH},
  456.     {"SEND", 3, CFG_SUBMIT},
  457.     {"SUBMIT", 3, CFG_SUBMIT},  /* SENd is an alias for SUBmit */
  458.     {"THRESHOLD", 3, CFG_THRESHOLD},
  459.     {"UPDATE", 3, CFG_UPDATE},
  460.     {"UPLOADS", 3, CFG_UPLOADS},
  461.     {"ALPHAPHONE", 4, CFG_ALPHAPHONE},
  462.     {"ALLOWUNPUB", 4, CFG_ALLOWUNPUB},
  463.     {NULL, 0, -1}
  464. };
  465.  
  466. static const struct switchstruct DOWSwitchTab[] = {
  467.     {"SUNDAY", 3, 0},
  468.     {"MONDAY", 3, 1},
  469.     {"TUESDAY", 3, 2},
  470.     {"WEDNESDAY", 3, 3},
  471.     {"THURSDAY", 3, 4},
  472.     {"FRIDAY", 3, 5},
  473.     {"SATURDAY", 3, 6},
  474.     {NULL, 0, -1}
  475. };
  476.  
  477. static const struct switchstruct PrivateDisp[] = {
  478.     {"NONE", 1, -2},
  479.     {"OK", 1, 0},
  480.     {"ZONE", 1, LEVEL_ZONE},
  481.     {"REGION", 1, LEVEL_REGION},
  482.     {"HOST", 2, LEVEL_HOST},
  483.     {"HUB", 2, LEVEL_HUB},
  484.     {NULL, 0, -1}
  485. };
  486.  
  487. static const struct switchstruct PointDisp[] = {
  488.     {"NONE", 3, -2},            /* not allowed */
  489.     {"HIDE", 1, -3},            /* kill any given phones */
  490.     {"OK", 1, 0},               /* allowed, don't change phones */
  491.     {"NODE", 3, LEVEL_NODE},    /* allowed, use node's phone */
  492.     {NULL, 0, -1}
  493. };
  494.  
  495. /* file - explicit filename
  496.    gfile - generic filename
  497.    [g]file - generic or explicit filename
  498.    pfile - filename with optional path
  499.    pgfile - generic filename with optional path
  500.  */
  501. /* *INDENT-OFF* */
  502. /* Indent tears the array lines :-( */
  503. struct
  504. {
  505.   int min, max;
  506. } arglimit[] = {
  507.   {4, 5},                       /* ARCCopy e.g. "Z pkzip -exo" */
  508.   {2, 2},                       /* BADfiles path */
  509.   {2, 2},                       /* BAUdrate a,b,c,d,e # without spaces!! */
  510.   {1, 1},                       /* CLEanup */
  511.   {2, 2},                       /* COMments pfile */
  512.   {2, 2},                       /* COPyright file */
  513.   {1, 1},                       /* DATA */
  514.   {2, 2},                       /* EPIlog file */
  515.   {1, 1},                       /* FILES */
  516.   {2, 2},                       /* MAIlfiles path */
  517.   {2, 4},                       /* MAKe type [ftnaddr [gfile]] */
  518.   {2, 2},                       /* MASter path */
  519.   {1, 2},                       /* MERge [pgfile] */
  520.   {2, 2},                       /* MESsages path */
  521.   {2, 2},                       /* MINphone parts */
  522.   {2, 2},                       /* NAMe name */
  523.   {2, 2},                       /* NETaddress ftnaddr */
  524.   {2, 5},                       /* NOTify {ERRors|RECeipt|ALL|SELF} [CRASH] [HOLD] [INTL] */
  525.   {2, 2},                       /* OUTDiff gfile */
  526.   {2, 2},                       /* OUTFile [g]file */
  527.   {2, 2},                       /* OUTPath path */
  528.   {2, 2},                       /* PRIvate disp */
  529.   {2, 2},                       /* PROCess day */
  530.   {2, 2},                       /* PROLog file */
  531.   {2, 2},                       /* PUBlish day */
  532.   {2, 5},                       /* {SENd|SUBmit} ftnaddr [CRASH] [HOLD] [INTL] */
  533.   {2, 3},                       /* {THReshold} arc [diff] */
  534.   {2, 2},                       /* UPDate path */
  535.   {2, 2},                       /* UPLoads path */
  536.   {2, 2},                       /* POInt disp */
  537.   {2, 2},                       /* BATCHFILE pfile */
  538.   {2, 2},                       /* CALLEDBATCHFILE pfile */
  539.   {4, 5},                       /* ARCMove e.g. "Z pkzip -exom" */
  540.   {4, 5},                       /* ARCOpen e.g. "Z pkunzip -o" */
  541.   {2, 2},                       /* ALPHaphone 1 or 0 - default 0 */
  542.   {2, 2}                        /* ALLOwunpub 1 or 0 - default 0 */
  543. };
  544. /* *INDENT-ON* */
  545.  
  546.  
  547. int parsecfgfile(FILE * CFG)
  548. {
  549.     struct tm *mytime;
  550.     int process_day;
  551.     int notifybits;
  552.     char *command;
  553.     char **flagptr;
  554.     int flagnum;
  555.     int argcounter;
  556.     int switchno;
  557.     char *workptr;
  558.     char foo[2];
  559.     int mode;
  560.     time_t thetime;
  561.     char *args[4];
  562.     char cfgline[linelength];
  563.     char cfgSplit[linelength];
  564.  
  565.     mode = 0;
  566.     while (fgets(cfgline, linelength - 1, CFG) != NULL)
  567.     {
  568.         workptr = strchr(cfgline, ';');
  569.         if (workptr)
  570.             *workptr = 0;
  571.         cutspaces(cfgline);
  572.         strcpy(cfgSplit, cfgline);
  573.         command = strtok(cfgSplit, cfgspacechars); /* Space and Tab */
  574.         if (!command)
  575.             continue;
  576.         switchno = xlate_switch(strupr(command), CfgEntries);
  577.         if (switchno == -1)
  578.         {
  579.             fprintf(stderr, "%s\n  -- Unknown keyword -- \"%s\"\n",
  580.                     cfgline, command);
  581.             mode = -1;
  582.             break;
  583.         }
  584.         argcounter = 1;
  585.         while (argcounter < arglimit[switchno].max)
  586.         {
  587.             if (!(args[argcounter - 1] = strtok(NULL, cfgspacechars)))
  588.                 break;
  589.             argcounter++;
  590.         }
  591.         if (arglimit[switchno].min > argcounter)
  592.         {
  593.             fprintf(stderr, "%s\n -- Too few parameters\n", cfgline);
  594.             mode = -1;
  595.             continue;
  596.         }
  597.         if (argcounter == arglimit[switchno].max && strtok(NULL, cfgspacechars)) /* Still 
  598.                                                                                     more 
  599.                                                                                     arguments... 
  600.                                                                                   */
  601.         {
  602.             fprintf(stderr, "%s\n -- Too many parameters\n", cfgline);
  603.             mode = -1;
  604.             continue;
  605.         }
  606.         switch (switchno)
  607.         {
  608.         case CFG_DATA:
  609.         case CFG_FILES:
  610.             mode |= switchno;
  611.             goto outofwhile;
  612.         case CFG_ARCCOPY:
  613.             ArcExt[0] = args[0][0];
  614.             if(args[3] != NULL)
  615.             sprintf(ArcCopyCmd, "%s %s %s", args[1], args[2], args[3]);
  616.             else
  617.             sprintf(ArcCopyCmd, "%s %s", args[1], args[2]);
  618.             break;
  619.         case CFG_ARCMOVE:
  620.             ArcExt[0] = args[0][0];
  621.             if(args[3] != NULL)
  622.             sprintf(ArcMoveCmd, "%s %s %s", args[1], args[2], args[3]);
  623.             else
  624.             sprintf(ArcMoveCmd, "%s %s", args[1], args[2]);
  625.             break;
  626.         case CFG_ARCOPEN:
  627.             ArcExt[0] = args[0][0];
  628.             if(args[3] != NULL)
  629.             sprintf(ArcOpenCmd, "%s %s %s", args[1], args[2], args[3]);
  630.             else
  631.             sprintf(ArcOpenCmd, "%s %s", args[1], args[2]);
  632.             break;
  633.         case CFG_BATCHFILE:
  634.             strcpy(BatchFile, args[0]);
  635.             break;
  636.         case CFG_CALLEDBATCHFILE:
  637.             strcpy(CalledBatchFile, args[0]);
  638.             break;
  639.         case CFG_CLEANUP:
  640.             do_clean = 1;
  641.             break;
  642.         case CFG_COMMENTS:
  643.             strcpy(CommentsFile, args[0]);
  644.             break;
  645.         case CFG_COPYRIGHT:
  646.             workptr = CopyrightFile;
  647.             goto OutputFile;
  648.         case CFG_EPILOG:
  649.             workptr = EpilogFile;
  650.             goto OutputFile;
  651.         case CFG_NAME:
  652.             sscanf(cfgline, "%*s %15s", namebuf);
  653.             break;
  654.         case CFG_MAKE:
  655.             MakeType = xlate_switch(strupr(args[0]), MakeTypes);
  656.             if (MakeType == -1)
  657.             {
  658.                 fprintf(stderr, "%s\n -- Don't know how to make \"%s\"\n",
  659.                         cfgline, args[0]);
  660.                 mode = -1;
  661.             }
  662.             if (MakeType != LEVEL_TOP) /* no composite (or master) list */
  663.             {
  664.                 if (argcounter == 2)
  665.                     workptr = "None";
  666.                 else
  667.                     workptr = args[1];
  668.                 if (getnodenum(&workptr, &MakeType, &MakeNum) != 0)
  669.                 {
  670.                     OutputErrorLine(stderr, cfgline, "\n", "\n", NULL);
  671.                     mode = -1;
  672.                 }
  673.                 if (argcounter == 4) /* Source file given */
  674.                 {
  675.                     if (filenodir(args[2]))
  676.                         strcpy(MakeSourceFile, args[2]);
  677.                     else
  678.                     {
  679.                         fprintf(stderr,
  680.                                 "%s\n -- Invalid file name -- \"%s\"\n",
  681.                                 cfgline, args[2]);
  682.                         mode = -1;
  683.                     }
  684.                 }
  685.             }
  686.             else /* making composite list */ if (argcounter > 2)
  687.             {
  688.                 fprintf(stderr, "%s\n -- To many parameters\n", cfgline);
  689.                 mode = -1;
  690.             }
  691.             break;
  692.         case CFG_MERGE:
  693.             if (argcounter == 2)
  694.                 strcpy(MergeFilename, args[0]);
  695.             else
  696.                 strcpy(MergeFilename, "NODELIST");
  697.             break;
  698.         case CFG_MINPHONE:
  699.             if (args[0][0] >= '1' && args[0][0] <= '9' && args[0][1] == 0)
  700.                 Minphone = args[0][0] - '0';
  701.             else
  702.             {
  703.                 fprintf(stderr,
  704.                         "MINPHONE argument \"%s\" not in range 1 to 9\n",
  705.                         args[0]);
  706.                 mode = -1;
  707.             }
  708.             break;
  709.         case CFG_ALPHAPHONE:
  710.             if (args[0][0] >= '0' && args[0][0] <= '2' && args[0][1] == 0)
  711.                 Alphaphone = args[0][0] - '0';
  712.             else
  713.             {
  714.                 fprintf(stderr,
  715.                         "ALPHAPHONE argument \"%s\" must be 0 or 1\n",
  716.                         args[0]);
  717.                 mode = -1;
  718.             }
  719.             break;
  720.         case CFG_ALLOWUNPUB:
  721.             if (args[0][0] >= '0' && args[0][0] <= '2' && args[0][1] == 0)
  722.                 Allowunpub = args[0][0] - '0';
  723.             else
  724.             {
  725.                 fprintf(stderr,
  726.                         "ALLOWUNPUB argument \"%s\" must be 0 or 1\n",
  727.                         args[0]);
  728.                 mode = -1;
  729.             }
  730.             break;
  731.         case CFG_NETADRESS:
  732.             if (ParseAddress(args[0], MyAddress) != 0)
  733.                 goto BadAddress;
  734.             break;
  735.         case CFG_PROCESS:
  736.             if ((process_day =
  737.                  xlate_switch(strupr(args[0]), DOWSwitchTab)) == -1)
  738.             {
  739.                 fprintf(stderr, "%s\n -- Invalid day of week \"%s\"\n",
  740.                         cfgline, args[0]);
  741.                 mode = -1;
  742.                 break;
  743.             }
  744.             time(&thetime);
  745.             mytime = localtime(&thetime);
  746.             if (mytime->tm_wday != process_day)
  747.                 ShouldProcess &= ~USUAL_PROCESSING;
  748.             break;
  749.         case CFG_PUBLISH:
  750.             NewExtWDay = xlate_switch(strupr(args[0]), DOWSwitchTab);
  751.             if (NewExtWDay == -1)
  752.             {
  753.                 fprintf(stderr, "%s\n -- Invalid day of week \"%s\"\n",
  754.                         cfgline, args[0]);
  755.                 mode = -1;
  756.                 break;
  757.             }
  758.             NewExtWDay = (NewExtWDay + 1) % 7; /* publishing day->new
  759.                                                   filextension day */
  760.             break;
  761.         case CFG_POINTS:
  762.             PointLevel = xlate_switch(strupr(args[0]), PointDisp);
  763.             if (PointLevel == -1)
  764.             {
  765.                 fprintf(stderr, "%s\n -- Invalid argument \"%s\"\n",
  766.                         cfgline, args[0]);
  767.                 mode = -1;
  768.                 break;
  769.             }
  770.             break;
  771.         case CFG_PRIVATE:
  772.             PrivateLevel = xlate_switch(strupr(args[0]), PrivateDisp);
  773.             if (PrivateLevel == -1)
  774.             {
  775.                 fprintf(stderr, "%s\n -- Invalid argument \"%s\"\n",
  776.                         cfgline, args[0]);
  777.                 mode = -1;
  778.                 break;
  779.             }
  780.             if (PrivateLevel > 0) /* Convert the keyword "pvt" into the
  781.                                      flag "pvt" */
  782.                 Levels[LEVEL_PRIVATE] = "";
  783.             break;
  784.         case CFG_THRESHOLD:
  785.             foo[0] = 0;
  786.             if (sscanf
  787.                 (cfgline, "%s %ld %ld%1s", command, &ARCThreshold,
  788.                  &DIFFThreshold, foo) != argcounter || foo[0] != 0)
  789.             {
  790.                 fprintf(stderr, "%s\n -- Invalid threshold number(s)\n",
  791.                         cfgline);
  792.                 mode = -1;
  793.             }
  794.             if (argcounter == 2)
  795.                 DIFFThreshold = ARCThreshold * 5 / 3;
  796.             else if (ARCThreshold > DIFFThreshold && DIFFThreshold != -1)
  797.             {
  798.                 fprintf(stderr,
  799.                         "%s\n -- Archive threshold must not be greater than Diff threshold\n",
  800.                         cfgline);
  801.                 mode = -1;
  802.             }
  803.             break;
  804.         case CFG_BADFILES:
  805.         case CFG_MASTER:
  806.         case CFG_MAILFILES:
  807.         case CFG_MESSAGES:
  808.         case CFG_OUTPATH:
  809.         case CFG_UPDATE:
  810.         case CFG_UPLOADS:
  811.             os_filecanonify(args[0]);
  812.             if (GetPath(args[0], switchno) == 0)
  813.             {
  814.                 fprintf(stderr, "%s\n -- Invalid Path -- \"%s\"\n",
  815.                         cfgline, args[0]);
  816.                 mode = -1;
  817.             }
  818.             break;
  819.         case CFG_OUTDIFF:
  820.             if (strchr(args[0], '.') != NULL)
  821.             {
  822.                 fprintf(stderr, "%s must contain a generic file name\n",
  823.                         command);
  824.                 mode = -1;
  825.             }
  826.             workptr = OutDiff;
  827.             goto OutputFile;
  828.         case CFG_OUTFILE:
  829.             workptr = OutFile;
  830.             goto OutputFile;
  831.         case CFG_PROLOG:
  832.             workptr = PrologFile;
  833.           OutputFile:
  834.             os_filecanonify(args[0]);
  835.             if (filenodir(args[0]))
  836.                 strcpy(workptr, args[0]);
  837.             else
  838.             {
  839.                 fprintf(stderr, "%s\n -- Invalid file name -- \"%s\"\n",
  840.                         cfgline, args[0]);
  841.                 mode = -1;
  842.             }
  843.             break;
  844.         case CFG_SUBMIT:
  845.         case CFG_NOTIFY:
  846.             notifybits = 0x111;
  847.             workptr = NULL;
  848.             if (argcounter >= 3)
  849.             {
  850.                 flagnum = argcounter - 2;
  851.                 flagptr = args + 1;
  852.                 do
  853.                 {
  854.                     notifybits |=
  855.                         xlate_switch(strupr(*flagptr), MailFlags);
  856.                     if (notifybits == -1)
  857.                         workptr = *flagptr;
  858.                     flagptr++;
  859.                 }
  860.                 while (--flagnum);
  861.             }
  862.             if (switchno == CFG_SUBMIT)
  863.             {
  864.                 notifybits &= MF_SUBMIT;
  865.                 if (ParseAddress(args[0], SubmitAddress) != 0)
  866.                 {
  867.                   BadAddress:
  868.                     fprintf(stderr,
  869.                             "%s\n -- Invalid network address -- \"%s\"\n",
  870.                             cfgline, args[0]);
  871.                     mode = -1;
  872.                     break;
  873.                 }
  874.             }
  875.             else
  876.             {
  877.                 switch (xlate_switch(strupr(args[0]), NotifyType))
  878.                 {
  879.                 case -1:
  880.                     fprintf(stderr,
  881.                             "%s\n -- Bad SEND parameter -- \"%s\"\n",
  882.                             cfgline, args[0]);
  883.                     mode = -1;
  884.                     break;
  885.                 case NOTIFY_RECEIPT:
  886.                     if ((MailerFlags & MF_ERRORS) == 0)
  887.                         notifybits &= MF_RECEIPT | MF_ERRORS;
  888.                     else
  889.                         notifybits &= MF_RECEIPT;
  890.                     break;
  891.                 case NOTIFY_ERRORS:
  892.                     notifybits &= MF_ERRORS;
  893.                     break;
  894.                 case NOTIFY_SELF:
  895.                     notifybits = MF_SELF;
  896.                     break;
  897.                 case NOTIFY_ALL:
  898.                     notifybits &= MF_RECEIPT | MF_ERRORS;
  899.                     break;
  900.                 }
  901.             }
  902.             MailerFlags |= notifybits;
  903.             if (workptr)        /* Pointing to an invalid flag */
  904.             {
  905.                 fprintf(stderr, "%s\n -- Bad message flag -- \"%s\"\n",
  906.                         cfgline, workptr);
  907.                 mode = -1;
  908.             }
  909.             break;
  910.         }
  911.     }
  912.   outofwhile:
  913.     if (CheckErrors(mode) == -1)
  914.         die(0xFF, 1, "Errors in configuration file");
  915.     return mode;
  916. }
  917.