home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / MXMS_160.LZH / MISC.C < prev    next >
C/C++ Source or Header  |  1991-06-24  |  38KB  |  1,338 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*    Misc.c      :Miscellaneous routines for MaxMail                       */
  4. /*                                                                          */
  5. /****************************************************************************/
  6.  
  7. #include "MaxMail.h"
  8. #include <sys\timeb.h>
  9.  
  10. struct user_cfg uscfg;
  11. int do_reset;
  12. int CurColor;
  13. int Hollercount=0;
  14. int Bells;
  15.  
  16. extern int newuser;
  17. extern int FirstArc;
  18.  
  19. void signon()
  20. {
  21.    char *p;
  22.    struct stat fbuf;
  23.  
  24.    setcolor(TextAttr[HILITE_TEXT]);
  25.  
  26.    clearscreen();
  27.  
  28.    sprintf(temp,"Begin, v%2.2f",Version);
  29.    logit(temp,'+');
  30.    if (!newuser) 
  31.       sprintf(temp,"%s logging on",LastUser.name);
  32.    else sprintf(temp,"New User: %s logging on",LastUser.name);
  33.    logit(temp,':');
  34.  
  35.    strout("MaxMail - a MAXIMUS mail/message archiver utility by Craig Derouen\r\n");
  36.    sprintf(temp,"\t *** Version %2.2f ***\r\n",Version);
  37.    strout(temp);
  38.  
  39.    setcolor(TextAttr[STD_TEXT]);
  40.    strcpy(temp1,LastUser.name);
  41.    p = strtok(temp1," ");        /* Fetch 1st name only, shows how friendly we are */
  42.    if (USERCFG.calls) {
  43.       sprintf(temp,"\r\nWelcome back to MaxMail, %s.\r\n",p);
  44.       strout(temp);
  45.       sprintf(temp,"You have had %d previous successful downloads. Good luck!\r\n",USERCFG.packcount);
  46.       strout(temp);
  47.    }
  48.    else {
  49.       sprintf(temp,"\r\nWelcome to MaxMail, %s.\r\n",p);
  50.       strout(temp);
  51.   }
  52.  
  53. /* Now test filedate on Bulletin file. If it is newer than last logon
  54.    of user, display it. */
  55.  
  56.    if(stat(BullFile,&fbuf) == 0 && !newuser ) {        /* File does exist */
  57.       if ((fbuf.st_mtime >= USERCFG.lasttime ))    {    /* See if changed since last logon */
  58.          logit("User is viewing bulletin file",'#');
  59.          strout("\r\nBulletins:\r\n");
  60.          show_file(BullFile,TRUE);
  61.       }
  62.    }
  63. }
  64.  
  65. void menu(void)
  66. {
  67.    int choice;
  68.    int good,x;
  69.    unsigned msgs;
  70.    struct msgupd_st *msgupd;
  71.    time_t testtime;
  72.    time_t thistime;
  73.  
  74.    choice = TRUE;
  75.    PackDone = FALSE;
  76.    while (choice) {
  77.       if (USERCFG.msgfrmt == 1)
  78.          qwkinit();
  79.       msgs = get_msgcount();
  80.       if (msgs) {
  81.          setcolor(TextAttr[HILITE_TEXT]);
  82.          if (PackDone){
  83.             msgs = msgs < MaxMsgs ? msgs : MaxMsgs;
  84.             sprintf(temp,"\r\nYou have %u messages in %s. Select [T]ransmit to download\r\n",msgs,ArcFile);
  85.             strout(temp);
  86.             strout("or select [R]eset,[A]dd or [D]elete to scan more messages/areas\r\n");
  87.             setcolor(TextAttr[STD_TEXT]);
  88.             strout("\r\nSelect a choice\r\n");
  89.          }
  90.          else {
  91.             setcolor(TextAttr[HILITE_TEXT]);
  92.             sprintf(temp,"\r\nThere are %u new messages in areas:\r\n",msgs);
  93.             strout(temp);
  94.             setcolor(TextAttr[STD_TEXT]);
  95.             show_areas(TRUE);
  96.             if (msgs > MaxMsgs) {
  97.                setcolor(TextAttr[ATTN_TEXT]);
  98.                sprintf(temp,"\r\nSorry, but only %u new messages can be packed up during this run.\r\n",MaxMsgs);
  99.                strout(temp);
  100.                sprintf(temp,"MaxMail will pack up the first %u messages it finds.\r\n",MaxMsgs);
  101.                strout(temp);
  102.             }
  103.             setcolor(TextAttr[HILITE_TEXT]);
  104.             strout("\r\nPress ENTER to capture new messages, or select a choice\r\n");
  105.          }
  106.       }
  107.       else {
  108.          setcolor(TextAttr[HILITE_TEXT]);
  109.          strout("\r\n Sorry, but you have NO new messages to capture\r\n");
  110.          strout(" in the current message areas you have selected.\r\n");
  111.          setcolor(TextAttr[STD_TEXT]);
  112.          strout("\r\nSelect a choice\r\n");
  113.       }
  114.       setcolor(TextAttr[STD_TEXT]);
  115.       strout("-------------------------------------------------------\r\n");
  116.       setcolor(TextAttr[MENU_KEY]);
  117.       strout("[C]hange configuration   [L]ist configuration\r\n");
  118.       strout("[A]dd message areas      [D]elete message areas\r\n");
  119.       strout("[R]eset message pointers [S]can for new messages\r\n");
  120.       if (YellOn) {
  121.          strout("[V]ersion                [Y]ell for sysop\r\n");
  122.          strout("[Q]uit back to Maximus");
  123.          if (Hangup && !IsLocal)
  124.             strout("   [G]oodbye, hang up\r\n");
  125.          else strout("\r\n");
  126.       }
  127.       else {
  128.          strout("[V]ersion                [Q]uit back to Maximus\r\n");
  129.          if (Hangup && !IsLocal)
  130.             strout("[G]oodbye, hang up\r\n");
  131.       }
  132.       if (HelpFile[0] != 0) {
  133.          setcolor(TextAttr[HILITE_TEXT]);
  134.          strout("[H]elp\r\n");
  135.       }
  136.       if (USERCFG.msgfrmt == 1) {
  137.          setcolor(TextAttr[HILITE_TEXT]);
  138.          strout("[U]pload REP packet\r\n");
  139.       }
  140.       if (PackDone) {
  141.          setcolor(TextAttr[HILITE_TEXT]);
  142.          strout("[T]ransmit archive\r\n");
  143.       }
  144.       if (LastUser.priv >= ASSTSYSOP) {
  145.          setcolor(TextAttr[STD_TEXT]);
  146.          strout("[Z]Sysop functions\r\n");
  147.       }
  148.       strout("\r\n");
  149.       good = FALSE;
  150.       while (!good) {
  151.          timeremain();
  152.          setcolor(TextAttr[PROMPT_TEXT]);
  153.          strout("Choice --> ");
  154.          ChatOk = TRUE;
  155.          x = chrin();
  156.          if (isalpha(x))
  157.             x &= 0x00df;        /* Force upper case, toupper() has side effects */
  158.          ChatOk = FALSE;
  159.          if(x == '\r')
  160.             x = 'S';
  161.          good = TRUE;
  162.          chrout((char) x);
  163.          strout("\r\n");
  164.          setcolor(TextAttr[STD_TEXT]);
  165.          switch (x) {
  166.             case 'A':
  167.                add_msgareas();
  168.                break;
  169.  
  170.             case 'C':
  171.                configmenu();
  172.                break;
  173.  
  174.             case 'D':
  175.                del_msgareas();
  176.                break;
  177.  
  178.             case 'G':
  179.                if (Hangup) {
  180.                   choice = FALSE;
  181.                   Hangup = 1;
  182.                }
  183.                break;
  184.  
  185.             case 'H':
  186.             case '?':
  187.                if (HelpFile[0]) {
  188.                   if (show_file(HelpFile,TRUE)) {
  189.                      setcolor(TextAttr[ATTN_TEXT]);
  190.                      strout("\r\nSorry, the help file is missing. Tell the sysop.\r\n");
  191.                      sprintf(temp,"User Helpfile %s is missing",HelpFile);
  192.                      logit(temp,'!');
  193.                      HelpFile[0] = 0;        /* Prevent it from being called again */
  194.                   }
  195.                }
  196.                break;
  197.  
  198.             case 'L':
  199.                list_config();
  200.                break;
  201.  
  202.             case 'Q':
  203.                choice = FALSE;
  204.                Hangup = 0;
  205.                if (!packer_del && PackDone) /* Kill any built archives */
  206.                   erase_arc();
  207.                break;
  208.  
  209.             case 'R':
  210.                edit_msgptrs();
  211.                break;
  212.  
  213.             case 'S':
  214.                if (msgs) {
  215.                /* Check last called date. Compare it to now and 24hour count */
  216.                   time(&thistime);
  217.                   testtime = thistime - USERCFG.lasttime;        /* How many seconds since last call? */
  218.                   if (testtime < (time_t) (3600 * 24) ) {        /* Seconds in 24 hours */
  219.                      if (!IsLocal && MaxDaily && LastUser.priv < ASSTSYSOP &&
  220.                         (USERCFG.dailycount >= (byte) MaxDaily)) { /* User can not scan */
  221.                         setcolor(TextAttr[ATTN_TEXT]);
  222.                         sprintf(temp,"\r\nSorry, %s, but you have already run MaxMail %d times today.\r\n",
  223.                            USERCFG.name,USERCFG.dailycount);
  224.                         strout(temp);
  225.                         sprintf(temp,"The sysop here only allows %d message runs from MaxMail daily.\r\n",MaxDaily);
  226.                         strout(temp);
  227.                         strout("Try running MaxMail again in 24 hours from now.\r\n");
  228.                      }
  229.                      else {
  230.                         if (scan_msgs() && totmsgs) {
  231.                            if(Packit()) {
  232.                               if (sendit()) {
  233.                                  if(packer_del)
  234.                                     PackDone = FALSE;
  235.                                  choice = FALSE;
  236.                               }
  237.                            }
  238.                         }
  239.                      }
  240.                   }
  241.                   else {
  242.                      USERCFG.dailycount = 0;        /* Reset it then */
  243.                      if (scan_msgs() && totmsgs) {
  244.                         if(Packit()) {
  245.                            if (sendit()) {
  246.                               PackDone = FALSE;
  247.                               choice = FALSE;
  248.                            }
  249.                         }
  250.                      }
  251.                   }
  252.                }
  253.                else good = FALSE;
  254.                break;
  255.  
  256.             case 'T':
  257.                if (PackDone) {
  258.                   if (sendit()) {
  259.                      PackDone = FALSE;
  260.                      choice = FALSE;
  261.                   }
  262.                }
  263.                else good = FALSE;
  264.                break;
  265.  
  266.             case 'U':
  267.                if (USERCFG.msgfrmt == 1) 
  268.                   getrep();
  269.                break;
  270.  
  271.             case 'V':
  272.                ShowVers();
  273.                break;
  274.  
  275.             case 'Y':
  276.                if (YellOn)
  277.                   Holler();
  278.                break;
  279.  
  280.             case 'Z':
  281.                if (LastUser.priv >= ASSTSYSOP) 
  282.                   Sys_menu();        /* We won't return from Sysop menu */
  283.                else good = FALSE;
  284.                break;
  285.  
  286.             case '!':        /* Redraw the full menu */
  287.                good = TRUE;
  288.                break;
  289.  
  290.             default:
  291.                good = FALSE;
  292.                break;
  293.          }
  294.       }
  295.    }
  296.    if (PackDone && packer_del) {        /* Pack file aborted */
  297.       if (LogMode == VERBOSE) logit("User aborted message pack",'~');
  298.       erase_arc();
  299.       msgupd = MSGUPD_1;
  300.       while (msgupd) {
  301.          msgupd->update = FALSE;
  302.          msgupd = msgupd->next;
  303.       }
  304.    }
  305.    return;
  306. }
  307.  
  308. void display_packers(void)
  309. {
  310.    int x,col;
  311.    struct packer_st *pack1;
  312.  
  313.    pack1 = PACKER_1;
  314.  
  315.    col = 0;
  316.    for (x = 0; x < totpackers; x++) {
  317.       sprintf(temp,"[%d]%s",x +1,pack1->packname);
  318.       while (strlen(temp) < 32) 
  319.          strcat(temp," ");
  320.       strout(temp);
  321.       if (col++) {
  322.          strout("\r\n");
  323.          col = 0;
  324.       }
  325.       pack1 = pack1->next;
  326.    }
  327.    if (col)
  328.       strout("\r\n");
  329.    return;
  330. }
  331.  
  332. void display_protos(void)
  333. {
  334.    int x,col;
  335.    struct proto_st *proto1;
  336.  
  337.    proto1 = PROTO_1;
  338.  
  339.    col = 0;
  340.    for (x = 0; x < totprotocols; x++) {
  341.       sprintf(temp,"[%d]%s",x +1,proto1->protoname);
  342.       while (strlen(temp) < 32) 
  343.          strcat(temp," ");
  344.       strout(temp);
  345.       if (col++) {
  346.          strout("\r\n");
  347.          col = 0;
  348.       }
  349.       proto1 = proto1->next;
  350.    }
  351.    if (col)
  352.       strout("\r\n");
  353.    return;
  354. }
  355.  
  356. /* Find the user in the config file */
  357.  
  358. int find_config(int handle,char *name,struct user_cfg *uscfg)
  359. {
  360.    int x,y;
  361.  
  362.    x = 0;
  363.    do_reset = FALSE;
  364.    lseek(handle,0L,SEEK_SET);        /* Rewind to begginning */
  365.    while (1) {
  366.       y = read(handle,(char *) uscfg,sizeof(struct user_cfg));
  367.       if( y < sizeof(struct user_cfg)) 
  368.          return(-1);
  369.       if (strcmpi(uscfg->name,name) == 0) { /* It's found! */
  370.          return(x);
  371.       }
  372.       x++;        /* Try next user */
  373.    }
  374. }
  375.  
  376. /* Find a blank slot in the config file */
  377.  
  378.  
  379. int find_blconfig(int handle)
  380. {
  381.    int x,y;
  382.  
  383.    x = 0;
  384.    lseek(handle,0L,SEEK_SET);        /* Rewind to begginning */
  385.    while (1) {
  386.       y = read(handle,(char *) &uscfg,sizeof(struct user_cfg));
  387.       if( y < sizeof(struct user_cfg)) 
  388.          return(-1);
  389.       if (uscfg.name[0] == 0)  /* It's found! */
  390.          return(x);
  391.       x++;        /* Try next user */
  392.    }
  393. }
  394.  
  395. int timeon(void)
  396. {
  397.    clock_t elapsed;
  398.    int t;
  399.  
  400.    elapsed = clock();
  401.    elapsed = startsecs - elapsed;
  402.    elapsed = elapsed / CLOCKS_PER_SEC;        /* Compute seconds */
  403.    t = (int) (elapsed / 60);
  404.    if (t < 0)
  405.       t = t * (-1);
  406.    return(t);
  407. }
  408.  
  409. void timeremain(void)
  410. {
  411.    int x;
  412.    char tstr[18];
  413.  
  414.    x = LastUser.timeremaining - timeon();        /* Fetch # of minutes on */
  415.    setcolor(TextAttr[TIME_LEFT]);
  416.    sprintf(tstr,"{%d min left} ",x);
  417.    strout(tstr);   
  418. }
  419.  
  420. struct proto_st *get_curprotolnk(void)
  421. {
  422.    int x;
  423.    struct proto_st *proto1;
  424.    struct proto_st *prev;
  425.  
  426.    proto1 = PROTO_1;        /* Point to first 1! */
  427.    for (x = 1; x < (int) USERCFG.protocol && proto1 != NULL; x++) {
  428.       prev = proto1;
  429.       proto1 = proto1->next;
  430.    }
  431.    if (proto1 == NULL) 
  432.       return(prev);
  433.    return(proto1);
  434. }
  435.  
  436. struct repupl_st *get_curreplnk(void)
  437. {
  438.    int x;
  439.    struct repupl_st *upl1;
  440.    struct repupl_st *prev;
  441.  
  442.    upl1 = REPUPL_1;        /* Point to first 1! */
  443.    for (x = 1; x < (int) USERCFG.protocol && upl1 != NULL; x++) {
  444.       prev = upl1;
  445.       upl1 = upl1->next;
  446.    }
  447.    if (upl1 == NULL) 
  448.       return(prev);
  449.    return(upl1);
  450. }
  451.  
  452. struct packer_st *get_curpacklnk(void)
  453. {
  454.    int x;
  455.    struct packer_st *pack1;
  456.    struct packer_st *prev;
  457.  
  458.    if (!USERCFG.packer)
  459.       return NULL;
  460.  
  461.    pack1 = PACKER_1;        /* Point to first 1! */
  462.    for (x = 1; x < (int) USERCFG.packer && pack1 != NULL; x++) {
  463.       prev = pack1;
  464.       pack1 = pack1->next;
  465.    }
  466.    if (pack1 == NULL) 
  467.       return(prev);
  468.    return(pack1);
  469. }
  470.  
  471. int get_kminute(void)
  472. {
  473.    int x,y;
  474.  
  475.    x = LastUser.flag / 10;         /* Compute cps */
  476.    y = LastUser.flag;
  477.    switch (LastUser.flag) {
  478.       case 300:
  479.          x -=  (x * 0.08f);        /* Slop off 8% */
  480.          break;
  481.  
  482.       case 1200:
  483.          x -=  (x * 0.18f);        /* Slop off 18% */
  484.          break;
  485.  
  486.       case 2400:
  487.          x -=  (x * 0.22f); 
  488.          break;
  489.  
  490.       case 4800:
  491.          x -=  (x * 0.25f); 
  492.          break;
  493.  
  494.       case 9600:
  495.          x -= (x * 0.28f);     
  496.          break;
  497.  
  498.       default:
  499.          x -= (x * 0.28f);     
  500.          break;
  501.    }
  502.    x *= 60;        /* Compute to minutes */
  503.    return x;
  504. }
  505.  
  506. /* The sysop menu */
  507. void Sys_menu(void)
  508. {
  509.    int x,choice,handl1,tuser;
  510.    char *p1;
  511.  
  512.    choice = TRUE;
  513.  
  514.    while (choice) {
  515.       setcolor(TextAttr[STD_TEXT]);
  516.       if (SysopMode) {
  517.          strout("\r\n\r\nLocal Sysop menu. Select a choice.\r\n");
  518.          strout("----------------------------------\r\n");
  519.       }
  520.       else {
  521.          strout("\r\n\r\nSysop menu. Select a choice.\r\n");
  522.          strout("----------------------------\r\n");
  523.       }
  524.       setcolor(TextAttr[MENU_KEY]);
  525.       strout("[D]elete a user          [E]rase user msg areas\r\n");
  526.       strout("[F]orce reconfig         [K]ill old users\r\n");
  527.       strout("[L]ist users             [V]iew user msg areas\r\n");
  528.       strout("[Q]uit\r\n");
  529.       if (!SysopMode) {
  530.          strout("\r\n");
  531.          timeremain();
  532.       }
  533.       else strout("[P]ack\r\n\r\n");
  534.       setcolor(TextAttr[PROMPT_TEXT]);
  535.       strout("Choice --> ");
  536.       x = chrin();
  537.       if (isalpha(x))
  538.          x &= 0x00df;
  539.       chrout((char) x);
  540.       strout("\r\n");
  541.       switch (x) {
  542.          case 'D':        /* Delete single users */
  543.             delete_users();
  544.             break;
  545.  
  546.          case 'E':        /* Erase user message areas */
  547.             if (test_task()) {
  548.                setcolor(TextAttr[ATTN_TEXT]);
  549.                strout("\r\nMaxMail is currently active in another partition. Try later.\r\n");
  550.                break;
  551.             }
  552.             setcolor(TextAttr[PROMPT_TEXT]);
  553.             strout("\r\nForce all users to re-do their msg area selection,\r\n");
  554.             strout("   or just single user? [a,s,Q] ");
  555.             x = chrin();
  556.             if (isalpha(x))
  557.                x &= 0xdf;
  558.             chrout((char) x);
  559.             strout("\r\n");
  560.             if(x == '\r')
  561.                x = 'Q';
  562.             if (x == 'A') {
  563.                if (!do_reset) {
  564.                   strout("Are you sure you want this? ");
  565.                   if (getyn(FALSE))
  566.                      do_reset = reset_config(USRCFG_MSGUPD);
  567.                }
  568.                else {
  569.                   setcolor(TextAttr[ATTN_TEXT]);
  570.                   strout("\r\nYou have already reset all the users during this session.\r\n");
  571.                }
  572.             }
  573.             else if(x == 'S'){        /* Single user reset */
  574.                strout("Enter user's name ---> ");
  575.                strin(temp);
  576.                if (!IsLocal)
  577.                   strout("\r\n");
  578.                p1 = strtok(temp,"\t\r\n");
  579.                if (p1) {
  580.                   handl1 = sopen(CfgFile,O_RDWR | O_BINARY | O_CREAT,SH_DENYNO,S_IREAD);
  581.                   if (handl1 == -1)
  582.                      aborterror(FILEOPEN,"Error opening User config file");
  583.                   tuser = find_config(handl1,p1,&uscfg);
  584.                   if (tuser < 0) {
  585.                      setcolor(TextAttr[ATTN_TEXT]);
  586.                      strout("Sorry but that user name does not exist.\r\n");
  587.                   }
  588.                   else {
  589.                      uscfg.flags |= USRCFG_MSGUPD;
  590.                      lseek(handl1,(long) (tuser * sizeof(struct user_cfg)),SEEK_SET);
  591.                      write(handl1,(struct user_cfg *) &uscfg,sizeof(struct user_cfg));
  592.                   }
  593.                   close(handl1);
  594.                }
  595.             }
  596.             break;
  597.  
  598.          case 'V':        /* List user message areas */
  599.             examine_user();
  600.             break;
  601.  
  602.          case 'F':        /* Force all users to re-do configuration */
  603.             if (test_task()) {
  604.                setcolor(TextAttr[ATTN_TEXT]);
  605.                strout("\r\nMaxMail is currently active in another partition. Try later.\r\n");
  606.                break;
  607.             }
  608.             setcolor(TextAttr[PROMPT_TEXT]);
  609.             strout("\r\nForce all users to re-do their configuration,\r\n");
  610.             strout("   or just single user? [a,s,Q] ");
  611.             x = chrin();
  612.             if (isalpha(x))
  613.                x &= 0xdf;
  614.             chrout((char) x);
  615.             strout("\r\n");
  616.             if(x == '\r')
  617.                x = 'Q';
  618.             if (x == 'A') {
  619.                if (!do_reset) {
  620.                   strout("Are you sure you want this? ");
  621.                   if (getyn(FALSE))
  622.                      do_reset = reset_config(USRCFG_FUPD);
  623.                }
  624.                else {
  625.                   setcolor(TextAttr[ATTN_TEXT]);
  626.                   strout("\r\nYou have already reset all the users during this session.\r\n");
  627.                }
  628.             }
  629.             else if(x == 'S'){        /* Single user reset */
  630.                strout("Enter user's name ---> ");
  631.                strin(temp);
  632.                if (!IsLocal)
  633.                   strout("\r\n");
  634.                p1 = strtok(temp,"\t\r\n");
  635.                if (p1) {
  636.                   handl1 = sopen(CfgFile,O_RDWR | O_BINARY | O_CREAT,SH_DENYNO,S_IREAD);
  637.                   if (handl1 == -1)
  638.                      aborterror(FILEOPEN,"Error opening User config file");
  639.                   tuser = find_config(handl1,p1,&uscfg);
  640.                   if (tuser < 0) {
  641.                      setcolor(TextAttr[ATTN_TEXT]);
  642.                      strout("Sorry but that user name does not exist.\r\n");
  643.                   }
  644.                   else {
  645.                      uscfg.flags |= USRCFG_FUPD;
  646.                      lseek(handl1,(long) (tuser * sizeof(struct user_cfg)),SEEK_SET);
  647.                      write(handl1,(struct user_cfg *) &uscfg,sizeof(struct user_cfg));
  648.                   }
  649.                   close(handl1);
  650.                }
  651.             }
  652.             break;
  653.  
  654.          case 'K':        /* Kill older users */
  655.             setcolor(TextAttr[PROMPT_TEXT]);
  656.             strout("\r\nThis will delete all MaxMail users who are no longer active on your bbs\r\n");
  657.             strout("Are you sure you want this? ");
  658.             if (getyn(FALSE))
  659.                kill_oldusers();
  660.             break;
  661.  
  662.          case 'L':        /* User stats */
  663.             user_stats();
  664.             break;
  665.  
  666.          case 'P':
  667.             if (SysopMode)
  668.                PackUsers();
  669.             break;
  670.  
  671.          case 'Q':        /* Quit */
  672.             choice = FALSE;
  673.             break;
  674.       }
  675.    }
  676.    strout("\r\n\r\n");
  677.    setcolor(TextAttr[STD_TEXT]);
  678.    return;
  679. }
  680.  
  681. /* Display selected message areas, if flag is TRUE, only areas
  682.     with new messages, else show ALL selected areas */
  683. void show_areas(int flag)
  684. {
  685.    int x,col,msgpos;
  686.    struct msgupd_st *msgupd;
  687.  
  688.    msgupd = MSGUPD_1;
  689.    setcolor(TextAttr[HILITE_TEXT]);
  690.    while (msgupd) {
  691.       msgpos = 0;
  692.       col = 0;
  693.       while (msgupd && msgpos < 20) {
  694.          fseek(afile,msgupd->areaindex,SEEK_SET);
  695.          fread(&AREA,astrlen,1,afile);
  696.          if ((flag && msgupd->msgcount) || !flag) {
  697.             setcolor(TextAttr[STD_TEXT]);
  698.             sprintf(temp,"[%03d]",msgupd->areano);
  699.             strout(temp);
  700.             setcolor(TextAttr[HILITE_TEXT]);
  701.             strncpy(temp1,AREA.msginfo,13);
  702.             temp1[13] = 0;
  703.             sprintf(temp," %s",temp1);
  704.             while (strlen(temp) <= 14) 
  705.                strcat(temp," ");
  706.             strout(temp);
  707.             if (msgupd->msgcount) {
  708.                sprintf(temp,"(%003u new msgs) ",msgupd->msgcount);
  709.                strout(temp);
  710.             }
  711.             else strout("(No new msgs)  ");
  712.       /* Build the flags display */
  713.             temp[0] = 0;
  714.             if (msgupd->attribute & ECHOMAIL)
  715.                strcat(temp,"E");
  716.             else if(msgupd->attribute & SYSMAIL)
  717.                strcat(temp,"S");
  718.             else strcat(temp,"L");
  719.             if (msgupd->flags & AREA_FORCED) 
  720.                strcat(temp,"*");        /* Forced area symbol */
  721.             while (strlen(temp) < 4)
  722.                strcat(temp," ");
  723.             setcolor(TextAttr[PROMPT_TEXT]);
  724.             strout(temp);
  725.             setcolor(TextAttr[HILITE_TEXT]);
  726.             if (col == 1) {
  727.                strout("\r\n");
  728.                col = 0;   
  729.             }
  730.             else col++;
  731.             msgpos++;
  732.          }
  733.          msgupd = msgupd->next;
  734.       }
  735.       if (msgupd) {
  736.          setcolor(TextAttr[STD_TEXT]);
  737.          strout("\r\nPress ESC to abort or any other key to continue");
  738.          x = chrin();
  739.          strout("\r\n");
  740.          if (x == 0x1b)
  741.             msgupd = NULL;
  742.       }
  743.    }
  744.    setcolor(TextAttr[STD_TEXT]);
  745.    if (col)
  746.       strout("\r\n");
  747. }
  748.  
  749. int is_selarea(int msgnum)
  750. {
  751.    struct msgupd_st *msgupd;
  752.    int x;
  753.  
  754.    msgupd = MSGUPD_1;
  755.    x = 1;
  756.    while (msgupd) {
  757.       if (msgupd->areano == (word) msgnum)
  758.          return x;        /* Return linked list number */
  759.       msgupd = msgupd->next;
  760.       x++;
  761.    }
  762.    return(FALSE);
  763. }
  764.  
  765. void update_msgs(void)
  766. {
  767.    struct msgupd_st *msgupd;
  768.    int x = FALSE;
  769.  
  770.    msgupd = MSGUPD_1;
  771.    while (msgupd) {
  772.       if (msgupd->update) {
  773.          msgupd->startmsg += msgupd->readmsgs;
  774.          adjust_lastread(msgupd->msgpath,msgupd->startmsg);
  775.          x = TRUE;
  776.       }
  777.       msgupd = msgupd->next;
  778.    }
  779.    if (x) {
  780.       setcolor(TextAttr[HILITE_TEXT]);
  781.       strout("\r\nYour lastread message pointers are now being updated\r\n");
  782.    }
  783. }
  784.  
  785. void adjust_lastread(char *msgpath,word num)
  786. {
  787.    char LastRdFile[65];
  788.    long pos;
  789.    int x;
  790.  
  791.    if (LastUser.lastread_ptr)
  792.       sprintf(LastRdFile,"%slastread.bbs",msgpath);
  793.    else sprintf(LastRdFile,"%slastread",msgpath);  
  794.    x = sopen(LastRdFile,O_RDWR | O_BINARY,SH_DENYNO,S_IWRITE);    /* Poke into the lastread file */
  795.    if (x >= 0) {        /* Is it there? */
  796.       pos = (long) (LastUser.lastread_ptr * sizeof(word));
  797.       if ((lseek(x,pos,SEEK_SET)) == pos) 
  798.          write(x,(word *) &num,sizeof(word));
  799.       close(x);
  800.    }
  801. }
  802.  
  803. word get_lastread(char *msgpath)
  804. {
  805.    char LastRdFile[65];
  806.    int x;
  807.    FILE *rdfile;
  808.    word num;
  809.    long pos;
  810.    struct stat fbuf;
  811.  
  812.    if (LastUser.lastread_ptr)        /* Is it the #0 user? */
  813.       sprintf(LastRdFile,"%slastread.bbs",msgpath);
  814.    else sprintf(LastRdFile,"%slastread",msgpath);  
  815.    x = sopen(LastRdFile,O_RDONLY | O_BINARY,SH_DENYNO,S_IREAD);    /* Poke into the lastread file */
  816.    if (x >= 0) {        /* Is it there? */
  817.       pos = (long) (LastUser.lastread_ptr * sizeof(word));
  818.       if ((lseek(x,pos,SEEK_SET)) == pos) {
  819.          read(x,(word *) &num,sizeof(word));
  820.          close(x);
  821.       }
  822.       else {        /* We need to append or create file */
  823.          close(x);        /* Re-open as hi level i/o, it's easier */
  824.          stat(LastRdFile,&fbuf);        /* We need size */
  825.          rdfile = _fsopen(LastRdFile,"ab+",SH_DENYNO);        /* Create */
  826.          if (rdfile != NULL) {        /* We have to append lastread file */
  827.             num = (word) (fbuf.st_size / sizeof(word));        /* How many ptrs so far? */
  828.             x = (int) LastUser.lastread_ptr - num;        /* How many to add */
  829.             num = 0;
  830.             while (x) {
  831.                fwrite((word *) &num,sizeof(word),1,rdfile);        /* Append as many as needed */
  832.                x--;
  833.             }
  834.             fclose(rdfile);
  835.          }
  836.          else num = 0;
  837.       }
  838.    }
  839.    else {        /* Create it then */
  840.       num = 0;
  841.       rdfile = _fsopen(LastRdFile,"wb+",SH_DENYNO);        /* Create */
  842.       if (rdfile != NULL) {        /* We may have to build lastread file */
  843.          if (LastUser.lastread_ptr) {        /* Not sysop */
  844.             x = LastUser.lastread_ptr;
  845.             while (x) {
  846.                fwrite((word *) &num,sizeof(word),1,rdfile);
  847.                x--;
  848.             }
  849.          }
  850.          else fwrite((word *) &num,sizeof(word),1,rdfile);
  851.          fclose(rdfile);
  852.       }
  853.    }
  854.    return num;
  855. }
  856.  
  857. struct msgupd_st *find_area(int msgnum)
  858. {
  859.    struct msgupd_st *msgst;
  860.  
  861.    msgst = MSGUPD_1;
  862.    while (msgst) {
  863.       if (msgst->areano == (word) msgnum)
  864.          break;
  865.       msgst = msgst->next;
  866.    }
  867.    return msgst;
  868. }
  869.  
  870. void delay_s(unsigned n)
  871. /* n = Number of seconds */
  872. {
  873.    n *= 1000;        /* Convert to seconds */
  874.    delay_ms(n);
  875. }
  876.  
  877. void delay_ms(unsigned n)
  878.  /* milleseconds to delay */
  879. {
  880.     struct timeb timebuf;
  881.     long end_time;
  882.     unsigned end_millitm;
  883.  
  884.     /* get current time and calculate ending time */
  885.     ftime(&timebuf);
  886.     end_time = timebuf.time + (n / 1000);
  887.     end_millitm = timebuf.millitm + (n % 1000);
  888.     if (end_millitm >= 1000) {
  889.         ++end_time;
  890.         end_millitm -= 1000;
  891.     }
  892.  
  893.     /* loop until ending time reached */
  894.     do ftime(&timebuf);
  895.     while (timebuf.time < end_time ||
  896.           (timebuf.time == end_time && timebuf.millitm < end_millitm));
  897. }
  898.  
  899. int find_realuser(char *name,int handle)
  900. {
  901.    int x;
  902.    struct _usr USER;
  903.  
  904.    lseek(handle,0L,SEEK_SET);
  905.    x = read(handle,(char *) &USER,user_slen);
  906.    while (x == user_slen) {
  907.       if (strcmpi(name,USER.name) == 0) {
  908.          if (USER.flag & UFLAG_deleted)
  909.             return(FALSE);        /* It's there but it is deleted! */
  910.          else return(TRUE);
  911.       }
  912.       x = read(handle,(char *) &USER,user_slen);
  913.    }
  914.    return(FALSE);        /* Couldn't find it */
  915. }
  916.  
  917. /* Test to see if this message area is a skip one, if so, return TRUE */
  918. int isskiparea(int msgarea)
  919. {
  920.    int x;
  921.  
  922.    if (LastUser.priv >= ASSTSYSOP || msgarea == 0)
  923.       return FALSE;    /* Sysops should always be able to get ALL areas */
  924.  
  925.    for (x = 0; x < SkipCount; x++) {
  926.       if(msgarea == *(SkipAreas[x]))
  927.          return TRUE;
  928.    }
  929.    return FALSE;
  930. }
  931.  
  932. /* Test to see if this message area is a forced one, if so, return TRUE */
  933. int isForcearea(int msgarea)
  934. {
  935.    int x;
  936.  
  937. /*   if (LastUser.priv >= ASSTSYSOP || msgarea == 0)
  938.       return FALSE; */     /* Sysops should'nt be forced */
  939.  
  940.    for (x = 0; x < ForceCount; x++) {
  941.       if(msgarea == *(ForceAreas[x]))
  942.          return TRUE;
  943.    }
  944.    return FALSE;
  945. }
  946.  
  947. void MarkForce(void)
  948. {
  949.    int x;
  950.    struct msgupd_st *new;
  951.    struct msgupd_st *msgupd;
  952.    struct msgupd_st *prev;
  953.  
  954.    for (x = 0; x < ForceCount; x++)  {
  955.       msgmark(*ForceAreas[x]);
  956.       msgupd = MSGUPD_1;
  957.       new = build1_area(*ForceAreas[x],FALSE);
  958.       if (new) {
  959.          USERCFG.totselareas++;
  960.          if (MSGUPD_1 == NULL) 
  961.             MSGUPD_1 = new;
  962.          else {        /* Attach it to the end */
  963.             prev = msgupd;
  964.             while (msgupd) {
  965.                prev = msgupd;
  966.                msgupd = msgupd->next;
  967.             }
  968.             prev->next = new;
  969.          }
  970.          new->next = NULL;
  971.          new->update = FALSE;
  972.       }
  973.    }
  974. }
  975.  
  976. void erase_arc()
  977. {
  978.    struct   find_t c_file;
  979.    char tname[13];
  980.    struct msgupd_st *msgupd;
  981.  
  982.  
  983.    tempdir();
  984.    
  985.  
  986.    if (QWKDir[0]) 
  987.       chdir("..");
  988.  
  989.    unlink(ArcFile);
  990.    unlink(StatName);
  991.    unlink(TxtFile);
  992.  
  993.    if (QWKDir[0]) 
  994.       chdir(QWKDir);
  995.  
  996.    if (USERCFG.msgfrmt == 1) {
  997.       if (_dos_findfirst("*.ndx",_A_NORMAL,&c_file) == 0) {
  998.          unlink(c_file.name);
  999.          while (_dos_findnext(&c_file) == 0)
  1000.             unlink(c_file.name);
  1001.       }
  1002.       unlink(ArcFile);
  1003.       unlink("Messages.dat");
  1004.       unlink("Control.dat");
  1005.       unlink("NewFiles.dat");
  1006.       sprintf(tname,"%s.rep",BBSid);
  1007.       unlink(tname);
  1008.    }
  1009.  
  1010.    msgupd = MSGUPD_1;
  1011.    while (msgupd) {        /* Remove update flag */
  1012.       msgupd->update = FALSE;
  1013.       msgupd = msgupd->next;
  1014.    }
  1015.  
  1016. /* Force arc recreation */
  1017.    PackDone = FALSE;
  1018.    FirstArc = -1;
  1019.    homedir();
  1020. }
  1021.  
  1022. /* Strip leading and trailing whitespace */
  1023. char *stripwhite(char *strng)
  1024. {
  1025.    char *p,*pp;
  1026.  
  1027.    while (*strng && isspace(*strng)) {        /* Trim leading space */
  1028.       pp = strng;
  1029.       p = strng + 1;
  1030.       while (*pp) {        /* Shift up characters */
  1031.          *pp = *p;
  1032.          p++;
  1033.          pp++;
  1034.       }
  1035.    }
  1036.  
  1037.    if (!*strng)        /* We have reached end of string */
  1038.       return(NULL);
  1039.  
  1040.    p = strng + (strlen(strng) - 1);        /* Point to tail */
  1041.    while (isspace(*p)) 
  1042.       p--;
  1043.    p[1] = 0;        /* Terminate at start of trailing space */
  1044.    return(strng);
  1045. }
  1046.  
  1047. /* Turn on given color attribute for video */
  1048. void setcolor(int color)
  1049. {
  1050.    byte back,fore;
  1051.    byte bit2,bit0;
  1052.    char attstr[20];
  1053.  
  1054.    fore = (byte) (color & 0x000f);
  1055.    back = (byte) (color & 0x00070);
  1056.    back = (byte) (back >> 4);
  1057.    sprintf(attstr,"\x1b[1;%d;%dm",back+40,fore+30);
  1058.  
  1059.    if (LastUser.ansi) {
  1060.       printf("\x1b[0m");        /* Reset attributes */
  1061.       FossSendStr("\x1b[0m");        /* Reset attributes */
  1062.       if (color & 0x0080) {        /* Test blink bit */
  1063.          printf("\x1b[5m");
  1064.          FossSendStr("\x1b[5m");
  1065.       }
  1066.       printf(attstr);
  1067.       FossSendStr(attstr);
  1068.    }
  1069.  
  1070.    else if (LastUser.avatar) {
  1071.       color |= 0x8;        /* Turn on intensity for foreground */
  1072.       printf(attstr); /* Print ANSI instead of avatar to local console */
  1073.  
  1074. /* Reverse bits 2 and 0 */
  1075.       bit2 = (byte) (color & 0x04);
  1076.       bit0 = (byte) (color & 0x01);
  1077.       color &= 0xfa;        /* Turn off bit 0 and bit 2 */
  1078.       color |= (bit0 << 2);
  1079.       color |= (bit2 >> 2);
  1080.  
  1081.       sprintf(attstr,"\x16\x01%c",color);
  1082.       FossSendStr(attstr);        /* Send out attribute byte */
  1083.    }
  1084.  
  1085.    CurColor = color;
  1086.    if ((word) color == TextAttr[ATTN_TEXT]) {
  1087.       FossSendStr("\07");
  1088.       if (IsLocal)
  1089.          printf("\07");
  1090.    }
  1091. }
  1092.  
  1093. /* Initiate chat mode with user */
  1094. void chat(void)
  1095. {
  1096.    unsigned ch;
  1097.    int key,col;
  1098.    int minutes;
  1099.  
  1100. /*   if (IsLocal)
  1101.       return; */        /* Makes no sense to chat with yourself! */
  1102.  
  1103.    logit("Sysop <-> User in chat mode",'#');
  1104.  
  1105.    setcolor(TextAttr[HILITE_TEXT]);
  1106.    strout("\r\n\r\nCHAT MODE: \r\n");
  1107.    col = 0;
  1108.    while (1) {
  1109.       minutes = timeon();        /* Establish a counter */
  1110.       while ((ch = FossGetCh()) == 0xFFFF) {
  1111.          check_carrier();
  1112.          if (timeon() > minutes + IDLETIME) {        /* User is idle too long */
  1113.             aborterror(USERIDLE,NULL);
  1114.          }
  1115.       }
  1116.       minutes = 0;        /* Reset idle time! */
  1117.       key = ch & 0xff;
  1118.       if (key == '\r') {        /* Carraige return */
  1119.          col = 0;
  1120.          chrout('\n');
  1121.       }
  1122.       else if (key == '\b') {        /* Backspace */
  1123.          chrout((char) key);
  1124.          chrout(' ');
  1125.          chrout((char) key);
  1126.       }
  1127.       else if (key == '\x1b')        /* Escape */
  1128.          break;
  1129.       else {
  1130.          chrout((char) key);
  1131.          col++;
  1132.          if (col >= 79) {        /* Crude word wrap */
  1133.             col = 0;
  1134.             chrout('\n');
  1135.          }
  1136.       }
  1137.    }
  1138.    logit("Chat end",'#');
  1139.    strout("\r\n\r\nEND CHAT:\r\n");
  1140. }
  1141.  
  1142. void Holler(void)
  1143. {
  1144.    int x;
  1145.    unsigned ch;
  1146.  
  1147.    if (Hollercount >= 3) {
  1148.       setcolor(TextAttr[ATTN_TEXT]);
  1149.       strout("\r\nYou have already hollered for the sysop 3 times.\r\n");
  1150.       return;
  1151.    }
  1152.    if (!Hollercount)        /* First time */
  1153.       logit("User is hollering for sysop",'#');
  1154.    setcolor(TextAttr[HILITE_TEXT]);
  1155.    strout("\r\nHollering for sysop. Press ESC to abort.....\r\n");
  1156.    setcolor(TextAttr[MENU_KEY]);
  1157.    printf("(SYSOP) Press ALT-C to start chat\r\n"); /* Show on local console */
  1158.    setcolor(TextAttr[HILITE_TEXT]);
  1159.    for (x=0; x < Bells; x++) {
  1160.       if (!IsLocal) {
  1161.          FossSendCh(0x07);
  1162.          FossSendCh(0x07);
  1163.          FossSendCh(0x07);
  1164.          FossSendCh(0x07);
  1165.       }
  1166.       tone(650,100);        /* Send bell to local console */
  1167.       tone(450,100);
  1168.       ch = FossGetCh();
  1169.       if (ch != 0xffff) {
  1170.          if (ch == 0x2e00) {
  1171.             chat();
  1172.             break;
  1173.          }
  1174.          if ((ch & 0x00ff) == 0x1b)        /* Escape */
  1175.             break;
  1176.       }
  1177.       delay_ms(500);        /* Delay 1/2 second */
  1178.    }
  1179.    Hollercount++;
  1180. }
  1181.  
  1182. void PackUsers(void)
  1183. {
  1184.    int handl1,handl2,y;
  1185.    int old,new;
  1186.    char drive[_MAX_DRIVE];
  1187.    char dir[_MAX_DIR];
  1188.    char fname[_MAX_FNAME];
  1189.    char tname[_MAX_PATH];
  1190.  
  1191.    handl1 = sopen(CfgFile,O_RDWR | O_BINARY,SH_DENYRW,S_IREAD);
  1192.    if (handl1 == -1) {
  1193.       setcolor(TextAttr[ATTN_TEXT]);
  1194.       strout("\r\nCan't open user file");
  1195.       aborterror(FILEOPEN,"Error opening User config file");
  1196.    }
  1197.  
  1198.    _splitpath(CfgFile,drive,dir,fname,temp);
  1199.    sprintf(tname,"%s%s%s.$$$",drive,dir,fname);
  1200.  
  1201.    handl2 = sopen(tname,O_CREAT | O_RDWR | O_BINARY,SH_DENYWR,S_IWRITE);
  1202.    if (handl2 == -1) {
  1203.       close(handl1);
  1204.       setcolor(TextAttr[ATTN_TEXT]);
  1205.       strout("\r\nCan't open temp file");
  1206.       aborterror(FILEOPEN,"Error opening temp User config file");
  1207.    }
  1208.  
  1209.    old = new = 0;
  1210.    y = read(handl1,(char *) &uscfg,sizeof(struct user_cfg));
  1211.    while (y == sizeof(struct user_cfg)) {
  1212.       old++;
  1213.       if (uscfg.name[0]) { /* Write only the current ones */
  1214.          write(handl2,(char *) &uscfg,sizeof(struct user_cfg));
  1215.          new++;
  1216.          strout("*");
  1217.       }
  1218.       else strout(".");
  1219.       y = read(handl1,(char *) &uscfg,sizeof(struct user_cfg));
  1220.    }
  1221.    strout("\r\n");
  1222.    close(handl1);
  1223.    close(handl2);
  1224.    if (new != old) {
  1225.       setcolor(TextAttr[HILITE_TEXT]);
  1226.       sprintf(temp1,"%d empty records of %d total records were deleted.\r\n",old - new,old);
  1227.       strout(temp1);
  1228.       sprintf(tname,"%s%s%s.bak",drive,dir,fname);
  1229.       unlink(tname);        /* Remove older backup */
  1230.       if(!rename(CfgFile,tname))    {    /* Move current file to backup */
  1231.          sprintf(temp1,"\r\nCreating MaxMail user backup file %s\r\n",tname);
  1232.          strout(temp1);
  1233.          sprintf(tname,"%s%s%s.$$$",drive,dir,fname);
  1234.          rename(tname,CfgFile);     /* Rename new file */
  1235.       }
  1236.       else {
  1237.          sprintf(tname,"%s%s%s.$$$",drive,dir,fname);
  1238.          unlink(tname);        /* Remove this new version */
  1239.       }
  1240.    }
  1241.    else unlink(tname);        /* Delete temp file then */
  1242. }
  1243.  
  1244.  
  1245. /* Create a left justified string (NOT null terminated!) padded with blanks */
  1246. void ljstring(char *dest,char *src,int len)
  1247. {
  1248.    int x;
  1249.    char *p;
  1250.  
  1251.    strncpy(dest,src,len);
  1252.    x = strlen(dest);
  1253.    p = dest + x;
  1254.    while (x < len) {
  1255.       *p = ' ';
  1256.       p++;
  1257.       x++;
  1258.    }
  1259. }
  1260.  
  1261. int copy2temp(char *src)
  1262. {
  1263.    char fname[_MAX_FNAME];
  1264.    char fext[_MAX_EXT];
  1265.    char tname[_MAX_PATH];
  1266.  
  1267.    _splitpath(src,tname,tname,fname,fext);
  1268.  
  1269.    if (tdir[0])
  1270.       sprintf(tname,"%s\\",tdir);
  1271.  
  1272.    if (QWKDir[0]) {
  1273.       strcat(tname,QWKDir);
  1274.       strcat(tname,"\\");
  1275.    }
  1276.    strcat(tname,fname);
  1277.    strcat(tname,fext);        /* Now we have fule destname */
  1278.    return(copyfile(src,tname));
  1279.  
  1280. }
  1281.  
  1282. int copyfile(char *srcname, char *destname)
  1283. {
  1284.    int src,dest;
  1285.    unsigned size,tt;
  1286.    char _far *buff;
  1287.  
  1288.    dest = sopen(destname,O_CREAT | O_TRUNC | O_BINARY | O_RDWR,SH_DENYNO,S_IWRITE);
  1289.    if (dest < 0)
  1290.       return -1;
  1291.  
  1292.    src = sopen(srcname,O_BINARY | O_RDWR,SH_DENYNO,S_IREAD);
  1293.    if (src < 0) {
  1294.       close(dest);
  1295.       unlink(destname);        /* Remove it */
  1296.       return -1;
  1297.    }
  1298.  
  1299.    buff = (char _far *) _fmalloc((1024 * 10) + 5);
  1300.    if (buff == NULL)
  1301.       aborterror(BADALLOC,NULL);
  1302.  
  1303.    _dos_read(src,buff,1024 * 10,&size);
  1304.    while (size) {
  1305.       if(_dos_write(dest,buff,size,&tt))
  1306.          break;
  1307.       if(_dos_read(src,buff,1024 * 10,&size))
  1308.          break;
  1309.    }
  1310.    close(dest);
  1311.    close(src);
  1312.    _ffree(buff);
  1313.    return 0;
  1314. }
  1315.  
  1316. /* Move to our home directory */
  1317. void homedir(void)
  1318. {
  1319.    if (QWKDir[0])
  1320.       chdir("..");
  1321.  
  1322.    if (tdir[0])
  1323.       switch_dir(PRM(sys_path));
  1324.  
  1325. }
  1326.  
  1327. /* Switch to tempdir if used */
  1328. void tempdir(void)
  1329. {
  1330.    if (tdir[0])
  1331.       switch_dir(tdir);
  1332.  
  1333.    if (QWKDir[0])
  1334.       if(chdir(QWKDir) != 0)
  1335.          QWKDir[0] = 0;
  1336. }
  1337.  
  1338.