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

  1. /************************************************************************/
  2. /*                log.c                    */
  3. /*                                    */
  4. /*       userlog code for  Citadel bulletin board system        */
  5. /************************************************************************/
  6.  
  7. /************************************************************************/
  8. /*                history                 */
  9. /* 83Jun13 BAK  Modified terminate to handle rcpm flag correctly.    */
  10. /* 83Jun11 BAK  Fixed phantom configuration bug.            */
  11. /* 83Feb27 CrT    Fixed login-in-Mail> bug.                */
  12. /* 83Feb26 CrT    Limited # new messages for new users.            */
  13. /* 83Feb18 CrT    Null pw problem fixed.                    */
  14. /* 82Dec06 CrT    2.00 release.                        */
  15. /* 82Nov03 CrT    Began local history file & general V1.2 cleanup     */
  16. /************************************************************************/
  17.  
  18. #include "b:210ctdl.h"
  19.  
  20. /************************************************************************/
  21. /*                contents                */
  22. /*                                    */
  23. /*    crypte()        encrypts/decrypts data blocks        */
  24. /*    getLog()        loads requested userlog record        */
  25. /*    hash()            hashes a string to an integer        */
  26. /*    login()         is menu-level routine to log caller in    */
  27. /*    logInit()        builds the RAM index to ctdllog.sys    */
  28. /*    newPW()         is menu-level routine to change a PW    */
  29. /*    newUser()        menu-level routine to log a new caller    */
  30. /*    noteLog()        enters a userlog record into RAM index    */
  31. /*    putLog()        stores a logBuffer into ctdllog.sys    */
  32. /*    PWSlot()        returns userlog.buf slot password is in */
  33. /*    slideLTab()        support routine for sorting logTab    */
  34. /*    sortLog()        sort userlog by time since last call    */
  35. /*    strCmpU()        strcpm(), but ignoring case distinctions*/
  36. /*    terminate()        menu-level routine to exit system    */
  37. /*??????userlog()??????        sysop special to display userlog    */
  38. /*    zapLogFile()        erases & re-initializes ctdllog.sys    */
  39. /************************************************************************/
  40.  
  41. /************************************************************************/
  42. /*    crypte() encrypts/decrypts data blocks                */
  43. /*                                    */
  44. /*  This was at first using a full multiply/add pseudo-random sequence    */
  45. /*  generator, but 8080s don't like to multiply.  Slowed down I/O    */
  46. /*  noticably.    Rewrote for speed.                    */
  47. /*  and subsequently removed to aide in debugging.              */
  48. /************************************************************************/
  49. #define b    fpc1
  50. #define c    fi1
  51. #define s    fi2
  52. crypte(buf, len, seed)
  53. char      *buf;
  54. unsigned  len, seed;
  55. {
  56. /*    seed    = (seed + cryptSeed) & 0xFF;            
  57.     b        = buf;                        
  58.     c        = len;                        
  59.     s        = seed;                        
  60.     for (;  c;    c--) {                        
  61.     *b++   ^= s;                            
  62.     s    = (s + CRYPTADD)  &  0xFF;                
  63.     }            
  64. */
  65. }
  66.  
  67. /************************************************************************/
  68. /*    getLog() loads requested log record into RAM buffer        */
  69. /************************************************************************/
  70. getLog(lBuf, n)
  71. struct logBuffer    *lBuf;
  72. int            n;
  73. {
  74.     if (lBuf == &logBuf)   thisLog    = n;
  75.  
  76.     n    *= SECSPERLOG;
  77.  
  78.     rseek(logfl, n, 0);
  79.     if (rread(logfl, lBuf, SECSPERLOG) >= 1000) {
  80.     printf("?getLog-rread fail");
  81.     }
  82.  
  83.     crypte(lBuf, (SECSPERLOG*SECTSIZE), n);    /* decode buffer    */
  84. }
  85.  
  86. /************************************************************************/
  87. /*    hash() hashes a string to an integer                */
  88. /************************************************************************/
  89. int hash(str)
  90. char *str;
  91. {
  92.     char toUpper();
  93.     int  h, i, shift;
  94.  
  95.     for (h=shift=0;  *str;  shift=(shift+1)&7, str++) {
  96.     h ^= (i=toUpper(*str)) << shift;
  97.     }
  98.     return h;
  99. }
  100.  
  101. /************************************************************************/
  102. /*    login() is the menu-level routine to log someone in        */
  103. /************************************************************************/
  104. login(password)
  105. char *password;    /* TRUE if parameters follow    */
  106. {
  107.     char getYesNo();
  108.     int  i, j;
  109.     int  foundIt, ltentry, match, ourSlot;
  110.  
  111.     foundIt =     ((ltentry = PWSlot(password)) != ERROR);
  112.  
  113.     if (foundIt && *password) {
  114.  
  115.     /* recite caller's name, etc:     */
  116.     mPrintf(" %s\n", logBuf.lbname);
  117.  
  118.     /* update userlog entries: */
  119.  
  120.     loggedIn     = TRUE;
  121.     setUp(TRUE);
  122.  
  123.     showMessages(NEWoNLY, FALSE);
  124.  
  125.     listRooms(/* doDull== */ !expert);
  126.  
  127.     outFlag = OUTOK;
  128.     if (
  129.         (
  130.         logBuf.lbId[MAILSLOTS-1]
  131.         -
  132.         (logBuf.lbvisit[   logBuf.lbgen[MAILROOM] & CALLMASK   ]+1)
  133.         < 0x8000
  134.         )
  135.         &&
  136.         logBuf.lbId[MAILSLOTS-1] - oldestLo       < 0x8000
  137.         &&
  138.         thisRoom != MAILROOM
  139.     )   {
  140.         mprintf("\n  * You have private mail in Mail> *\n ");
  141.     }
  142.  
  143.     } else {
  144.     /* discourage password-guessing: */
  145.     if (strLen(password) > 1)   pause(2000);
  146.     if (!unlogLoginOk  &&  whichIO==MODEM)    {
  147.         mPrintf(" No record -- leave message to 'sysop' in Mail>\n ");
  148.     } else if (getYesNo(" No record: Enter as new user"))    newUser();
  149.     }
  150. }
  151.  
  152. /************************************************************************/
  153. /*    logInit() indexes userlog.buf                    */
  154. /************************************************************************/
  155. logInit() {
  156.     int i;
  157.     int count;
  158.  
  159.     count = 0;
  160.  
  161.     /* clear logTab */
  162.     for (i=0;  i<MAXLOGTAB;  i++) logTab[i].ltnewest    = ERROR;
  163.  
  164.     /* load logTab: */
  165.     for (thisLog=0;  thisLog<MAXLOGTAB;  thisLog++) {
  166.     printf("log#%d\n", thisLog);
  167.     getLog(&logBuf, thisLog);
  168.  
  169.     /* count valid entries:         */
  170.     if (logBuf.lbvisit[0] != ERROR) count++;
  171.  
  172.     /* copy relevant info into index:   */
  173.     logTab[thisLog].ltnewest = logBuf.lbvisit[0];
  174.     logTab[thisLog].ltlogSlot= thisLog;
  175.     logTab[thisLog].ltnmhash = hash(logBuf.lbname);
  176.     logTab[thisLog].ltpwhash = hash(logBuf.lbpw  );
  177.     }
  178.     printf(" logInit--%d valid log entries\n", count);
  179.     sortLog();
  180. }
  181.  
  182. /************************************************************************/
  183. /*    newPW() is menu-level routine to change one's password        */
  184. /*    since some Citadel nodes run in public locations, we avoid    */
  185. /*    displaying passwords on the console.                */
  186. /************************************************************************/
  187. newPW() {
  188.     char oldPw[NAMESIZE];
  189.     char pw[NAMESIZE];
  190.     char *s;
  191.     int i, goodPW;
  192.  
  193.     /* save password so we can find current user again: */
  194.     strcpy(oldPw, logBuf.lbpw);
  195.     storeLog();
  196.     do {
  197.     echo    = CALLER;
  198.     getString(" new password", pw, NAMESIZE);
  199.     normalizeString(pw);
  200.     echo    = BOTH;
  201.  
  202.     /* check that PW isn't already claimed: */
  203.     goodPW = (PWSlot(pw) == ERROR  &&  strlen(pw) >= 2);
  204.  
  205.     if (!goodPW) mprintf("\n Poor password\n ");
  206.  
  207.     } while (
  208.     (strlen(pw) < 2  || !goodPW        )
  209.     &&
  210.     (haveCarrier     || whichIO==CONSOLE)
  211.     );
  212.  
  213.     doCR();
  214.     PWSlot(oldPw);            /* reload old log entry         */
  215.     pw[NAMESIZE-1] = 0x00;        /* insure against loss of carrier:  */
  216.  
  217.     if (goodPW    &&  strlen(pw) > 1) {    /* accept new PW:            */
  218.     strcpy(logBuf.lbpw, pw);
  219.     logTab[0].ltpwhash    = hash(pw);
  220.     }
  221.  
  222.     mprintf("\n %s\n pw: ", logBuf.lbname);
  223.     if (whichIO == CONSOLE) {
  224.     printf("%s\n ", logBuf.lbpw);
  225.     } else {
  226.     s    = logBuf.lbpw;
  227.     while (*s)    outMod(*s++);
  228.     doCR();
  229.     }
  230. }
  231.  
  232. /************************************************************************/
  233. /*    newUser() prompts for name and password             */
  234. /************************************************************************/
  235. newUser() {
  236.     char    getYesNo();
  237.     char    fullnm[NAMESIZE];
  238.     char    pw[NAMESIZE];
  239.     char    *s;
  240.     int     good, g, h, i, ok, ourSlot, zero;
  241.     unsigned    low;
  242.  
  243.  
  244.     configure();    /* make sure new users configure reasonably    */
  245.  
  246.     if (!expert)   tutorial("password.blb");
  247.  
  248.     do {
  249.     /* get name and check for uniqueness... */
  250.     do {
  251.         getString(" Name", fullnm, NAMESIZE);
  252.         normalizeString(fullnm);
  253.         h     = hash(fullnm);
  254.         for (i=0, good=TRUE;   i<MAXLOGTAB && good;   i++) {
  255.         if (h == logTab[i].ltnmhash) good = FALSE;
  256.         }
  257.         if (
  258.         !h
  259.         ||
  260.         h==hash("Citadel")
  261.         ||
  262.         h==hash("Sysop")
  263.         ) {
  264.         good = FALSE;
  265.         }
  266.         /* lie sometimes -- hash collision !=> name collision */
  267.         if (!good) mprintf("We already have a %s\n", fullnm);
  268.     } while (!good    &&  (haveCarrier || whichIO==CONSOLE));
  269.  
  270.     /* get password and check for uniqueness...    */
  271.     do {
  272.         echo    = CALLER;
  273.         getString(" password",  pw, NAMESIZE);
  274.         normalizeString(pw);
  275.         echo    = BOTH    ;
  276.  
  277.         h     = hash(pw);
  278.         for (i=0, good=strLen(pw) > 1;  i<MAXLOGTAB  &&  good;  i++) {
  279.         if (h == logTab[i].ltpwhash) good = FALSE;
  280.         }
  281.         if (!h)   good = FALSE;
  282.         if (!good) {
  283.         mprintf("\n Poor password\n ");
  284.         }
  285.     } while( !good    &&  (haveCarrier || whichIO==CONSOLE));
  286.  
  287.     mprintf("\n nm: %s", fullnm);
  288.     mprintf("\n pw: ");
  289.     if (whichIO == CONSOLE) {
  290.         printf("%s\n ", pw);
  291.     } else {
  292.         echo = CALLER;
  293.         mPrintf("%s\n ", pw);
  294.         echo = BOTH;
  295.     }
  296.     } while (
  297.     !getYesNo("OK")
  298.     &&
  299.     (haveCarrier || whichIO==CONSOLE)
  300.     );
  301.  
  302.     if (ok && (haveCarrier || whichIO==CONSOLE)) {
  303.  
  304.     /* kick least recent caller out of userlog and claim entry:    */
  305.     ourSlot         = logTab[MAXLOGTAB-1].ltlogSlot;
  306.     slideLTab(0, MAXLOGTAB-1);
  307.     logTab[0].ltlogSlot = ourSlot;
  308.     getLog(&logBuf, ourSlot);
  309.  
  310.     /* copy info into record:    */
  311.     strcpy(logBuf.lbname, fullnm);
  312.     strcpy(logBuf.lbpw, pw);
  313.  
  314.     low = newestLo-50;
  315.     if (oldestLo-low < 0x8000)   low = oldestLo;
  316.     for (i=1;  i<MAXVISIT;    i++)   logBuf.lbvisit[i]= low;
  317.     logBuf.lbvisit[                   0]= newestLo;
  318.     logBuf.lbvisit[            (MAXVISIT-1)]= oldestLo;
  319.  
  320.     /* initialize rest of record:    */
  321.     for (i=0;  i<MAXROOMS;    i++) {
  322.         if (roomTab[i].rtflags & PUBLIC) {
  323.         g = (roomTab[i].rtgen);
  324.         logBuf.lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
  325.         } else {
  326.         /* set to one less */
  327.         g = (roomTab[i].rtgen + (MAXGEN-1)) % MAXGEN;
  328.         logBuf.lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
  329.         }
  330.     }
  331.     for (i=0;  i<MAILSLOTS;  i++)  {
  332.         logBuf.lbslot[i]    = 0;
  333.         logBuf.lbId[  i]    = oldestLo -1;
  334.     }
  335.  
  336.     /* fill in logTab entries    */
  337.     logTab[0].ltpwhash    = hash(pw)       ;
  338.     logTab[0].ltnmhash    = hash(fullnm)       ;
  339.     logTab[0].ltlogSlot    = thisLog       ;
  340.     logTab[0].ltnewest    = logBuf.lbvisit[0];
  341.  
  342.     /* special kludge for Mail> room, to signal no new mail:   */
  343.     roomTab[MAILROOM].rtlastMessage = logBuf.lbId[MAILSLOTS-1];
  344.  
  345.     loggedIn = TRUE;
  346.  
  347.     storeLog();
  348.  
  349.     listRooms(/* doDull== */ !expert);
  350.     }
  351. }
  352.  
  353. /************************************************************************/
  354. /*    noteLog() notes logTab entry in RAM buffer in master index    */
  355. /************************************************************************/
  356. noteLog() {
  357.     int i, j, slot;
  358.  
  359.     /* figure out who it belongs between:    */
  360.     for (i=0;  logTab[i].ltnewest > logBuf.lbvisit[0];    i++);
  361.  
  362.     /* note location and open it up:        */
  363.     slot = i;
  364.     slideltab(slot, MAXLOGTAB-1);
  365.  
  366.     /* insert new record */
  367.     logTab[slot].ltnewest    = logBuf.lbvisit[0]  ;
  368.     logTab[slot].ltlogSlot    = thisLog         ;
  369.     logTab[slot].ltpwhash    = hash(logBuf.lbpw)  ;
  370.     logTab[slot].ltnmhash    = hash(logBuf.lbname);
  371. }
  372.  
  373. /************************************************************************/
  374. /*    putLog() stores givend log record into ctdllog.sys        */
  375. /************************************************************************/
  376. putLog(lBuf, n)
  377. struct logBuffer    *lBuf;
  378. int            n;
  379. {
  380.     n    *= SECSPERLOG;
  381.  
  382.     crypte(lBuf, (SECSPERLOG*SECTSIZE), n);    /* encode buffer    */
  383.  
  384.     rseek(logfl, n, 0);
  385.     if (rwrite(logfl, lBuf, SECSPERLOG) != SECSPERLOG) {
  386.     printf("?putLog-rwrite fail");
  387.     }
  388.  
  389.     crypte(lBuf, (SECSPERLOG*SECTSIZE), n);    /* decode buffer    */
  390. }
  391.  
  392. /************************************************************************/
  393. /*    PWSlot() returns userlog.buf slot password is in, else ERROR    */
  394. /*    NB: we also leave the record for the user in logBuf.        */
  395. /************************************************************************/
  396. int PWSlot(pw)
  397. char pw[NAMESIZE];
  398. {
  399.     int  h, i;
  400.     int  foundIt, ourSlot;
  401.  
  402.     h = hash(pw);
  403.  
  404.     /* Check all passwords in memory: */
  405.     for(i=0, foundIt=FALSE;  !foundIt && i<MAXLOGTAB;  i++) {
  406.     /* check for password match here */
  407.  
  408.     /* If password matches, check full password            */
  409.     /* with current newUser code, password hash collisions should    */
  410.     /* not be possible... but this is upward compatable & cheap    */
  411.     if (logTab[i].ltpwhash == h) {
  412.         ourSlot    = logTab[i].ltlogSlot;
  413.         getLog(&logBuf, ourSlot);
  414.  
  415.         if (strCmpU(pw, logBuf.lbpw) == SAMESTRING) {
  416.         /* found a complete match */
  417.         thisSlot = i   ;
  418.         foundIt  = TRUE;
  419.         }
  420.     }
  421.     }
  422.     if (foundIt)   return thisSlot;
  423.     else       return ERROR   ;
  424. }
  425.  
  426. /************************************************************************/
  427. /*    slideLTab() slides bottom N lots in logTab down.  For sorting.    */
  428. /************************************************************************/
  429. slideLTab(slot, last)
  430. int slot;
  431. int last;
  432. {
  433.     int i, j;
  434.  
  435.     /* open slot up: (movmem isn't guaranteed on overlaps) */
  436.     for (i=last-1;  i>=slot;  i--)  {
  437.     movmem(&logTab[i], &logTab[i+1], sizeLTentry);
  438.     }
  439. }
  440.  
  441. /************************************************************************/
  442. /* sortLog ShellSorts userlog by time of last call            */
  443. /************************************************************************/
  444. sortLog() {
  445. #define TSIZE 10
  446.     char *temp[TSIZE];
  447.     int finis, i, intCount, step;
  448.  
  449.     printf("sortLog...\n");
  450.     if(sizeLTentry > TSIZE) {
  451.     printf("!!!increase TSIZE in sortLog to %>d\n", sizeLTentry);
  452.     }
  453.  
  454.     intCount = 0;
  455.     for(finis=FALSE, step=MAXLOGTAB >> 1;  !finis || step>1;  ) {
  456.     if (finis) {
  457.         step = step/3 + 1;
  458.         finis = FALSE;
  459.     }
  460.  
  461.     finis    = TRUE;
  462.  
  463.     printf("stepsize=%d\n", step);
  464.  
  465.     for(i=step;  i<MAXLOGTAB;  i++) {
  466.         if(logTab[i-step].ltnewest < logTab[i].ltnewest) {
  467.         intCount++;
  468.         finis    = FALSE;
  469.  
  470.         /* interchange two entries */
  471.         movmem(&logTab[i-step], temp, sizeLTentry);
  472.         movmem(&logTab[i], &logTab[i-step], sizeLTentry);
  473.         movmem(temp, &logTab[i], sizeLTentry);
  474.         }
  475.     }
  476.     }
  477.     printf("sortLog: %d interchanges\n", intCount);
  478. }
  479.  
  480. /************************************************************************/
  481. /*    storeLog() stores the current log record.            */
  482. /************************************************************************/
  483. storeLog()  {
  484.  
  485.     logTab[0].ltnewest        = newestLo;
  486.  
  487.     logBuf.lbvisit[0]        = newestLo;
  488.     logBuf.lbwidth        = termWidth;
  489.     logBuf.lbnulls        = termNulls;
  490.     logBuf.lbflags        = expert | termUpper | termLF | termTab | aide;
  491.  
  492.     if (loggedIn)     putLog(&logBuf, thisLog);  /*<<<<added test */
  493. }
  494.  
  495. /************************************************************************/
  496. /*    strCmpU() is strcmp(), but ignoring case distinctions        */
  497. /************************************************************************/
  498. int strCmpU(s, t)
  499. char s[], t[];
  500. {
  501.     char toUpper();
  502.     int  i;
  503.  
  504.     i    = 0;
  505.  
  506.     while (toUpper(s[i]) == toUpper(t[i])) {
  507.     if (s[i++] == '\0')  return 0;
  508.     }
  509.     return  toUpper(s[i]) - toUpper(t[i]);
  510. }
  511.  
  512. /************************************************************************/
  513. /*    terminate() is menu-level routine to exit system        */
  514. /************************************************************************/
  515. terminate(discon)
  516. char discon;
  517.     /* 1.  parameter <discon> is TRUE or FALSE.        */
  518.     /* 2.  if <discon> is TRUE, breaks modem connection    */
  519.     /*     or switches whichIO from CONSOLE to MODEM,    */
  520.     /*     as appropriate.                    */
  521.     /* 3.  modifies externs: struct logBuf,         */
  522.     /*             struct logTab            */
  523.     /* 4.  returns no values                */
  524.     /*          modified    dvm 9-82            */
  525. {
  526.     if (loggedIn) {
  527.     mprintf(" %s logged out\n ", logBuf.lbname);
  528.  
  529.     logBuf.lbgen[thisRoom]    = roomBuf.rbgen << GENSHIFT;
  530.     if (haveCarrier || onConsole)    storeLog();
  531.     loggedIn = FALSE;
  532.  
  533.     setUp(TRUE);
  534.     }
  535.  
  536.     if (discon)  {
  537.     switch (whichIO) {
  538.     case MODEM:
  539.         if (rcpm)  {
  540.         writeSysTab();
  541.         exitToCpm = TRUE;
  542.             } else    interpret(pHangUp);
  543.         break;
  544.     case CONSOLE:
  545.         whichIO =  MODEM;
  546.         printf("\n'MODEM' mode.\n ");
  547.         break;
  548.     }
  549.     }
  550. }
  551.  
  552. /************************************************************************/
  553. /*    zapLogFile() erases & re-initializes userlog.buf        */
  554. /************************************************************************/
  555. zapLogFile() {
  556.     char getCh(), toUpper();
  557.     int  i;
  558.  
  559.     printf("\nWipe out log file? ");
  560.     if (toUpper(getCh()) != 'Y')   return;
  561.  
  562.     /* clear RAM buffer out:            */
  563.     logBuf.lbvisit[0]    = ERROR;
  564.     for (i=0;  i<MAILSLOTS;  i++) {
  565.     logBuf.lbslot[i]= ERROR;
  566.     logBuf.lbId[i]    = ERROR;
  567.     }
  568.     for (i=0;  i<NAMESIZE;  i++) {
  569.     logBuf.lbname[i]= 0;
  570.     logBuf.lbpw[i]    = 0;
  571.     }
  572.  
  573.     /* write empty buffer all over file;    */
  574.     for (i=0;  i<MAXLOGTAB;  i++) {
  575.     putLog(&logBuf, i);
  576.     }
  577. }
  578.