home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / bts314b4 / btctl.c < prev    next >
C/C++ Source or Header  |  1992-12-21  |  33KB  |  822 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*  (C) Copyright 1987-90, Bit Bucket Software Co., a Delaware Corporation. */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*               This module was written by Vince Perriello                 */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*                 BinkleyTerm OMMM Control File Generator                  */
  17. /*                                                                          */
  18. /*                                                                          */
  19. /*    For complete  details  of the licensing restrictions, please refer    */
  20. /*    to the License  agreement,  which  is published in its entirety in    */
  21. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.240.    */
  22. /*                                                                          */
  23. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  24. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  25. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  26. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  27. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  28. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  29. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  30. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  31. /*                                                                          */
  32. /*                                                                          */
  33. /* You can contact Bit Bucket Software Co. at any one of the following      */
  34. /* addresses:                                                               */
  35. /*                                                                          */
  36. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:132/491, 1:141/491  */
  37. /* P.O. Box 460398                AlterNet 7:491/0                          */
  38. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  39. /*                                Internet f491.n132.z1.fidonet.org         */
  40. /*                                                                          */
  41. /* Please feel free to contact us at any time to share your comments about  */
  42. /* our software and/or licensing policies.                                  */
  43. /*                                                                          */
  44. /*--------------------------------------------------------------------------*/
  45.  
  46. #include <stdio.h>
  47. #include <signal.h>
  48. #include <ctype.h>
  49. #include <conio.h>
  50. #include <stdlib.h>
  51. #include <string.h>
  52. #ifndef __TOS__
  53. #include <sys/types.h>
  54. #include <sys/stat.h>
  55. #endif
  56.  
  57. #ifdef __TURBOC__
  58. #ifdef __TOS__
  59. #include <ext.h>
  60. #else
  61. #include <alloc.h>
  62. #endif
  63. #else
  64. #ifndef LATTICE
  65. #include <malloc.h>
  66. #endif
  67. #endif
  68.  
  69. struct parse_list {
  70.         size_t p_length;
  71.         char *p_string;
  72.         };
  73.  
  74. /*
  75.  * Use portable word size defintions
  76.  */
  77.  
  78. #ifdef ATARIST
  79.  
  80. #include <portab.h>
  81.  
  82. #ifndef H_BINK
  83. typedef WORD word;
  84. typedef BYTE byte;
  85. #endif
  86.  
  87. #else
  88. typedef unsigned bit;
  89. typedef unsigned int word;
  90. typedef unsigned char byte;
  91. #endif
  92.  
  93. #define write_binary "wb"
  94. #ifdef __TOS__
  95. #define read_ascii "r"
  96. #else
  97. #define read_ascii "ra"
  98. #endif
  99.  
  100. /*--------------------------------------------------------------------------*/
  101. /* The following is excerpted from the control structures used by Opus 1.10 */
  102. /* as it is currently implemented. The only part that really concerns BTCTL */
  103. /* is that part of the _PRM structure that contains the version number and  */
  104. /* the network address. Only those parts are actually handled by this code. */
  105. /* We suspect that no changes will be made in that part of the structure    */
  106. /* between now and the release of Opus 1.10. If I were you, I would make    */
  107. /* no such assumptions about the rest.                                      */
  108. /*--------------------------------------------------------------------------*/
  109.  
  110. #define  THIS_CTL_VERSION  16       /* PRM structure version number         */
  111.  
  112. #define CTLSIZE 1
  113. #define OFS     char*
  114.  
  115. #define  MAX_EXTERN         8       /* max. number of external programs     */
  116. #define  MAXCLASS          12       /* number of possible priv levels       */
  117. #define  ALIAS_CNT         15       /* number of matrix addresses           */
  118.  
  119. /*--------------------------------------------------------------------------*/
  120. /* FIDONET ADDRESS STRUCTURE                                                */
  121. /*--------------------------------------------------------------------------*/
  122. typedef struct _ADDRESS
  123.    {
  124.    word  Zone;
  125.    word  Net;
  126.    word  Node;
  127.    word  Point;
  128.    } ADDR;
  129.  
  130. /*--------------------------------------------------------------------------*/
  131. /* Attributes of a given class of users                                     */
  132. /*--------------------------------------------------------------------------*/
  133. struct   class_rec
  134.    {
  135.    byte  ClassPriv;
  136.    byte  class_fill;
  137.    word   max_time;      /* max cume time per day         */
  138.    word   max_call;      /* max time for one call         */
  139.    word   max_dl;        /* max dl bytes per day          */
  140.    word  ratio;         /* ul:dl ratio                   */
  141.    word  min_baud;      /* speed needed for logon        */
  142.    word  min_file_baud; /* speed needed for file xfer    */
  143.    };
  144.  
  145. /*--------------------------------------------------------------------------*/
  146. /* Registers to pass to a FOSSIL appendage                                  */
  147. /*--------------------------------------------------------------------------*/
  148. struct _FOSREGS
  149.    {
  150.    word  ax;
  151.    word  bx;
  152.    word  cx;
  153.    word  dx;
  154.    };
  155.  
  156. /*--------------------------------------------------------------------------*/
  157. /* The format of the PRM file, VERSION 16                                   */
  158. /*                                                                          */
  159. /* THIS IS AN EXPLOSIVE STRUCTURE.  IT IS SUBJECT TO CHANGE WITH NO NOTICE. */
  160. /*                                                                          */
  161. /* Offsets to the following item(s) are guaranteed:                         */
  162. /*                                                                          */
  163. /*      byte   version;        /* OFFSET 0, all versions                    */
  164. /*      byte   task_num;       /* OFFSET 1, 16+                             */
  165. /*                                                                          */
  166. /*--------------------------------------------------------------------------*/
  167.  
  168. struct _PRM
  169.    {
  170.                /*-----------------------------------------------------------*/
  171.                /* DATA                                                      */
  172.                /*-----------------------------------------------------------*/
  173.          byte  version;        /* for safety                          STABLE*/
  174.          byte  task_num;       /* for multi-tasking systems           STABLE*/
  175.          ADDR  alias[ALIAS_CNT];
  176.  
  177.          byte  video;          /* 0=Dos, 1=Fossil 2=IBM                     */
  178.          byte  testmode;       /* input from keyboard, not modem            */
  179.  
  180.          word  carrier_mask;
  181.          word  handshake_mask;
  182.          word  max_baud;       /* fastest speed we can use                  */
  183.          word  com_port;       /* Com1=0, Com2=1, FF=keyboard               */
  184.  
  185.          byte  multitasker;    /* flag for DoubleDos (see below)            */
  186.          byte  mailer_type;    /* 0=Opus, 1=load external, 2=call external  */
  187.  
  188.          byte  ModemFlag;      /* (See MODEM FLAG below)                    */
  189.          byte  LogFlag;        /* (See LOG FLAG below)                      */
  190.  
  191.          byte  StyleFlag;      /* (See STYLE FLAG below)                    */
  192.          byte  FWDflag;        /* Bits to control IN TRANSIT messages       */
  193.  
  194.          byte  Flags;          /* See "FLAGS" below                         */
  195.          byte  Flags2;         /* See "FLAGS 2" below                       */
  196.  
  197.          byte  edit_exit;      /* ERRORLEVEL to use if Matrix area changed  */
  198.          byte  exit_val;       /* ERRORLEVEL to use after caller            */
  199.  
  200.          byte  crashexit;      /* non-zero= ErrorLevel exit                 */
  201.          byte  arc_exit;       /* ErrorLevel for after incomming ARCmail    */
  202.  
  203.          byte  echo_exit;      /* ERRORLEVEL for after inbound echomail     */
  204.          byte  UDB_Flags;      /* User data base flags                      */
  205.  
  206.          word  min_baud;       /* minimum baud to get on-line               */
  207.          word  color_baud;     /* min baud for graphics                     */
  208.          word  date_style;     /* Used for FILES.BBS display                */
  209.  
  210.          byte  logon_priv;     /* Access level for new users                */
  211.          byte  seenby_priv;    /* Min priv to see SEEN_BY line              */
  212.  
  213.          byte  ctla_priv;      /* Priv to see CONTROL-A lines in messages   */
  214.          byte  FromFilePriv;   /* Priv. for doing message from file         */
  215.  
  216.          byte  AskPrivs[16];   /* Array of privs. for message attr ask's    */
  217.          byte  AssumePrivs[16];/* Array of privs. for message attr assume's */
  218.  
  219.          word  logon_time;     /* time to give for logons                   */
  220.  
  221.          word  matrix_mask;
  222.          
  223.          word  MinNetBaud;     /* minimum baud rate for remote netmail      */
  224.          word  MaxJanusBaud;   /* fastest baud to use Ianus                 */
  225.  
  226.          struct class_rec class[MAXCLASS];
  227.          struct _FOSREGS FosRegs[10];
  228.  
  229.          word  F_Reward;       /* File upload time reward percentage        */
  230.  
  231.          word  last_area;      /* Highest msg area presumed to exist        */
  232.          word  last_farea;     /* Highest file area presumed to exist       */
  233.  
  234.          word  PRM_FILL3[17];
  235.  
  236.  
  237.                /*-----------------------------------------------------------*/
  238.                /* OFFSETS                                                   */
  239.                /*-----------------------------------------------------------*/
  240.  
  241.                                /*-------------------------------------------*/
  242.                                /* MODEM COMMAND STRINGS                     */
  243.                                /*-------------------------------------------*/
  244.          OFS   MDM_Init;       /* modem initialization string               */
  245.          OFS   MDM_PreDial;    /* modem dial command sent before number     */
  246.          OFS   MDM_PostDial;   /* modem command sent after dialed number    */
  247.          OFS   MDM_LookBusy;   /* mdm cmd to take modem off hook            */
  248.  
  249.                                /*-------------------------------------------*/
  250.                                /* PRIMROSE PATHS                            */
  251.                                /*-------------------------------------------*/
  252.          OFS   misc_path;      /* path to BBS/GBS files                     */
  253.          OFS   sys_path;       /* path to SYSTEM?.BBS files                 */
  254.          OFS   temppath;       /* place to put temporary files              */
  255.          OFS   net_info;       /* path to NODELIST files                    */
  256.          OFS   mailpath;       /* place to put received netmail bundles     */
  257.          OFS   filepath;       /* place to put received netmail files       */
  258.          OFS   hold_area;      /* path to pending outbound matrix traffic   */
  259.  
  260.                                /*-------------------------------------------*/
  261.                                /* DATA FILE NAMES                           */
  262.                                /*-------------------------------------------*/
  263.          OFS   user_file;      /* path/filename of User.Bbs                 */
  264.          OFS   sched_name;     /* name of file with _sched array            */
  265.          OFS   syl;            /* default system language file              */
  266.          OFS   usl;            /* default user language file                */
  267.  
  268.                                /*-------------------------------------------*/
  269.                                /* MISCELLANEOUS TEXT                        */
  270.                                /*-------------------------------------------*/
  271.          OFS   system_name;    /* board's name                              */
  272.          OFS   sysop;          /* sysop's name                              */
  273.          OFS   timeformat;
  274.          OFS   dateformat;
  275.          OFS   protocols[MAX_EXTERN]; /* external file protocol programs    */
  276.  
  277.                                /*-------------------------------------------*/
  278.                                /* BBS/GBS SUPPORT FILES                     */
  279.                                /*-------------------------------------------*/
  280.          OFS   logo;           /* first file shown to a caller              */
  281.          OFS   welcome;        /* shown after logon                         */
  282.          OFS   newuser1;
  283.          OFS   newuser2;
  284.          OFS   rookie;
  285.  
  286.          OFS   HLP_Editor;     /* Intro to msg editor for novices.          */
  287.          OFS   HLP_Replace;    /* Explain the Msg.Editor E)dit command      */
  288.          OFS   HLP_Inquire;    /* Explain the Msg. I)nquire command         */
  289.          OFS   HLP_Locate;     /* Explain the Files L)ocate command         */
  290.          OFS   HLP_Contents;   /* Explain the Files C)ontents command       */
  291.          OFS   HLP_OPed;       /* help file for the full-screen editor      */
  292.          OFS   OUT_Leaving;    /* Bon Voyage                                */
  293.          OFS   OUT_Return;     /* Welcome back from O)utside                */
  294.          OFS   ERR_DayLimit;   /* Sorry, you've been on too long...         */
  295.          OFS   ERR_TimeWarn;   /* warning about forced hangup               */
  296.          OFS   ERR_TooSlow;    /* explains minimum logon baud rate          */
  297.          OFS   ERR_XferBaud;   /* explains minimum file transfer baud rate  */
  298.          OFS   LIST_MsgAreas;  /* dump file... used instead of Dir.Bbs      */
  299.          OFS   LIST_FileAreas; /* dump file... used instead of Dir.Bbs      */
  300.         
  301.          OFS   FREQ_MyFiles;   /* file to send when FILES is file requested */
  302.          OFS   FREQ_OKList;    /* list of files approved for file requests  */
  303.          OFS   FREQ_About;     /* File Request: ABOUT file                  */
  304.  
  305.          OFS   OEC_Quotes;
  306.          OFS   byebye;         /* file displayed at logoff                  */
  307.          OFS   local_editor;   /* text editor to use in keyboard mode       */
  308.          OFS   barricade;
  309.          OFS   Files_BBS;      /* FILES.BBS filename override for CD ROM    */
  310.          OFS   mailer;         /* full external mailer command              */
  311.          OFS   common;         /* File with data common to all tasks        */
  312.  
  313.          OFS   OFS_Filler[13];
  314.  
  315.                /*-----------------------------------------------------------*/
  316.                /* Log_Name must always be the last offset in this struct    */
  317.                /* because Bbs_Init uses that symbol to flag the end of      */
  318.                /* the offsets.                                              */
  319.                /*-----------------------------------------------------------*/
  320.          OFS   log_name;       /* name of the log file                      */
  321.  
  322.  
  323.                /*-----------------------------------------------------------*/
  324.                /* Big blob of stuff                                         */
  325.                /* It's a sequence of null-terminated character arrays...    */
  326.                /* pointed-to by the offsets (above).                        */
  327.                /*-----------------------------------------------------------*/
  328.          char  buf[CTLSIZE];
  329.    };
  330.  
  331. /* Stuff used later on here */
  332.  
  333. void           main (void);
  334. void           errxit (char *);
  335. char           *fancy_str (char *);
  336. char           *add_backslash (char *);
  337. char           *delete_backslash (char *);
  338. char           *ctl_string (char *);
  339. char           *ctl_slash_string (char *);
  340. char           *skip_blanks (char *);
  341. void            parse_config (char *);
  342. void            b_initvars (void);
  343. void            b_defaultvars (void);
  344. int             parse (char *, struct parse_list *);
  345.  
  346. char           *BTCTL_ANN = "BTCtl - Revision 2.40\n\n";
  347. char           *config_name = "Binkley.Cfg";
  348. char           *BINKpath = NULL;
  349. int             pvtnet = 0;
  350. int             net_params = 0;
  351. int             Zone = 1;
  352.  
  353. /*--------------------------------------------------------------------------*/
  354. /* BTCTL                                                                    */
  355. /* Parse the BINKLEY.CFG file and write out a BINKLEY.PRM file (for use by  */
  356. /* OMMM) and a MAIL.SYS file (for use by FASTTOSS, SCANMAIL, SIRIUS, etc).  */
  357. /* If the environment variable BINKLEY exists use the path specified for    */
  358. /* ALL input and output files.                                              */
  359. /*--------------------------------------------------------------------------*/
  360.  
  361. /*--------------------------------------------------------------------------*/
  362. /* MAIL.SYS file structure                                                  */
  363. /*--------------------------------------------------------------------------*/
  364. struct _mail
  365. {
  366. word             pri_node;       /* Our node number                          */
  367. float           fudge;          /* Unknown/unused                           */
  368. word             rate;           /* Maximum baud rate                        */
  369. char            mailpath[80];   /* Path for incomming messages              */
  370. char            filepath[80];   /* Path for incomming files                 */
  371. word             pri_net;        /* Our network number                       */
  372. word             alt_node;       /* Alternate node number (mainly for HOSTS) */
  373. word             alt_net;        /* Alternate net number (mainly for HOSTS)  */
  374. };
  375.  
  376. struct _mail    mailsys;        /* MAIL.SYS used by SIRIUS  */
  377. struct _PRM     ctl;            /* where the .CTL stuff is  */
  378.  
  379. int             num_addrs = 0;
  380.  
  381. void main ()
  382. {
  383.    char           *envptr;
  384.    FILE           *stream;
  385.    char            temp[80];
  386.    char           *skip_blanks ();
  387.    struct stat     statbuf;
  388.    int             k;
  389.  
  390.    printf (BTCTL_ANN);
  391.  
  392.    b_initvars ();
  393.  
  394.    envptr = getenv ("BINKLEY");                  /* get path from environment */
  395.    if ((envptr != NULL)                          /* If there was one, and     */
  396.        && (stat (config_name,&statbuf) != 0))    /* No BINKLEY.CFG locally,   */
  397.       {
  398.       BINKpath = malloc (strlen (envptr) + 2);   /* make room for new */
  399.       strcpy (BINKpath, envptr);                 /* use BINKLEY as our path   */
  400.       add_backslash (BINKpath);
  401.       }
  402.  
  403.    parse_config ("Binkley.Evt");
  404.    parse_config (config_name);
  405.  
  406.    b_defaultvars ();
  407.  
  408.    /*
  409.     * Print out what we got.
  410.     */
  411.  
  412.    if (ctl.system_name != NULL)
  413.       printf ("System: %s\n",ctl.system_name);
  414.  
  415.    if (ctl.sysop != NULL)
  416.       printf ("Sysop:  %s\n",ctl.sysop);
  417.  
  418.    for (k = 0; k < ALIAS_CNT; k++)               /* And the alias list        */
  419.       {
  420.       if (!ctl.alias[k].Zone)
  421.          break;
  422.       printf ("Address %u:%u/%u.%u\n",
  423.                ctl.alias[k].Zone,
  424.                ctl.alias[k].Net,
  425.                ctl.alias[k].Node,
  426.                ctl.alias[k].Point);
  427.       }
  428.  
  429.    if (ctl.mailpath != NULL)
  430.       printf ("Net Mailpath %s\n",ctl.mailpath);
  431.  
  432.    if (ctl.filepath != NULL)
  433.       printf ("Net Filepath %s\n",ctl.filepath);
  434.  
  435.    printf ("\n");
  436.  
  437.    if (!net_params)
  438.       errxit ("Not enough information to establish Netmail session");
  439.  
  440.    /*
  441.     * Okay, we have the nodelist data from the BINKLEY.CFG file.
  442.     * Now write it into a BINKLEY.PRM file.
  443.     */
  444.  
  445.    if (BINKpath != NULL)                         /* If there was a BINKLEY,   */
  446.       {
  447.       strcpy (temp, BINKpath);                   /* use it here too           */
  448.       }
  449.    else
  450.       temp[0] = '\0';
  451.    strcat (temp, "Binkley.Prm");                 /* add in the file name      */
  452.  
  453.    if ((stream = fopen (temp, write_binary)) == NULL)    /* OK, let's open the file   */
  454.       errxit ("Unable to open BINKLEY.PRM");
  455.    if (fwrite (&ctl, sizeof (ctl), 1, stream) != 1) /* Try to write data out  */
  456.       errxit ("Could not write control file data to BINKLEY.PRM");
  457.    fclose (stream);                              /* close output file         */
  458.    printf ("Version 16 Control file successfully written\n");
  459.    printf ("oMMM 1.30 or above is required to use it\n\n");
  460.  
  461.    /*
  462.     * BINKLEY.PRM now written. Let's write a MAIL.SYS file too.
  463.     */
  464.  
  465.    mailsys.pri_node = ctl.alias[0].Node;
  466.    mailsys.pri_net  = ctl.alias[0].Net;
  467.    mailsys.alt_node = ctl.alias[1].Node;
  468.    mailsys.alt_net  = ctl.alias[1].Net;
  469.    strcpy (mailsys.mailpath, ctl.mailpath);
  470.    strcpy (mailsys.filepath, ctl.filepath);
  471.  
  472.    if (BINKpath != NULL)                         /* If there was a BINKLEY,   */
  473.       {
  474.       strcpy (temp, BINKpath);                   /* use it here too           */
  475.       }
  476.    else
  477.       temp[0] = '\0';
  478.    strcat (temp, "Mail.Sys");                    /* add in the file name      */
  479.  
  480.    if ((stream = fopen (temp, write_binary)) == NULL)    /* OK, let's open the file   */
  481.       errxit ("Could not open MAIL.SYS");        /* no file, no work to do    */
  482.    if (fwrite (&mailsys, sizeof (mailsys), 1, stream) != 1)
  483.       errxit ("Unable to write data to MAIL.SYS");  /* Try to write data out  */
  484.    fclose (stream);                              /* close output file         */
  485.    printf ("MAIL.SYS file successfully written\n"); /* Notify user of success */
  486. }
  487.  
  488. /**
  489.  ** b_initvars -- called before parse_config. Sets defaults that we want
  490.  ** to have set FIRST.
  491.  **/
  492.  
  493.  
  494. void b_initvars ()
  495. {
  496.    int k;
  497.  
  498.    ctl.version = 16;
  499.    for (k = 0; k < ALIAS_CNT; k++)               /* And the alias list        */
  500.       {
  501.       ctl.alias[k].Zone = ctl.alias[k].Net = 
  502.       ctl.alias[k].Node = ctl.alias[k].Point = 0;
  503.       }
  504.  
  505.    ctl.alias[0].Zone = 1;                        /* Make sure we have a zone  */
  506.    ctl.alias[0].Net = ctl.alias[0].Node = -1;    /* Default Fidonet address   */
  507.    ctl.alias[0].Point = 0;
  508.  
  509.    ctl.system_name = ctl.sysop = 
  510.    ctl.hold_area = ctl.mailpath = ctl.filepath = NULL;
  511. }
  512.  
  513. /**
  514.  ** b_defaultvars -- called after all parse_config passes complete.
  515.  ** sets anything not handled by parse_config to default if we know it.
  516.  **/
  517.  
  518.  
  519. void b_defaultvars ()
  520. {
  521.    /* Set up "point" address correctly if we can */
  522.    
  523.    if (ctl.alias[0].Point)
  524.       {
  525.       ctl.alias[0].Net   = pvtnet;
  526.       ctl.alias[0].Node  = ctl.alias[0].Point;
  527.       ctl.alias[0].Point = 0;
  528.       }
  529.  
  530.    /* If we have the minimum information to do netmail, set the flag */
  531.  
  532.    if ((ctl.alias[0].Zone  != 0)
  533.    &&  (ctl.alias[0].Net   != 0)
  534.    &&  (ctl.system_name    != NULL)
  535.    &&  (ctl.sysop          != NULL)
  536.    &&  (ctl.hold_area      != NULL)
  537.    &&  (ctl.filepath       != NULL)
  538.    &&  (ctl.mailpath       != NULL))
  539.       net_params = 1;
  540. }
  541.  
  542.  
  543. struct parse_list config_lines[] = {
  544.                                     {4,  "Zone"},
  545.                                     {6,  "System"},
  546.                                     {5,  "Sysop"},
  547.                                     {4,  "Boss"},
  548.                                     {5,  "Point"},
  549.                                     {3,  "Aka"},
  550.                                     {7,  "Address"},
  551.                                     {4,  "Hold"},
  552.                                     {7,  "NetFile"},
  553.                                     {7,  "NetMail"},
  554.                                     {7,  "Include"},
  555.                                     {10, "PrivateNet"},
  556.                                     {0, NULL}
  557. };
  558.  
  559.  
  560. void parse_config (config_file)
  561. char *config_file;
  562. {
  563.    FILE *stream;
  564.    char temp[256];
  565.    char *c;
  566.    int i;
  567.    int boss_net = 0;
  568.    int boss_node = 0;
  569.  
  570.    if (BINKpath != NULL)
  571.       sprintf (temp, "%s%s", BINKpath, config_file);
  572.    else
  573.       strcpy (temp, config_file);
  574.  
  575.    if ((stream = fopen (temp, read_ascii)) == NULL)    /* OK, let's open the file   */
  576.       return;                                    /* no file, no work to do    */
  577.  
  578.    while ((fgets (temp, 255, stream)) != NULL)   /* Now we parse the file ... */
  579.       {
  580.       c = temp;                                  /* Check out the first char  */
  581.       if ((*c == '%') || (*c == ';'))            /* See if it's a comment
  582.                                                   * line */
  583.          continue;
  584.  
  585.       i = (int) strlen (temp);                         /* how long this line is     */
  586.  
  587.       if (i < 3)
  588.          continue;                               /* If too short, ignore it   */
  589.  
  590.       c = &temp[--i];                            /* point at last character   */
  591.       if (*c == '\n')                            /* if it's a newline,        */
  592.          *c = '\0';                              /* strip it off              */
  593.  
  594.       switch (parse (temp, config_lines))
  595.          {
  596.          case 1:                                /* "Zone"         */
  597.             c = skip_blanks (&temp[4]);
  598.             Zone = atoi (c);
  599.             if (!Zone)                          /* if we didn't find a zone  */
  600.                printf ("Illegal zone: %s\n", &temp[4]);
  601.             break;
  602.  
  603.          case 2:                                /* "System"       */
  604.             ctl.system_name = ctl_string (&temp[6]);
  605.             break;
  606.  
  607.          case 3:                                /* "Sysop"        */
  608.             ctl.sysop = ctl_string (&temp[5]);
  609.             break;
  610.  
  611.          case 4:                                /* "Boss"         */
  612.             c = skip_blanks (&temp[4]);
  613.             sscanf (c, "%d/%d", &boss_net, &boss_node);
  614.             if (boss_net)
  615.                pvtnet = boss_net;
  616.             break;
  617.  
  618.          case 5:                                /* "Point"        */
  619.             i = 5;
  620.             goto address;
  621.  
  622.          case 6:                                /* "Aka"          */
  623.             i = 3;
  624.             goto address;
  625.  
  626.          case 7:                                /* "Address"      */
  627.             i = 7;
  628. address:
  629.             ctl.alias[num_addrs].Point = 0;
  630.             c = skip_blanks (&temp[i]);
  631.             i = sscanf (c, "%hd:%hd/%hd.%hd",
  632.                        &ctl.alias[num_addrs].Zone,
  633.                        &ctl.alias[num_addrs].Net,
  634.                        &ctl.alias[num_addrs].Node,
  635.                        &ctl.alias[num_addrs].Point);
  636.             if (i < 3)
  637.                {
  638.                i = sscanf (c, "%hd/%hd.%hd", 
  639.                           &ctl.alias[num_addrs].Net,
  640.                           &ctl.alias[num_addrs].Node,
  641.                           &ctl.alias[num_addrs].Point);
  642.                if (i < 2)
  643.                    break;
  644.                ctl.alias[num_addrs].Zone = Zone;
  645.                }
  646.             Zone = ctl.alias[0].Zone;           /* First is real default */
  647.             ++num_addrs;
  648.             break;
  649.  
  650.          case 8:                               /* "Hold"         */
  651.             ctl.hold_area = ctl_slash_string (&temp[4]);
  652.             break;
  653.  
  654.          case 9:                               /* "NetFile"      */
  655.             ctl.filepath = ctl_slash_string (&temp[7]);
  656.             break;
  657.  
  658.          case 10:                              /* "NetMail"      */
  659.             ctl.mailpath = ctl_slash_string (&temp[7]);
  660.             break;
  661.  
  662.          case 11:                               /* "Include"      */
  663.             c = skip_blanks (&temp[7]);
  664.             parse_config (c);
  665.             break;
  666.  
  667.          case 12:                               /* "PrivateNet"   */
  668.             c = skip_blanks (&temp[10]);
  669.             pvtnet = atoi (c);
  670.             break;
  671.  
  672.          default:
  673.             break;
  674.          }
  675.       }
  676.    fclose (stream);                              /* close input file          */
  677.  
  678. }
  679.  
  680. int parse (input, list)
  681. char *input;
  682. struct parse_list list[];
  683.  
  684. {
  685.    int i;
  686.  
  687.    for (i = 0; list[i].p_length; i++)
  688.       {
  689.       if (strnicmp (input, list[i].p_string, list[i].p_length) == 0)
  690.          return (++i);
  691.       }
  692.    return (-1);
  693. }
  694.  
  695. void errxit (error)
  696. char           *error;
  697. {
  698.    printf ("\r\n%s\n", error);
  699.    exit (0);
  700. }
  701.  
  702. char *fancy_str (string)
  703. char *string;
  704. {
  705.    register int flag = 0;
  706.    char *s;
  707.  
  708.    s = string;
  709.  
  710.    while (*string)
  711.       {
  712.       if (isalpha (*string))                     /* If alphabetic,     */
  713.          {
  714.          if (flag)                               /* already saw one?   */
  715.             *string = tolower (*string);         /* Yes, lowercase it  */
  716.          else
  717.             {
  718.             flag = 1;                            /* first one, flag it */
  719.             *string = toupper (*string);         /* Uppercase it       */
  720.             }
  721.          }
  722.       else /* if not alphabetic  */ flag = 0;    /* reset alpha flag   */
  723.       string++;
  724.       }
  725.  
  726.    return (s);
  727. }
  728.  
  729. char *add_backslash (str)
  730. char           *str;
  731. {
  732.    char           *p;
  733.  
  734.    p = str + strlen (str) - 1;
  735.  
  736.    /* Strip off the trailing blanks */
  737.    while ((p >= str) && (isspace (*p)))
  738.       {
  739.       *p = '\0';
  740.       --p;
  741.       }
  742.  
  743.    /* Put a backslash if there isn't one */
  744.    if ((*p != '\\') && (*p != '/'))
  745.       {
  746.       *(++p) = '\\';
  747.       *(++p) = '\0';
  748.       }
  749.  
  750.    return (fancy_str (str));
  751. }
  752.  
  753. char *delete_backslash (str)
  754. char           *str;
  755. {
  756.    char           *p;
  757.  
  758.    p = str + strlen (str) - 1;
  759.  
  760.    if (p >= str)
  761.       {
  762.       /* Strip off the trailing blanks */
  763.       while ((p >= str) && (isspace (*p)))
  764.          {
  765.          *p = '\0';
  766.          --p;
  767.          }
  768.  
  769.       /* Get rid of backslash if there is one */
  770.       if ((p >=str) && ((*p == '\\') || (*p == '/')))
  771.          {
  772.          if ((p > str) && (*(p-1) != ':'))      /* Don't delete on root */
  773.             *p = '\0';
  774.          }
  775.       }
  776.  
  777.    return (fancy_str (str));
  778. }
  779. char           *ctl_string (source)             /* malloc & copy to ctl      */
  780. char           *source;
  781. {
  782.    char           *dest, *c;
  783.  
  784.    c = skip_blanks (source);    /* get over the blanks       */
  785.    dest = malloc (strlen (c) + 1);      /* allocate space for string */
  786.    strcpy (dest, c);            /* copy the stuff over       */
  787.    return (dest);               /* and return the address    */
  788. }
  789.  
  790. char           *ctl_slash_string (source)       /* malloc & copy to ctl      */
  791. char *source;
  792. {
  793.    char *dest, *c;
  794.    size_t i;
  795.    struct stat buffer;
  796.  
  797.    c = skip_blanks (source);                    /* get over the blanks       */
  798.    i = strlen (c);                              /* get length of remainder   */
  799.    if (i < 1)                                   /* must have at least 1      */
  800.       return (NULL);                            /* if not, return NULL       */
  801.    dest = malloc (i+2);                          /* allocate space for string */
  802.    strcpy (dest, c);                            /* copy the stuff over       */
  803.    delete_backslash (dest);                     /* get rid of trailing stuff */
  804.    /* Check to see if the directory exists */
  805.    if (stat (dest, &buffer) || (!(buffer.st_mode & S_IFDIR)))
  806.       {
  807.       printf ("Directory '%s' does not exist!\n", dest);
  808.       printf ("  BinkleyTerm may fail to execute properly because of this!\n");
  809.       return(NULL);
  810.       }
  811.    add_backslash (dest);                         /* add the backslash         */
  812.    return (dest);                                /* return the directory name */
  813. }
  814.  
  815. char           *skip_blanks (string)
  816. char           *string;
  817. {
  818.    while (*string == ' ' || *string == '\t')
  819.       ++string;
  820.    return (string);
  821. }
  822.