home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / top2src.zip / INIT.C < prev    next >
C/C++ Source or Header  |  2000-07-13  |  30KB  |  945 lines

  1. /******************************************************************************
  2. INIT.C       Initialization procedure.
  3.  
  4.     Copyright 1993 - 2000 Paul J. Sidorsky
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License, version 2, as
  8.     published by the Free Software Foundation.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19. This module contains the initialization and startup code for TOP.
  20. ******************************************************************************/
  21.  
  22. #include "top.h"
  23.  
  24. /* DEBUG mode variable.  This isn't in GLOBAL.C because it mostly pertains
  25.    to initialization. */
  26. FILE *debuglog = NULL; /* Name of the debug log. */
  27. /* DEBUG mode function prototypes. */
  28. void wdl(char *msg);
  29. void _USERENTRY closedebuglog(void);
  30.  
  31. /* init() - Initializes files, variables, and the door kit.
  32.    Parameters:  argc - Number of command line arguments.
  33.                 argv - String array of command line arguments.
  34.    Returns:  Nothing.
  35. */
  36. void init(XINT argc, char *argv[])
  37. {
  38. /* Temporary node number, result code, task to perform. */
  39. XINT tnod = -1, res, todo = 0;
  40. unsigned char valcode[11]; /* Validation code for RegKey. */
  41. char drive[MAXDRIVE]; /* Drive where TOP.EXE is located. */
  42. char dir[MAXDIR]; /* Directory where TOP.EXE is located. */
  43. char file[MAXFILE]; /* Base file name of TOP executable (usually TOP). */
  44. char ext[MAXEXT]; /* Extension of TOP executable (usually .EXE) */
  45. #if !defined(__OS2__) && !defined(__WIN32__)
  46. unsigned char shchk; /* Share check flag. */
  47. #endif
  48.  
  49. /* This function is quite long and could probably be broken up into
  50.    subfunctions for managability. */
  51.  
  52. #if !defined(__OS2__) && !defined(__WIN32__)
  53. /* Check for SHARE support under DOS. */
  54. asm {
  55.     mov ax,01000h
  56.     int 0x2F
  57.     mov shchk, al
  58.     }
  59.  
  60. /* 0xFF is returned if SHARE is installed. */
  61. if (shchk != 0xFF)
  62.     {
  63.     printf("\nSHARE compatibility not found!\r\nPlease check to make sure "
  64.            "that SHARE.EXE is loaded or that your operating\nenvironment's "
  65.            "SHARE compatibility is turned on.\n");
  66.     exit(207);
  67.     }
  68. #endif
  69.  
  70. /* Check for extended command line parameters. */
  71. if (argc >= 3)
  72.     {
  73.     /* Debug mode. */
  74.     if (!stricmp(argv[2], "DEBUG"))
  75.         {
  76.         /* Open the debug log. */
  77.         debuglog = fopen("TOPDEBUG.LOG", "at");
  78.         atexit(closedebuglog);
  79.         wdl("--------------------------------------------");
  80.         }
  81. #ifdef __WIN32__
  82.     /* Comm handle under Win95. */
  83.     if (!strnicmp(argv[2], "/HANDLE:", 8))
  84.         {
  85.         od_control.od_open_handle = strtol(&argv[2][8], NULL, 10);
  86.         }
  87. #endif
  88.     }
  89.  
  90. #if !defined(__OS2__) && !defined(__WIN32__)
  91. #ifdef FORTIFY
  92. /* Enable Fortify memory checker under DOS in debug mode. */
  93. if (debuglog == NULL)
  94.     {
  95.     Fortify_Disable();
  96.     }
  97. #endif
  98. #endif
  99.  
  100. /* Initialize the random number generator.  Random numbers are currently
  101.    not used, but were used by the poker and other game modules in past. */
  102. randomize();
  103.  
  104. /* Initialize the polling timer. */
  105. lastpoll = myclock();
  106.  
  107. /* Initialize the validation code for RegKey.  This is done on a character-
  108.    by-character basis to make the code less obvious to potential hackers
  109.    looking on from a hex editor. */
  110. // * Deleted *
  111.  
  112. /* Initialize door kit registration information. */
  113. #ifdef __OS2__
  114. // * Deleted *
  115. #else
  116. // * Deleted *
  117. #endif
  118.  
  119. /* Set program name in the door kit. */
  120. #if defined(__OS2__)
  121. sprintf(od_control.od_prog_name, "TOP/2 v%s", ver);
  122. #elif defined(__WIN32__)
  123. sprintf(od_control.od_prog_name, "TOP/95 v%s", ver);
  124. /* Additional information for Win95 About dialog. */
  125. strcpy(od_control.od_prog_copyright,
  126.        "Copyright 1993 - 1998 ISMWare");
  127. strcpy(od_control.od_prog_version,
  128.        "32-bit Windows 95/NT Version");
  129. #else
  130. sprintf(od_control.od_prog_name, "TOP v%s", ver);
  131. #endif
  132.  
  133. /* General door kit settings. */
  134. od_control.od_nocopyright = TRUE;
  135. od_control.od_always_clear = TRUE;
  136. #ifdef __OS2__
  137. od_control.od_no_messages = TRUE;
  138. #endif
  139.  
  140. /* Door kit inbound comm buffer size.  The larger size makes TOP handle
  141.    screen dumps from users (which can occur often in a chat door) better. */
  142. od_control.od_in_buf_size = 8192;
  143.  
  144. /* Clear the user's record number. */
  145. user_rec_num = -1;
  146.  
  147. /* Clear the node type flags. */
  148. localmode = 0; lanmode = 0;
  149.  
  150. /* Door kit appearance. */
  151. od_control.mps = NO_MPS;
  152. od_control.default_personality = PER_RA;
  153.  
  154. wdl("First variable init completed");
  155.  
  156. #ifdef __OS2__
  157. /* Handle additional OS/2 command line parameters. */
  158. ProcessCmdLine(argc, argv);
  159. #endif
  160.  
  161. /* Handle extra TOP tasks. */
  162. if (argc >= 2)
  163.     {
  164.     /* Cheap-ass user deletor and security editor. */
  165.     if (!stricmp(argv[1], "EDIT"))
  166.         {
  167.         todo = 1;
  168.         tnod = 1;
  169.         localmode = 1;
  170.         }
  171.     /* User file packer. */
  172.     if (!stricmp(argv[1], "PACK"))
  173.         {
  174.         todo = 2;
  175.         tnod = 1;
  176.         localmode = 1;
  177.         }
  178.     }
  179.  
  180. /* Get the node number from the TASK envirionment variable. */
  181. if (getenv("TASK") != NULL)
  182.     {
  183.     tnod = atoi(getenv("TASK"));
  184.     }
  185.  
  186. /* Get the node number from the command line if it's there. */
  187. if (argc >= 2 && !todo)
  188.     {
  189.     tnod = atoi(argv[1]);
  190.     }
  191.  
  192. /* Set the final node number. */
  193. if (tnod > 0)
  194.     {
  195.     od_control.od_node = tnod;
  196.     }
  197.  
  198. /* Set the default node as 1 if none has been found or specified. */
  199. if (od_control.od_node == 0)
  200.     {
  201.     od_control.od_node = 1;
  202.     }
  203.  
  204. /* We need to force this setting early as it's used by one of the file
  205.    opening routines. */
  206. cfg.maxretries = 1;
  207. //cfg.maxmsglen = 255;
  208.  
  209. wdl("Command line processing completed");
  210.  
  211. /* Initialize node configuration data and word splitter buffers.  The node
  212.    configuration loader requires the node configuration data buffer
  213.    (obviously) and the word splitter, so these get allocated before everything
  214.    else.*/
  215. nodecfg = malloc(sizeof(TOP_nodecfg_typ));
  216. word_str = malloc(256);
  217. word_pos = calloc(128, sizeof(XINT));
  218. word_len = calloc(128, sizeof(XINT));
  219. wordret = malloc(256);
  220. if (nodecfg == NULL || word_str == NULL || word_pos == NULL ||
  221.     word_len == NULL || wordret == NULL)
  222.     {
  223.     printf("\nNot enough memory to load Node Configuration!\n");
  224.     exit(202);
  225.     }
  226.  
  227. /* Find out where TOP.EXE is. */
  228. fnsplit(argv[0], drive, dir, file, ext);
  229. sprintf(word_str, "%s%s", drive, dir);
  230.  
  231. /* Load the node configuration.  This is done first because a lot of
  232.    information from the node configuration is needed to initialize the
  233.    door kit. */
  234. if (!loadnodecfg(word_str))
  235.     {
  236.     printf("\nCan't load Node Configuration for node %i!\n",
  237.            od_control.od_node);
  238.     exit(100);
  239.     }
  240.  
  241. /* Kludge forces for local and lan nodes.  As the note suggests this should
  242.    be handled more eloquently. */
  243. if (nodecfg->type == NODE_LOCAL) // Won't eventually need this....
  244.     {
  245.     localmode = 1;
  246.     }
  247. if (nodecfg->type == NODE_LAN)
  248.     {
  249.     lanmode = 1;
  250.     }
  251.  
  252. wdl("Node configuration read properly");
  253.  
  254. /* Under LAN or Local modes, there is no need for a drop file, carrier
  255.    detection, or time limit. */
  256. if (localmode || lanmode)
  257.     {
  258.     od_control.od_disable = DIS_INFOFILE | DIS_CARRIERDETECT | DIS_TIMEOUT;
  259.     }
  260.  
  261. /* If one is configured, set the drop file path.  This can include the
  262.    filename under OpenDoors specifications although it usually doesn't. */
  263. if (nodecfg->dropfilepath[0])
  264.     {
  265.     strcpy(od_control.info_path, nodecfg->dropfilepath);
  266.     }
  267.  
  268. /* Setup the configuration file processor.  Although the built-in OpenDoors
  269.    configuration options aren't even mentioned, this seemed like the best
  270.    place to handle the configuration information since the processing is
  271.    built into OD. */
  272. od_control.od_config_file = INCLUDE_CONFIG_FILE;
  273. od_control.od_config_filename = nodecfg->cfgfile;
  274. od_control.od_config_function = processcfg;
  275.  
  276. /* Copy communication information from the node configuration to OD. */
  277. od_control.od_com_method = nodecfg->fossil ? COM_FOSSIL : COM_INTERNAL;
  278. od_control.port = nodecfg->port - 1;
  279. od_control.baud = nodecfg->speed;
  280. od_control.od_com_address = nodecfg->portaddress;
  281. od_control.od_com_irq = nodecfg->portirq;
  282. od_control.od_com_no_fifo = !nodecfg->usefifo;
  283. od_control.od_com_fifo_trigger = nodecfg->fifotrigger;
  284. od_control.od_com_rx_buf = nodecfg->rxbufsize;
  285. od_control.od_com_tx_buf = nodecfg->txbufsize;
  286.  
  287. wdl("OpenDoors pre-init completed");
  288.  
  289. /* Fire up OpenDoors. */
  290. od_init();
  291.  
  292. /* Initialize the kernel timer and our custom kernel function. */
  293. time(&lastkertime);
  294. od_control.od_ker_exec = top_kernel;
  295.  
  296. /* Initialize a temporary user name and location under local/LAN modes so
  297.    the status line doesn't look terrible. */
  298. if (localmode || lanmode)
  299.     {
  300.     strcpy(od_control.user_name, "Unknown User");
  301.     strcpy(od_control.user_location, "Unknown");
  302.     }
  303.  
  304. /* Initlialize the log file.  OpenDoors' built-in logging is used. */
  305. strcpy(od_control.od_logfile_name, nodecfg->logfile);
  306. od_log_open();
  307.  
  308. wdl("OpenDoors init completed");
  309.  
  310. /* Initialize some door kit variables. */
  311. od_control.od_inactivity = cfg.inactivetime;
  312. od_control.od_clear_on_exit = FALSE;
  313.  
  314. /* For some reason long ago I thought memory handlers were needed before
  315.    shelling to DOS and that swapping may have been crashing it.  This
  316.    was later discovered to not only be false, but that the handlers were
  317.    actually preventing shelling from working themselves. */
  318. /*od_control.od_cbefore_shell = preshell;
  319. od_control.od_cafter_shell = postshell;
  320. od_control.od_swapping_disable = TRUE;*/
  321.  
  322. /* Override OpenDoors' rather unusual (IMO) default errorlevels.  I don't
  323.    know many other programs (and especially doors) that return 10 on a
  324.    normal exit! */
  325. od_control.od_errorlevel[0] = TRUE;   /* Turn on custom errorlevels */
  326. od_control.od_errorlevel[1] = 255;    /* Critical */
  327. od_control.od_errorlevel[2] = 1;      /* DCD loss */
  328. od_control.od_errorlevel[3] = 5;      /* Alt-H    */
  329. od_control.od_errorlevel[4] = 2;      /* Time Up  */
  330. od_control.od_errorlevel[5] = 3;      /* Inactive */
  331. od_control.od_errorlevel[6] = 4;      /* Alt-D    */
  332. od_control.od_errorlevel[7] = 0;      /* Normal   */
  333.  
  334. /* In case OpenDoors tried to reset the node number, we want to force it
  335.    back to the one the user told us to use, if any. */
  336. if (tnod > 0)
  337.     {
  338.     od_control.od_node = tnod;
  339.     }
  340. if (od_control.od_node == 0)
  341.     {
  342.     od_control.od_node = 1;
  343.     }
  344.  
  345. /* Adjust some settings that we don't really need in LAN/local modes. */
  346. if (localmode || lanmode)
  347.     {
  348.     /* No inactivity timer. */
  349.     od_control.od_inactivity = 0;
  350.     /* Since timeout is disabled the time remaining doesn't matter, but
  351.        this makes it look like the user has a lot of time left. */
  352.     od_control.user_timelimit = 1440;
  353.     /* Force an update of the status line. */
  354.     od_kernel();
  355.     /* Turn the status line updating off. */
  356.     od_control.od_status_on = FALSE;
  357.     }
  358.  
  359. /* Initialize RA credit usage if enabled. */
  360. if (cfg.usecredits)
  361.     {
  362.     orignumcreds = od_control.user_credit;
  363.     }
  364.  
  365. wdl("OpenDoors post-init completed");
  366.  
  367. /* Initialize BBS interface functions if enabled. */
  368. switch(cfg.bbstype)
  369.     {
  370.     case BBS_RA2: ra_init(); break;
  371.     case BBS_MAX2: max_init(); break;
  372. #ifdef __OS2__
  373.     case BBS_MAX3: max_mcpinit(); break;
  374. #endif
  375.     case BBS_SBBS11: sbbs_init(); break;
  376.     }
  377.  
  378. wdl("BBS function init completed");
  379.  
  380. /* Perform the memory allocations.  This is one of the few initialization
  381.    tasks that is sub-functioned, though this was originally done because
  382.    of the shell memory handlers described above.  Sometimes good things
  383.    result from stupid blunders. */
  384. res = memalloc();
  385. /* Now that the memory has been allocated, we need the exit handler. */
  386. od_control.od_before_exit = before_exit;
  387. /* Abort if not enough memory. */
  388. if (res)
  389.     {
  390.     printf("\nOut Of Memory!\n");
  391.     od_log_write(top_output(OUT_STRING, getlang("LogOutOfMemory")));
  392.     od_exit(200, FALSE);
  393.     }
  394.  
  395. wdl("Memory allocation completed");
  396.  
  397. /* Open the files.  Again, this was sub-functioned because of the shell
  398.    handlers. */
  399. openfiles();
  400.  
  401. wdl("Files opened");
  402.  
  403. /* Clear all node statuses. */
  404. memset(activenodes, 0, MAXNODES);
  405.  
  406. /* Initialize TOP registration information. */
  407. memset(registeredto, 0, 513);
  408. memset(regname, 0, 128);
  409. memset(regsystem, 0, 256);
  410. memset(regtype, 0, 128);
  411.  
  412. wdl("Memory init completed");
  413.  
  414. /* Check to see if TOP is registered. */
  415. // * Deleted *
  416.  
  417. if (registeredtop == RK_REGISTERED)
  418.     {
  419.     char *tx = NULL; /* Working pointer. */
  420.  
  421.     /* The format of the registration string is:
  422.        <name>#<system>#<type>
  423.        # stands for an ASCII #255 character. */
  424.  
  425.     /* Find the first #255. */
  426.     tx = strchr(registeredto, 255);
  427.     /* At one point I thought I might make the system name (and later the
  428.        type, which was not part of the original key system) optional so I
  429.        devised the code to still accept the key even if no system and/or
  430.        type was found.  Probably not a good idea from a security
  431.        standpoint. */
  432.     if (tx != NULL)
  433.         {
  434.         /* If we found a #255, get the system name. */
  435.         strcpy(regsystem, tx + 1);
  436.         /* Blank out the rest of the string so the name copy will work. */
  437.         strset(tx, '\0');
  438.         /* Find the next #255. */
  439.         tx = strchr(regsystem, 255);
  440.         if (tx != NULL)
  441.             {
  442.             /* If we found one, set the registration type. */
  443.             strcpy(regtype, tx + 1);
  444.             /* Blank out the rest of the string. */
  445.             strset(tx, '\0');
  446.             }
  447.         }
  448.     /* Copy the name (which is now the only thing left in registeredto). */
  449.     strcpy(regname, registeredto);
  450.  
  451.     /* Match the sysop name and BBS name with the ones configured. */
  452.     if (strcmp(regname, cfg.sysopname) || strcmp(regsystem, cfg.bbsname))
  453.         {
  454.         registeredtop = RK_UNREGISTERED;
  455.         }
  456.     }
  457.  
  458. /* Test registration again because it may have been turned off in the
  459.    above section. */
  460. if (registeredtop == RK_REGISTERED)
  461.     {
  462.     /* NoRegName allows the sysop's real name to be left off the
  463.        registration message. */
  464.     if (cfg.noregname)
  465.         {
  466.         unsigned long tkey = 0; /* Temporary key. */
  467.  
  468.         /* If this is on we use the key generator (with different
  469.            seed values) to make a "serial number" from the sysop's
  470.            name. */
  471.         // * Deleted *
  472.         sprintf(regname, "%lu", tkey);
  473.         }
  474.     /* This is the friendly way of logging that the registration was
  475.        successfully processed. */
  476.     od_log_write("Thanks for registering!");
  477.     }
  478. else
  479.     {
  480.     /* This is the not-so-friendly way of logging that the
  481.        registration wasn't found. */
  482.     od_log_write("UNREGISTERED EVALUATION VERSION.  Please register!");
  483.     }
  484.  
  485. /* We don't need the registration string buffer any more. */
  486. dofree(registeredto);
  487.  
  488. wdl("Registration check & process completed");
  489.  
  490. /* Load the language file.  The name is taken from the configuration
  491.    information. */
  492. if (!loadlang())
  493.     {
  494.     printf("\nNot enough memory to load language file!\n");
  495.     od_log_write(top_output(OUT_STRING, getlang("LogCantLoadLang")));
  496.     od_exit(203, FALSE);
  497.     }
  498.  
  499. wdl("Language file loaded");
  500.  
  501. /* Load CHANNELS.CFG. */
  502. if (!loadchan())
  503.     {
  504.     printf("\nCan't load channel definition list!\n");
  505.     od_log_write(top_output(OUT_STRING, getlang("LogCantLoadChan")));
  506.     od_exit(204, FALSE);
  507.     }
  508.  
  509. wdl("Channel file loaded");
  510.  
  511. if (lanmode)
  512.     {
  513.     /* Counter, free node holder.  The choice of xz as a variable name is
  514.        probably left over from my BASIC years, when unintelligible variable
  515.        names were the norm. */
  516.     XINT d, xz = -1;
  517.  
  518.     /* This section is the whole reason LAN mode exists.  It finds a free
  519.        node if the one requested isn't available. */
  520.  
  521.     /* See which nodes are using TOP. */
  522.     check_nodes_used(FALSE);
  523.     /* Loop for each remaining node using the specified node as a
  524.        starting point. */
  525.     for (d = od_control.od_node + 1; d < MAXNODES && xz == -1; d++)
  526.         {
  527.         if (!activenodes[d])
  528.             {
  529.             /* Found a free node. */
  530.             xz = d;
  531.             }
  532.         }
  533.     if (xz == -1)
  534.         {
  535.         /* Didn't find a free node. */
  536.         top_output(OUT_SCREEN, getlang("NoFreeNode"));
  537.         top_output(OUT_SCREEN, getlang("ContactSuper"));
  538.         od_log_write(top_output(OUT_STRING, getlang("LogNoFreeNode")));
  539.         od_exit(101, FALSE);
  540.         }
  541.     /* Reset the node and reopen any node-specific files. */
  542.     od_control.od_node = xz;
  543.     lan_updateopenfiles();
  544.  
  545. wdl("LAN init completed");
  546.  
  547.     }
  548. else wdl("LAN init not needed");
  549.  
  550. if (localmode || lanmode)
  551.     {
  552.     struct text_info ti; /* Screen mode information. */
  553.  
  554.     gettextinfo(&ti);
  555.     if (ti.currmode == BW40 || ti.currmode == BW80)
  556.         {
  557.         /* If a monochrome screen mode (not necessarily a mono monitor) is
  558.            detected, turn off ANSI since it isn't really needed. */
  559.         od_control.user_ansi = FALSE;
  560.         }
  561.     else
  562.         {
  563.         /* Force ANSI on a colour screen.  Given that there is no worry
  564.            of transmission time in local/LAN mode, it seems logical to
  565.            turn it on. */
  566.         od_control.user_ansi = TRUE;
  567.         }
  568.     /* Local RIP isn't supported by the door kit. */
  569.     od_control.user_rip = FALSE;
  570.  
  571. wdl("Local init completed");
  572.  
  573.     }
  574. else wdl("Local init not needed");
  575.  
  576. /* Perform some final appearance work. */
  577. od_set_personality("RemoteAccess");
  578. trim_string(od_control.user_location, od_control.user_location, 0);
  579. od_kernel();
  580.  
  581. wdl("OD Log init completed");
  582.  
  583. /* We don't use OD's own bulky colour strings so turn it off. */
  584. od_control.od_colour_delimiter = '\0';
  585.  
  586. /* Reset the screen attribute. */
  587. od_set_colour(D_GREY, D_BLACK);
  588.  
  589. /* Clear the MIX file info. */
  590. memset(&midxfileinfo, 0, sizeof(struct ffblk));
  591.  
  592. /* Log the node type. */
  593. if (localmode)
  594.     {
  595.     od_log_write(top_output(OUT_STRING, getlang("LogLocal")));
  596.     }
  597. if (lanmode)
  598.     {
  599.     od_log_write(top_output(OUT_STRING, getlang("LogLAN")));
  600.     }
  601. if (!localmode && !lanmode)
  602.     {
  603.     od_log_write(top_output(OUT_STRING, getlang("LogDoor")));
  604.     }
  605.  
  606. wdl("Secondary memory init completed");
  607.  
  608. /* Execute a selected task. */
  609. if (todo > 0)
  610.     {
  611. wdl("Init completed - initiating command-line-selected task");
  612.     od_log_write(top_output(OUT_STRING, getlang("LogOneRunMode")));
  613.     switch(todo)
  614.         {
  615.         /* TOP EDIT. */
  616.         case 1: useredit(); break;
  617.         /* TOP PACK. */
  618.         case 2: if (argc > 3) strcpy(outbuf, argv[3]); else outbuf[0] = 0;
  619.                 if (argc > 2) strcpy(word_str, argv[2]); else word_str[0] = 0;
  620.                 userpack();
  621.                 break;
  622.         }
  623.     }
  624.  
  625. /* Clear all forget statuses. */
  626. memset(forgetstatus, 0, MAXNODES);
  627.  
  628. /* Unused Poker initialization code. */
  629. /*//|for (res = 0; res < cfg.pokermaxgames; res++)
  630.     {
  631.     pokerlockflags[res] = 0;
  632.     pokeretimes[res] = 0xFFFFFFFFUL;
  633.     pokerdtimes[res] = 0xFFFF;
  634.     pokerwtimes[res] = 0xFFFF;
  635.     pokeringame[res] = 0;
  636.     }*///|
  637.  
  638. /* Initialize the channel number. */
  639. curchannel = cfg.defaultchannel;
  640.  
  641. wdl("Tertiary memory init completed");
  642.  
  643. /* Initialize the number of action files, which is done by counting the
  644.    words in the action file string.  todo is used in the loop because I was
  645.    too lazy to type the entire variable name. */
  646. numactfiles = todo = split_string(cfg.actfilestr);
  647. // Errs from hell
  648. /* Allocate space for all of the filenames. */
  649. cfg.actfilenames = calloc(todo + 1, sizeof(unsigned char XFAR *));
  650. /* Loop for each file. */
  651. for (res = 0; res <= todo; res++)
  652.     {
  653.     /* Initialize the filename buffer. */
  654.     cfg.actfilenames[res] = malloc(13);
  655.     memset(cfg.actfilenames[res], 0, 13);
  656.     if (res == 0)
  657.         {
  658.         /* List 0 is the personal action list, so copy the name from the
  659.            language file. */
  660.         strcpy(cfg.actfilenames[res],
  661.                strupr(top_output(OUT_STRING, getlang("PersActListName"))));
  662.         }
  663.     else
  664.         {
  665.         strncpy(cfg.actfilenames[res], get_word(res - 1), 8);
  666.         }
  667.     strupr(cfg.actfilenames[res]);
  668.     }
  669.  
  670. wdl("Pre-action init completed");
  671.  
  672. /* Load the action files.  Not sure why the note is there to fix the
  673.    check but it could be because of the partially-allocated status that
  674.    can occur if it fails. */
  675. if (!loadactions()) // Fix this check later.
  676.     {
  677.     od_log_write(top_output(OUT_STRING, getlang("LogCantLoadActs")));
  678.     od_exit(205, FALSE);
  679.     }
  680.  
  681. wdl("Actions loaded");
  682.  
  683. /* Load CENSOR.CFG. */
  684. if (!load_censor_words())
  685.     {
  686.     od_log_write(top_output(OUT_STRING, getlang("LogCantLoadCWords")));
  687.     }
  688.  
  689. wdl("Censor Words Loaded");
  690.  
  691. /* Load spawnable programs, which was a feature removed from TOP due to
  692.    instability. */
  693. //load_spawn_progs(); // check return value later
  694.  
  695. /* Load BIOQUES.CFG. */
  696. if (!loadbioquestions())
  697.     {
  698.     od_log_write(top_output(OUT_STRING, getlang("LogCantLoadBioQues")));
  699.     }
  700.  
  701. /* Copy predefined BBS status types into a string array, which was how they
  702.    were handled before the language file existed. */
  703. for (res = 0; res < 11; res++)
  704.     {
  705.     sprintf(outbuf, "SBBSStatusType%i", res);
  706.     sbbs_statustypes[res] = getlang(outbuf);
  707.     if (res < 8)
  708.         {
  709.         sprintf(outbuf, "RAStatusType%i", res);
  710.         ra_statustypes[res] = getlang(outbuf);
  711.         }
  712.     }
  713.  
  714. wdl("BBS Status Strings Initialized");
  715.  
  716. wdl("Initialization completed");
  717.  
  718. /* Phew!  All done! */
  719. return;
  720. }
  721.  
  722. /* openfiles() - Opens all major files used by TOP.
  723.    Parameters:  None.
  724.    Returns:  Nothing.
  725.    Notes:  Aborts on its own if an error occurs.
  726. */
  727. void openfiles(void)
  728. {
  729. unsigned char tnam[512]; /* Temporary filename buffer. */
  730. XINT res = 0; /* Result code. */
  731.  
  732. /* Open all files that TOP needs to keep open while it runs. */
  733.  
  734. /* User file. */
  735. sprintf(tnam, "%sUSERS.TOP", cfg.toppath);
  736. userfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  737.                                   S_IREAD | S_IWRITE);
  738. /* res holds the number of errors that occurred, which is not used right
  739.    now but could be reported for debugging purposes. */
  740. res += (userfil == -1);
  741. /* Node index. */
  742. sprintf(tnam, "%sNODEIDX.TCH", cfg.topworkpath);
  743. nidxfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  744.                                   S_IREAD | S_IWRITE);
  745. res += (nidxfil == -1);
  746. if (nidxfil != -1 && filelength(nidxfil) <
  747.     (long) ((long) od_control.od_node + 1L) * (long) sizeof(node_idx_typ))
  748.     {
  749.     /* Adjust the size of the node index if it is too small. */
  750.     chsize(nidxfil, (long) ((long) od_control.od_node + 1L) *
  751.                    (long) sizeof(node_idx_typ));
  752.     }
  753. /* Active node index. */
  754. sprintf(tnam, "%sNODEIDX2.TCH", cfg.topworkpath);
  755. nidx2fil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  756.                                    S_IREAD | S_IWRITE);
  757. res += (nidx2fil == -1);
  758. /* Message file for this node.  (Incoming messages.) */
  759. sprintf(tnam, "%sMSG%05i.TCH", cfg.topworkpath, od_control.od_node);
  760. msginfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  761.                                    S_IREAD | S_IWRITE);
  762. res += (msginfil == -1);
  763. /* Open BBS-specific files if needed. */
  764. if (cfg.bbstype != BBS_UNKNOWN && bbs_call_openfiles)
  765.     {
  766.     res += (*bbs_call_openfiles)();
  767.     }
  768. /* Message index for this node.  (Incoming messages.) */
  769. sprintf(tnam, "%sMIX%05i.TCH", cfg.topworkpath, od_control.od_node);
  770. midxinfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  771.                                     S_IREAD | S_IWRITE);
  772. res += (midxinfil == -1);
  773. /* Message change index. */
  774. sprintf(tnam, "%sCHGIDX.TCH", cfg.topworkpath);
  775. chgfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  776.                                  S_IREAD | S_IWRITE);
  777. res += (chgfil == -1);
  778. /* Adjust the size of the change index if it is too small. */
  779. if (chgfil != -1)
  780.     {
  781.     chsize(chgfil, MAXNODES);
  782.     }
  783. /* Channel data (CMI) index. */
  784. sprintf(tnam, "%sCHANIDX.TCH", cfg.topworkpath);
  785. chidxfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  786.                                  S_IREAD | S_IWRITE);
  787. res += (chidxfil == -1);
  788. /* Games data files, not used as the games were removed. */
  789. /*//|sprintf(tnam, "%sSLOTSTAT.TOP", cfg.toppath);
  790. slotsfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  791.                                    S_IREAD | S_IWRITE);
  792. res += (slotsfil == -1);
  793. if (slotsfil != -1)
  794.     {
  795.     chsize(slotsfil, sizeof(slots_stat_typ));
  796.     }
  797. sprintf(tnam, "%sPOKERDAT.TCH", cfg.toppath);
  798. pokdatafil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  799.                                      S_IREAD | S_IWRITE);
  800. res += (pokdatafil == -1);*///|
  801. /* Biography response index. */
  802. sprintf(tnam, "%sBIOIDX.TOP", cfg.toppath);
  803. bioidxfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  804.                                    S_IREAD | S_IWRITE);
  805. res += (bioidxfil == -1);
  806. /* Adjust the size of the index if it is too small. */
  807. if (bioidxfil != -1 &&
  808.     filelength(bioidxfil) < (filelength(userfil) / sizeof(user_data_typ)) *
  809.                             MAXBIOQUES * sizeof(long))
  810.     {
  811.     chsize(bioidxfil, (filelength(userfil) / sizeof(user_data_typ)) *
  812.                        MAXBIOQUES * sizeof(long));
  813.     }
  814. /* Biography responses. */
  815. sprintf(tnam, "%sBIORESP.TOP", cfg.toppath);
  816. biorespfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE,
  817.                                     S_IREAD | S_IWRITE);
  818. res += (biorespfil == -1);
  819.  
  820. /* Abort on error. */
  821. if (res)
  822.     {
  823.     top_output(OUT_SCREEN, getlang("CantInitFiles"));
  824.     od_exit(201, FALSE);
  825.     }
  826.  
  827. return;
  828. }
  829.  
  830. /* lan_updateopenfiles() - Reopen node-dependant files in LAN mode.
  831.    Parameters:  None.
  832.    Returns:  Nothing.
  833.    Notes:  Aborts on its own if an error occurs.
  834. */
  835. void lan_updateopenfiles(void)
  836. {
  837. unsigned char tnam[512]; /* Temporary filename buffer. */
  838. XINT res = 0; /* Result code. */
  839.  
  840. /* This function opens files that use the node number in LAN mode, after
  841.    TOP has found a free node number. */
  842.  
  843. /* Close the previously open files that are affected. */
  844. close(msginfil); close(ipcinfil); close(midxinfil);
  845.  
  846. /* Adjust the size of the node index for the new node if it is too small. */
  847. if (filelength(nidxfil) <
  848.     (long) ((long) od_control.od_node + 1L) * (long) sizeof(node_idx_typ))
  849.     {
  850.     chsize(nidxfil, (long) ((long) od_control.od_node + 1L) *
  851.                    (long) sizeof(node_idx_typ));
  852.     }
  853.  
  854. /* Incoming messages. */
  855. sprintf(tnam, "%sMSG%05i.TCH", cfg.topworkpath, od_control.od_node);
  856. msginfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE, S_IREAD | S_IWRITE);
  857. res += (msginfil == -1);
  858. /* Reopen any BBS-specific files that need the node number. */
  859. if (cfg.bbstype != BBS_UNKNOWN && bbs_call_updateopenfiles)
  860.     {
  861.     res += (*bbs_call_updateopenfiles)();
  862.     }
  863. /* Incoming message index. */
  864. sprintf(tnam, "%sMIX%05i.TCH", cfg.topworkpath, od_control.od_node);
  865. midxinfil = sh_open(tnam, O_RDWR | O_CREAT | O_BINARY, SH_DENYNONE, S_IREAD | S_IWRITE);
  866. res += (midxinfil == -1);
  867.  
  868. /* Abort on error. */
  869. if (res)
  870.     {
  871.     top_output(OUT_SCREEN, getlang("CantInitFiles"));
  872.     od_exit(201, FALSE);
  873.     }
  874.  
  875. return;
  876. }
  877.  
  878. /* memalloc() - Allocate most of the memory TOP uses.
  879.    Parameters:  None.
  880.    Returns:  TRUE on error, FALSE if successful.
  881. */
  882. char memalloc(void)
  883. {
  884. char mres = 0; /* Result code. */
  885.  
  886. /* See GLOBAL.C for variable descriptions.  TOP allocates all memory even
  887.    on error, for simplicity.  The |= assignment used allows TOP to
  888.    preserve any previously detected error while continuing the allocation. */
  889.  
  890. /* Remember to change before_exit() when adding new pointers! */
  891. mres |= ((handles = calloc(MAXNODES, 31)) == NULL);
  892. mres |= ((activenodes = malloc(MAXNODES)) == NULL);
  893. mres |= ((outbuf = malloc(512)) == NULL);
  894. mres |= ((regname = malloc(128)) == NULL);
  895. mres |= ((regsystem = malloc(256)) == NULL);
  896. mres |= ((regtype = malloc(128)) == NULL);
  897. mres |= ((forgetstatus = malloc(MAXNODES)) == NULL);
  898. mres |= ((busynodes = malloc(MAXNODES)) == NULL);
  899. mres |= ((registeredto = malloc(513)) == NULL);
  900. mres |= ((node = malloc(sizeof(node_idx_typ))) == NULL);
  901. mres |= ((outputstr = malloc(513)) == NULL);
  902. mres |= ((lastcmd = malloc(256)) == NULL);
  903. mres |= ((chan = calloc(cfg.maxchandefs, sizeof(channel_data_typ))) ==
  904.          NULL);
  905. mres |= ((bioques = calloc(MAXBIOQUES, sizeof(bio_ques_typ))) == NULL);
  906. /*//|mres |= ((pokerlockflags = malloc(cfg.pokermaxgames)) == NULL);
  907. mres |= ((pokeretimes = calloc(cfg.pokermaxgames, sizeof(time_t))) ==
  908.          NULL);
  909. mres |= ((pokerdtimes = calloc(cfg.pokermaxgames, sizeof(XINT))) == NULL);
  910. mres |= ((pokerwtimes = calloc(cfg.pokermaxgames, sizeof(XINT))) == NULL);
  911. mres |= ((pokeringame = malloc(cfg.pokermaxgames)) == NULL);*///|
  912.  
  913. return mres;
  914. }
  915.  
  916. /* wdl() - Write a message to the DEBUG log.
  917.    Parameters:  wdl - String to write to the log.
  918.    Returns:  Nothing.
  919. */
  920. void wdl(char *msg)
  921.     {
  922.  
  923.     /* Only write if we're in DEBUG mode, i.e. if the debug log has been
  924.        opened. */
  925.     if (debuglog != NULL)
  926.         {
  927.         fprintf(debuglog, "%s\n", msg);
  928.         }
  929.  
  930.     }
  931.  
  932. /* closedebuglog() - Closes the TOP DEBUG log.
  933.    Parameters:  None.
  934.    Returns:  Nothing.
  935. */
  936. void _USERENTRY closedebuglog(void)
  937.     {
  938.  
  939.     /* Close the debug log. */
  940.     fclose(debuglog);
  941.  
  942.     }
  943.  
  944.  
  945.