home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / msq31004.zip / config.c next >
C/C++ Source or Header  |  1995-07-16  |  38KB  |  1,463 lines

  1. /* config.c
  2. **
  3. ** released into the PUBLIC DOMAIN 30 jul 1990 by jim nutt
  4. ** Changes released into the PUBLIC DOMAIN 10, jul 1994 by John Dennis
  5. **
  6. ** Finds & reads config files, initializes everything.
  7. **
  8. */
  9.  
  10. #define  TEXTLEN  512
  11. #define  NDEBUG   1
  12. #define AREAS_BBS 0
  13.  
  14. #include "msged.h"
  15. #include "main.h"
  16. #include "config.h"
  17. #include "nshow.h"
  18. #include "bmg.h"
  19.  
  20. /*#include <direct.h>*/
  21.  
  22.  
  23. /* non-local prototypes */
  24.  
  25. void   e_assignkey(unsigned int key, char *label);
  26. void   r_assignkey(unsigned int key, char *label);
  27.  
  28.  
  29. /* local variables */
  30.  
  31. static GROUP *group            = NULL;
  32. static int    areas_type       = 0,
  33.               num_groups       = 0,
  34.               check_area_files = 0;
  35.  
  36. static char *cfgverbs[] =
  37. {
  38.     "name",          "address",         "privatenet",       "alias",
  39.     "outfile",       "lastread",        "tosslog",          "userlist",
  40.     "swappath",      "nodepath",        "nodelist",         "helpfile",
  41.     "xxxxx",         "areafile",        "useroffset",       "quote",
  42.     "attribution",   "forwardline",     "redirline",        "followup",
  43.     "replyarea",     "replyextra",      "alterfunc",        "switch",
  44.     "qquotes",       "sqllast",         "video",            "color",
  45.     "right",         "quoteright",      "tabsize",          "curstart",
  46.     "curend",        "fido",            "squish",           "uucp",
  47.     "domain",        "gate",            "origin",           "readkey",
  48.     "editkey",       "function",        "include",          "speller",
  49.     "videoseg",      "maxx",             "maxy",            "template",
  50.     "uucpname",      "group",            "colour",          "editor",
  51.     NULL
  52.    };
  53.  
  54. static struct colorverb colortable[] =
  55. {
  56.     {"black",     0x00}, {"blue",      0x01}, {"green",     0x02},
  57.     {"cyan",      0x03}, {"red",       0x04}, {"magenta",   0x05},
  58.     {"brown",     0x06}, {"lgrey",     0x07}, {"dgrey",     0x08},
  59.     {"lblue",     0x09}, {"lgreen",    0x0A}, {"lcyan",     0x0B},
  60.     {"lred",      0x0C}, {"lmagenta",  0x0D}, {"yellow",    0x0E},
  61.     {"white",     0x0F}, {"intense",   0x08}, {"_black",    0x00},
  62.     {"_blue",     0x10}, {"_green",    0x20}, {"_cyan",     0x30},
  63.     {"_red",      0x40}, {"_magenta",  0x50}, {"_brown",    0x60},
  64.     {"_lgrey",    0x70}, {"_dgrey",    0x80}, {"_lblue",    0x90},
  65.     {"_lgreen",   0xA0}, {"_lcyan",    0xB0}, {"_lred",     0xC0},
  66.     {"_lmagenta", 0xD0}, {"_yellow",   0xE0}, {"_white",    0xF0},
  67.     {"_blink",    0x80}, {NULL, 0x00}
  68.     };
  69.  
  70. static char *cfgcolors[] =
  71. {
  72.     "mainnorm",    "mainquote",    "mainkludge",   "maintempl",   "maininfo",
  73.     "maindivide",  "mainheader",   "mainhdrtxt",   "mainblock",   "mainedit",
  74.     "mainwarn",    "mainnetinf",   "menuborder",   "menunorm",    "menuselect",
  75.     "helpborder",  "helptitle",    "helpnorm",     "helphilight", "infoborder",
  76.     "infonorm",    "inputborder",  "inputnorm",    "inputedit",   "dlgborder",
  77.     "dlgnorm",     "dlgchnorm",    "dlgchsel",     "dlgennorm",   "dlgensel",
  78.     "dlgbutsel",   "dlgbutnorm",   "dlgbutshadow", "listbdr",     "listtitle",
  79.     "listnorm",    "listinfo",     "listselect",    NULL
  80. };
  81.  
  82. static char *cfgswitches[] =
  83. {
  84.     "hardquote", "savecc", "rawcc", "seen-bys", "shownotes",
  85.     "confirm", "showaddr", "msgids", "opusdate", "datearvd",
  86.     "chopquote", "qquotes", "uselastr", "showcr", "showeol",  
  87.     "realmsgn", "usemouse", "editcronly", "usepid", "soteot",
  88.     "tearline", "showsystem", NULL
  89. };
  90.  
  91.  
  92. /*
  93. **
  94. ** Strips leading whitespaces from a string.
  95. **
  96. */
  97.  
  98. char *  striplwhite(char *s)
  99. {
  100.     while (*s && isspace((unsigned char)*s))
  101.         s++;
  102.     return(s);
  103. }
  104.  
  105.  
  106. /*
  107. **
  108. ** Strips trailing spaces from a string.
  109. **
  110. */
  111.  
  112. char *  striptwhite(char *s)
  113. {
  114.     char *c = s;
  115.  
  116.     if (!s)
  117.         return NULL;
  118.  
  119.     s = c + strlen(c) - 1;  /* dunno why I reversed it */
  120.     while (((s > c) && *s && isspace((unsigned char)*s)) 
  121.            || (*s == '\\') || (*s == '/'))
  122.     {
  123.         *s = '\0'; s--;
  124.     }
  125.     return((c) ? c : NULL);
  126. }
  127.  
  128.  
  129. /*
  130. **
  131. ** Skips from current position to first blank found.
  132. **
  133. */
  134.  
  135. char *  skip_to_blank(char *str)
  136. {
  137.     while (str && *str && !isspace((unsigned char)*str)) str++;
  138.  
  139.     return str;
  140. }
  141.  
  142.  
  143. /*
  144. **
  145. ** Kills a trailing slash from a path.
  146. **
  147. */
  148.  
  149. void  kill_trail_slash(char *s)
  150. {
  151.     char *c = s + strlen(s) - 1;
  152.  
  153.     if (*c == '\\' || *c == '/')
  154.         *c = '\0';
  155. }
  156.  
  157.  
  158. /*
  159. **
  160. ** Returns the number of the passed verb in relation to
  161. ** the cfgverbs array, or -1 if the passed verb is not
  162. ** in the array.
  163. **
  164. */
  165.  
  166. int GetVerbNum(char *verb)
  167. {
  168.     int i = 0;
  169.  
  170.     while (cfgverbs[i] != NULL) {
  171.         if (strcmp(verb, cfgverbs[i]) == 0)
  172.             return i;
  173.         i++;
  174.     }
  175.     return -1;
  176. }
  177.  
  178.  
  179. /*
  180. **
  181. ** Assigns the passed named area to the global colour array.
  182. **
  183. */
  184.  
  185. void AssignColor(char *name, int color)
  186. {
  187.     int i = 0;
  188.  
  189.     while (cfgcolors[i] != NULL)
  190.     {
  191.         if (stricmp(name, cfgcolors[i]) == 0)
  192.         {
  193.             cm[i] = color;
  194.             return;
  195.         }
  196.         i++;
  197.     }
  198.     printf("\nunknown color argument: %s\n", name);
  199. }
  200.  
  201.  
  202. /*
  203. **
  204. ** Assigns the passed switch name to on or off.
  205. **
  206. */
  207.  
  208. void AssignSwitch(char *swtch, int OnOff)
  209. {
  210.     int i = 0;
  211.  
  212.     while (cfgswitches[i] != NULL)
  213.     {
  214.         if (stricmp(swtch, cfgswitches[i]) == 0)
  215.             break;
  216.         i++;
  217.     }
  218.  
  219.     if (cfgswitches[i] == NULL)
  220.     {
  221.         printf("\nunknown switch: %s\n", swtch);
  222.         return;
  223.     }
  224.  
  225.     switch (i)
  226.     {
  227.         case 0:  SW->hardquote     = OnOff; break;
  228.         case 1:  SW->savecc        = OnOff; break;
  229.         case 2:  SW->rawcc         = OnOff; break;
  230.         case 3:  SW->seenbys       = OnOff; break;
  231.         case 4:  SW->shownotes     = OnOff; break;
  232.         case 5:  SW->confirmations = OnOff; break;
  233.         case 6:  SW->showaddr      = OnOff; break;
  234.         case 7:  SW->msgids        = OnOff; break;
  235.         case 8:  SW->opusdate      = OnOff; break;
  236.         case 9:  SW->datearrived   = OnOff; break;
  237.         case 10: SW->chopquote     = OnOff; break;
  238.         case 11: SW->qquote        = OnOff; break;
  239.         case 12: SW->use_lastr     = OnOff; break;
  240.         case 13: SW->showcr        = OnOff; break;
  241.         case 14: SW->showeol       = OnOff; break;
  242.         case 15: SW->showrealmsgn  = OnOff; break;
  243.         case 16: SW->usemouse      = OnOff; break;
  244.         case 17: SW->editcronly    = OnOff; break;
  245.         case 18: SW->usepid        = OnOff; break;
  246.         case 19: SW->soteot        = OnOff; break;
  247.         case 20: SW->tearline      = OnOff; break;
  248.         case 21: SW->showsystem    = OnOff; break;
  249.         default: printf("\nunknown switch: %s\n", swtch); break;
  250.     }
  251. }
  252.  
  253.  
  254. /*
  255. ** Searches through the colortable for the matching
  256. ** colorname and returns the color, or -1 if not found.
  257. */
  258.  
  259. int GetColor(char *color)
  260. {
  261.     int i = 0;
  262.  
  263.     while (colortable[i].name != NULL)
  264.     {
  265.         if (stricmp(color, colortable[i].name) == 0)
  266.             return colortable[i].color;
  267.         i++;
  268.     }
  269.     printf("\nunknown color: %s\n", color);
  270.     return -1;
  271. }
  272.  
  273.  
  274. /*
  275. **
  276. ** Determines if the passed char is a token seperator.
  277. **
  278. */
  279.  
  280. int toksep(char ch)
  281. {
  282.     switch ((int) ch)
  283.     {
  284.         case ' '  :
  285.         case ','  :
  286.         case '\r' :
  287.         case '\t' :
  288.         case '\n' :
  289.             return TRUE;
  290.         default   :
  291.             return FALSE;
  292.     }
  293. }
  294.  
  295.  
  296. /*
  297. **
  298. ** Gets num tokens from a string, seperated by a default set of tokens.
  299. ** Handles stuff bewtween quotes as one token.
  300. **
  301. */
  302.  
  303. void parse_tokens(char *str, char *tokens[], int num)
  304. {
  305.     int   i    = 0;
  306.     char *s    = str;
  307.     int   done = 0;
  308.  
  309.     while (!done && i < num)
  310.     {
  311.         if (toksep(*s))
  312.             while (*s && toksep(*s)) s++;
  313.  
  314.         if (*s == ';')
  315.         {
  316.             /*
  317.             ** We hit a comment... dinna process anymore.
  318.             */
  319.  
  320.             tokens[i] = NULL;
  321.             break;
  322.         }
  323.  
  324.         if (*s == '\"')
  325.         {
  326.             tokens[i++] = ++s;
  327.  
  328.             while (*s && *s != '\"') s++;
  329.         }
  330.         else
  331.         {
  332.             tokens[i++] = s;
  333.             while (*s && !toksep(*s)) s++;
  334.         }
  335.         if (*s == '\0')
  336.         {
  337.             tokens[i] = NULL;
  338.             done      = TRUE;
  339.         }
  340.         else
  341.             *s++ = '\0';
  342.     }
  343.     tokens[i] = NULL;
  344. }
  345.  
  346.  
  347. /*
  348. **
  349. ** Opens cfn first, and returns if successful, else it tries
  350. ** env.  env can be considered the default name.
  351. **
  352. */
  353.  
  354. static FILE *  fileopen(char *env, char *cfn)
  355. {
  356.     FILE    *fp;
  357.  
  358.     if (cfn)
  359.     {
  360.         if ((fp = fopen(cfn, "r")) != NULL)
  361.             return fp;
  362.     }
  363.  
  364.     fp = fopen(env, "r");
  365.  
  366.     return fp;
  367. }
  368.  
  369.  
  370. /*
  371. **
  372. ** Parses a macro.
  373. **
  374. */
  375.  
  376. static unsigned int *  parse_macro(char *macro)
  377. {
  378.     unsigned int *m;
  379.     unsigned int *t;
  380.     int l;
  381.     char tmp[5];
  382.  
  383.     t = m = (unsigned int *) calloc(strlen(macro) * 2,sizeof(int));
  384.  
  385.     if ((t == (void *) NULL) || (macro == NULL))
  386.         return(NULL);
  387.  
  388.     while (*macro)
  389.     {
  390.         if (*macro == '^')
  391.         {
  392.             *t++ = (unsigned int) (*(macro + 1) == '^') ? '^' : (toupper(*(macro + 1)) - 64);
  393.             macro += 2;
  394.         }
  395.         else if (*macro == '\\')
  396.         {
  397.             if (*(macro + 1) == '\\')
  398.             {
  399.                 *t++   = (unsigned int) '\\';
  400.                 macro += 2;
  401.             }
  402.             else
  403.             {
  404.                 memset(tmp,0,sizeof tmp);
  405.                 strncpy(tmp,macro+1,4);
  406.                 *t++   = (unsigned int) strtol(tmp,NULL,0) << 8;
  407.                 macro += 5;
  408.             }
  409.         }
  410.         else
  411.             *t++ = (unsigned int) *macro++;
  412.     }
  413.     *t = 0;
  414.     l  = (int) (t - m) + 1;
  415.     
  416.     t = realloc(m, l * sizeof (int));
  417.  
  418.     if (t)
  419.         return(t);
  420.  
  421.     return(m);
  422. }
  423.  
  424.  
  425. /*
  426. **
  427. ** Sets the username and the template for an area.
  428. **
  429. */
  430.  
  431. static void SetAreaInfo(AREA *a)
  432. {
  433.     int i;
  434.  
  435.     for (i = 0; i < num_groups; i++)
  436.     {
  437.         if (bmg_find(a->description, group[i].search) != NULL)
  438.             break;
  439.     }
  440.  
  441.     if (i != num_groups)
  442.     {
  443.         a->username = group[i].username;
  444.         a->template = group[i].template;
  445.     }
  446. }
  447.  
  448.  
  449. /*
  450. **
  451. ** Adds a new area to the area-list.
  452. **
  453. */
  454.  
  455. static void  AddArea(AREA *a)
  456. {
  457.     int i;
  458.     char *d, *t, *p;
  459.  
  460.     for (i = 0; i < SW->areas; i++)
  461.         if ((arealist[i].path != NULL) && (stricmp(a->path, arealist[i].path) == 0))
  462.             break;
  463.  
  464.     if (i == SW->areas)
  465.     {
  466.         /*
  467.         ** It's a new area, so we add it to the end of the list.
  468.         */
  469.  
  470.         SW->areas++;
  471.         SW->area = SW->areas - 1;
  472.         arealist = realloc(arealist, SW->areas * sizeof(struct _area));
  473.  
  474.         if (arealist == NULL)
  475.             outamemory();
  476.  
  477.         memset(&(CurArea), 0, sizeof(struct _area));
  478.  
  479.         CurArea = *a;
  480.  
  481.         if (a->addr.domain)
  482.             CurArea.addr.domain = strdup(a->addr.domain);
  483.  
  484.         CurArea.description = strdup(a->description);
  485.         CurArea.tag         = strdup(a->tag);
  486.         CurArea.path        = strdup(a->path);
  487.  
  488.         kill_trail_slash(CurArea.path);
  489.     }
  490.     else
  491.     {
  492.         /*
  493.         ** We redefine the area to the new defaults,
  494.         ** with the exception of the path, dag and desc.
  495.         */
  496.  
  497.         release(arealist[i].addr.domain);
  498.         p = arealist[i].path;
  499.         t = arealist[i].tag;
  500.         d = arealist[i].description;
  501.  
  502.         arealist[i]             = *a;
  503.         arealist[i].path        = p;
  504.         arealist[i].tag         = t;
  505.         arealist[i].description = d;
  506.         if (a->addr.domain)
  507.             arealist[i].addr.domain = strdup(a->addr.domain);
  508.     }
  509.     SetAreaInfo(&arealist[i]);
  510.  
  511.     /*
  512.     ** Clean up after us...
  513.     */
  514.  
  515.     release(a->tag);
  516.     release(a->description);
  517.     release(a->path);
  518.     release(a->addr.domain);
  519. }
  520.  
  521.  
  522. /*
  523. **
  524. ** Checks a file in the areas.bbs format and gets all
  525. ** the area definitions. First attemps to open the file
  526. ** specified on the commandline, and if that fails, tries
  527. ** for the default name "areas.bbs".
  528. **
  529. */
  530.  
  531. static void  checkareas(char *areafile)
  532. {
  533.     AREA    a;                      /* current area */
  534.     char    buffer[TEXTLEN];        /* line buffer */
  535.     FILE   *fp   = NULL;            /* file handle */
  536.     char   *s    = NULL;            /* pointer */
  537.     int     flag = 1;               /* found host name? */
  538.     int     sq   = 0;               /* a squish base? */
  539.     char   *tokens[12];
  540.  
  541.     if ((fp = fileopen("areas.bbs", areafile)) == NULL)
  542.         return;
  543.  
  544.     if (fp != NULL)
  545.     {
  546.         while (fgets(buffer, TEXTLEN, fp) != NULL)
  547.         {
  548.             if ((*buffer == '\r') || (*buffer == '\n'))
  549.                 continue;
  550.  
  551.             s = striplwhite(buffer);
  552.  
  553.             if ((*s == ';') || (*s == '-') || (*s == '#'))
  554.                 continue;
  555.  
  556.             if ((strchr(buffer,'!')) && flag)
  557.             {
  558.                 char *p = strrchr(buffer,'!');
  559.                 if (p != NULL)
  560.                 {
  561.                     *p = '\0';
  562.  
  563.                     release(ST->origin);
  564.                     ST->origin = strdup(buffer);
  565.                 }
  566.                 flag = 0;
  567.                 continue;
  568.             }
  569.  
  570.             if (*s == '$')
  571.             {
  572.                 sq = 1;
  573.                 s++;
  574.             }
  575.             else
  576.                 sq = 0;
  577.  
  578.             /*
  579.             ** Grab the tokens on the line.
  580.             */
  581.  
  582.             memset(tokens, 0, sizeof(tokens));
  583.             parse_tokens(s, tokens, 4);
  584.  
  585.             if (tokens[0] == NULL || tokens[1] == NULL)
  586.                 continue;
  587.  
  588.             memset(&a, 0, sizeof(AREA));
  589.  
  590.             a.echomail      = 1;
  591.             a.msgtype       = FIDO;
  592.             a.path          = strdup(tokens[0]);
  593.             a.tag           = strdup(tokens[1]);
  594.             a.description   = strdup(tokens[1]);
  595.             a.addr.notfound = 1;
  596.  
  597.             kill_trail_slash(a.path);
  598.  
  599.             if (tokens[2] != NULL && strlen(tokens[2]) >= 7)
  600.             {
  601.                 s = tokens[2];
  602.                 if (*s == '-' && toupper(*(s + 1)) == 'P')
  603.                     a.addr = parsenode(s + 2);
  604.             }
  605.  
  606.             if (a.addr.notfound)
  607.             {
  608.                 a.addr = thisnode;
  609.                 if (thisnode.domain)
  610.                     a.addr.domain = strdup(thisnode.domain);
  611.             }
  612.  
  613.             strlwr(a.path);
  614.             strupr(a.tag);
  615.  
  616.             if (sq)
  617.                 a.msgtype = SQUISH;
  618.  
  619.             AddArea(&a);
  620.         }
  621.     }
  622.     if (fp != NULL)
  623.         fclose(fp);
  624. }
  625.  
  626.  
  627. /*
  628. **
  629. ** Reads the areas in a squish config file.
  630. **
  631. */
  632.  
  633. static void  check_squish(char *areafile)
  634. {
  635.     AREA   a;
  636.     char   buffer[TEXTLEN];
  637.     char  *tokens[20];
  638.     FILE  *fp = NULL;
  639.     int    i  = 0;
  640.     char  *s;
  641.  
  642.     if ((fp = fileopen("squish.cfg", areafile)) == NULL)
  643.         return;
  644.  
  645.     if (fp != NULL)
  646.     {
  647.         while (fgets(buffer, TEXTLEN, fp) != NULL)
  648.         {
  649.             if ((*buffer == '\r') || (*buffer == '\n'))
  650.                 continue;
  651.  
  652.             s = striplwhite(buffer);
  653.  
  654.             if ((*s == ';') || (*s == '-') || (*s == '#'))
  655.                 continue;
  656.  
  657.             memset(tokens, 0, sizeof(tokens));
  658.             parse_tokens(s, tokens, 15);
  659.  
  660.             if (tokens[0] == NULL)
  661.                 continue;
  662.  
  663.             if (!stricmp(tokens[0],     "echoarea") ||
  664.                     !stricmp(tokens[0], "netarea")  ||
  665.                     !stricmp(tokens[0], "badarea")  ||
  666.                     !stricmp(tokens[0], "dupearea"))
  667.             {
  668.                 if (tokens[1] == NULL || tokens[2] == NULL)
  669.                     continue;
  670.  
  671.                 memset(&a, 0, sizeof(AREA));
  672.  
  673.                 if (!stricmp(tokens[0], "echoarea"))
  674.                     a.echomail = 1;
  675.                 else
  676.                 {
  677.                     a.netmail = 1;
  678.                     a.priv = 1;
  679.                 }
  680.  
  681.                 a.msgtype       = FIDO;
  682.                 a.addr.notfound = 1;
  683.                 a.tag           = strdup(tokens[1]);
  684.                 a.path          = strdup(tokens[2]);
  685.                 a.description   = strdup(tokens[1]);
  686.  
  687.                 strupr(a.tag);
  688.                 strlwr(a.path);
  689.  
  690.                 i = 3;
  691.                 while ((s = tokens[i]) != NULL)
  692.                 {
  693.                     if (*s == ';')
  694.                     {
  695.                         i = 0;
  696.                         break;
  697.                     }
  698.                     else if (*s == '-' && *(s + 1) && *(s + 1) == '$')
  699.                     {
  700.                         a.msgtype = SQUISH;
  701.                     }
  702.                     else if (*s == '-' && *(s + 1) && toupper(*(s + 1)) == 'P')
  703.                     {
  704.                         /*
  705.                         ** An address is specified... get it.
  706.                         */
  707.  
  708.                         release(a.addr.domain);
  709.                         a.addr = parsenode(s + 2);
  710.                     }
  711.                     else if (*s == '-' && *(s + 1) && *(s + 1) == '0')
  712.                     {
  713.                         /*
  714.                         ** A passthru area... ignore it.
  715.                         */
  716.  
  717.                         release(a.tag);
  718.                         release(a.description);
  719.                         release(a.path);
  720.                         release(a.addr.domain);
  721.                         i = 0;
  722.                         break;
  723.                     }
  724.                     i++;
  725.                 }
  726.  
  727.                 if (i == 0)
  728.                     continue;
  729.  
  730.                 if (a.addr.notfound)
  731.                 {
  732.                     a.addr = thisnode;
  733.                     if (thisnode.domain)
  734.                         a.addr.domain = strdup(thisnode.domain);
  735.                 }
  736.                 AddArea(&a);
  737.             }
  738.         }
  739.     }
  740.     if (fp != NULL)
  741.         fclose(fp);
  742. }
  743.  
  744.  
  745. /*
  746. **
  747. ** Reads in an area definition in the msged.cfg format.
  748. **
  749. */
  750.  
  751. static void  parsemail(char *keyword, char *value)
  752. {
  753.     char  *tokens[20];
  754.     char  *s;
  755.     AREA   a;
  756.  
  757.     memset(&a, 0, sizeof a);
  758.     memset(tokens, 0, sizeof tokens);
  759.  
  760.     switch (tolower(*keyword))        /* one letter is enough for now */
  761.     { 
  762.         default  :
  763.         case 'f' : a.msgtype = FIDO;   break;
  764.         case 's' : a.msgtype = SQUISH; break;
  765.     }
  766.  
  767.     parse_tokens(value, tokens, 5);
  768.  
  769.     if (tokens[2] == NULL)
  770.         return;
  771.  
  772.     s = tokens[0];
  773.  
  774.     while (*s)
  775.     {
  776.         switch (tolower(*s))               /* one letter is enough */
  777.         {
  778.             case 'n' : a.news     = 1; break;
  779.             case 'u' : a.uucp     = 1; break;
  780.             case 'm' : a.netmail  = 1; break;
  781.             case 'e' : a.echomail = 1; break;
  782.             case 'p' : a.priv     = 1; break;
  783.             case 'h' : a.hold     = 1; break;
  784.             case 'd' : a.direct   = 1; break;
  785.             case 'c' : a.crash    = 1; break;
  786.             case 'k' : a.killsent = 1; break;
  787.             case 'l' : a.local    = 1; break;
  788.             default  : break;
  789.         }
  790.         s++;
  791.     }
  792.  
  793.     if (!a.echomail && !a.netmail && !a.uucp && !a.news)
  794.         a.local = 1;
  795.  
  796.     a.description   = strdup(tokens[1]);
  797.     a.path          = strdup(tokens[2]);
  798.     a.addr.notfound = 1;
  799.  
  800.     if (a.echomail)
  801.     {
  802.         if (tokens[3] != NULL)
  803.         {
  804.             a.tag = strdup(tokens[3]);
  805.             if (tokens[4] != NULL)
  806.                 a.addr = parsenode(tokens[4]);
  807.         }
  808.         else
  809.             a.tag = strdup(a.description);
  810.     }
  811.     else
  812.     {
  813.         a.tag = strdup(a.description);
  814.         if (tokens[3] != NULL)
  815.             a.addr = parsenode(tokens[3]);
  816.     }
  817.  
  818.     if (a.addr.notfound)
  819.     {
  820.         a.addr = thisnode;
  821.         if (thisnode.domain)
  822.             a.addr.domain = strdup(thisnode.domain);
  823.     }
  824.     AddArea(&a);
  825. }
  826.  
  827.  
  828. /*
  829. **
  830. ** Parses an alias.
  831. **
  832. **
  833. */
  834.  
  835. static void  parse_alias(char *value)
  836. {
  837.     ALIAS  a;
  838.     char  *tokens[6];
  839.     char  *s;
  840.  
  841.     memset(&a, 0, sizeof a);
  842.     memset(tokens, 0, sizeof(tokens));
  843.  
  844.     parse_tokens(value, tokens, 5);
  845.  
  846.     if (tokens[2] == NULL)
  847.         return;
  848.  
  849.     a.alias = strdup(tokens[0]);
  850.     a.name  = strdup(tokens[1]);
  851.  
  852.     if (!stricmp(tokens[2], "uucp"))
  853.         a.addr.internet = 1;
  854.     else
  855.         a.addr  = parsenode(tokens[2]);
  856.  
  857.     if ((s = tokens[3]) != NULL)
  858.     {
  859.         a.attrib.local = 1;
  860.         a.attr         = 1;
  861.         while (*s)
  862.         {
  863.             switch (tolower(*s))
  864.             {
  865.                 case 'p' : a.attrib.private  = 1; break;
  866.                 case 'h' : a.attrib.hold     = 1; break;
  867.                 case 'd' : a.attrib.direct   = 1; break;
  868.                 case 'c' : a.attrib.crash    = 1; break;
  869.                 case 'k' : a.attrib.killsent = 1; break;
  870.                 case 'n' : a.attr = 0;            break;
  871.                 default  : break;
  872.             }
  873.             s++;
  874.         }
  875.         if (tokens[4] != NULL)
  876.             a.subj = strdup(tokens[4]);
  877.     }
  878.  
  879.     aliaslist = realloc(aliaslist, (++SW->otheraliases) * sizeof(struct _alias));
  880.  
  881.     if (aliaslist == NULL)
  882.         outamemory();
  883.  
  884.     aliaslist[SW->otheraliases - 1] = a;
  885. }
  886.  
  887.  
  888. /*
  889. **
  890. ** Handles the areafiles...
  891. **
  892. */
  893.  
  894. void  do_areafile(char *value)
  895. {
  896.     char *tokens[3];
  897.  
  898.     memset(tokens, 0, sizeof(tokens));
  899.     parse_tokens(value, tokens, 2);
  900.  
  901.     if (tokens[0] == NULL)
  902.         return;
  903.  
  904.     areas_type = AREAS_BBS;
  905.  
  906.     if (toupper(*tokens[0]) == 'S')
  907.         areas_type = SQUISH;
  908.  
  909.     if (tokens[1])
  910.     {
  911.         if (areas_type == AREAS_BBS)
  912.             checkareas(tokens[1]);
  913.         else
  914.             check_squish(tokens[1]);
  915.     }
  916.     else
  917.     {
  918.         /*
  919.         ** If no area-file was specified, then we want to check later.
  920.         */
  921.  
  922.         check_area_files = 1;
  923.     }
  924. }
  925.  
  926.  
  927. /*
  928. **
  929. ** Hanldes an entire config file.
  930. **
  931. **
  932. */
  933.  
  934. static void  parseconfig(FILE *fp)
  935. {
  936.     char    progress_indicators[4] = {'-', '\\', '|', '/'};
  937.     char    buffer[TEXTLEN];
  938.     char   *keyword = NULL;
  939.     char   *value   = NULL;
  940.     char   *s       = NULL;
  941.     char   *tokens[20];
  942.     int     i, line_num = 0;
  943.  
  944.     memset(buffer, 0, TEXTLEN);
  945.  
  946.     while (!feof(fp))
  947.     {
  948.         line_num++;
  949.         printf("%c\b", progress_indicators[line_num % 4]);
  950.         
  951.         if (fgets(buffer, TEXTLEN, fp) == NULL)
  952.             return;
  953.  
  954.         keyword = strtok(buffer, " \t\n\r");
  955.  
  956.         if (keyword)
  957.             strlwr(keyword);
  958.         else
  959.             continue;
  960.  
  961.         if ((*keyword) == ';')
  962.             continue;
  963.  
  964.         value = strtok(NULL, ";\n\r");
  965.         value = striptwhite(value);
  966.  
  967.         /* clear the pointers in the array */
  968.  
  969.         memset(tokens, 0, sizeof(tokens));
  970.  
  971.         while (value && *value && isspace((unsigned char)*value))
  972.             if ((*value == '\n') || (*value == ';'))
  973.                 break;
  974.             else
  975.                 value++;
  976.  
  977.         switch(GetVerbNum(keyword))
  978.         {
  979.             case -1:
  980.                 printf("\nunknown config verb: %s\n", keyword);
  981.                 break;
  982.  
  983.             case  0:
  984.                 parse_tokens(value, tokens, 3);
  985.                 if (tokens[0] != NULL)
  986.                 {
  987.                     for (i = 0; i < 11; i++)
  988.                     {
  989.                         if (user_list[i].name == NULL)
  990.                             break;
  991.                     }
  992.                     if (i < 11)
  993.                     {
  994.                         user_list[i].name = strdup(tokens[0]);
  995.  
  996.                         if (tokens[1] != NULL)
  997.                             user_list[i].lastread = strdup(tokens[1]);
  998.  
  999.                         if (tokens[2] != NULL)
  1000.                             user_list[i].offset = atol(tokens[2]);
  1001.  
  1002.                         if (i == 0)
  1003.                         {
  1004.                             release(ST->username);
  1005.                             ST->username = strdup(user_list[i].name);
  1006.  
  1007.                             if (user_list[i].lastread)
  1008.                             {
  1009.                                 release(ST->lastread);
  1010.                                 ST->lastread = strdup(user_list[i].lastread);
  1011.                             }
  1012.                             SW->useroffset = user_list[i].offset;
  1013.                         }
  1014.                     }
  1015.                 }
  1016.                 break;
  1017.  
  1018.             case 1:
  1019.                 alias = realloc(alias, (++SW->aliascount) * sizeof(ADDRESS));
  1020.                 alias[SW->aliascount - 1] = parsenode(value);
  1021.                 break;
  1022.  
  1023.             case 2:
  1024.                 SW->pointnet = (int) strtol(value, NULL, 0);
  1025.                 break;
  1026.  
  1027.             case 3:
  1028.                 parse_alias(value);
  1029.                 break;
  1030.  
  1031.             case 4:
  1032.                 release(ST->outfile);
  1033.                 ST->outfile = strdup(value);
  1034.                 break;
  1035.  
  1036.             case 5:
  1037.                 if (user_list[0].name == NULL)
  1038.                 {
  1039.                     release(ST->lastread);
  1040.                     ST->lastread          = strdup(value);
  1041.                     user_list[0].lastread = strdup(value);
  1042.                 }
  1043.                 break;
  1044.  
  1045.             case 6:
  1046.                 release(ST->confmail);
  1047.                 ST->confmail = strdup(value);
  1048.                 break;
  1049.  
  1050.             case 7:
  1051.                 ST->fidolist = strdup(strtok(value, ",\n"));
  1052.                 if ((ST->userlist = strtok(NULL,",\n")) != NULL)
  1053.                     ST->userlist = strdup(ST->userlist);
  1054.                 break;
  1055. #ifndef __OS2__
  1056.             case 8:
  1057.                 release(ST->swap_path);
  1058.                 kill_trail_slash(value);
  1059.                 ST->swap_path = strdup(value);
  1060.                 break;
  1061. #endif
  1062.             case 9:
  1063.                 release(ST->nodepath);
  1064.                 ST->nodepath = strdup(value);
  1065.                 break;
  1066.  
  1067.             case 10:
  1068.                 parse_tokens(value, tokens, 3);
  1069.                 if (tokens[2] != NULL)
  1070.                 {
  1071.                     node_lists = realloc(node_lists, (++SW->nodelists) * sizeof(D_LIST));
  1072.  
  1073.                     if (node_lists == NULL)
  1074.                         outamemory();
  1075.  
  1076.                     node_lists[SW->nodelists - 1].name      = strdup(tokens[0]);
  1077.                     node_lists[SW->nodelists - 1].base_name = strdup(tokens[1]);
  1078.                     node_lists[SW->nodelists - 1].sysop     = strdup(tokens[2]);
  1079.  
  1080.                     if (SW->nodelists == 1)
  1081.                     {
  1082.                         ST->nodebase = node_lists[SW->nodelists - 1].base_name;
  1083.                         ST->sysop    = node_lists[SW->nodelists - 1].sysop;
  1084.                     }
  1085.                 }
  1086.                 break;
  1087.  
  1088.             case 11:
  1089.                 release(ST->helpfile);
  1090.                 ST->helpfile = strdup(value);
  1091.                 break;
  1092.  
  1093.             case 12:
  1094.                 break;
  1095.  
  1096.             case 13:
  1097.                 do_areafile(value);
  1098.                 break;
  1099.  
  1100.             case 14:
  1101.                 SW->useroffset = atoi(value);
  1102.                 break;
  1103.  
  1104.             case 15:
  1105.                 release(ST->quotestr);
  1106.                 striptwhite(value);
  1107.                 s = ST->quotestr = strdup(value);
  1108.                 while (*s)
  1109.                 {
  1110.                     *s = (*s == (char) '_') ? (char) ' ' : *s;
  1111.                     s++;
  1112.                 }
  1113.                 break;
  1114.  
  1115.             case 22:
  1116.                 parse_tokens(value, tokens, 2);
  1117.  
  1118.                 if (tokens[0] && tokens[1])
  1119.                 {
  1120.                     int var = 0;
  1121.                     char *c;
  1122.  
  1123.                     c = striplwhite(tokens[0]);
  1124.                     s = striplwhite(tokens[1]);
  1125.  
  1126.                     if ((*s != '\0') && (*c != '\0'))
  1127.                     {
  1128.                         while (*c && !isspace((unsigned char)*c))
  1129.                         {
  1130.                             switch (toupper(*c))
  1131.                             {
  1132.                                 case 'Q' :
  1133.                                     if (!(var & MT_REP) && !(var & MT_NEW))
  1134.                                         var |= MT_QUO;
  1135.                                     break;
  1136.  
  1137.                                 case 'R' :
  1138.                                     if (!(var & MT_QUO) && !(var & MT_NEW))
  1139.                                         var |= MT_REP;
  1140.                                     break;
  1141.  
  1142.                                 case 'N' :
  1143.                                     if (!(var & MT_QUO) && !(var & MT_REP))
  1144.                                         var |= MT_NEW;
  1145.                                     break;
  1146.  
  1147.                                 case 'A' : var |= MT_ARC; break;
  1148.                                 case 'F' : var |= MT_FOL;  break;
  1149.                                 default  : break;
  1150.                             }
  1151.                             c++;
  1152.                         }
  1153.                         if (!stricmp("replyquote", s))
  1154.                             SW->rquote = var;
  1155.                         else if (!stricmp("replyotherarea", s))
  1156.                             SW->rotharea = var;
  1157.                         else if (!stricmp("replyfollow", s))
  1158.                             SW->rfollow = var;
  1159.                         else if (!stricmp("replyextra", s))
  1160.                             SW->rextra = var;
  1161.                     }
  1162.                 }
  1163.                 break;
  1164.  
  1165.             case 23:
  1166.                 parse_tokens(value, tokens, 2);
  1167.                 if (tokens[1] != NULL)
  1168.                     AssignSwitch(value, (stricmp(tokens[1], "on") == 0) ? 1 : 0);
  1169.                 break;
  1170.  
  1171.             case 24:
  1172.                 SW->qquote = 1;
  1173.                 break;
  1174.  
  1175.             case 25:
  1176.                 SW->use_lastr = 1;
  1177.                 break;
  1178.  
  1179.             case 26:
  1180.                 /* do nothing */
  1181.                 break;
  1182.  
  1183.             case 27:
  1184.             case 50:
  1185.                 parse_tokens(value, tokens, 3);
  1186.                 if (tokens[2] != NULL)
  1187.                 {
  1188.                     int fcol, bcol;
  1189.  
  1190.                     fcol = GetColor(tokens[1]);
  1191.                     bcol = GetColor(tokens[2]);
  1192.  
  1193.                     if (fcol == -1 || bcol == -1)
  1194.                         continue;
  1195.  
  1196.                     AssignColor(tokens[0], fcol|bcol);
  1197.                 }
  1198.                 break;
  1199.  
  1200.             case 28:
  1201.                 SW->rm = (int) strtol(value,NULL,0);
  1202.                 break;
  1203.  
  1204.             case 29:
  1205.                 SW->qm = (int) strtol(value,NULL,0);
  1206.                 break;
  1207.  
  1208.             case 30:
  1209.                 SW->tabsize = (int) strtol(value,NULL,0);
  1210.                 break;
  1211.  
  1212.             case 31:
  1213.                 cur_start = atoi(value);
  1214.                 break;
  1215.  
  1216.             case 32:
  1217.                 cur_end = atoi(value);
  1218.                 break;
  1219.  
  1220.             case 33:
  1221.             case 34:
  1222.                 parsemail(keyword, value);
  1223.                 break;
  1224.  
  1225.             case 35:
  1226.                 uucp_gate = parsenode(value);
  1227.                 break;
  1228.  
  1229.             case 36:
  1230.                 domain_list = realloc(domain_list, (++SW->domains) * sizeof(ADDRESS));
  1231.  
  1232.                 if (domain_list == NULL)
  1233.                     outamemory();
  1234.  
  1235.                 domain_list[SW->domains - 1] = parsenode(value);
  1236.                 break;
  1237.  
  1238.             case 37:
  1239.                 if (value) strlwr(value);
  1240.                 if (strncmp(value, "zones",5) == 0)
  1241.                     SW->gate = GZONES;
  1242.                 else if (strncmp(value, "domains",7) == 0)
  1243.                     SW->gate = GDOMAINS;
  1244.                 else if (strncmp(value, "both",4) == 0)
  1245.                     SW->gate = BOTH;
  1246.                 else if (strncmp(value, "none",4) == 0)
  1247.                     SW->gate = 0;
  1248.                 break;
  1249.  
  1250.             case 38:
  1251.                 if (value != NULL)
  1252.                 {
  1253.                     release(ST->origin);
  1254.                     ST->origin = strdup(value);
  1255.                 }
  1256.                 break;
  1257.  
  1258.             case 39:
  1259.             case 40:
  1260.                 if (value)
  1261.                 {
  1262.                     strlwr(value);
  1263.                     i     = (int) strtol(value,&value,0);
  1264.                     value = striplwhite(value);
  1265.                 }
  1266.                 if (*keyword == 'e')
  1267.                     e_assignkey(i, value);
  1268.                 else
  1269.                     r_assignkey(i, value);
  1270.                 break;
  1271.  
  1272.             case 41:
  1273.                 i = (int) strtol(value,&s,0);
  1274.                 s = striplwhite(s);
  1275.  
  1276.                 if ((i >= 0) && (i <= 40))
  1277.                     macros[i] = parse_macro(s);
  1278.                 break;
  1279.  
  1280.             case 42:
  1281.             {
  1282.                 FILE *ifp;
  1283.                 if ((ifp = fopen(value,"r")) != NULL)
  1284.                 {
  1285.                     parseconfig(ifp);
  1286.                     fclose(ifp);
  1287.                 }
  1288.             }
  1289.             break;
  1290.  
  1291.             case 45:
  1292.                 maxx = (int) strtol(value,NULL,0);
  1293.                 break;
  1294.  
  1295.             case 46:
  1296.                 maxy = (int) strtol(value,NULL,0);
  1297.                 break;
  1298.  
  1299.             case 47:
  1300.                 templates = realloc(templates, (++SW->numtemplates) * sizeof(char *));
  1301.  
  1302.                 if (templates == NULL)
  1303.                     outamemory();
  1304.  
  1305.                 templates[SW->numtemplates - 1] = strdup(value);
  1306.  
  1307.                 if (SW->numtemplates == 1)
  1308.                 {
  1309.                     ST->template = strdup(templates[SW->numtemplates - 1]);
  1310.                 }
  1311.                 break;
  1312.  
  1313.             case 48:
  1314.                 release(ST->uucpgate);
  1315.                 ST->uucpgate = strdup(value);
  1316.  
  1317.             case 49:
  1318.                 group = realloc(group, (++num_groups) * sizeof(GROUP));
  1319.  
  1320.                 if (group == NULL)
  1321.                     outamemory();
  1322.  
  1323.                 parse_tokens(value, tokens, 3);
  1324.  
  1325.                 if (tokens[2] != NULL)
  1326.                 {
  1327.                     group[num_groups - 1].search   = strdup(strupr(tokens[0]));
  1328.                     group[num_groups - 1].username = atoi(tokens[1]);
  1329.                     /* mod PE 1995-04-12 to protect against wild user */
  1330.                     if ((group[num_groups - 1].username >= MAXUSERS)
  1331.                         || (group[num_groups - 1].username >= MAXUSERS)
  1332.                         || (user_list[group[num_groups - 1].username].name 
  1333.                             == NULL))
  1334.                     {
  1335.                         group[num_groups - 1].username = 0;
  1336.                     }                    
  1337.                     group[num_groups - 1].template = atoi(tokens[2]);
  1338.                     /* mod PE 1995-04-08 to protect against wild template */
  1339.                     if (group[num_groups - 1].template >= SW->numtemplates)
  1340.                     {
  1341.                         group[num_groups - 1].template = 0;
  1342.                     }
  1343.                 }
  1344.                 break;
  1345.                 
  1346.             case 51:
  1347.                 ST->editorName = strdup(value);
  1348.                 break;
  1349.  
  1350.             default :
  1351.                 printf("\nunknown config verb: %s\n", keyword);
  1352.                 break;
  1353.         }
  1354.         memset(buffer, 0, TEXTLEN);
  1355.     }
  1356. }
  1357.  
  1358.  
  1359. /*
  1360. **
  1361. ** Handles the entire configuration process.
  1362. **
  1363. **
  1364. */
  1365.  
  1366. void  opening(char *cfgfile, char *areafile)
  1367. {
  1368.     WND    *hCurr, *hWnd;
  1369.     FILE   *fp        = NULL;
  1370.     int     count     = 0,i;
  1371.     char    cfnname[] = "msged.cfg";
  1372.     char    tmp[PATHLEN];
  1373.  
  1374.     InitVars();
  1375.  
  1376.     printf("Msgedsq %s; FTSC & Squish compatible Mail Editor", VERSION CLOSED);
  1377.  
  1378.     if ((fp = fileopen(cfnname, cfgfile)) == NULL)
  1379.     {
  1380.         if (cfgfile == NULL)
  1381.             cfgfile = cfnname;
  1382.  
  1383.         printf("\n\nCould not find config file %s", cfgfile);
  1384.         exit(-1);
  1385.     }
  1386.  
  1387.     printf("\n\nReading configuration file: %s => ", (cfgfile == NULL) ? cfnname : cfgfile);
  1388.  
  1389.     if (fp)
  1390.     {
  1391.         parseconfig(fp);
  1392.     }
  1393.  
  1394.     for (i = 0; i < 40; i++)
  1395.         count += (macros[i] != (void *) NULL) ? 1 : 0;
  1396.  
  1397.     if (fp) fclose(fp);
  1398.  
  1399.     if (check_area_files)
  1400.     {
  1401.         if (areas_type == AREAS_BBS)
  1402.             checkareas(areafile);
  1403.         else
  1404.             check_squish(areafile);
  1405.     }
  1406.  
  1407.     if (!arealist)
  1408.     {
  1409.         printf("\n\nError! At least one message area must be defined.");
  1410.         exit(-1);
  1411.     }
  1412.  
  1413.     printf("\b Finished.\n");
  1414.  
  1415.     InitScreen();
  1416.  
  1417.     cursor(0);
  1418.  
  1419.     SW->rm = (SW->rm > maxx)   ? maxx : SW->rm;
  1420.     SW->qm = (SW->qm > SW->rm) ? SW->rm - strlen(ST->quotestr) : SW->qm;
  1421.  
  1422.     hCurr = Wtop();
  1423.     hWnd  = WPopUp(60, 15, SBDR|SHADOW, cm[IN_BTXT], cm[IN_NTXT]);
  1424.  
  1425.     if (!hWnd) outamemory();
  1426.  
  1427.     WTitle(" System Information ", cm[IN_BTXT]);
  1428.     WPutsCen(1, cm[IN_NTXT], "Msgedsq FTS & Squish Compatible Mail Editor");
  1429.     WPutsCen(2, cm[IN_NTXT], "v"VERSION CLOSED "; Authors Paul Edwards, John Dennis, Jim Nutt");
  1430.     WPutsCen(3, cm[IN_NTXT], "modifications by Bill Bond");
  1431.     WPutsCen(4, cm[IN_NTXT], "Compiled : "__DATE__" " __TIME__);
  1432.  
  1433.     sprintf(tmp, "Screen of %d by %d ", maxx, maxy);
  1434.     WPutsCen(5, cm[IN_NTXT], tmp);
  1435.     sprintf(tmp, "User is %s at %s%s", ST->username, show_address(&thisnode), (SW->aliascount > 1) ? " (primary)" : "");
  1436.     WPutsCen(6, cm[IN_NTXT], tmp);
  1437.  
  1438.     if (ST->origin != NULL)
  1439.         WPutsCen(7, cm[IN_NTXT], ST->origin);
  1440.     else
  1441.         WPutsCen(7, cm[IN_NTXT], "No \"Origin:\" line!");
  1442.  
  1443.     sprintf(tmp, "%d Message areas found", SW->areas);
  1444.     WPutsCen(8, cm[IN_NTXT], tmp);
  1445.     sprintf(tmp, "%d Macros defined",count);
  1446.     WPutsCen(9, cm[IN_NTXT], tmp);
  1447.  
  1448.     mygetcwd(tmp,PATHLEN);
  1449.     strlwr(tmp);
  1450.     ST->home = strdup(tmp);
  1451.  
  1452.     sprintf(tmp, "home directory is %s", ST->home);
  1453.     WPutsCen(10, cm[IN_NTXT], tmp);
  1454.     WPutsCen(12, cm[IN_NTXT], "Press <enter> to continue");
  1455.  
  1456.     GetKey();
  1457.  
  1458.     WClose(hWnd);
  1459.     WCurr(hCurr);
  1460. }
  1461.  
  1462. /* end */
  1463.