home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol150 / 211rooma.c < prev    next >
Encoding:
C/C++ Source or Header  |  1984-04-29  |  18.5 KB  |  688 lines

  1. /************************************************************************/
  2. /*                rooma.c                 */
  3. /*        room code fore Citadel bulletin board system        */
  4. /************************************************************************/
  5.  
  6. /************************************************************************/
  7. /*                history                 */
  8. /*                                    */
  9. /* 83Feb24    Insert check for insufficient RAM, externs too low.    */
  10. /* 82Dec06 CrT    2.00 release.                        */
  11. /* 82Nov05 CrT    main() splits off to become citadel.c            */
  12. /************************************************************************/
  13.  
  14. #include "b:210ctdl.h"
  15.  
  16. /************************************************************************/
  17. /*                Contents                */
  18. /*                                    */
  19. /*    dumpRoom()        tells us # new messages etc        */
  20. /*    fileDir()        prints out a filename for a dir listing */
  21. /*    fillMailRoom()        set up Mail> from log record        */
  22. /*    gotoRoom()        handles "g(oto)" command for menu    */
  23. /*    init()            system startup initialization        */
  24. /*    initCitadel()                            */
  25. /*    initSysop()                            */
  26. /*    listRooms()        lists known rooms            */
  27. /*    openFile()        opens a .sys file            */
  28. /*    readSysTab()        restores system state from citadel.tab    */
  29. /*    roomExists()        returns slot# of named room else ERROR    */
  30. /*    setSpace()        set default disk and user#        */
  31. /*    setUp()                             */
  32. /*    systat()        shows current system status        */
  33. /*    wildCard()        expands ambiguous filenames        */
  34. /*    writeSysTab()        saves state of system in citadel.tab    */
  35. /*                                    */
  36. /************************************************************************/
  37.  
  38.  
  39. /************************************************************************/
  40. /*    dumpRoom() tells us # new messages etc                */
  41. /************************************************************************/
  42. dumpRoom() {
  43.     int fileDir();
  44.     int i, count, loc, newCount, no;
  45.  
  46.     for (newCount=0, count=0, i=0;   i<MSGSPERRM;   i++) {
  47.  
  48.     loc    = roomBuf.vp.msg[i].rbmsgLoc;
  49.     no    = roomBuf.vp.msg[i].rbmsgNo ;
  50.     if (loc != ERROR) {
  51.         /* comparisons which take 64K wraparound into account:    */
  52.         if (no - oldestLo
  53.         < 0x8000
  54.         ) {
  55.         count++;
  56.         }
  57.  
  58.         /* don't boggle -- just checking against newestLo as of */
  59.         /* the last time we were  in this room:            */
  60.         if (no -
  61.            (logBuf.lbvisit[ logBuf.lbgen[thisRoom] & CALLMASK ]+1)
  62.         < 0x8000
  63.         ) {
  64.         newCount++;
  65.         }
  66.     }
  67.     }
  68.     /* lazy patch: */
  69.     if (newCount > count)   newCount = count;
  70.  
  71.     mprintf(" %d messages\n ", count);
  72.     if (loggedIn && newCount > 0)   mprintf(" %d new\n", newCount);
  73.     if ((roomBuf.rbflags & CPMDIR) && !expert) {
  74.     /* list directory also: */
  75.     doCR();
  76.     wildCard(fileDir, "*.*");
  77.     }
  78. }
  79.  
  80.  
  81. /************************************************************************/
  82. /*    fileDir() prints out one filename and size, for a dir listing    */
  83. /************************************************************************/
  84. fileDir(fileName)
  85. char *fileName;
  86. {
  87.     struct fcb    block;
  88.  
  89.     char tempName[NAMESIZE], tBuf[2*NAMESIZE];
  90.  
  91.     outFlag = OUTOK;
  92.  
  93.     unspace(fileName, tempName);
  94.     setFcb(&block,    tempName);
  95.     bdos(GETfILEsIZE, &block);        /* very slow on MMS BIOS! */
  96.  
  97.     FDSectCount    += block.fcbRecn;
  98.  
  99.     sprintf(tBuf, "%s%5d  ", fileName, block.fcbRecn);
  100.     putWord(tBuf);
  101.     mAbort();        /* chance to next(!)/pause/skip */
  102. }
  103.  
  104. /************************************************************************/
  105. /*    fillMailRoom()                            */
  106. /************************************************************************/
  107. fillMailRoom()     {
  108.     int i;
  109.  
  110.     /* mail room -- copy messages in logBuf to room: */
  111.     for (i=0;  i<MSGSPERRM;  i++) {
  112.     roomBuf.vp.msg[i].rbmsgLoc  = ERROR;
  113.     roomBuf.vp.msg[i].rbmsgNo   = ERROR;
  114.     }
  115.     for (i=0;  i<MAILSLOTS;  i++) {
  116.     if (i==MSGSPERRM)   break;  /* for MSGSPRRM < MAILSLOTS */
  117.     roomBuf.vp.msg[i].rbmsgLoc  = logBuf.lbslot[i];
  118.     roomBuf.vp.msg[i].rbmsgNo   = logBuf.lbId[i]  ;
  119.     }
  120.     noteRoom();
  121. }
  122.  
  123. /************************************************************************/
  124. /*    gotoRoom() is the menu fn to travel to a new room        */
  125. /*    returns TRUE if room is Lobby>, else FALSE            */
  126. /************************************************************************/
  127. char gotoRoom(nam)
  128. char *nam;
  129. {
  130.     int  i, foundit, newStuff, nwest, roomNo;
  131.  
  132.     if (!strLen(nam)) {
  133.  
  134.     /* update log entry for current room:    */
  135.     logBuf.lbgen[thisRoom] = roomBuf.rbgen << GENSHIFT;
  136.     foundit = FALSE;    /* leaves us in Lobby> if nothing found */
  137.     newStuff= FALSE;
  138.  
  139.     for (i    = 0
  140.          ;
  141.          i<MAXROOMS  &&  !foundit
  142.          ;
  143.          i++
  144.     ) {
  145.         if (
  146.         (roomTab[i].rtflags & INUSE)
  147.         &&
  148.         (roomTab[i].rtgen == (logBuf.lbgen[i]>>GENSHIFT))
  149.         ) {
  150.         nwest = logBuf.lbvisit[logBuf.lbgen[i] & CALLMASK]+1;
  151.  
  152.         if (roomTab[i].rtlastMessage - nwest  < 0x8000) {
  153.             if (i != thisRoom    &&   (i != AIDEROOM   ||   aide))   {
  154.             foundit = i;
  155.             newStuff= TRUE;
  156.             }
  157.         }
  158.         }
  159.     }
  160.  
  161.     getRoom(foundit, &roomBuf);
  162.     mprintf("%s\n ", roomBuf.rbname);
  163.     } else {
  164.  
  165.     /* non-empty room name, so now we look for it: */
  166.     if (
  167.         (roomNo = roomExists(nam)) == ERROR
  168.         ||
  169.         (roomNo==AIDEROOM  &&  !aide)
  170.     ) {
  171.         mPrintf(" ?no %s room\n", nam);
  172.     } else {
  173.         /* update log entry for current room:   */
  174.         if (loggedIn)   logBuf.lbgen[thisRoom] = roomBuf.rbgen << GENSHIFT;
  175.  
  176.         getRoom(roomNo, &roomBuf);
  177.  
  178.         /* if may have been unknown... if so, note it:    */
  179.         if ((logBuf.lbgen[thisRoom] >> GENSHIFT) != roomBuf.rbgen) {
  180.         logBuf.lbgen[thisRoom] = (
  181.             (roomBuf.rbgen << GENSHIFT) +
  182.             (MAXVISIT -1)
  183.         );
  184.         }
  185.     }
  186.     }
  187.     setUp(FALSE);
  188.     dumpRoom();
  189.     return  newStuff;    /* was thisRoom */
  190. }
  191.  
  192. /************************************************************************/
  193. /*    init() -- master system initialization                */
  194. /************************************************************************/
  195. init() {
  196.     char     getCh(), readSysTab(), toUpper();
  197.     char     *msgFile;
  198.     unsigned codend(), endExt(), externs(), topOfMem();
  199.  
  200.     if (!readSysTab()) exit();
  201.  
  202.     setSpace(homeDisk, homeUser);
  203.  
  204.     /* 1K RAM might not actually be sufficient... */
  205.     if (topOfMem() - codEnd() < 1024)    {
  206.     printf("Not enough RAM!");
  207.     exit();
  208.     }
  209.     if (codEnd() >= externs())     {
  210.     printf("Externs too low!");
  211.     exit();
  212.     }
  213.  
  214. #ifdef XYZZY
  215.     printf("code ends ....at  %u\n", codend()  );
  216.     printf("externs start at  %u\n", externs() );
  217.     printf("externs end   at  %u\n", endext()  );
  218.     printf("free RAM ends at  %u\n", topofmem());
  219. #endif
  220.  
  221.     if (FALSE) getText();        /* dummy to force load        */
  222.     exitToCpm    = FALSE;        /* not time to quit yet!    */
  223.     sizeLTentry = sizeOf(logTab[0]);    /* just had to try that feature */
  224.     outFlag    = OUTOK;        /* not p(ausing)        */
  225.  
  226.     pullMessage = FALSE;        /* not pulling a message    */
  227.     pulledMLoc    = ERROR;        /* haven't pulled one either    */
  228.     pulledMId    = ERROR;
  229.  
  230.     debug    = FALSE;
  231.     loggedIn    = FALSE;
  232.     thisRoom    = LOBBY;
  233.  
  234.     whichIO    = CONSOLE;
  235.     loggedIn    = FALSE;
  236.     setUp(TRUE);
  237.  
  238.     /* we initmodem at beginning & end both...*/
  239.     modemInit();
  240.  
  241.     monthTab[1] = "Jan";
  242.     monthTab[2] = "Feb";
  243.     monthTab[3] = "Mar";
  244.     monthTab[4] = "Apr";
  245.     monthTab[5] = "May";
  246.     monthTab[6] = "Jun";
  247.     monthTab[7] = "Jul";
  248.     monthTab[8] = "Aug";
  249.     monthTab[9] = "Sep";
  250.     monthTab[10]= "Oct";
  251.     monthTab[11]= "Nov";
  252.     monthTab[12]= "Dec";
  253.  
  254.     if (!clock)   interpret(pInitDate);
  255.  
  256.     /* open message files: */
  257.     msgFile    = "a:ctdlmsg.sys";
  258.     *msgFile   += msgDisk;
  259.     openFile(msgFile,         &msgfl );
  260.     openFile("ctdlroom.sys", &roomfl);
  261.     openFile("ctdllog.sys",  &logfl );
  262.  
  263.     getRoom(0, &roomBuf);    /* load Lobby>    */
  264.     modemInit();
  265. }
  266.  
  267. /************************************************************************/
  268. /*    initCitadel() does not reformat data files            */
  269. /************************************************************************/
  270. initCitadel() {
  271.     whichIO = MODEM;
  272.     setUp(FALSE);
  273. }
  274.  
  275. /************************************************************************/
  276. /*    listRooms() lists known rooms                    */
  277. /************************************************************************/
  278. listRooms(doDull)
  279. char doDull;    /* TRUE to list unchanged rooms also    */
  280. {
  281.     char str[NAMESIZE+3];
  282.     char boringRooms, doBoringRooms, hasUnseenStuff, shownHidden;
  283.     int  i;
  284.  
  285.     shownHidden = FALSE;
  286.     boringRooms = FALSE;
  287.     mprintf("\n Rooms with unread messages:\n ");
  288.     for (doBoringRooms=FALSE;  doBoringRooms<=doDull;  doBoringRooms++) {
  289.     for (i=0;  i<MAXROOMS;    i++) {
  290.         if (
  291.         (roomTab[i].rtflags & INUSE)
  292.         &&  (
  293.             /* list it if public or previously visited: */
  294.             (roomTab[i].rtflags & PUBLIC)
  295.             ||    (
  296.             loggedIn   &&
  297.             roomTab[i].rtgen == (logBuf.lbgen[i] >> GENSHIFT)
  298.             )
  299.             || debug
  300.         )
  301.         ) {
  302.         /* do only rooms with unseen messages first pass,  */
  303.         /* only rooms without unseen messages second pass: */
  304.         hasUnseenStuff    =  (
  305.             roomTab[i].rtlastMessage - (
  306.             logBuf.lbvisit[ logBuf.lbgen[i] & CALLMASK ]+1
  307.             )  <  0x8000
  308.         );
  309.         if (!hasUnseenStuff)   boringRooms  = TRUE;
  310.  
  311.         if (
  312.             (!doBoringRooms &&    hasUnseenStuff)  ||
  313.             ( doBoringRooms && !hasUnseenStuff)
  314.         ) {
  315.             strcpy(str, roomTab[i].rtname);
  316.  
  317.             if (roomTab[i].rtflags & CPMDIR)    strcat(str, ":");
  318.             else                strcat(str, ">");
  319.  
  320.             if (! (roomTab[i].rtflags & PUBLIC)) {
  321.             strcat(str, "*");
  322.             shownHidden    = TRUE;
  323.             }
  324.             mprintf(" %s", str);
  325.         }
  326.         }
  327.     }
  328.     if (boringRooms && !doBoringRooms  && doDull)  {
  329.         mprintf("\n No unseen msgs in:\n ");
  330.     }
  331.     }
  332.     if (!expert && shownHidden) mprintf("\n \n * => hidden room\n ");
  333. }
  334.  
  335. /************************************************************************/
  336. /*    openFile() opens one of the .sys files.             */
  337. /************************************************************************/
  338. openFile(filename, fd)
  339. char *filename;
  340. int  *fd;
  341. {
  342.     /* open message file */
  343.     if ((*fd = open(filename, 2)) == ERROR) {
  344.     printf("?no %s", filename);
  345.     exit();
  346.     }
  347.     rsrec(*fd);     /* initialize for random io */
  348. }
  349.  
  350. /************************************************************************/
  351. /*    readSysTab() restores state of system from SYSTEM.TAB        */
  352. /*    returns:    TRUE on success, else FALSE            */
  353. /*        destroys SYSTEM.TAB after read, to prevent erroneous re-use */
  354. /*        in the event of a crash.                    */
  355. /************************************************************************/
  356. readSysTab() {
  357.     char getc();
  358.     char fBuf[BUFSIZ];
  359.     char *c;
  360.  
  361.     if(fopen("ctdlTabl.sys", fBuf) == ERROR) {
  362.     printf("?no ctdlTabl.sys!");
  363.     return(FALSE);
  364.     }
  365.  
  366.     if (
  367.     getw(fBuf) !=  &firstExtern
  368.     ||
  369.     getw(fBuf) !=  &lastExtern
  370.     ) {
  371.     printf("?old ctdlTabl.sys!");
  372.     return(FALSE);
  373.     }
  374.     c    = &firstExtern;
  375.     while (c < &lastExtern)   *c++ = getc(fBuf);
  376.  
  377.     unlink("ctdlTabl.sys");
  378.     return(TRUE);
  379. }
  380.  
  381. /************************************************************************/
  382. /*    roomExists() returns slot# of named room else ERROR        */
  383. /************************************************************************/
  384. int roomExists(room)
  385. char *room;
  386. {
  387.     int i;
  388.  
  389.     for (i=0;  i<MAXROOMS;  i++) {
  390.     if (
  391.         roomTab[i].rtflags & INUSE     &&
  392.         strCmpU(room, roomTab[i].rtname) == SAMESTRING
  393.     ) {
  394.         return(i);
  395.     }
  396.     }
  397.     return(ERROR);
  398. }
  399.  
  400. /************************************************************************/
  401. /*    setSpace() moves us to a disk and user#             */
  402. /************************************************************************/
  403. setSpace(disk, user)
  404. char disk, user;
  405. {
  406.     bdos(SETdISK, disk);
  407.     ourDisk    = disk;
  408.  
  409.     bdos(SETuSER, user);
  410.     ourUser    = user;
  411. }
  412.  
  413. /************************************************************************/
  414. /*    setUp()                             */
  415. /************************************************************************/
  416. setUp(justIn)
  417. char justIn;
  418. {
  419.     int g, i, j, ourSlot;
  420.  
  421.     echo        = BOTH;     /* just in case         */
  422.     usingWCprotocol    = FALSE;    /* also redundant        */
  423.  
  424.     if (!loggedIn)   {
  425.     prevChar    = ' ';
  426.     termWidth   = 32;
  427.     termLF        = LFMASK;
  428.     termUpper   = TRUE;
  429.     termNulls   = 5;
  430.     expert        = FALSE;
  431.     aide        = FALSE;
  432.  
  433.     if (justIn)   {
  434.         /* set up logBuf so everything is new...        */
  435.         for (i=0;  i<MAXVISIT;  i++)  logBuf.lbvisit[i] = oldestLo;
  436.  
  437.         /* no mail for anonymous folks: */
  438.         roomTab[MAILROOM].rtlastMessage = newestLo;
  439.         for (i=0;  i<MAILSLOTs;  i++)   logBuf.lbId[i]  = 0;
  440.  
  441.         logBuf.lbname[0]    =0;
  442.  
  443.         for (i=0;  i<MAXROOMS;  i++) {
  444.         if (roomTab[i].rbflags & PUBLIC) {
  445.             /* make public rooms known: */
  446.             g            = roomTab[i].rtgen;
  447.             logBuf.lbgen[i]    = (g << GENSHIFT) + (MAXVISIT-1);
  448.         } else {
  449.             /* make private rooms unknown: */
  450.             g            = (roomTab[i].rtgen + (MAXGEN-1)) % MAXGEN;
  451.             logBuf.lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
  452.         }
  453.         }
  454.     }
  455.     } else {
  456.     /* loggedIn: */
  457.     termWidth   = logBuf.lbwidth;
  458.     termNulls   = logBuf.lbnulls;
  459.     termLF        = logBuf.lbflags & LFMASK ;
  460.     termUpper   = logBuf.lbflags & UCMASK ;
  461.     expert        = logBuf.lbflags & EXPERT ;
  462.     termTab     = logBuf.lbflags & TABMASK;
  463.     aide        = logBuf.lbflags & AIDE   ;
  464.  
  465.     if (justIn)   {
  466.         /* set gen on all unknown rooms  --  INUSE or no: */
  467.         for (i=0;  i<MAXROOMS;  i++) {
  468.         if (!(roomTab[i].rtflags & PUBLIC)) {
  469.             /* it is private -- is it unknown? */
  470.             if ((logBuf.lbgen[i] >> GENSHIFT)    !=   roomTab[i].rtgen) {
  471.             /* yes -- set    gen = (realgen-1) % MAXGEN */
  472.             j = (roomTab[i].rtgen + (MAXGEN-1)) % MAXGEN;
  473.             logBuf.lbgen[ i ] =  (j << GENSHIFT) + (MAXVISIT-1);
  474.             }
  475.         }
  476.         else if ((logBuf.lbgen[i] >> GENSHIFT)    !=  roomTab[i].rtgen)  {
  477.             /* newly created public room -- remember to visit it; */
  478.             logBuf.lbgen[i] = (roomTab[i].rtgen << GENSHIFT) +1;
  479.         }
  480.         }
  481.         /* special kludge for Mail> room, to signal new mail:   */
  482.         roomTab[MAILROOM].rtlastMessage = logBuf.lbId[MAILSLOTS-1];
  483.  
  484.         /* slide lbvisit array down and change lbgen entries to match: */
  485.         for (i=(MAXVISIT-2);  i;  i--) {
  486.         logBuf.lbvisit[i] = logBuf.lbvisit[i-1];
  487.         }
  488.         logBuf.lbvisit[(MAXVISIT-1)]    = oldestLo;
  489.         for (i=0;  i<MAXROOMS;  i++) {
  490.         if ((logBuf.lbgen[i] & CALLMASK)  <  (MAXVISIT-2)) {
  491.             logBuf.lbgen[i]++;
  492.         }
  493.         }
  494.  
  495.         /* Slide entry to top of log table: */
  496.         ourSlot = logTab[thisSlot].ltlogSlot;
  497.         slideltab(0, thisSlot);
  498.  
  499.         logTab[0].ltpwhash        = hash(logBuf.lbpw);
  500.         logTab[0].ltnmhash        = hash(logBuf.lbname);
  501.         logTab[0].ltlogSlot     = ourSlot;
  502.         logTab[0].ltnewest        = newestLo;
  503.     }
  504.     }
  505.     logBuf.lbvisit[0]    = newestLo;
  506.  
  507.     onConsole    = (whichIO == CONSOLE);
  508.     if (thisRoom == MAILROOM)    fillMailRoom();
  509.  
  510.     if (thisRoom == MAILROOM  &&  whichIO == MODEM)   echo = CALLER;
  511.     else                          echo = BOTH  ;
  512. }
  513.  
  514. /************************************************************************/
  515. /*    systat() prints out current system status            */
  516. /************************************************************************/
  517. systat() {
  518.     int i;
  519.  
  520.     printDate(
  521.     interpret(pGetYear ),
  522.     interpret(pGetMonth),
  523.     interpret(pGetDay  )
  524.     );
  525.  
  526. #ifdef XYZZY
  527.     if (debug) mprintf(" *catChar=%d catSector=%d\n*", catChar, catSector);
  528. #endif
  529.  
  530.     mprintf("\n Width %d, %s%slinefeeds, %d nulls\n",
  531.     termWidth,
  532.     termUpper  ?  "UPPERCASE ONLY, " : "",
  533.     termLF       ?  ""         : "no ",
  534.     termNulls
  535.     );
  536.  
  537. #ifdef XYZZY
  538.     if (debug) mprintf(" *lowId=%u %u, highId=%u %u\n*",
  539.     oldestHi, oldestLo,
  540.     newestHi, newestLo
  541.     );
  542. #endif
  543.  
  544.     if (loggedIn) {
  545.     mprintf(" Logged in as %s\n", logBuf.lbname);
  546. #ifdef XYZZY
  547.     if (debug) {
  548.         for (i=0; i<MAXVISIT; i++) {
  549.         printf("lbvisit[%d]=%u\n", i, logBuf.lbvisit[i]);
  550.         }
  551.         printf("lbgen>>GENSHIFT==%d; roomTab.rtgen==%d; roomBuf.rbgen==%d\n"
  552.         , logBuf.lbgen[thisRoom]>>GENSHIFT, roomTab[thisRoom].rtgen,
  553.         roomBuf.rbgen
  554.         );
  555.         printf("lbgen&CALLMASK==%d\n", logBuf.lbgen[thisRoom]&CALLMASK);
  556.     }
  557. #endif
  558.     }
  559.  
  560.     mprintf(" %d messages,",            newestLo-oldestLo +1);
  561.     mprintf(" last is %u %u,\n",        newestHi, newestLo  );
  562.     mprintf(" %dK message space,\n",        maxMSector >> 3     );
  563.     mprintf(" %d-entry log\n",            MAXLOGTAB        );
  564. }
  565.  
  566.  
  567. /************************************************************************/
  568. /*    unspace() copies a filename, removing blanks            */
  569. /************************************************************************/
  570. unspace(from, to)
  571. char *from, *to;
  572. {
  573.     while (*to =  *from++)   if (*to != ' ')   to++;
  574. }
  575.  
  576. /************************************************************************/
  577. /*    wildCard()                            */
  578. /* Adapted from YAM which borrowed from Richard Greenlaw's expander.    */
  579. /************************************************************************/
  580. #define UFNsIZE        13    /* size of "filename.ext" plus a null.    */
  581.  
  582. wildCard(fn, filename)
  583. int (*fn)();
  584. char *filename;     /* may be ambiguous.  No drive or user numbers. */
  585. {
  586.     char toLower();
  587.     int  strCmp();
  588.  
  589.     struct fcb    block, *pBlock;
  590.  
  591.     char *p, *q, c, byteAddr, finished;
  592.  
  593.     int  fileCount, i, m;
  594.  
  595.     char tBuf[SECTSIZE];
  596.     struct {
  597.     char unambig[UFNsIZE];    /* filename                */
  598.     } *fp;
  599.  
  600.     if (
  601.     filename[1]         == ':'   ||
  602.     setFcb(&block, filename) == 255
  603.     ) {
  604.     /* bad filename: */
  605.     mprintf("%s?\n ", filename);
  606.     return;
  607.     }
  608.  
  609.     bdos(SETdMA, tBuf);
  610.  
  611.     setSpace(roomBuf.rbdisk, roomBuf.rbuser);
  612.  
  613.     if ( (byteAddr=bdos(FINDfIRST, &block))  ==  255)    {
  614.     /* no such file */
  615.     mprintf("no %s\n ", filename);
  616.     setSpace(homeDisk, homeUser);
  617.     return;
  618.     }
  619.  
  620.     /* search directory for all matches: */
  621.     for (
  622.     fp=msgBuf.mbtext, fileCount=0, finished=FALSE;
  623.  
  624.     !finished;
  625.  
  626.     fp++, fileCount++,
  627.     finished = ((byteAddr=bdos(FINDnEXT, &block)) == 255)
  628.     ) {
  629.  
  630.     /* figure out where BDOS stashed our fcb:   */
  631.     pBlock = tBuf + 32*(byteAddr % 4);  /* "% 4"? --CrT            */
  632.  
  633.     p   = fp;
  634.  
  635.     if (fp > (&msgBuf.mbtext[MAXTEXT-100]))  {
  636.         printf("too many files!!\n");
  637.         setSpace(homeDisk, homeUser);
  638.         return;
  639.     }
  640.  
  641.     /* copy filename from directory:     */
  642.     q    = pBlock;
  643.     for (i=8;  i;  i--)   *p++   = toLower(*++q & 0x7F);
  644.     *p++ = '.';
  645.  
  646.     /* get file extention: */
  647.     for (i=3;  i;  i--)  *p++    = toLower(*++q & 0x7F);
  648.     *p   = '\0';         /* tie off with null */
  649.     }
  650.  
  651.     qSort(msgBuf.mbtext, fileCount, UFNsIZE, strCmp);
  652.  
  653.     outFlag    = OUTOK;
  654.     for (fp=msgBuf.mbtext;  fileCount-- && outFlag!=OUTSKIP;  fp++) {
  655.     (*fn)(fp);
  656.     }
  657.     setSpace(homeDisk, homeUser);
  658. }
  659.  
  660. /************************************************************************/
  661. /*    writeSysTab() saves state of system in SYSTEM.TAB        */
  662. /*    returns:    TRUE on success, else ERROR            */
  663. /************************************************************************/
  664. writeSysTab() {
  665.     /*    extern int opsLogChar, opsLogSector, catChar, catSector;    */
  666.     /*    extern int lowId, highId, nextRoom;                */
  667.     /*    extern struct logTab, struct roomTab;                */
  668.  
  669.     char *c;
  670.     char fBuf[BUFSIZ];
  671.  
  672.     if(fcreat("ctdlTabl.sys", fBuf) == ERROR) {
  673.     printf("?can't make ctdlTabl.sys");
  674.     return(ERROR);
  675.     }
  676.  
  677.     /* write loc & len so we can detect bad ctdlTabl.sys files: */
  678.     putw(&firstExtern, fBuf);
  679.     putw(&lastExtern,  fBuf);
  680.  
  681.     c    = &firstExtern;
  682.     while (c < &lastExtern)   putc(*c++, fBuf);
  683.  
  684.     fflush(fBuf);
  685.     fclose(fBuf);
  686.     return(TRUE);
  687. }
  688.