home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / SCFG / SCFG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-26  |  49.0 KB  |  1,968 lines

  1. #line 2 "SCFG.C"
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. /****************************************************************************/
  6. /* Synchronet configuration utility                                         */
  7. /****************************************************************************/
  8.  
  9. #include "scfg.h"
  10.  
  11. #ifdef __FLAT__
  12.     unsigned _stklen=64000;
  13. #else
  14.     unsigned _stklen=32000;
  15. #endif
  16.  
  17. extern char *wday[];    /* names of weekdays (3 char) */
  18. extern char uifc_status;
  19.  
  20. /********************/
  21. /* Global Variables */
  22. /********************/
  23.  
  24. long freedosmem;
  25. int  no_dirchk=0,no_msghdr=0,forcesave=0,all_msghdr=0;
  26. char **opt;
  27. char tmp[256];
  28. char *nulstr="";
  29. char **mdm_type;
  30. char **mdm_file;
  31. int  mdm_types;
  32. int  backup_level=3;
  33.  
  34. read_cfg_text_t txt={
  35.     "\7\r\nError opening %s for read.\r\n",
  36.     "","",
  37.     "\7\r\nError allocating %u bytes of memory\r\n",
  38.     "\7\r\nERROR: Offset %lu in %s\r\n\r\n" };
  39.  
  40. char *invalid_code=
  41. "Invalid Internal Code:\n\n"
  42. "Internal codes can be up to eight characters in length and can only\n"
  43. "contain valid DOS filename characters. The code you have entered\n"
  44. "contains one or more invalid characters.";
  45.  
  46. char *num_flags=
  47. "Number of Flags Needed:\n\n"
  48. "If you want users to be required to have all the flags, select All.\n"
  49. "\n"
  50. "If you want users to be required to have any one or more of the flags,\n"
  51. "select One (Allowed).";
  52.  
  53.  
  54. void allocfail(uint size)
  55. {
  56. cprintf("\7Error allocating %u bytes of memory.\r\n",size);
  57. bail(1);
  58. }
  59.  
  60. time_t checktime(void)
  61. {
  62.     struct tm tm;
  63.  
  64. memset(&tm,0,sizeof(tm));
  65. tm.tm_year=94;
  66. tm.tm_mday=1;
  67. return(mktime(&tm)^0x2D24BD00L);
  68. }
  69.  
  70. int main(int argc, char **argv)
  71. {
  72.     char    **mopt,*p;
  73.     int     i,j,main_dflt=0,no_emsovl=0,chat_dflt=0;
  74.     uint    u;
  75.     long    l;
  76.     char     str[129];
  77.     FILE    *instream;
  78. #ifndef __FLAT__
  79.     union    REGS reg;
  80. #endif
  81.  
  82. printf("\r\nSynchronet Configuration Util (%s)  v%s%c  Developed 1995-1997 "
  83.     "Rob Swindell\r\n",
  84. #ifdef __OS2__
  85.     "OS/2"
  86. #elif defined(__FLAT__)
  87.     "DOS/Win32"
  88. #else
  89.     "DOS"
  90. #endif
  91.     ,VERSION,REVISION);
  92.  
  93. if(argc>1)
  94.     strcpy(ctrl_dir,argv[1]);
  95. else
  96.     getcwd(ctrl_dir,MAXDIR);
  97. if(argc>2) {
  98.     for(i=2;i<argc;i++) {
  99.         if(!stricmp(argv[i],"/M"))      /* Show free mem */
  100.             show_free_mem=!show_free_mem;
  101.         else if(!stricmp(argv[i],"/N")) /* No EMS */
  102.             no_emsovl=!no_emsovl;
  103. #if !defined(__FLAT__)
  104.         else if(!strnicmp(argv[i],"/T",2)) /* Windows/OS2 time slice API */
  105.             mswtyp=atoi(argv[i]+2);
  106. #endif
  107.         else if(!strnicmp(argv[i],"/C",2)) /* Force color mode */
  108.             uifc_status|=UIFC_COLOR;
  109.         else if(!strnicmp(argv[i],"/B",2)) /* Backup level */
  110.             backup_level=atoi(argv[i]+2);
  111.         else if(!stricmp(argv[i],"/S")) /* No dir checking */
  112.             no_dirchk=!no_dirchk;
  113.         else if(!stricmp(argv[i],"/H")) /* No msg header updating */
  114.             no_msghdr=!no_msghdr;
  115.         else if(!stricmp(argv[i],"/U")) /* Update all message headers */
  116.             all_msghdr=!all_msghdr;
  117.         else if(!stricmp(argv[i],"/F")) /* Force save of config files */
  118.             forcesave=!forcesave;
  119.         else {
  120.             printf("\r\nusage: scfg <ctrl_dir> [/c] [/m] [/n] [/s] [/u] [/h] "
  121.                 "[/t#] [/b#]\r\n"
  122.                 "\r\n"
  123.                 "/c  =  force color mode\r\n"
  124.                 "/m  =  show free memory\r\n"
  125.                 "/n  =  don't use EMS\r\n"
  126.                 "/s  =  don't check directories\r\n"
  127.                 "/f  =  force save of config files\r\n"
  128.                 "/u  =  update all message base status headers\r\n"
  129.                 "/h  =  don't update message base status headers\r\n"
  130.                 "/t# =  set supported time slice APIs to #\r\n"
  131.                 "/b# =  set automatic back-up level (default=3 max=10)\r\n"
  132.                 );
  133.             exit(0); } } }
  134.  
  135. if(backup_level>10) backup_level=10;
  136.  
  137. if(ctrl_dir[strlen(ctrl_dir)-1]!='\\' && ctrl_dir[strlen(ctrl_dir)-1]!=':')
  138.         strcat(ctrl_dir,"\\");
  139.  
  140. init_mdms();
  141.  
  142. uifcini();
  143.  
  144. #if !defined(__FLAT__)
  145. if(!no_emsovl) {
  146.     cputs("\r\nEMS: ");
  147.     if((i=open("EMMXXXX0",O_RDONLY))==-1)
  148.         cputs("not installed.");
  149.     else {
  150.         close(i);
  151.         reg.h.ah=0x46;            /* Get EMS version */
  152.         int86(0x67,®,®);
  153.         if(reg.h.ah)
  154.             cputs("\7error getting version.");
  155.         else {
  156.             cprintf("Version %u.%u ",(reg.h.al&0xf0)>>4,reg.h.al&0xf);
  157.             if(_OvrInitEms(0,0,23))    /* use up to 360K */
  158.                 cprintf("allocation failed."); } }
  159.     cputs("\r\n"); }
  160. #endif
  161.  
  162. #ifdef __FLAT__
  163. if(putenv("TZ=UCT0"))
  164.     printf("putenv() failed!\n");
  165. tzset();
  166. #endif
  167.  
  168. if((l=checktime())!=0) {   /* Check binary time */
  169.     printf("Time problem (%08lx)\n",l);
  170.     exit(1); }
  171.  
  172. if((opt=(char **)MALLOC(sizeof(char *)*(MAX_OPTS+1)))==NULL)
  173.     allocfail(sizeof(char *)*(MAX_OPTS+1));
  174. for(i=0;i<(MAX_OPTS+1);i++)
  175.     if((opt[i]=(char *)MALLOC(MAX_OPLN))==NULL)
  176.         allocfail(MAX_OPLN);
  177.  
  178. if((mopt=(char **)MALLOC(sizeof(char *)*14))==NULL)
  179.     allocfail(sizeof(char *)*14);
  180. for(i=0;i<14;i++)
  181.     if((mopt[i]=(char *)MALLOC(64))==NULL)
  182.         allocfail(64);
  183.  
  184. txt.reading=nulstr;
  185. txt.readit=nulstr;
  186.  
  187. strcpy(str,argv[0]);
  188. p=strrchr(str,'\\');
  189. if(!p) {
  190.     sprintf(helpdatfile,"..\\EXEC\\SCFGHELP.DAT");
  191.     sprintf(helpixbfile,"..\\EXEC\\SCFGHELP.IXB"); }
  192. else {
  193.     *p=0;
  194.     sprintf(helpdatfile,"%s\\SCFGHELP.DAT",str);
  195.     sprintf(helpixbfile,"%s\\SCFGHELP.IXB",str); }
  196.  
  197. sprintf(str,"Synchronet Configuration for %s v%s",
  198. #if defined(__OS2__)
  199.     "OS/2"
  200. #elif defined(__FLAT__)
  201.     "DOS/Win32"
  202. #else
  203.     "DOS"
  204. #endif
  205.     ,VERSION);
  206. if(uscrn(str)) {
  207.     cprintf("USCRN failed!\r\n");
  208.     bail(1); }
  209. i=0;
  210. strcpy(mopt[i++],"Nodes");
  211. strcpy(mopt[i++],"System");
  212. strcpy(mopt[i++],"Networks");
  213. strcpy(mopt[i++],"File Areas");
  214. strcpy(mopt[i++],"File Options");
  215. strcpy(mopt[i++],"Chat Features");
  216. strcpy(mopt[i++],"Message Areas");
  217. strcpy(mopt[i++],"Message Options");
  218. strcpy(mopt[i++],"Command Shells");
  219. strcpy(mopt[i++],"External Programs");
  220. strcpy(mopt[i++],"Text File Sections");
  221. mopt[i][0]=0;
  222. #ifndef __FLAT__
  223. freedosmem=farcoreleft();
  224. #endif
  225. while(1) {
  226. #if 0
  227.     if(freedosmem!=farcoreleft()) {
  228.         errormsg(WHERE,ERR_CHK,"lost memory",freedosmem-farcoreleft());
  229.         freedosmem=farcoreleft(); }
  230. #endif
  231.     SETHELP(WHERE);
  232. /*
  233. Main Configuration Menu:
  234.  
  235. This is the main menu of the Synchronet configuration utility (SCFG).
  236. From this menu, you have the following choices:
  237.  
  238.     Nodes                  : Add, delete, or configure nodes
  239.     System                  : System-wide configuration options
  240.     Networks              : Message networking configuration
  241.     File Areas              : File area configuration
  242.     File Options          : File area options
  243.     Chat Features          : Chat actions, sections, pagers, and gurus
  244.     Message Areas          : Message area configuration
  245.     Message Options       : Message and email options
  246.     External Programs      : Events, editors, and online programs
  247.     Text File Sections      : General text file area
  248.  
  249. Use the arrow keys and  ENTER  to select an option, or  ESC  to exit.
  250. */
  251.     switch(ulist(WIN_ORG|WIN_MID|WIN_ESC|WIN_ACT,0,0,30,&main_dflt,0
  252.         ,"Configure",mopt)) {
  253.         case 0:
  254.             upop("Reading MAIN.CNF...");
  255.             read_main_cfg(txt);
  256.             upop(0);
  257.             node_menu();
  258.             free_main_cfg();
  259.             break;
  260.         case 1:
  261.             upop("Reading MAIN.CNF...");
  262.             read_main_cfg(txt);
  263.             upop("Reading XTRN.CNF...");
  264.             read_xtrn_cfg(txt);
  265.             upop(0);
  266.             sys_cfg();
  267.             free_xtrn_cfg();
  268.             free_main_cfg();
  269.             break;
  270.         case 2:
  271.             upop("Reading MAIN.CNF...");
  272.             read_main_cfg(txt);
  273.             upop("Reading MSGS.CNF...");
  274.             read_msgs_cfg(txt);
  275.             upop(0);
  276.             net_cfg();
  277.             free_msgs_cfg();
  278.             free_main_cfg();
  279.             break;
  280.         case 3:
  281.             upop("Reading MAIN.CNF...");
  282.             read_main_cfg(txt);
  283.             upop("Reading FILE.CNF...");
  284.             read_file_cfg(txt);
  285.             upop(0);
  286.             xfer_cfg();
  287.             free_file_cfg();
  288.             free_main_cfg();
  289.             break;
  290.         case 4:
  291.             upop("Reading MAIN.CNF...");
  292.             read_main_cfg(txt);
  293.             upop("Reading FILE.CNF...");
  294.             read_file_cfg(txt);
  295.             upop(0);
  296.             xfer_opts();
  297.             free_file_cfg();
  298.             free_main_cfg();
  299.             break;
  300.         case 5:
  301.             upop("Reading CHAT.CNF...");
  302.             read_chat_cfg(txt);
  303.             upop(0);
  304.             while(1) {
  305.                 i=0;
  306.                 strcpy(opt[i++],"Artificial Gurus");
  307.                 strcpy(opt[i++],"Multinode Chat Actions");
  308.                 strcpy(opt[i++],"Multinode Chat Channels");
  309.                 strcpy(opt[i++],"External Sysop Chat Pagers");
  310.                 opt[i][0]=0;
  311.                 j=ulist(WIN_ORG|WIN_ACT|WIN_CHE,0,0,0,&chat_dflt,0
  312.                     ,"Chat Features",opt);
  313.                 if(j==-1) {
  314.                     j=save_changes(WIN_MID);
  315.                     if(j==-1)
  316.                         continue;
  317.                     if(!j)
  318.                         write_chat_cfg();
  319.                     break; }
  320.                 switch(j) {
  321.                     case 0:
  322.                         guru_cfg();
  323.                         break;
  324.                     case 1:
  325.                         actsets_cfg();
  326.                         break;
  327.                     case 2:
  328.                         chan_cfg();
  329.                         break;
  330.                     case 3:
  331.                         page_cfg();
  332.                         break; } }
  333.             free_chat_cfg();
  334.             break;
  335.         case 6:
  336.             upop("Reading MAIN.CNF...");
  337.             read_main_cfg(txt);
  338.             upop("Reading MSGS.CNF...");
  339.             read_msgs_cfg(txt);
  340.             upop(0);
  341.             msgs_cfg();
  342.             free_msgs_cfg();
  343.             free_main_cfg();
  344.             break;
  345.         case 7:
  346.             upop("Reading MAIN.CNF...");
  347.             read_main_cfg(txt);
  348.             upop("Reading MSGS.CNF...");
  349.             read_msgs_cfg(txt);
  350.             upop(0);
  351.             msg_opts();
  352.             free_msgs_cfg();
  353.             free_main_cfg();
  354.             break;
  355.         case 8:
  356.             upop("Reading MAIN.CNF...");
  357.             read_main_cfg(txt);
  358.             upop(0);
  359.             shell_cfg();
  360.             free_main_cfg();
  361.             break;
  362.         case 9:
  363.             upop("Reading MAIN.CNF...");
  364.             read_main_cfg(txt);
  365.             upop("Reading XTRN.CNF...");
  366.             read_xtrn_cfg(txt);
  367.             upop(0);
  368.             xprogs_cfg();
  369.             free_xtrn_cfg();
  370.             free_main_cfg();
  371.             break;
  372.         case 10:
  373.             upop("Reading MAIN.CNF...");
  374.             read_main_cfg(txt);
  375.             upop("Reading FILE.CNF...");
  376.             read_file_cfg(txt);
  377.             upop(0);
  378.             txt_cfg();
  379.             free_file_cfg();
  380.             free_main_cfg();
  381.             break;
  382.         case -1:
  383.             i=0;
  384.             strcpy(opt[0],"Yes");
  385.             strcpy(opt[1],"No");
  386.             opt[2][0]=0;
  387.             SETHELP(WHERE);
  388. /*
  389. Exit SCFG:
  390.  
  391. If you want to exit the Synchronet configuration utility, select Yes.
  392. Otherwise, select No or hit  ESC .
  393. */
  394.             i=ulist(WIN_MID,0,0,0,&i,0,"Exit SCFG",opt);
  395.             if(!i)
  396.                 bail(0);
  397.             break; } }
  398. }
  399.  
  400. /****************************************************************************/
  401. /* Checks the changes variable. If there have been no changes, returns 2.    */
  402. /* If there have been changes, it prompts the user to change or not. If the */
  403. /* user escapes the menu, returns -1, selects Yes, 0, and selects no, 1     */
  404. /****************************************************************************/
  405. int save_changes(int mode)
  406. {
  407.     int i=0;
  408.  
  409. if(!changes)
  410.     return(2);
  411. strcpy(opt[0],"Yes");
  412. strcpy(opt[1],"No");
  413. opt[2][0]=0;
  414. if(mode&WIN_SAV && savdepth)
  415.     savnum++;
  416. SETHELP(WHERE);
  417. /*
  418. Save Changes:
  419.  
  420. You have made some changes to the configuration. If you want to save
  421. these changes, select Yes. If you are positive you DO NOT want to save
  422. these changes, select No. If you are not sure and want to review the
  423. configuration before deciding, hit  ESC .
  424. */
  425. i=ulist(mode|WIN_ACT,0,0,0,&i,0,"Save Changes",opt);
  426. if(mode&WIN_SAV && savdepth)
  427.     savnum--;
  428. if(i!=-1)
  429.     changes=0;
  430. return(i);
  431. }
  432.  
  433. void txt_cfg()
  434. {
  435.     static int txt_dflt,bar;
  436.     char str[81],code[9],done=0,*p;
  437.     int j,k;
  438.     uint i;
  439.     static txtsec_t savtxtsec;
  440.  
  441. while(1) {
  442.     for(i=0;i<total_txtsecs;i++)
  443.         sprintf(opt[i],"%-25s",txtsec[i]->name);
  444.     opt[i][0]=0;
  445.     j=WIN_ORG|WIN_ACT|WIN_CHE;
  446.     if(total_txtsecs)
  447.         j|=WIN_DEL|WIN_GET;
  448.     if(total_txtsecs<MAX_OPTS)
  449.         j|=WIN_INS|WIN_INSACT|WIN_XTR;
  450.     if(savtxtsec.name[0])
  451.         j|=WIN_PUT;
  452.     SETHELP(WHERE);
  453. /*
  454. Text File Sections:
  455.  
  456. This is a list of General Text File (G-File) Sections configured for
  457. your system. G-File sections are used to store text files that can be
  458. viewed freely by the users. Common text file section topics include
  459. ANSI Artwork, System Information, Game Help Files, and other special
  460. interest topics.
  461.  
  462. To add a text file section, select the desired location with the arrow
  463. keys and hit  INS .
  464.  
  465. To delete a text file section, select it and hit  DEL .
  466.  
  467. To configure a text file, select it and hit  ENTER .
  468. */
  469.     i=ulist(j,0,0,45,&txt_dflt,&bar,"Text File Sections",opt);
  470.     if((signed)i==-1) {
  471.         j=save_changes(WIN_MID);
  472.         if(j==-1)
  473.             continue;
  474.         if(!j)
  475.             write_file_cfg();
  476.         return; }
  477.     if((i&MSK_ON)==MSK_INS) {
  478.         i&=MSK_OFF;
  479.         strcpy(str,"ANSI Artwork");
  480.         SETHELP(WHERE);
  481. /*
  482. Text Section Name:
  483.  
  484. This is the name of this text section.
  485. */
  486.         if(uinput(WIN_MID|WIN_SAV,0,0,"Text Section Name",str,40
  487.             ,K_EDIT)<1)
  488.             continue;
  489.         sprintf(code,"%.8s",str);
  490.         p=strchr(code,SP);
  491.         if(p) *p=0;
  492.         strupr(code);
  493.         SETHELP(WHERE);
  494. /*
  495. Text Section Internal Code:
  496.  
  497. Every text file section must have its own unique internal code for
  498. Synchronet to reference it by. It is helpful if this code is an
  499. abreviation of the name.
  500. */
  501.         if(uinput(WIN_MID|WIN_SAV,0,0,"Text Section Internal Code",code,8
  502.             ,K_EDIT|K_UPPER)<1)
  503.             continue;
  504.         if(!code_ok(code)) {
  505.             helpbuf=invalid_code;
  506.             umsg("Invalid Code");
  507.             helpbuf=0;
  508.             continue; }
  509.         if((txtsec=(txtsec_t **)REALLOC(txtsec
  510.             ,sizeof(txtsec_t *)*(total_txtsecs+1)))==NULL) {
  511.             errormsg(WHERE,ERR_ALLOC,nulstr,total_txtsecs+1);
  512.             total_txtsecs=0;
  513.             bail(1);
  514.             continue; }
  515.         if(total_txtsecs)
  516.             for(j=total_txtsecs;j>i;j--)
  517.                 txtsec[j]=txtsec[j-1];
  518.         if((txtsec[i]=(txtsec_t *)MALLOC(sizeof(txtsec_t)))==NULL) {
  519.             errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(txtsec_t));
  520.             continue; }
  521.         memset((txtsec_t *)txtsec[i],0,sizeof(txtsec_t));
  522.         strcpy(txtsec[i]->name,str);
  523.         strcpy(txtsec[i]->code,code);
  524.         total_txtsecs++;
  525.         changes=1;
  526.         continue; }
  527.     if((i&MSK_ON)==MSK_DEL) {
  528.         i&=MSK_OFF;
  529.         FREE(txtsec[i]);
  530.         total_txtsecs--;
  531.         for(j=i;j<total_txtsecs;j++)
  532.             txtsec[j]=txtsec[j+1];
  533.         changes=1;
  534.         continue; }
  535.     if((i&MSK_ON)==MSK_GET) {
  536.         i&=MSK_OFF;
  537.         savtxtsec=*txtsec[i];
  538.         continue; }
  539.     if((i&MSK_ON)==MSK_PUT) {
  540.         i&=MSK_OFF;
  541.         *txtsec[i]=savtxtsec;
  542.         changes=1;
  543.         continue; }
  544.     i=txt_dflt;
  545.     j=0;
  546.     done=0;
  547.     while(!done) {
  548.         k=0;
  549.         sprintf(opt[k++],"%-27.27s%s","Name",txtsec[i]->name);
  550.         sprintf(opt[k++],"%-27.27s%s","Access Requirements"
  551.             ,txtsec[i]->ar);
  552.         sprintf(opt[k++],"%-27.27s%s","Internal Code",txtsec[i]->code);
  553.         opt[k][0]=0;
  554.         switch(ulist(WIN_ACT|WIN_MID,0,0,60,&j,0,txtsec[i]->name
  555.             ,opt)) {
  556.             case -1:
  557.                 done=1;
  558.                 break;
  559.             case 0:
  560.                 SETHELP(WHERE);
  561. /*
  562. Text Section Name:
  563.  
  564. This is the name of this text section.
  565. */
  566.                 strcpy(str,txtsec[i]->name);    /* save */
  567.                 if(!uinput(WIN_MID|WIN_SAV,0,10
  568.                     ,"Text File Section Name"
  569.                     ,txtsec[i]->name,40,K_EDIT))
  570.                     strcpy(txtsec[i]->name,str);
  571.                 break;
  572.             case 1:
  573.                 sprintf(str,"%s Text Section",txtsec[i]->name);
  574.                 getar(str,txtsec[i]->ar);
  575.                 break;
  576.             case 2:
  577.                 strcpy(str,txtsec[i]->code);
  578.                 SETHELP(WHERE);
  579. /*
  580. Text Section Internal Code:
  581.  
  582. Every text file section must have its own unique internal code for
  583. Synchronet to reference it by. It is helpful if this code is an
  584. abreviation of the name.
  585. */
  586.                 uinput(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
  587.                     ,str,8,K_EDIT|K_UPPER);
  588.                 if(code_ok(str))
  589.                     strcpy(txtsec[i]->code,str);
  590.                 else {
  591.                     helpbuf=invalid_code;
  592.                     umsg("Invalid Code");
  593.                     helpbuf=0; }
  594.                 break; } } }
  595. }
  596.  
  597. void shell_cfg()
  598. {
  599.     static int shell_dflt,shell_bar;
  600.     char str[81],code[9],done=0,*p;
  601.     int j,k;
  602.     uint i;
  603.     static shell_t savshell;
  604.  
  605. while(1) {
  606.     for(i=0;i<total_shells;i++)
  607.         sprintf(opt[i],"%-25s",shell[i]->name);
  608.     opt[i][0]=0;
  609.     j=WIN_ORG|WIN_ACT|WIN_CHE;
  610.     if(total_shells)
  611.         j|=WIN_DEL|WIN_GET;
  612.     if(total_shells<MAX_OPTS)
  613.         j|=WIN_INS|WIN_INSACT|WIN_XTR;
  614.     if(savshell.name[0])
  615.         j|=WIN_PUT;
  616.     SETHELP(WHERE);
  617. /*
  618. Command Shells:
  619.  
  620. This is a list of Command Shells configured for your system.
  621. Command shells are the programmable command and menu structures which
  622. are available for your BBS.
  623.  
  624. To add a command shell section, select the desired location with the arrow
  625. keys and hit  INS .
  626.  
  627. To delete a command shell, select it and hit  DEL .
  628.  
  629. To configure a command shell, select it and hit  ENTER .
  630. */
  631.     i=ulist(j,0,0,45,&shell_dflt,&shell_bar,"Command Shells",opt);
  632.     if((signed)i==-1) {
  633.         j=save_changes(WIN_MID);
  634.         if(j==-1)
  635.             continue;
  636.         if(!j)
  637.             write_main_cfg();
  638.         return; }
  639.     if((i&MSK_ON)==MSK_INS) {
  640.         i&=MSK_OFF;
  641.         strcpy(str,"Menu Shell");
  642.         SETHELP(WHERE);
  643. /*
  644. Command Shell Name:
  645.  
  646. This is the descriptive name of this command shell.
  647. */
  648.         if(uinput(WIN_MID|WIN_SAV,0,0,"Command Shell Name",str,40
  649.             ,K_EDIT)<1)
  650.             continue;
  651.         sprintf(code,"%.8s",str);
  652.         p=strchr(code,SP);
  653.         if(p) *p=0;
  654.         strupr(code);
  655.         SETHELP(WHERE);
  656. /*
  657. Command Shell Internal Code:
  658.  
  659. Every command shell must have its own unique internal code for
  660. Synchronet to reference it by. It is helpful if this code is an
  661. abreviation of the name.
  662.  
  663. This code will be the base filename used to load the shell from your
  664. EXEC directory. e.g. A shell with an internal code of MYBBS would
  665. indicate a Baja shell file named MYBBS.BIN in your EXEC directory.
  666. */
  667.         if(uinput(WIN_MID|WIN_SAV,0,0,"Command Shell Internal Code",code,8
  668.             ,K_EDIT|K_UPPER)<1)
  669.             continue;
  670.         if(!code_ok(code)) {
  671.             helpbuf=invalid_code;
  672.             umsg("Invalid Code");
  673.             helpbuf=0;
  674.             continue; }
  675.         if((shell=(shell_t **)REALLOC(shell
  676.             ,sizeof(shell_t *)*(total_shells+1)))==NULL) {
  677.             errormsg(WHERE,ERR_ALLOC,nulstr,total_shells+1);
  678.             total_shells=0;
  679.             bail(1);
  680.             continue; }
  681.         if(total_shells)
  682.             for(j=total_shells;j>i;j--)
  683.                 shell[j]=shell[j-1];
  684.         if((shell[i]=(shell_t *)MALLOC(sizeof(shell_t)))==NULL) {
  685.             errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(shell_t));
  686.             continue; }
  687.         memset((shell_t *)shell[i],0,sizeof(shell_t));
  688.         strcpy(shell[i]->name,str);
  689.         strcpy(shell[i]->code,code);
  690.         total_shells++;
  691.         changes=1;
  692.         continue; }
  693.     if((i&MSK_ON)==MSK_DEL) {
  694.         i&=MSK_OFF;
  695.         FREE(shell[i]);
  696.         total_shells--;
  697.         for(j=i;j<total_shells;j++)
  698.             shell[j]=shell[j+1];
  699.         changes=1;
  700.         continue; }
  701.     if((i&MSK_ON)==MSK_GET) {
  702.         i&=MSK_OFF;
  703.         savshell=*shell[i];
  704.         continue; }
  705.     if((i&MSK_ON)==MSK_PUT) {
  706.         i&=MSK_OFF;
  707.         *shell[i]=savshell;
  708.         changes=1;
  709.         continue; }
  710.     i=shell_dflt;
  711.     j=0;
  712.     done=0;
  713.     while(!done) {
  714.         k=0;
  715.         sprintf(opt[k++],"%-27.27s%s","Name",shell[i]->name);
  716.         sprintf(opt[k++],"%-27.27s%s","Access Requirements"
  717.             ,shell[i]->ar);
  718.         sprintf(opt[k++],"%-27.27s%s","Internal Code",shell[i]->code);
  719.         opt[k][0]=0;
  720.         SETHELP(WHERE);
  721. /*
  722. Command Shell:
  723.  
  724. A command shell is a programmed command and menu structure that you or
  725. your users can use to navigate the BBS. For every command shell
  726. configured here, there must be an associated .BIN file in your EXEC
  727. directory for Synchronet to execute.
  728.  
  729. Command shell files are created by using the Baja command shell compiler
  730. to turn Baja source code (.SRC) files into binary files (.BIN) for
  731. Synchronet to interpret. See the example .SRC files in the TEXT
  732. directory and the documentation for the Baja compiler for more details.
  733. */
  734.         switch(ulist(WIN_ACT|WIN_MID,0,0,60,&j,0,shell[i]->name
  735.             ,opt)) {
  736.             case -1:
  737.                 done=1;
  738.                 break;
  739.             case 0:
  740.                 SETHELP(WHERE);
  741. /*
  742. Command Shell Name:
  743.  
  744. This is the descriptive name of this command shell.
  745. */
  746.                 strcpy(str,shell[i]->name);    /* save */
  747.                 if(!uinput(WIN_MID|WIN_SAV,0,10
  748.                     ,"Command Shell Name"
  749.                     ,shell[i]->name,40,K_EDIT))
  750.                     strcpy(shell[i]->name,str);
  751.                 break;
  752.             case 1:
  753.                 sprintf(str,"%s Command Shell",shell[i]->name);
  754.                 getar(str,shell[i]->ar);
  755.                 break;
  756.             case 2:
  757.                 strcpy(str,shell[i]->code);
  758.                 SETHELP(WHERE);
  759. /*
  760. Command Shell Internal Code:
  761.  
  762. Every command shell must have its own unique internal code for
  763. Synchronet to reference it by. It is helpful if this code is an
  764. abreviation of the name.
  765.  
  766. This code will be the base filename used to load the shell from your
  767. EXEC directory. e.g. A shell with an internal code of MYBBS would
  768. indicate a Baja shell file named MYBBS.BIN in your EXEC directory.
  769. */
  770.                 uinput(WIN_MID|WIN_SAV,0,17,"Internal Code (unique)"
  771.                     ,str,8,K_EDIT|K_UPPER);
  772.                 if(code_ok(str))
  773.                     strcpy(shell[i]->code,str);
  774.                 else {
  775.                     helpbuf=invalid_code;
  776.                     umsg("Invalid Code");
  777.                     helpbuf=0; }
  778.                 break; } } }
  779. }
  780.  
  781. /****************************************************************************/
  782. /* Deletes all files in dir 'path' that match file spec 'spec'              */
  783. /****************************************************************************/
  784. int delfiles(char *inpath, char *spec)
  785. {
  786.     char str[256],path[128],done,c;
  787.     int files=0;
  788.     struct ffblk ff;
  789.  
  790. strcpy(path,inpath);
  791. c=strlen(path);
  792. if(path[c-1]!='\\' && path[c-1]!=':')
  793.     strcat(path,"\\");
  794. sprintf(str,"%s%s",path,spec);
  795. done=findfirst(str,&ff,0);
  796. while(!done) {
  797.     sprintf(str,"%s%s",path,ff.ff_name);
  798.     if(remove(str))
  799.         errormsg(WHERE,ERR_REMOVE,str,0);
  800.     else
  801.         files++;
  802.     done=findnext(&ff); }
  803. return(files);
  804. }
  805.  
  806. int whichlogic()
  807. {
  808.     int i;
  809.  
  810. i=0;
  811. strcpy(opt[0],"Greater than or Equal");
  812. strcpy(opt[1],"Equal");
  813. strcpy(opt[2],"Not Equal");
  814. strcpy(opt[3],"Less than");
  815. opt[4][0]=0;
  816. if(savdepth)
  817.     savnum++;
  818. SETHELP(WHERE);
  819. /*
  820. Select Logic for Requirement:
  821.  
  822. This menu allows you to choose the type of logic evaluation to use
  823. in determining if the requirement is met. If, for example, the user's
  824. level is being evaluated and you select Greater than or Equal from
  825. this menu and set the required level to 50, the user must have level
  826. 50 or higher to meet this requirement. If you selected Equal from
  827. this menu and set the required level to 50, the user must have level
  828. 50 exactly. If you select Not equal and level 50, then the user
  829. must have any level BUT 50. And if you select Less than from this
  830. menu and level 50, the user must have a level below 50.
  831. */
  832. i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Select Logic",opt);
  833. if(savdepth)
  834.     savnum--;
  835. return(i);
  836. }
  837.  
  838. int whichcond()
  839. {
  840.     int i;
  841.  
  842. i=0;
  843. strcpy(opt[0],"AND (Both/All)");
  844. strcpy(opt[1],"OR  (Either/Any)");
  845. opt[2][0]=0;
  846. if(savdepth)
  847.     savnum++;
  848. SETHELP(WHERE);
  849. /*
  850. Select Logic for Multiple Requirements:
  851.  
  852. If you wish this new parameter to be required along with the other
  853. parameters, select AND to specify that both or all of the
  854. parameter requirments must be met.
  855.  
  856. If you wish this new parameter to only be required if the other
  857. parameter requirements aren't met, select OR to specify that either
  858. or any of the parameter requirements must be met.
  859. */
  860. i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Multiple Requirement Logic",opt);
  861. if(savdepth)
  862.     savnum--;
  863. return(i);
  864. }
  865.  
  866.  
  867. void getar(char *desc, char *inar)
  868. {
  869.     static int curar;
  870.     char str[128],ar[128];
  871.     int i,j,len,done=0,n;
  872.  
  873. strcpy(ar,inar);
  874. while(!done) {
  875.     len=strlen(ar);
  876.     if(len>=30) {      /* Needs to be shortened */
  877.         str[0]=0;
  878.         n=strlen(ar);
  879.         for(i=0;i<n;i++) {                    /* Shorten operators */
  880.             if(!strncmp(ar+i,"AND",3)) {
  881.                 strcat(str,"&");
  882.                 i+=2; }
  883.             else if(!strncmp(ar+i,"NOT",3)) {
  884.                 strcat(str,"!");
  885.                 i+=2; }
  886.             else if(!strncmp(ar+i,"EQUAL",5)) {
  887.                 strcat(str,"=");
  888.                 i+=4; }
  889.             else if(!strncmp(ar+i,"EQUALS",6)) {
  890.                 strcat(str,"=");
  891.                 i+=5; }
  892.             else if(!strncmp(ar+i,"EQUAL TO",8)) {
  893.                 strcat(str,"=");
  894.                 i+=7; }
  895.             else if(!strncmp(ar+i,"OR",2)) {
  896.                 strcat(str,"|");
  897.                 i+=1; }
  898.             else
  899.                 strncat(str,ar+i,1); }
  900.         strcpy(ar,str);
  901.         len=strlen(ar); }
  902.  
  903.     if(len>=30) {
  904.         str[0]=0;
  905.         n=strlen(ar);
  906.         for(i=0;i<n;i++) {                    /* Remove spaces from ! and = */
  907.             if(!strncmp(ar+i," ! ",3)) {
  908.                 strcat(str,"!");
  909.                 i+=2; }
  910.             else if(!strncmp(ar+i,"= ",2)) {
  911.                 strcat(str,"=");
  912.                 i++; }
  913.             else if(!strncmp(ar+i," = ",3)) {
  914.                 strcat(str,"=");
  915.                 i+=2; }
  916.             else
  917.                 strncat(str,ar+i,1); }
  918.         strcpy(ar,str);
  919.         len=strlen(ar); }
  920.  
  921.     if(len>=30) {
  922.         str[0]=0;
  923.         n=strlen(ar);
  924.         for(i=0;i<n;i++) {                    /* Remove spaces from & and | */
  925.             if(!strncmp(ar+i," & ",3)) {
  926.                 strcat(str," ");
  927.                 i+=2; }
  928.             else if(!strncmp(ar+i," | ",3)) {
  929.                 strcat(str,"|");
  930.                 i+=2; }
  931.             else
  932.                 strncat(str,ar+i,1); }
  933.         strcpy(ar,str);
  934.         len=strlen(ar); }
  935.  
  936.     if(len>=30) {                    /* change week days to numbers */
  937.         str[0]=0;
  938.         n=strlen(ar);
  939.         for(i=0;i<n;i++) {
  940.             for(j=0;j<7;j++)
  941.                 if(!strnicmp(ar+i,wday[j],3)) {
  942.                     strcat(str,itoa(j,tmp,10));
  943.                     i+=2;
  944.                     break; }
  945.             if(j==7)
  946.                 strncat(str,ar+i,1); }
  947.         strcpy(ar,str);
  948.         len=strlen(ar); }
  949.  
  950.     if(len>=30) {                  /* Shorten parameters */
  951.         str[0]=0;
  952.         n=strlen(ar);
  953.         for(i=0;i<n;i++) {
  954.             if(!strncmp(ar+i,"AGE",3)) {
  955.                 strcat(str,"$A");
  956.                 i+=2; }
  957.             else if(!strncmp(ar+i,"BPS",3)) {
  958.                 strcat(str,"$B");
  959.                 i+=2; }
  960.             else if(!strncmp(ar+i,"PCR",3)) {
  961.                 strcat(str,"$P");
  962.                 i+=2; }
  963.             else if(!strncmp(ar+i,"RIP",3)) {
  964.                 strcat(str,"$*");
  965.                 i+=2; }
  966.             else if(!strncmp(ar+i,"SEX",3)) {
  967.                 strcat(str,"$S");
  968.                 i+=2; }
  969.             else if(!strncmp(ar+i,"UDR",3)) {
  970.                 strcat(str,"$K");
  971.                 i+=2; }
  972.             else if(!strncmp(ar+i,"DAY",3)) {
  973.                 strcat(str,"$W");
  974.                 i+=2; }
  975.             else if(!strncmp(ar+i,"ANSI",4)) {
  976.                 strcat(str,"$[");
  977.                 i+=3; }
  978.             else if(!strncmp(ar+i,"UDFR",4)) {
  979.                 strcat(str,"$D");
  980.                 i+=3; }
  981.             else if(!strncmp(ar+i,"FLAG",4)) {
  982.                 strcat(str,"$F");
  983.                 i+=3; }
  984.             else if(!strncmp(ar+i,"NODE",4)) {
  985.                 strcat(str,"$N");
  986.                 i+=3; }
  987.             else if(!strncmp(ar+i,"NULL",4)) {
  988.                 strcat(str,"$0");
  989.                 i+=3; }
  990.             else if(!strncmp(ar+i,"TIME",4)) {
  991.                 strcat(str,"$T");
  992.                 i+=3; }
  993.             else if(!strncmp(ar+i,"USER",4)) {
  994.                 strcat(str,"$U");
  995.                 i+=3; }
  996.             else if(!strncmp(ar+i,"REST",4)) {
  997.                 strcat(str,"$Z");
  998.                 i+=3; }
  999.             else if(!strncmp(ar+i,"LOCAL",5)) {
  1000.                 strcat(str,"$G");
  1001.                 i+=4; }
  1002.             else if(!strncmp(ar+i,"LEVEL",5)) {
  1003.                 strcat(str,"$L");
  1004.                 i+=4; }
  1005.             else if(!strncmp(ar+i,"TLEFT",5)) {
  1006.                 strcat(str,"$R");
  1007.                 i+=4; }
  1008.             else if(!strncmp(ar+i,"TUSED",5)) {
  1009.                 strcat(str,"$O");
  1010.                 i+=4; }
  1011.             else if(!strncmp(ar+i,"EXPIRE",6)) {
  1012.                 strcat(str,"$E");
  1013.                 i+=5; }
  1014.             else if(!strncmp(ar+i,"CREDIT",6)) {
  1015.                 strcat(str,"$C");
  1016.                 i+=5; }
  1017.             else if(!strncmp(ar+i,"EXEMPT",6)) {
  1018.                 strcat(str,"$X");
  1019.                 i+=5; }
  1020.             else if(!strncmp(ar+i,"RANDOM",6)) {
  1021.                 strcat(str,"$Q");
  1022.                 i+=5; }
  1023.             else if(!strncmp(ar+i,"LASTON",6)) {
  1024.                 strcat(str,"$Y");
  1025.                 i+=5; }
  1026.             else if(!strncmp(ar+i,"LOGONS",6)) {
  1027.                 strcat(str,"$V");
  1028.                 i+=5; }
  1029.             else if(!strncmp(ar+i,":00",3)) {
  1030.                 i+=2; }
  1031.             else
  1032.                 strncat(str,ar+i,1); }
  1033.         strcpy(ar,str);
  1034.         len=strlen(ar); }
  1035.     if(len>=30) {                  /* Remove all spaces and &s */
  1036.         str[0]=0;
  1037.         n=strlen(ar);
  1038.         for(i=0;i<n;i++)
  1039.             if(ar[i]!=SP && ar[i]!='&')
  1040.                 strncat(str,ar+i,1);
  1041.         strcpy(ar,str);
  1042.         len=strlen(ar); }
  1043.     i=0;
  1044.     sprintf(opt[i++],"Requirement String (%s)",ar);
  1045.     strcpy(opt[i++],"Clear Requirements");
  1046.     strcpy(opt[i++],"Set Required Level");
  1047.     strcpy(opt[i++],"Set Required Flag");
  1048.     strcpy(opt[i++],"Set Required Age");
  1049.     strcpy(opt[i++],"Set Required Sex");
  1050.     strcpy(opt[i++],"Set Required Connect Rate");
  1051.     strcpy(opt[i++],"Set Required Post/Call Ratio");
  1052.     strcpy(opt[i++],"Set Required Number of Credits");
  1053.     strcpy(opt[i++],"Set Required Upload/Download Ratio");
  1054.     strcpy(opt[i++],"Set Required Upload/Download File Ratio");
  1055.     strcpy(opt[i++],"Set Required Time of Day");
  1056.     strcpy(opt[i++],"Set Required Day of Week");
  1057.     strcpy(opt[i++],"Set Required Node Number");
  1058.     strcpy(opt[i++],"Set Required User Number");
  1059.     strcpy(opt[i++],"Set Required Time Remaining");
  1060.     strcpy(opt[i++],"Set Required Days Till Expiration");
  1061.     opt[i][0]=0;
  1062.     SETHELP(WHERE);
  1063. /*
  1064. Access Requirements:
  1065.  
  1066. This menu allows you to edit the access requirement string for the
  1067. selected feature/section of your BBS. You can edit the string
  1068. directly (see documentation for details) or use the Set Required...
  1069. options from this menu to automatically fill in the string for you.
  1070. */
  1071.     sprintf(str,"%s Requirements",desc);
  1072.     switch(ulist(WIN_ACT|WIN_MID|WIN_SAV,0,0,60,&curar,0,str,opt)) {
  1073.         case -1:
  1074.             done=1;
  1075.             break;
  1076.         case 0:
  1077.             SETHELP(WHERE);
  1078. /*
  1079. Key word    Symbol        Description
  1080. ────────────────────────────────────────────────────────────────────────
  1081. AND           &         More than one requirement (optional)
  1082. NOT           !         Logical negation (i.e. NOT EQUAL)
  1083. EQUAL          =         Equality required
  1084. OR              |         Either of two or more parameters is required
  1085. AGE           $A        User's age (years since birthdate, 0-255)
  1086. BPS           $B        User's current connect rate (bps)
  1087. FLAG          $F        User's flag (A-Z)
  1088. LEVEL          $L        User's level (0-99)
  1089. NODE          $N        Current node (1-250)
  1090. PCR           $P        User's post/call ratio (0-100)
  1091. SEX           $S        User's sex/gender (M or F)
  1092. TIME          $T        Time of day (HH:MM, 00:00-23:59)
  1093. TLEFT          $R        User's time left online (minutes, 0-255)
  1094. TUSED          $O        User's time online this call (minutes, 0-255)
  1095. USER          $U        User's number (1-xxxx)
  1096. */
  1097.             uinput(WIN_MID|WIN_SAV,0,0,"Requirement String",ar,LEN_ARSTR
  1098.                 ,K_EDIT|K_UPPER);
  1099.             break;
  1100.         case 1:
  1101.             i=1;
  1102.             strcpy(opt[0],"Yes");
  1103.             strcpy(opt[1],"No");
  1104.             opt[2][0]=0;
  1105.             if(savdepth)
  1106.                 savnum++;
  1107.             SETHELP(WHERE);
  1108. /*
  1109. Clear Requirements:
  1110.  
  1111. If you wish to clear the current requirement string, select Yes.
  1112. Otherwise, select No.
  1113. */
  1114.             i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Are You Sure",opt);
  1115.             if(savdepth)
  1116.                 savnum--;
  1117.             if(!i) {
  1118.                 ar[0]=0;
  1119.                 changes=1; }
  1120.             break;
  1121.         case 2:
  1122.             if(strlen(ar)>=30) {
  1123.                 umsg("Maximum string length reached");
  1124.                 break; }
  1125.             i=whichlogic();
  1126.             if(i==-1)
  1127.                 break;
  1128.             str[0]=0;
  1129.             SETHELP(WHERE);
  1130. /*
  1131. Required Level:
  1132.  
  1133. You are being prompted to enter the security level to be used in this
  1134. requirement evaluation. The valid range is 0 (zero) through 99.
  1135. */
  1136.             uinput(WIN_MID|WIN_SAV,0,0,"Level",str,2,K_NUMBER);
  1137.             if(!str[0])
  1138.                 break;
  1139.             if(ar[0]) {
  1140.                 j=whichcond();
  1141.                 if(j==-1)
  1142.                     break;
  1143.                 if(!j)
  1144.                     strcat(ar," AND ");
  1145.                 else
  1146.                     strcat(ar," OR "); }
  1147.             strcat(ar,"LEVEL ");
  1148.             switch(i) {
  1149.                 case 1:
  1150.                     strcat(ar,"= ");
  1151.                     break;
  1152.                 case 2:
  1153.                     strcat(ar,"NOT = ");
  1154.                     break;
  1155.                 case 3:
  1156.                     strcat(ar,"NOT ");
  1157.                     break; }
  1158.             strcat(ar,str);
  1159.             break;
  1160.         case 3:
  1161.             if(strlen(ar)>=30) {
  1162.                 umsg("Maximum string length reached");
  1163.                 break; }
  1164.  
  1165.             for(i=0;i<4;i++)
  1166.                 sprintf(opt[i],"Flag Set #%d",i+1);
  1167.             opt[i][0]=0;
  1168.             i=0;
  1169.             if(savdepth)
  1170.                 savnum++;
  1171.             i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Select Flag Set",opt);
  1172.             if(savdepth)
  1173.                 savnum--;
  1174.             if(i==-1)
  1175.                 break;
  1176.             str[0]=0;
  1177.             SETHELP(WHERE);
  1178. /*
  1179. Required Flag:
  1180.  
  1181. You are being prompted to enter the security flag to be used in this
  1182. requirement evaluation. The valid range is A through Z.
  1183. */
  1184.             uinput(WIN_MID|WIN_SAV,0,0,"Flag (A-Z)",str,1
  1185.                 ,K_UPPER|K_ALPHA);
  1186.             if(!str[0])
  1187.                 break;
  1188.             if(ar[0]) {
  1189.                 j=whichcond();
  1190.                 if(j==-1)
  1191.                     break;
  1192.                 if(!j)
  1193.                     strcat(ar," AND ");
  1194.                 else
  1195.                     strcat(ar," OR "); }
  1196.             strcat(ar,"FLAG ");
  1197.             if(i)
  1198.                 strcat(ar,itoa(i+1,tmp,10));
  1199.             strcat(ar,str);
  1200.             break;
  1201.         case 4:
  1202.             if(strlen(ar)>=30) {
  1203.                 umsg("Maximum string length reached");
  1204.                 break; }
  1205.             i=whichlogic();
  1206.             if(i==-1)
  1207.                 break;
  1208.             str[0]=0;
  1209.             SETHELP(WHERE);
  1210. /*
  1211. Required Age:
  1212.  
  1213. You are being prompted to enter the user's age to be used in this
  1214. requirement evaluation. The valid range is 0 through 255.
  1215. */
  1216.             uinput(WIN_MID|WIN_SAV,0,0,"Age",str,3,K_NUMBER);
  1217.             if(!str[0])
  1218.                 break;
  1219.             if(ar[0]) {
  1220.                 j=whichcond();
  1221.                 if(j==-1)
  1222.                     break;
  1223.                 if(!j)
  1224.                     strcat(ar," AND ");
  1225.                 else
  1226.                     strcat(ar," OR "); }
  1227.             strcat(ar,"AGE ");
  1228.             switch(i) {
  1229.                 case 1:
  1230.                     strcat(ar,"= ");
  1231.                     break;
  1232.                 case 2:
  1233.                     strcat(ar,"NOT = ");
  1234.                     break;
  1235.                 case 3:
  1236.                     strcat(ar,"NOT ");
  1237.                     break; }
  1238.             strcat(ar,str);
  1239.             break;
  1240.         case 5:
  1241.             if(strlen(ar)>=30) {
  1242.                 umsg("Maximum string length reached");
  1243.                 break; }
  1244.             str[0]=0;
  1245.             SETHELP(WHERE);
  1246. /*
  1247. Required Sex:
  1248.  
  1249. You are being prompted to enter the user's gender to be used in this
  1250. requirement evaluation. The valid values are M or F (for male or
  1251. female).
  1252. */
  1253.             uinput(WIN_MID|WIN_SAV,0,0,"Sex (M or F)",str,1
  1254.                 ,K_UPPER|K_ALPHA);
  1255.             if(!str[0])
  1256.                 break;
  1257.             if(ar[0]) {
  1258.                 j=whichcond();
  1259.                 if(j==-1)
  1260.                     break;
  1261.                 if(!j)
  1262.                     strcat(ar," AND ");
  1263.                 else
  1264.                     strcat(ar," OR "); }
  1265.             strcat(ar,"SEX ");
  1266.             strcat(ar,str);
  1267.             break;
  1268.         case 6:
  1269.             if(strlen(ar)>=30) {
  1270.                 umsg("Maximum string length reached");
  1271.                 break; }
  1272.             i=whichlogic();
  1273.             if(i==-1)
  1274.                 break;
  1275.             str[0]=0;
  1276.             SETHELP(WHERE);
  1277. /*
  1278. Required Connect Rate (BPS):
  1279.  
  1280. You are being prompted to enter the connect rate to be used in this
  1281. requirement evaluation. The valid range is 300 through 57600.
  1282. */
  1283.             uinput(WIN_MID|WIN_SAV,0,0,"Connect Rate (BPS)",str,5,K_NUMBER);
  1284.             if(!str[0])
  1285.                 break;
  1286.             j=atoi(str);
  1287.             if(j>=300 && j<30000) {
  1288.                 j/=100;
  1289.                 sprintf(str,"%d",j); }
  1290.             if(ar[0]) {
  1291.                 j=whichcond();
  1292.                 if(j==-1)
  1293.                     break;
  1294.                 if(!j)
  1295.                     strcat(ar," AND ");
  1296.                 else
  1297.                     strcat(ar," OR "); }
  1298.             strcat(ar,"BPS ");
  1299.             switch(i) {
  1300.                 case 1:
  1301.                     strcat(ar,"= ");
  1302.                     break;
  1303.                 case 2:
  1304.                     strcat(ar,"NOT = ");
  1305.                     break;
  1306.                 case 3:
  1307.                     strcat(ar,"NOT ");
  1308.                     break; }
  1309.             strcat(ar,str);
  1310.             break;
  1311.         case 7:
  1312.             if(strlen(ar)>=30) {
  1313.                 umsg("Maximum string length reached");
  1314.                 break; }
  1315.             i=whichlogic();
  1316.             if(i==-1)
  1317.                 break;
  1318.             str[0]=0;
  1319.             SETHELP(WHERE);
  1320. /*
  1321. Required Post/Call Ratio:
  1322.  
  1323. You are being prompted to enter the post/call ratio to be used in this
  1324. requirement evaluation (percentage). The valid range is 0 through 100.
  1325. */
  1326.             uinput(WIN_MID|WIN_SAV,0,0,"Post/Call Ratio (Percentage)"
  1327.                 ,str,3,K_NUMBER);
  1328.             if(!str[0])
  1329.                 break;
  1330.             if(ar[0]) {
  1331.                 j=whichcond();
  1332.                 if(j==-1)
  1333.                     break;
  1334.                 if(!j)
  1335.                     strcat(ar," AND ");
  1336.                 else
  1337.                     strcat(ar," OR "); }
  1338.             strcat(ar,"PCR ");
  1339.             switch(i) {
  1340.                 case 1:
  1341.                     strcat(ar,"= ");
  1342.                     break;
  1343.                 case 2:
  1344.                     strcat(ar,"NOT = ");
  1345.                     break;
  1346.                 case 3:
  1347.                     strcat(ar,"NOT ");
  1348.                     break; }
  1349.             strcat(ar,str);
  1350.             break;
  1351.         case 8:
  1352.             if(strlen(ar)>=30) {
  1353.                 umsg("Maximum string length reached");
  1354.                 break; }
  1355.             i=whichlogic();
  1356.             if(i==-1)
  1357.                 break;
  1358.             str[0]=0;
  1359.             SETHELP(WHERE);
  1360. /*
  1361. Required Number of Credits:
  1362.  
  1363. You are being prompted to enter the number of credits (in kilobytes) to
  1364. be used in this requirement evaluation. The valid range is 0 through
  1365. 65535.
  1366. */
  1367.             uinput(WIN_MID|WIN_SAV,0,0,"Required Credits",str,5,K_NUMBER);
  1368.             if(!str[0])
  1369.                 break;
  1370.             if(ar[0]) {
  1371.                 j=whichcond();
  1372.                 if(j==-1)
  1373.                     break;
  1374.                 if(!j)
  1375.                     strcat(ar," AND ");
  1376.                 else
  1377.                     strcat(ar," OR "); }
  1378.             strcat(ar,"CREDIT ");
  1379.             switch(i) {
  1380.                 case 1:
  1381.                     strcat(ar,"= ");
  1382.                     break;
  1383.                 case 2:
  1384.                     strcat(ar,"NOT = ");
  1385.                     break;
  1386.                 case 3:
  1387.                     strcat(ar,"NOT ");
  1388.                     break; }
  1389.             strcat(ar,str);
  1390.             break;
  1391.         case 9:
  1392.             if(strlen(ar)>=30) {
  1393.                 umsg("Maximum string length reached");
  1394.                 break; }
  1395.             i=whichlogic();
  1396.             if(i==-1)
  1397.                 break;
  1398.             str[0]=0;
  1399.             SETHELP(WHERE);
  1400. /*
  1401. Required Upload/Download Ratio:
  1402.  
  1403. You are being prompted to enter the upload/download ratio to be used in
  1404. this requirement evaluation (percentage). The valid range is 0 through
  1405. 100. This ratio is based on the number of bytes uploaded by the user
  1406. divided by the number of bytes downloaded.
  1407. */
  1408.             uinput(WIN_MID|WIN_SAV,0,0,"Upload/Download Ratio (Percentage)"
  1409.                 ,str,3,K_NUMBER);
  1410.             if(!str[0])
  1411.                 break;
  1412.             if(ar[0]) {
  1413.                 j=whichcond();
  1414.                 if(j==-1)
  1415.                     break;
  1416.                 if(!j)
  1417.                     strcat(ar," AND ");
  1418.                 else
  1419.                     strcat(ar," OR "); }
  1420.             strcat(ar,"UDR ");
  1421.             switch(i) {
  1422.                 case 1:
  1423.                     strcat(ar,"= ");
  1424.                     break;
  1425.                 case 2:
  1426.                     strcat(ar,"NOT = ");
  1427.                     break;
  1428.                 case 3:
  1429.                     strcat(ar,"NOT ");
  1430.                     break; }
  1431.             strcat(ar,str);
  1432.             break;
  1433.         case 10:
  1434.             if(strlen(ar)>=30) {
  1435.                 umsg("Maximum string length reached");
  1436.                 break; }
  1437.             i=whichlogic();
  1438.             if(i==-1)
  1439.                 break;
  1440.             str[0]=0;
  1441.             SETHELP(WHERE);
  1442. /*
  1443. Required Upload/Download File Ratio:
  1444.  
  1445. You are being prompted to enter the upload/download ratio to be used in
  1446. this requirement evaluation (percentage). The valid range is 0 through
  1447. 100. This ratio is based on the number of files uploaded by the user
  1448. divided by the number of files downloaded.
  1449. */
  1450.             uinput(WIN_MID|WIN_SAV,0,0
  1451.                 ,"Upload/Download File Ratio (Percentage)"
  1452.                 ,str,3,K_NUMBER);
  1453.             if(!str[0])
  1454.                 break;
  1455.             if(ar[0]) {
  1456.                 j=whichcond();
  1457.                 if(j==-1)
  1458.                     break;
  1459.                 if(!j)
  1460.                     strcat(ar," AND ");
  1461.                 else
  1462.                     strcat(ar," OR "); }
  1463.             strcat(ar,"UDFR ");
  1464.             switch(i) {
  1465.                 case 1:
  1466.                     strcat(ar,"= ");
  1467.                     break;
  1468.                 case 2:
  1469.                     strcat(ar,"NOT = ");
  1470.                     break;
  1471.                 case 3:
  1472.                     strcat(ar,"NOT ");
  1473.                     break; }
  1474.             strcat(ar,str);
  1475.             break;
  1476.         case 11:
  1477.             if(strlen(ar)>=30) {
  1478.                 umsg("Maximum string length reached");
  1479.                 break; }
  1480.             i=0;
  1481.             strcpy(opt[0],"Before");
  1482.             strcpy(opt[1],"After");
  1483.             opt[2][0]=0;
  1484.             if(savdepth)
  1485.                 savnum++;
  1486.             i=ulist(WIN_MID|WIN_SAV,0,0,0,&i,0,"Time Relationship",opt);
  1487.             if(savdepth)
  1488.                 savnum--;
  1489.             if(i==-1)
  1490.                 break;
  1491.             str[0]=0;
  1492.             SETHELP(WHERE);
  1493. /*
  1494. Required Time of Day:
  1495.  
  1496. You are being prompted to enter the time of day to be used in this
  1497. requirement evaluation (24 hour HH:MM format). The valid range is 0
  1498. through 23:59.
  1499. */
  1500.             uinput(WIN_MID|WIN_SAV,0,0,"Time of Day (HH:MM)",str,5,K_UPPER);
  1501.             if(!str[0])
  1502.                 break;
  1503.             if(ar[0]) {
  1504.                 j=whichcond();
  1505.                 if(j==-1)
  1506.                     break;
  1507.                 if(!j)
  1508.                     strcat(ar," AND ");
  1509.                 else
  1510.                     strcat(ar," OR "); }
  1511.             strcat(ar,"TIME ");
  1512.             if(!i)
  1513.                 strcat(ar,"NOT ");
  1514.             strcat(ar,str);
  1515.             break;
  1516.         case 12:
  1517.             if(strlen(ar)>=30) {
  1518.                 umsg("Maximum string length reached");
  1519.                 break; }
  1520.             i=whichlogic();
  1521.             if(i==-1)
  1522.                 break;
  1523.             SETHELP(WHERE);
  1524. /*
  1525. Required Day of Week:
  1526.  
  1527. You are being prompted to select a day of the week as an access
  1528. requirement value.
  1529. */
  1530.             for(n=0;n<7;n++)
  1531.                 strcpy(opt[n],wday[n]);
  1532.             opt[n][0]=0;
  1533.             n=0;
  1534.             if(savdepth)
  1535.                 savnum++;
  1536.             n=ulist(WIN_MID|WIN_SAV,0,0,0,&n,0,"Select Day of Week",opt);
  1537.             if(savdepth)
  1538.                 savnum--;
  1539.             if(n==-1)
  1540.                 break;
  1541.             strcpy(str,wday[n]);
  1542.             strupr(str);
  1543.             if(ar[0]) {
  1544.                 j=whichcond();
  1545.                 if(j==-1)
  1546.                     break;
  1547.                 if(!j)
  1548.                     strcat(ar," AND ");
  1549.                 else
  1550.                     strcat(ar," OR "); }
  1551.             strcat(ar,"DAY ");
  1552.             switch(i) {
  1553.                 case 1:
  1554.                     strcat(ar,"= ");
  1555.                     break;
  1556.                 case 2:
  1557.                     strcat(ar,"NOT = ");
  1558.                     break;
  1559.                 case 3:
  1560.                     strcat(ar,"NOT ");
  1561.                     break; }
  1562.             strcat(ar,str);
  1563.             break;
  1564.         case 13:
  1565.             if(strlen(ar)>=30) {
  1566.                 umsg("Maximum string length reached");
  1567.                 break; }
  1568.             i=whichlogic();
  1569.             if(i==-1)
  1570.                 break;
  1571.             str[0]=0;
  1572.             SETHELP(WHERE);
  1573. /*
  1574. Required Node:
  1575.  
  1576. You are being prompted to enter the number of a node to be used in this
  1577. requirement evaluation. The valid range is 1 through 250.
  1578. */
  1579.             uinput(WIN_MID|WIN_SAV,0,0,"Node Number",str,3,K_NUMBER);
  1580.             if(!str[0])
  1581.                 break;
  1582.             if(ar[0]) {
  1583.                 j=whichcond();
  1584.                 if(j==-1)
  1585.                     break;
  1586.                 if(!j)
  1587.                     strcat(ar," AND ");
  1588.                 else
  1589.                     strcat(ar," OR "); }
  1590.             strcat(ar,"NODE ");
  1591.             switch(i) {
  1592.                 case 1:
  1593.                     strcat(ar,"= ");
  1594.                     break;
  1595.                 case 2:
  1596.                     strcat(ar,"NOT = ");
  1597.                     break;
  1598.                 case 3:
  1599.                     strcat(ar,"NOT ");
  1600.                     break; }
  1601.             strcat(ar,str);
  1602.             break;
  1603.         case 14:
  1604.             if(strlen(ar)>=30) {
  1605.                 umsg("Maximum string length reached");
  1606.                 break; }
  1607.             i=whichlogic();
  1608.             if(i==-1)
  1609.                 break;
  1610.             str[0]=0;
  1611.             SETHELP(WHERE);
  1612. /*
  1613. Required User Number:
  1614.  
  1615. You are being prompted to enter the user's number to be used in this
  1616. requirement evaluation.
  1617. */
  1618.             uinput(WIN_MID|WIN_SAV,0,0,"User Number",str,5,K_NUMBER);
  1619.             if(!str[0])
  1620.                 break;
  1621.             if(ar[0]) {
  1622.                 j=whichcond();
  1623.                 if(j==-1)
  1624.                     break;
  1625.                 if(!j)
  1626.                     strcat(ar," AND ");
  1627.                 else
  1628.                     strcat(ar," OR "); }
  1629.             strcat(ar,"USER ");
  1630.             switch(i) {
  1631.                 case 1:
  1632.                     strcat(ar,"= ");
  1633.                     break;
  1634.                 case 2:
  1635.                     strcat(ar,"NOT = ");
  1636.                     break;
  1637.                 case 3:
  1638.                     strcat(ar,"NOT ");
  1639.                     break; }
  1640.             strcat(ar,str);
  1641.             break;
  1642.  
  1643.         case 15:
  1644.             if(strlen(ar)>=30) {
  1645.                 umsg("Maximum string length reached");
  1646.                 break; }
  1647.             i=whichlogic();
  1648.             if(i==-1)
  1649.                 break;
  1650.             str[0]=0;
  1651.             SETHELP(WHERE);
  1652. /*
  1653. Required Time Remaining:
  1654.  
  1655. You are being prompted to enter the time remaining to be used in this
  1656. requirement evaluation (in minutes). The valid range is 0 through 255.
  1657. */
  1658.             uinput(WIN_MID|WIN_SAV,0,0,"Time Remaining (minutes)"
  1659.                 ,str,3,K_NUMBER);
  1660.             if(!str[0])
  1661.                 break;
  1662.             if(ar[0]) {
  1663.                 j=whichcond();
  1664.                 if(j==-1)
  1665.                     break;
  1666.                 if(!j)
  1667.                     strcat(ar," AND ");
  1668.                 else
  1669.                     strcat(ar," OR "); }
  1670.             strcat(ar,"TLEFT ");
  1671.             switch(i) {
  1672.                 case 1:
  1673.                     strcat(ar,"= ");
  1674.                     break;
  1675.                 case 2:
  1676.                     strcat(ar,"NOT = ");
  1677.                     break;
  1678.                 case 3:
  1679.                     strcat(ar,"NOT ");
  1680.                     break; }
  1681.             strcat(ar,str);
  1682.             break;
  1683.  
  1684.         case 16:
  1685.             if(strlen(ar)>=30) {
  1686.                 umsg("Maximum string length reached");
  1687.                 break; }
  1688.             i=whichlogic();
  1689.             if(i==-1)
  1690.                 break;
  1691.             str[0]=0;
  1692.             SETHELP(WHERE);
  1693. /*
  1694. Required Days Till User Account Expiration:
  1695.  
  1696. You are being prompted to enter the required number of days till the
  1697. user's account will expire.
  1698. */
  1699.             uinput(WIN_MID|WIN_SAV,0,0,"Days Till Expiration"
  1700.                 ,str,5,K_NUMBER);
  1701.             if(!str[0])
  1702.                 break;
  1703.             if(ar[0]) {
  1704.                 j=whichcond();
  1705.                 if(j==-1)
  1706.                     break;
  1707.                 if(!j)
  1708.                     strcat(ar," AND ");
  1709.                 else
  1710.                     strcat(ar," OR "); }
  1711.             strcat(ar,"EXPIRE ");
  1712.             switch(i) {
  1713.                 case 1:
  1714.                     strcat(ar,"= ");
  1715.                     break;
  1716.                 case 2:
  1717.                     strcat(ar,"NOT = ");
  1718.                     break;
  1719.                 case 3:
  1720.                     strcat(ar,"NOT ");
  1721.                     break; }
  1722.             strcat(ar,str);
  1723.             break;
  1724.             } }
  1725. sprintf(inar,"%.*s",LEN_ARSTR,ar);
  1726. }
  1727.  
  1728. char code_ok(char *str)
  1729. {
  1730.  
  1731. if(!strlen(str))
  1732.     return(0);
  1733. if(strcspn(str," \\/.|<>*?+[]:=\";,")!=strlen(str))
  1734.     return(0);
  1735. return(1);
  1736. }
  1737.  
  1738. /****************************************************************************/
  1739. /*                          Functions from MISC.C                           */
  1740. /****************************************************************************/
  1741.  
  1742. /****************************************************************************/
  1743. /* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
  1744. /* number of times if the attempted file is already open or denying access  */
  1745. /* for some other reason.   All files are opened in BINARY mode.            */
  1746. /****************************************************************************/
  1747. int nopen(char *str, int access)
  1748. {
  1749.     int file,share,count=0;
  1750.  
  1751. if(access==O_RDONLY) share=O_DENYWRITE;
  1752.     else share=O_DENYALL;
  1753. while(((file=open(str,O_BINARY|share|access,S_IWRITE))==-1)
  1754.     && errno==EACCES && count++<LOOP_NOPEN);
  1755. if(file==-1 && errno==EACCES)
  1756.     cputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
  1757. return(file);
  1758. }
  1759.  
  1760. /****************************************************************************/
  1761. /* This function performs an nopen, but returns a file stream with a buffer */
  1762. /* allocated.                                                                */
  1763. /****************************************************************************/
  1764. FILE *fnopen(int *file, char *str, int access)
  1765. {
  1766.     char mode[128];
  1767.     FILE *stream;
  1768.  
  1769. if(((*file)=nopen(str,access))==-1)
  1770.     return(NULL);
  1771.  
  1772. if(access&O_APPEND) {
  1773.     if(access&O_RDONLY)
  1774.         strcpy(mode,"a+");
  1775.     else
  1776.         strcpy(mode,"a"); }
  1777. else {
  1778.     if(access&O_WRONLY)
  1779.         strcpy(mode,"r+");
  1780.     else
  1781.         strcpy(mode,"r"); }
  1782. stream=fdopen((*file),mode);
  1783. if(stream==NULL) {
  1784.     close(*file);
  1785.     return(NULL); }
  1786. setvbuf(stream,NULL,_IOFBF,16*1024);
  1787. return(stream);
  1788. }
  1789.  
  1790.  
  1791. /****************************************************************************/
  1792. /* Converts an ASCII Hex string into an unsigned long                       */
  1793. /****************************************************************************/
  1794. unsigned long ahtoul(char *str)
  1795. {
  1796.     unsigned long l,val=0;
  1797.  
  1798. while((l=(*str++)|0x20)!=0x20)
  1799.     val=(l&0xf)+(l>>6&1)*9+val*16;
  1800. return(val);
  1801. }
  1802.  
  1803. /****************************************************************************/
  1804. /* Returns in 'string' a character representation of the number in l with   */
  1805. /* commas. Maximum value of l is 4 gigabytes.                               */
  1806. /****************************************************************************/
  1807. char *ultoac(ulong l, char *string)
  1808. {
  1809.     char str[81];
  1810.     char i,j;
  1811.  
  1812. ultoa(l,str,10);
  1813. if(!(strlen(str)%3)) i=(strlen(str)/3)-1;
  1814.     else i=strlen(str)/3;
  1815. j=strlen(str)+i;
  1816. string[j--]=0;
  1817. i=strlen(str)-1;
  1818. while(i!=-1) {
  1819.     if(!((strlen(str)-i)%3)) {
  1820.         string[j--]=str[i--];
  1821.         string[j--]=','; }
  1822.     else string[j--]=str[i--]; }
  1823. return(string);
  1824. }
  1825.  
  1826. /****************************************************************************/
  1827. /* If the directory 'path' doesn't exist, create it.                          */
  1828. /****************************************************************************/
  1829. void md(char *inpath)
  1830. {
  1831.     char path[256],str[128];
  1832.     struct ffblk ff;
  1833.     int curdisk,disk;
  1834.  
  1835. if(!inpath[0] || no_dirchk)
  1836.     return;
  1837. if(!strcmp(inpath+1,":\\")) {
  1838.     curdisk=getdisk();
  1839.     disk=toupper(inpath[0])-'A';
  1840.     setdisk(disk);
  1841.     if(getdisk()!=disk) {
  1842.         sprintf(str,"Invalid drive %c:",toupper(inpath[0]));
  1843.         umsg(str); }
  1844.     setdisk(curdisk);
  1845.     return; }
  1846. strcpy(path,inpath);
  1847. if(path[strlen(path)-1]=='\\')
  1848.     path[strlen(path)-1]=0;
  1849. if(!strcmp(path,"."))               /* Don't try to make '.' */
  1850.     return;
  1851. if(findfirst(path,&ff,FA_DIREC))
  1852.     if(mkdir(path)) {
  1853.         sprintf(str,"Failed to create %s",path);
  1854.         umsg(str); }
  1855. }
  1856.  
  1857.  
  1858. void bail(int code)
  1859. {
  1860.     char        str[256];
  1861.     int         i,x;
  1862.     smbstatus_t status;
  1863.  
  1864. if(code) {
  1865.     cputs("\r\nHit a key...");
  1866.     getch(); }
  1867. else if(forcesave) {
  1868.     upop("Loading Configs...");
  1869.     read_main_cfg(txt);
  1870.     read_msgs_cfg(txt);
  1871.     read_file_cfg(txt);
  1872.     read_chat_cfg(txt);
  1873.     read_xtrn_cfg(txt);
  1874.     upop(0);
  1875.     write_main_cfg();
  1876.     write_msgs_cfg();
  1877.     write_file_cfg();
  1878.     write_chat_cfg();
  1879.     write_xtrn_cfg(); }
  1880.  
  1881. uifcbail();
  1882.  
  1883. exit(code);
  1884. }
  1885.  
  1886. /****************************************************************************/
  1887. /* Error handling routine. Prints to local and remote screens the error     */
  1888. /* information, function, action, object and access and then attempts to    */
  1889. /* write the error information into the file ERROR.LOG in the text dir.     */
  1890. /****************************************************************************/
  1891. void errormsg(int line, char *source,  char action, char *object, ulong access)
  1892. {
  1893.     char scrn_buf[8000];
  1894.     char actstr[256];
  1895.  
  1896. gettext(1,1,80,scrn_len,scrn_buf);
  1897. clrscr();
  1898. switch(action) {
  1899.     case ERR_OPEN:
  1900.         strcpy(actstr,"opening");
  1901.         break;
  1902.     case ERR_CLOSE:
  1903.         strcpy(actstr,"closeing");
  1904.         break;
  1905.     case ERR_FDOPEN:
  1906.         strcpy(actstr,"fdopen");
  1907.         break;
  1908.     case ERR_READ:
  1909.         strcpy(actstr,"reading");
  1910.         break;
  1911.     case ERR_WRITE:
  1912.         strcpy(actstr,"writing");
  1913.         break;
  1914.     case ERR_REMOVE:
  1915.         strcpy(actstr,"removing");
  1916.         break;
  1917.     case ERR_ALLOC:
  1918.         strcpy(actstr,"allocating memory");
  1919.         break;
  1920.     case ERR_CHK:
  1921.         strcpy(actstr,"checking");
  1922.         break;
  1923.     case ERR_LEN:
  1924.         strcpy(actstr,"checking length");
  1925.         break;
  1926.     case ERR_EXEC:
  1927.         strcpy(actstr,"executing");
  1928.         break;
  1929.     default:
  1930.         strcpy(actstr,"UNKNOWN"); }
  1931. cprintf("ERROR -     line: %d\r\n",line);
  1932. cprintf("            file: %s\r\n",source);
  1933. cprintf("          action: %s\r\n",actstr);
  1934. cprintf("          object: %s\r\n",object);
  1935. cprintf("          access: %ld (%lx)\r\n",access,access);
  1936. cputs("\r\n<Hit any key>");
  1937. getch();
  1938. puttext(1,1,80,scrn_len,scrn_buf);
  1939. }
  1940.  
  1941. /****************************************************************************/
  1942. /* Puts a backslash on path strings                                         */
  1943. /****************************************************************************/
  1944. void backslash(char *str)
  1945. {
  1946.     int i;
  1947.  
  1948. i=strlen(str);
  1949. if(i && str[i-1]!='\\') {
  1950.     str[i]='\\'; str[i+1]=0; }
  1951. }
  1952.  
  1953. /****************************************************************************/
  1954. /* Checks the disk drive for the existence of a file. Returns 1 if it       */
  1955. /* exists, 0 if it doesn't.                                                 */
  1956. /* Called from upload                                                       */
  1957. /****************************************************************************/
  1958. char fexist(char *filespec)
  1959. {
  1960.     struct ffblk f;
  1961.  
  1962. if(findfirst(filespec,&f,0)==0)
  1963.     return(1);
  1964. return(0);
  1965. }
  1966.  
  1967. /* End of SCFG.C */
  1968.