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