home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c004 / 1.ddi / CTSRVR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-18  |  26.6 KB  |  1,124 lines

  1. /*
  2.  *    c-tree Server System Independent Code
  3.  *
  4.  *    This program is the CONFIDENTIAL and PROPRIETARY property 
  5.  *    of FairCom(R) Corporation. Any unauthorized use, reproduction or
  6.  *    transfer of this program is strictly prohibited.
  7.  *
  8.  *      Copyright (c) 1987, 1988, 1989 FairCom Corporation
  9.  *    (Subject to limited distribution and
  10.  *     restricted disclosure only.)
  11.  *    *** ALL RIGHTS RESERVED ***
  12.  *
  13.  *    4006 West Broadway
  14.  *    Columbia, MO 65203
  15.  *
  16.  *
  17.  *    c-tree(R)    Version 4.3
  18.  *            Release C 
  19.  *            February 7, 1989 17:30
  20.  *
  21.  */
  22.  
  23. #include "ctstdr.h"
  24. #include "ctoptn.h"
  25. #include "ctstrc.h"
  26. #include "ctvrec.h"
  27. #include "cterrc.h"
  28. #include "ctcomm.h"
  29. #include "ctdecl.h"
  30.  
  31. /*
  32.  * Define CHECK_LOCK if you wish the server to make sure no conflicting
  33.  * lock is held during data file updates.
  34.  *
  35.  * Define MUST_LOCK if you wish the server to make sure that the user
  36.  * issuing a data file update holds a write-lock.
  37.  *
  38.  * Otherwise, the server assumes that the application programs are well
  39.  * behaved; i.e., they have acquired necessary locks.
  40.  *
  41.     #define CHECK_LOCK  or #define MUST_LOCK
  42.  *
  43.  * If either of the options are defined, then a lock conflict or missing lock
  44.  * results in an error 57 (DADV_ERR) on writes, rewrites or deletes.
  45.  */
  46.  
  47. #define        cts_nodsec  srvprm.spns
  48. #define        cts_buffer  srvprm.spbf
  49. #define        cts_maxsmsg srvprm.spsz
  50. #define        cts_maxlok  srvprm.splk
  51. #define        cts_keyops  srvprm.spky
  52. #define        rqsts        cts_stat.srqsts
  53. #define        redo        cts_stat.sredo
  54. #define        sets        cts_stat.ssets
  55. #define        waks        cts_stat.swaks
  56. #define        uwaks        cts_stat.suwaks
  57. #define        retry        cts_stat.sretry
  58.  
  59. MESSAGE        *rmsg;
  60. LONG           *usrtim;
  61. SRVPRM        srvprm;
  62.  
  63. COUNT        cur_usrid;
  64. MESSAGE        omsg;
  65. UCOUNT        srvsiz;
  66. KEYOPS           *cts_kops;
  67. TEXT           *srvmsg,*srvdat;
  68. COUNT        cts_mxusr  = CTS_MAXUSR;
  69. COUNT        cts_mxfil  = CTS_MAXFIL;
  70. SSTATUS        cts_stat       = {0};
  71. LOCAL LONG    ffrq[MAX_FUNC] = {0};
  72. LOCAL MESSAGE     imsg,*umsg;
  73. LOCAL UCOUNT   *ausrsiz;
  74. LOCAL UCOUNT   *akopsiz,cts_zkop;
  75. LOCAL COUNT   **afilmap;
  76. LOCAL USRCON   *ausrcon;
  77. LOCAL COUNT    *ausrmap;
  78. LOCAL LONG     *ausrtrn;
  79.  
  80.  
  81. TEXT           *getmid(),*mballc();
  82. LONG        getumsg();
  83. COUNT        getctf(),norspn(),dedusr();
  84. #ifdef VARLDATA
  85. COUNT        getvhdr(),putvhdr();
  86. #endif
  87.  
  88. CTFILE           *tstfnm();
  89. LONG        time();
  90.  
  91. extern CTFILE *ct_key;
  92. extern COUNT   uerr_cod,avlfil,ct_mxfil;
  93. extern RECLOK *ct_loklst,*ct_frelst;
  94. extern LONG    ct_gsrl;
  95.  
  96. /* DO NOT MODIFY THESE #defines. Your locking protocol is specified above */
  97. #ifdef LOCK_TEST
  98. #undef LOCK_TEST
  99. #endif
  100. #ifdef CHECK_LOCK
  101. #define LOCK_TEST CHK_LOCK
  102. #endif
  103. #ifdef MUST_LOCK
  104. #define LOCK_TEST MST_LOCK
  105. #endif
  106. #ifdef LOCK_TEST
  107. COUNT           cts_lok();
  108. #endif
  109.  
  110. LOCAL VOID setsrlpos(msgp)
  111. MESSAGE            *msgp;
  112. {
  113.     cpybuf(&msgp->mfiln,&ct_gsrl,sizeof(ct_gsrl));
  114. }
  115.  
  116. LOCAL UCOUNT min(a,b)
  117. UCOUNT      a,b;
  118. {
  119.     if (b < a)
  120.         return(b);
  121.     else
  122.         return(a);
  123. }
  124.  
  125. COUNT chkopn(fn)
  126. PFAST TEXT      *fn;
  127. {
  128.     FAST CTFILE *ctnum;
  129.  
  130.     for (ctnum = ct_key; ctnum < ct_key + ct_mxfil; ctnum++)
  131.         if ((ctnum->chnacs == 'y' || ctnum->chnacs == 'v') &&
  132. #ifdef CT_ANSI
  133.             ctnum->fd != (RNDFILE) NULL &&
  134. #else
  135.             ctnum->fd >= 0 &&
  136. #endif
  137.             strcmp(fn,ctnum->flname) == 0)
  138.             return(ctnum->filnum);
  139.     return(-1);
  140. }
  141.  
  142. LOCAL trycls(usrn,filno)
  143. COUNT         usrn,filno;
  144. {
  145.     FAST CTFILE *ctnum;
  146.     FAST RECLOK *cp;
  147.     RECLOK        *np;
  148.     COUNT        temp,afil;
  149.  
  150.     VOID pshlst();
  151.  
  152.     afil = afilmap[usrn][filno];
  153.     if ((ctnum = tstfnm(afil)) == NULL)
  154.         return;
  155.     afilmap[usrn][filno] = -1;
  156.     if (ctnum->kmem > 0) /* a member is not closed directly */
  157.         return;
  158.     for (temp = ctnum->nmem + filno; temp > filno; temp--)
  159.         afilmap[usrn][temp] = -1;
  160.  
  161.     if (--ctnum->usrcnt > 0) {
  162.         cp = ctnum->rlokh;
  163.         while (cp != NULL) {
  164.             np = cp->rllink;
  165.             if (cp->rlusrn == usrn)
  166.                 pshlst(cp,ctnum);
  167.             cp = np;
  168.         }
  169.     } else {
  170.         if (ctnum->rlokt != NULL) {
  171.             ctnum->rlokt->rllink = ct_frelst;
  172.             ct_frelst         = ctnum->rlokh;
  173.             ctnum->rlokh         = ctnum->rlokt  = NULL;
  174.         }
  175.         temp = ctnum->nmem + 1;
  176.         CLSFIL(afil,0);
  177.         avlfil += temp;
  178.     }
  179. }
  180.  
  181. LOCAL COUNT chkcon(usrn,filno,segop)
  182. COUNT           usrn,filno,segop;
  183. {
  184.     FAST USRCON *u;
  185.     COUNT         blocker;
  186.  
  187.     for (u = ausrcon; u < ausrcon + cts_mxusr; u++)
  188.         if (u->ucfiln == filno && u->ucsgop == segop) {
  189.             if (segop == CTXTND || (segop != CTXTND &&
  190.                   imsg.mpntr >= u->ucbpos && imsg.mpntr < u->ucepos)) {
  191.                 blocker = (COUNT) (u - ausrcon);
  192. #ifndef CTS_CPLD
  193.                 (ausrcon + usrn)->ucslep = blocker;
  194. #endif
  195.                 if (usrn == blocker) terr(979);
  196.                 return(blocker);
  197.             }
  198.         }
  199.  
  200.     return(-2);
  201. }
  202.  
  203. LOCAL COUNT wakcon(usrn,filno,segop)
  204. COUNT           usrn,filno,segop;
  205. {
  206.     FAST USRCON *u;
  207.     COUNT         awake;
  208.     FAST CTFILE *ctnum;
  209.     TEXT        *usrmsg;
  210.  
  211.     ctnum  = ct_key + filno;
  212.     u      = ausrcon + usrn;
  213.     usrmsg = u->ucmsgp;
  214.  
  215.     if (u->ucsgop == segop) {
  216.         waks++;
  217.         u->ucsgop =  CTNONE;
  218.         if (segop == CTREAD) {
  219.         if (--ctnum->ucred < 0)
  220.             terr(978);
  221.         } else if (segop == CTWRITE) {
  222.         if (--ctnum->ucwrt < 0)
  223.             terr(977);
  224.         } else if (segop == CTXTND) {
  225.         if (ctnum->ucext != YES)
  226.             terr(976);
  227.         else
  228.             ctnum->ucext = NO;
  229.         } else
  230.         terr(974);
  231.  
  232. #ifndef CTS_CPLD
  233.         for (u = ausrcon; u < ausrcon + cts_mxusr; u++)
  234.         if (u->ucslep == usrn) {
  235.             awake     = (COUNT) (u - ausrcon);
  236.             u->ucslep = -2;
  237.             uwaks++;
  238.             ctrspn(usrmsg,umsg + awake,
  239.                 sizeof(MESSAGE),awake);
  240.         }
  241. #endif
  242.     }
  243.     return(NO_ERROR);
  244. }
  245.  
  246. LOCAL COUNT setcon(usrn,filno,segop,len,msgptr)
  247. COUNT           usrn,filno,segop;
  248. UCOUNT                    len;
  249. TEXT                       *msgptr;
  250. {
  251.     FAST USRCON *u;
  252.     FAST CTFILE *ctnum;
  253.  
  254.     ctnum     = ct_key + filno;
  255.     u         = ausrcon + usrn;
  256.     u->ucfiln = filno;
  257.  
  258.     if (u->ucsgop == segop)
  259.         return(NO_ERROR);
  260.     else if (u->ucsgop != CTNONE)
  261.         terr(970);
  262.     u->ucsgop = segop;
  263.     u->ucmsgp = msgptr;
  264.     sets++;
  265.  
  266.     if (segop == CTREAD)
  267.         ctnum->ucred++;
  268.     else if (segop == CTWRITE)
  269.         ctnum->ucwrt++;
  270.     else if (segop == CTXTND) {
  271.         ctnum->ucext = YES;
  272.         return(NO_ERROR);
  273.     } else
  274.         terr(975);
  275.  
  276.     u->ucbpos = imsg.mpntr;
  277.     u->ucepos = imsg.mpntr + len;
  278.  
  279.     return(NO_ERROR);
  280. }
  281.  
  282. VOID stpusr(usrn)
  283. COUNT        usrn;
  284. {
  285.     FAST COUNT   i;
  286.     FAST USRCON *u;
  287.  
  288.     if (usrn >= 0 && usrn < cts_mxusr && ausrmap[usrn] != NO) {
  289.         if (ausrtrn[usrn])
  290.             transact(ABRTRAN,usrn,ausrtrn);
  291.         (u = ausrcon + usrn)->ucslep = -2;
  292.         if (u->ucsgop != CTNONE)
  293.             wakcon(usrn,u->ucfiln,u->ucsgop);
  294.         u->ucsgop = CTNONE;
  295.         for (i = 0; i < cts_mxfil; i++)
  296.             if (afilmap[usrn][i] > -1) {
  297.                 trycls(usrn,i);
  298.             }
  299.         ausrmap[usrn] = NO;
  300.     }
  301. }
  302.  
  303. #ifdef CTS_ISAM
  304. LOCAL COUNT MLTKEY(usrn,nops,tp)
  305. COUNT                usrn,nops;
  306. PFAST TEXT            *tp;
  307. {
  308.     FAST KEYOPS *k;
  309.     COUNT         i,keyno;
  310.  
  311.     for (i = 1, k = cts_kops; i++ <= nops; k++, tp += cts_zkop) {
  312.         cpybuf(k,tp,cts_zkop);
  313.         keyno = afilmap[usrn][k->kokeyn];
  314.         if ((ct_key + keyno)->ucext && k->komode == FN_ADDKEY && 
  315.             chkcon(usrn,keyno,CTXTND) > -1)
  316.             return(-1);
  317.     }
  318.  
  319.     for (i = 1, k = cts_kops; i <= nops; i++, k++) {
  320.         keyno = afilmap[usrn][k->kokeyn];
  321.         if (k->komode == FN_ADDKEY && ADDKEY(keyno,k->kobufr,
  322.             k->kopntr,REGADD))
  323.             return(i);
  324.         if (k->komode == FN_DELCHK && DELCHK(keyno,k->kobufr,
  325.             k->kopntr))
  326.             return(i);
  327.     }
  328.     return(0);
  329. }
  330. #endif
  331.  
  332. stpsrv(try,lmt,usrflg)
  333. LONG   try;
  334. int       lmt;
  335. COUNT           usrflg;
  336. {
  337.     COUNT   usrn;
  338.     CTFILE *ctnum;
  339.  
  340.     for (usrn = 0; usrn < cts_mxusr; usrn++)
  341.         if (ausrtrn[usrn]) {
  342.             if (try < lmt)
  343.             return(usrn + 1);
  344.             else
  345.             transact(ABRTRAN,usrn,ausrtrn);
  346.         }
  347.     for (ctnum = ct_key; ctnum < ct_key + ct_mxfil; ctnum++)
  348.         if (ctnum->chnacs == 'y')
  349.             CLSFIL(ctnum->filnum,0);
  350.  
  351.     if (usrflg < 0)
  352.         signoff(ffrq,ausrcon,ausrmap,ausrtrn);
  353.     return(0);
  354. }
  355.  
  356. main(argc,argv)
  357. int argc;
  358. char *argv[];
  359. {
  360.     COUNT           *ctp;
  361.     RECLOK           *curlst,*prvlst;
  362.     USRCON           *ucon;
  363.     UCOUNT        temp;
  364.  
  365.     VOID        mainloop();
  366.  
  367.     getsenv(&srvprm,argc,argv);
  368.  
  369.     if (INTREE(cts_buffer,cts_mxfil,cts_nodsec))
  370.         srvexit("Could not allocate dynamic space for server",
  371.             uerr_cod,0);
  372.     rmsg = &omsg;
  373.     if ((afilmap = (COUNT **) mballc(cts_mxusr,sizeof(COUNT *))) ==
  374.          NULL ||
  375.        (ctp = (COUNT *) mballc(cts_mxusr * cts_mxfil,sizeof(COUNT))) ==
  376.          NULL ||
  377.        (umsg = (MESSAGE *) mballc(cts_mxusr,sizeof(MESSAGE))) == NULL ||
  378.        (cts_keyops > 1 && (cts_kops = (KEYOPS *) mballc(cts_keyops,
  379.          sizeof(KEYOPS))) == NULL) ||
  380.        (ct_loklst = (RECLOK *) mballc(cts_maxlok,sizeof(RECLOK))) == NULL ||
  381.        (ausrcon   = (USRCON *) mballc(cts_mxusr,sizeof(USRCON))) == NULL ||
  382.        (ausrmap   =  (COUNT *) mballc(cts_mxusr,sizeof(COUNT)))  == NULL ||
  383.        (ausrtrn   =   (LONG *) mballc(cts_mxusr,sizeof(LONG)))  == NULL ||
  384.        (akopsiz   = (UCOUNT *) mballc(cts_mxusr,sizeof(UCOUNT))) == NULL ||
  385.        (usrtim    =   (LONG *) mballc(cts_mxusr,sizeof(LONG)))   == NULL ||
  386.        (ausrsiz   = (UCOUNT *) mballc(cts_mxusr + 1,sizeof(UCOUNT))) == 
  387.          NULL)
  388.         srvexit(
  389. "Could not allocate dynamic space for control structures",uerr_cod = SSCB_ERR,
  390.             0);
  391.  
  392.     ausrsiz[cts_mxusr] = sizeof(MESSAGE);
  393.     for (temp = 0, ucon = ausrcon; temp < cts_mxusr; temp++, ucon++) {
  394.         ucon->ucslep  = -2;
  395.         ucon->ucsgop  = CTNONE;
  396.         afilmap[temp] = ctp;
  397.         ctp          += cts_mxfil;
  398.     }
  399.     for (prvlst = NULL, curlst = ct_loklst; curlst < ct_loklst + cts_maxlok;
  400.         prvlst = curlst, curlst++)
  401.         curlst->rllink = prvlst;
  402.     ct_frelst = prvlst;
  403.  
  404.     if ((srvmsg = getmid(srvsiz = cts_maxsmsg,cts_mxusr)) == NULL)
  405.         srvexit("Could not open server message area.",uerr_cod,0);
  406.     else
  407.         srvdat = srvmsg + sizeof(MESSAGE);
  408.  
  409.     /* prepare for main loop. prploop in ctsrve.c */
  410.     prploop();
  411.  
  412.     /* execute main server loop */
  413.     for(;;)
  414.         mainloop();
  415. }
  416.  
  417. VOID mainloop() {
  418.     USRCON           *ucon;
  419.     TEXT        outval[MAXLEN];
  420.     TEXT           *cp;
  421.     TEXT           *usrmsg,*usrdat;
  422.     COUNT        ufilno,filno,prmchk;
  423.     UCOUNT        usrsiz,temp,savext;
  424.     FILEPARM    fpm;
  425.     FAST CTFILE    *ctnum,*ltnum;
  426.     POINTER        recbyt;
  427.     VRLEN        unused;
  428. #ifdef VARLDATA
  429.     VHDR        tvhdr;
  430. #endif
  431.  
  432.             /* main SERVER loop */
  433.     rqsts++;
  434.     if (prmchk = ctrqst(&srvmsg,&imsg)) {
  435.         if (prmchk == NO_RQST)
  436.             return;
  437.         srvexit("Could not read request",0,0);
  438.     } else
  439.         srvdat = srvmsg + sizeof(MESSAGE);
  440.  
  441. cmbloop:
  442.  
  443.     /* setup output message pointers */
  444.     cpybuf(rmsg,&imsg,sizeof(MESSAGE));
  445.     cur_usrid    = rmsg->musrn;
  446.     ucon        = ausrcon + cur_usrid;
  447.     usrmsg         = srvmsg;
  448.     usrdat         = usrmsg + sizeof(MESSAGE);
  449.     if (imsg.mfunc  < TST_MESSAGE) {
  450.         usrsiz     = ausrsiz[cur_usrid];
  451.         cts_zkop = akopsiz[cur_usrid];
  452.         ffrq[imsg.mfunc]++;
  453.     } else if (imsg.mfunc < MAX_FUNC) {
  454.         usrsiz = sizeof(MESSAGE);
  455.         ffrq[imsg.mfunc]++;
  456.     }
  457.     
  458.     /* perform function */
  459.     uerr_cod = NO_ERROR;
  460.  
  461.     ufilno     = imsg.mfiln;
  462.     if (imsg.mfunc < TST_MLTOPS) {
  463.         if (ufilno >= 0 && ufilno < cts_mxfil)
  464.             filno = afilmap[cur_usrid][ufilno];
  465.         else {
  466.             filno = 0;
  467.             imsg.mfunc = TST_BADFIL;
  468.         }
  469.     } else
  470.         filno = ufilno;
  471.  
  472.  
  473.     /* test for legal filno range before computing ctnum */
  474.     if ((imsg.mfunc < FN_FOPNCRE || imsg.mfunc > FN_LOPNCRE) &&
  475.         imsg.mfunc < TST_MLTOPS)
  476.         ctnum = tstfnm(filno);
  477.  
  478.     if (imsg.mretc != CMBREDAT)
  479.         rmsg->mdlen = 0;
  480.  
  481.     if (uerr_cod == NO_ERROR) switch (imsg.mfunc) {
  482. case FN_ADDKEY:
  483.         if (ctnum->ucext && chkcon(cur_usrid,filno,CTXTND) > -1) {
  484.             uerr_cod = STRY_ERR;
  485.             break;
  486.         }
  487.         temp        = imsg.mseqn;
  488.         rmsg->mseqn = 0;
  489.         ADDKEY(filno,srvdat,imsg.mpntr,temp);
  490.         break;
  491. case FN_DELBLD:
  492.         rmsg->mpntr = DELBLD(filno,srvdat);
  493.         break;
  494. case FN_DELCHK:
  495.         DELCHK(filno,srvdat,imsg.mpntr);
  496.         break;
  497. #ifdef CTS_ISAM
  498. case FN_MLTKEY:
  499.         rmsg->mseqn = MLTKEY(imsg.musrn,imsg.mseqn,srvdat);
  500.         if (rmsg->mseqn < 0) {
  501.             uerr_cod    = STRY_ERR;
  502.             rmsg->mseqn = imsg.mseqn;
  503.         }
  504.         break;
  505. #endif
  506. case FN_EQLKEY:
  507.         rmsg->mpntr = EQLKEY(filno,srvdat);
  508.         break;
  509. case FN_FRSKEY:
  510.         rmsg->mpntr = FRSKEY(filno,usrdat);
  511.         break;
  512. case FN_LSTKEY:
  513.         rmsg->mpntr = LSTKEY(filno,usrdat);
  514.         break;
  515. case FN_NXTKEY:
  516.         rmsg->mpntr = NXTKEY(filno,usrdat);
  517.         break;
  518. case FN_PRVKEY:
  519.         rmsg->mpntr = PRVKEY(filno,usrdat);
  520.         break;
  521. case FN_FRCKEY:
  522.         rmsg->mpntr = FRCKEY(filno,usrdat,imsg.mseqn);
  523.         break;
  524. case FN_GTEKEY:
  525.         rmsg->mpntr = GTEKEY(filno,srvdat,outval);
  526.         break;
  527. case FN_GTKEY:
  528.         rmsg->mpntr = GTKEY(filno,srvdat,outval);
  529.         break;
  530. case FN_LTEKEY:
  531.         rmsg->mpntr = LTEKEY(filno,srvdat,outval);
  532.         break;
  533. case FN_LTKEY:
  534.         rmsg->mpntr = LTKEY(filno,srvdat,outval);
  535.         break;
  536.  
  537. case FN_OPNFIL:
  538.         cpybuf(&fpm,srvdat,sizeof(FILEPARM));
  539.         if ((fpm.fpmod & NONEXCLUSIVE) == NONEXCLUSIVE)
  540.             /* only set READFIL flag if SHARED & READFIL both on */
  541.             fpm.fpmod &= ~SHARED;
  542.         if ((filno = chkopn(fpm.fpnam)) < 0) {
  543.             if ((filno = getctf()) < 0) {
  544.                 uerr_cod = SNFB_ERR;
  545.                 break;
  546.             } else if (OPNFIL(filno,fpm.fpnam,
  547.                 fpm.fpmod & ~PERMANENT)) {
  548.                 retctf(filno);
  549.                 break;
  550.             } else {
  551.                 ctnum = ct_key + filno;
  552.                 ctnum->usrcnt = 0;
  553.                 ctnum->ucext  = ctnum->ucred = ctnum->ucwrt = 0;
  554.             }
  555.         } else { /* check for conflicts */
  556.             ctnum = ct_key + filno;
  557.             /* check for exclusive rqst */
  558.             if (!(NONEXCLUSIVE & fpm.fpmod) ||
  559.                 (ctnum->flmode & NONEXCLUSIVE) != (fpm.fpmod &
  560.                  NONEXCLUSIVE)) {
  561.                 uerr_cod = FNOP_ERR;
  562.                 break;
  563.             }
  564.             if (ctnum->ucext && 
  565.                 chkcon(cur_usrid,filno,CTXTND) > -1) {
  566.                 uerr_cod = STRY_ERR;
  567.                 break;
  568.             }
  569.         }
  570.         temp  = 0;
  571.         ltnum = ctnum;
  572.         cp    = usrdat;
  573.         ctnum->usrcnt++;
  574.  
  575.         do {
  576.             temp += HDRSIZ;
  577.             if (temp <= usrsiz - sizeof(MESSAGE)) {
  578.                 cpybuf(cp,ltnum,HDRSIZ);
  579.                 rmsg->mdlen = temp;
  580.                 cp       += HDRSIZ;
  581.             }
  582.             afilmap[cur_usrid][ufilno++] = ltnum - ct_key;
  583.             ltnum = ltnum->xmem;
  584.         } while (ltnum != (CTFILE *) NULL);
  585.  
  586.         if (ctnum->usrcnt == 1 && rmsg->mdlen < ((ctnum->nmem + 1) *
  587.             HDRSIZ))
  588.             setcon(cur_usrid,filno,CTXTND,(UCOUNT) 0,usrmsg);
  589.         break;
  590.  
  591. case FN_CREDAT:
  592.         cpybuf(&fpm,srvdat,sizeof(FILEPARM));
  593.         if (chkopn(fpm.fpnam) >= 0)
  594.             uerr_cod = DOPN_ERR;
  595.         else if ((filno = getctf()) < 0)
  596.             uerr_cod = SNFB_ERR;
  597.         else if (CREDAT(filno,fpm.fpnam,fpm.fplen,fpm.fpxtd,
  598.             fpm.fpmod & ~PERMANENT) == NO_ERROR) {
  599.             ctnum = ct_key + filno;
  600.             cpybuf(usrdat,ctnum,rmsg->mdlen = HDRSIZ);
  601.             ctnum->usrcnt = 1;
  602.             afilmap[cur_usrid][ufilno] = filno;
  603.         } else
  604.             retctf(filno);
  605.         break;
  606.  
  607. case FN_CREIDX:
  608.         cpybuf(&fpm,srvdat,sizeof(FILEPARM));
  609.         if (chkopn(fpm.fpnam) >= 0)
  610.             uerr_cod = KOPN_ERR;
  611.         else if ((filno = getctf()) < 0)
  612.             uerr_cod = SNFB_ERR;
  613.         else if (getctm(fpm.fpmem,ct_key + filno) < 0) {
  614.             retctf(filno);
  615.             uerr_cod = SNFB_ERR;
  616.         } else if (CREIDX(filno,fpm.fpnam,fpm.fplen,fpm.fptyp,fpm.fpdup,
  617.             fpm.fpmem,fpm.fpxtd,fpm.fpmod & ~PERMANENT) == NO_ERROR) {
  618.             ctnum = ct_key + filno;
  619.             cpybuf(usrdat,ctnum,rmsg->mdlen = HDRSIZ);
  620.             ctnum->usrcnt = 1;
  621.             while (ctnum != (CTFILE *) NULL) {
  622.                 afilmap[cur_usrid][ufilno++] = ctnum - ct_key;
  623.                 ctnum = ctnum->xmem;
  624.             }
  625.         } else
  626.             retctf(filno);
  627.         break;
  628.  
  629. case FN_CREMEM:
  630.         cpybuf(&fpm,srvdat,sizeof(FILEPARM));
  631.         if (CREMEM(filno,fpm.fplen,fpm.fptyp,fpm.fpdup,fpm.fpmem) ==
  632.             NO_ERROR) {
  633.             ctnum = ct_key + filno;
  634.             while (fpm.fpmem-- > 0)
  635.                 ctnum = ctnum->xmem;
  636.             cpybuf(usrdat,ctnum,rmsg->mdlen = HDRSIZ);
  637.         }
  638.         break;
  639.  
  640. case FN_DATENT:
  641.         rmsg->mpntr = DATENT(filno);
  642.         break;
  643. case FN_SERIALNUM:
  644.         rmsg->mpntr = SERIALNUM(filno);
  645.         break;
  646. case FN_IDXENT:
  647.         rmsg->mpntr = IDXENT(filno);
  648.         break;
  649. case FN_FLUSHDOS:
  650.         flushdos(filno);
  651.         break;
  652. case FN_LOKREC:
  653.         LOKREC(filno,imsg.mseqn,imsg.mpntr);
  654.         break;
  655. case FN_DLOCK:
  656.         DLOCK(imsg.mpntr,ctnum);
  657.         break;
  658. case FN_UDLOCK:
  659.         UDLOCK(imsg.mpntr,ctnum);
  660.         break;
  661. case FN_RLOCK:
  662.         RLOCK(imsg.mpntr,ctnum);
  663.         break;
  664. #ifdef CTS_ISAM
  665. case FN_MLTULK:
  666.         if (imsg.mvlen == 0)
  667.             terr(968);
  668.         UDLOCK(imsg.mpntr,ctnum);
  669.         temp = 0;
  670.         while (--imsg.mvlen != 0) {
  671.             cpybuf(&recbyt,srvdat + temp,sizeof(POINTER));
  672.             cpybuf(&ufilno,srvdat + temp + sizeof(POINTER),
  673.                 sizeof(COUNT));
  674.             filno = afilmap[cur_usrid][ufilno];
  675.             ctnum = ct_key + filno;
  676.             UDLOCK(recbyt,ctnum);
  677.             temp += (sizeof(POINTER) + sizeof(COUNT));
  678.         }
  679.         break;
  680. #endif
  681. case FN_NEWREC:
  682.         if (ctnum->ucext && chkcon(cur_usrid,filno,CTXTND) > -1) {
  683.             uerr_cod = STRY_ERR;
  684.             break;
  685.         }
  686.         if ((rmsg->mpntr = NEWREC(filno)) != DRNZERO)
  687.             setsrlpos(rmsg);
  688.         break;
  689. #ifdef CTS_ISAM
  690. case FN_MLTWRT:
  691.         temp = imsg.mvlen;
  692.         if (imsg.mpntr == DRNZERO) {
  693.           if (ctnum->ucext && chkcon(cur_usrid,filno,CTXTND) > -1) {
  694.             uerr_cod = STRY_ERR;
  695.             break;
  696.           }
  697.           imsg.mseqn = 0;
  698.           if ((rmsg->mpntr = NEWREC(filno)) == DRNZERO) {
  699.             rmsg->mseqn = 1;
  700.             break;
  701.           } else
  702.             imsg.mpntr = rmsg->mpntr;
  703.         }
  704.         if (temp) {
  705.             cpybuf(srvdat + temp - 1,&ct_gsrl,sizeof(ct_gsrl));
  706. #ifndef NATURAL_SERIAL
  707. #ifdef LOW_HIGH
  708.             revobj(srvdat + temp - 1,sizeof(ct_gsrl));
  709. #endif
  710. #endif
  711.         }
  712. #ifdef LOCK_TEST
  713.         if ((ctnum->flmode & NONEXCLUSIVE) &&
  714.             (uerr_cod = cts_lok(imsg.musrn,filno,0,LOCK_TEST,
  715.             imsg.mpntr))) {
  716.             rmsg->mseqn = 2;
  717.             break;
  718.         }
  719. #endif
  720.         if (WRTREC(filno,imsg.mpntr,srvdat))
  721.             rmsg->mseqn = 2;
  722.         else
  723.             rmsg->mseqn = 0;
  724.         if (rmsg->mseqn == 0)
  725.             setsrlpos(rmsg);
  726.         break;
  727. #endif
  728.  
  729. #ifdef VARLDATA
  730. case FN_GTVLEN:
  731.         rmsg->mvlen = GTVLEN(filno,imsg.mpntr);
  732.         break;
  733.  
  734. case FN_NEWVREC:
  735.         if (ctnum->ucext && chkcon(cur_usrid,filno,CTXTND) > -1) {
  736.             uerr_cod = STRY_ERR;
  737.             break;
  738.         }
  739.         if ((rmsg->mpntr = NEWVREC(filno,imsg.mvlen)) != DRNZERO)
  740.             setsrlpos(rmsg);
  741.         break;
  742.  
  743. case FN_RETVREC:
  744. #ifdef LOCK_TEST
  745.         if ((ctnum->flmode & NONEXCLUSIVE) &&
  746.             (uerr_cod = cts_lok(imsg.musrn,filno,0,LOCK_TEST,
  747.             imsg.mpntr)))
  748.             break;
  749. #endif
  750.         RETVREC(filno,imsg.mpntr);
  751.         break;
  752. #endif
  753.  
  754. case FN_RETREC:
  755. #ifdef LOCK_TEST
  756.         if ((ctnum->flmode & NONEXCLUSIVE) &&
  757.             (uerr_cod = cts_lok(imsg.musrn,filno,0,LOCK_TEST,
  758.             imsg.mpntr)))
  759.             break;
  760. #endif
  761.         RETREC(filno,imsg.mpntr);
  762.         break;
  763.  
  764. case FN_CLSFIL:
  765.         trycls(cur_usrid,ufilno);
  766.         break;
  767.  
  768. case FN_DELFIL:
  769.         DELFIL(filno);
  770.         break;
  771.  
  772. case FN_TSTREC:
  773.         if (imsg.mpntr > ctnum->numrec) {
  774.             rmsg->mpntr = DRNZERO;
  775.             uerr_cod    = LEOF_ERR;
  776.         } else
  777.             rmsg->mpntr = ctnum->numrec;
  778.         break;
  779.  
  780. case CNT_HDROUT:
  781.         temp  = HDRSIZ;
  782.         ltnum = ctnum;
  783.         cp    = usrdat;
  784.         while (imsg.mseqn-- > 0)
  785.             ltnum = ltnum->xmem;
  786.         do {
  787.             cpybuf(cp,ltnum,HDRSIZ);
  788.             rmsg->mdlen = temp;
  789.             temp       += HDRSIZ;
  790.             cp       += HDRSIZ;
  791.             ltnum        = ltnum->xmem;
  792.         } while (temp <= usrsiz - sizeof(MESSAGE) &&
  793.             ltnum != (CTFILE *) NULL);
  794.  
  795.         if (ltnum == (CTFILE *) NULL)
  796.             wakcon(cur_usrid,filno,CTXTND);
  797.         break;
  798.  
  799. case TST_MSGSIZ:
  800. case TST_SPCLOG:
  801.         /* check for dead users */
  802.         chkusrtim(usrtim,ausrmap,ausrtrn);
  803.  
  804.         /* assign user number */
  805.         imsg.musrn = cur_usrid = cts_mxusr;
  806.  
  807.         /* test for shut down in progress */
  808.         if (cts_stat.shtdwn && imsg.mfunc == TST_MSGSIZ) {
  809.             rmsg->musrn = cts_mxusr;
  810.             uerr_cod    = SHUT_ERR;
  811.         } else {
  812.             for (temp = 0; temp < cts_mxusr; temp++)
  813.             if (ausrmap[temp] == NO) {
  814.                 ausrmap[temp]        = YES;
  815.                 imsg.musrn        = rmsg->musrn = cur_usrid =
  816.                                     temp;
  817.                 ausrsiz[cur_usrid]  = imsg.mvlen;
  818.                 akopsiz[cur_usrid]  = imsg.mretc;
  819.                 ucon            = ausrcon + cur_usrid;
  820.                 ucon->ucslep        = -2;
  821.                 ucon->ucsgop        = CTNONE;
  822.                 rmsg->mseqn        = cts_keyops;
  823.                 for (filno = 0; filno < cts_mxfil; filno++)
  824.                     afilmap[cur_usrid][filno] = -1;
  825.                 break;
  826.             }
  827.             if (cur_usrid == cts_mxusr) {
  828.             rmsg->musrn = imsg.musrn = cts_mxusr;
  829.             uerr_cod    = SOUT_ERR;
  830.             } else if (imsg.mvlen > srvsiz)
  831.             uerr_cod    = SMSG_ERR;
  832.             else if (imsg.mseqn > MAXLEN)
  833.             uerr_cod    = SMXL_ERR;
  834.         }
  835.  
  836.         /* save message id */
  837.         getumsg(&imsg,cur_usrid,usrmsg);
  838.         break;
  839.  
  840. case FN_STATUS:
  841.         cp = srvdat;
  842.         rmsg->mvlen = rmsg->mdlen = 0;
  843.         if (imsg.mseqn < 0) {
  844.           cts_stat.susers = cts_stat.strans = 0;
  845.           for (temp = 0; temp < cts_mxusr; temp++) {
  846.             if (ausrmap[temp] != NO) cts_stat.susers++;
  847.             if (ausrtrn[temp] != 0L) cts_stat.strans++;
  848.           }
  849.           cpybuf(srvdat,(TEXT *) &cts_stat,
  850.             rmsg->mdlen = sizeof(SSTATUS));
  851.           cp += sizeof(SSTATUS);
  852.           rmsg->mseqn = 0;
  853.         }
  854.         temp = sizeof(COUNT) + sizeof(LONG);
  855.         while (rmsg->mseqn < MAX_FUNC) {
  856.           if (ffrq[rmsg->mseqn]) {
  857.             if ((rmsg->mdlen + temp) > (usrsiz - sizeof(MESSAGE)))
  858.                 break;
  859.             cpybuf(cp,&rmsg->mseqn,sizeof(COUNT));
  860.             cp += sizeof(COUNT);
  861.             cpybuf(cp,&ffrq[rmsg->mseqn],sizeof(LONG));
  862.             cp += sizeof(LONG);
  863.             rmsg->mdlen += temp;
  864.             rmsg->mvlen++;
  865.           }
  866.           rmsg->mseqn++;
  867.         }
  868.         if (rmsg->mseqn >= MAX_FUNC)
  869.             rmsg->mseqn = 0;
  870.         uerr_cod = NO_ERROR;
  871.         break;
  872.  
  873. case FN_STFILE:
  874.         rmsg->mvlen = rmsg->mdlen = 0;
  875.         cp        = srvdat;
  876.         while (rmsg->mseqn < cts_mxfil) {
  877.             ctnum = ct_key + rmsg->mseqn;
  878.             if ((ctnum->chnacs == 'y' || ctnum->chnacs == 'v') &&
  879. #ifdef CT_ANSI
  880.                  ctnum->fd != (RNDFILE) NULL) {
  881. #else
  882.                  ctnum->fd > -1) {
  883. #endif
  884.                 temp = strlen(ctnum->flname) + 1;
  885.                 if ((temp + rmsg->mdlen + sizeof(COUNT)) >
  886.                     (usrsiz - sizeof(MESSAGE)))
  887.                         break;
  888.                 rmsg->mvlen++;
  889.                 rmsg->mdlen += (temp + sizeof(COUNT));
  890.                 strcpy(cp,ctnum->flname);
  891.                 cp += temp;
  892.                 cpybuf(cp,&ctnum->usrcnt,sizeof(COUNT));
  893.                 cp += sizeof(COUNT);
  894.             }
  895.             rmsg->mseqn++;
  896.         }
  897.         if (rmsg->mseqn >= cts_mxfil)
  898.             rmsg->mseqn = 0;
  899.         uerr_cod    = NO_ERROR;
  900.         break;
  901.  
  902. case TST_STPSRV:
  903.         imsg.musrn = cur_usrid = cts_mxusr;
  904.         cts_stat.shtdwn++;
  905.         getumsg(&imsg,cur_usrid,usrmsg);
  906.         if (stpsrv(cts_stat.shtdwn,CTS_DOWN,cur_usrid)) {
  907.             rmsg->merrn = STRN_ERR;
  908.             rmsg->mpntr = cts_stat.shtdwn;
  909.             rmsg->mseqn = CTS_DOWN;
  910.             ctrspn(usrmsg,rmsg,usrsiz,cur_usrid);
  911.             return;
  912.         }
  913.         rmsg->merrn = 0;
  914.         signoff(ffrq,ausrcon,ausrmap,ausrtrn);
  915.         ctrspn(usrmsg,rmsg,usrsiz,cur_usrid);
  916.         ridmid();
  917.         srvexit("Successful c-tree Termination",0,0);
  918.  
  919. case TST_DEDUSR:
  920.         if ((cur_usrid = dedusr(imsg.mpntr)) > -1)
  921.             stpusr(cur_usrid);
  922.         /* no response is sent back to requester */
  923.         return;
  924.  
  925. case TST_STPUSR:
  926.         stpusr(cur_usrid);
  927.         ctrspn(usrmsg,rmsg,usrsiz,-(cur_usrid + 1));
  928.         /* negative user id signals end of user connection */
  929.         return;
  930.  
  931. case TST_BADFIL:
  932.         uerr_cod = SFIL_ERR;
  933.         break;
  934.  
  935. case TST_EXISTS:
  936.         usrtim[imsg.mseqn] = time();
  937.         uerr_cod = NO_ERROR;
  938.         return;
  939.  
  940. case TST_TRAN:
  941.         if (imsg.mfiln == BEGTRAN && cts_stat.shtdwn)
  942.             uerr_cod = SHUT_ERR;
  943.         else
  944.             uerr_cod = transact(imsg.mfiln,imsg.musrn,ausrtrn);
  945.         break;
  946.  
  947. case CNT_RECIN:
  948.         if (ctnum->ucred > 0 && chkcon(cur_usrid,filno,CTREAD) > -1) {
  949.             uerr_cod = STRY_ERR;
  950.             break;
  951.         }
  952.  
  953. #ifdef VARLDATA
  954.         if (imsg.mretc == VAR1st) { /* 1st seg of variable length */
  955. #ifdef LOCK_TEST
  956.             if ((ctnum->flmode & NONEXCLUSIVE) &&
  957.                 (uerr_cod = cts_lok(imsg.musrn,filno,0,LOCK_TEST,
  958.                 imsg.mpntr)))
  959.                 break;
  960. #endif
  961.             if (getvhdr(ctnum,imsg.mpntr,&tvhdr))
  962.                 break;
  963.             if (tvhdr.trclen < imsg.mvlen) {
  964.                 uerr_cod = VLEN_ERR;
  965.                 break;
  966.             }
  967.             tvhdr.urclen = imsg.mvlen;
  968.             tvhdr.recmrk = VACT_FLAG;
  969.  
  970.             unused       = tvhdr.trclen - imsg.mvlen;
  971.             if (unused > (ctnum->reclen + SIZVHDR) && unused > 64)
  972.                 tvhdr.trclen = imsg.mvlen;
  973.             else
  974.                 unused = 0;
  975.             if (putvhdr(ctnum,imsg.mpntr,&tvhdr))
  976.                 break;
  977.  
  978.             if (unused) {     /* reclaim space */
  979.                 recbyt        = imsg.mpntr + imsg.mvlen +
  980.                             SIZVHDR;
  981.                 tvhdr.recmrk  = VDEL_FLAG;
  982.                 tvhdr.trclen  = unused - SIZVHDR;
  983.                 tvhdr.urclen  = 0;
  984.                 if (putvhdr(ctnum,recbyt,&tvhdr))
  985.                     break;
  986.                 savext          = ctnum->extsiz;
  987.                 ctnum->extsiz = 0;
  988.                 RETVREC(filno,recbyt);
  989.                 ctnum->extsiz = savext;
  990.                 if (uerr_cod)
  991.                     break;
  992.             }
  993.         }
  994. #endif
  995.  
  996. #ifdef LOCK_TEST
  997.         if (imsg.mretc != VAR1st && (ctnum->flmode & NONEXCLUSIVE))
  998.             if (imsg.mseqn == ((imsg.mvlen + imsg.mdlen - 1) /
  999.                 imsg.mdlen) - 1)
  1000.                 if (uerr_cod = cts_lok(imsg.musrn,filno,0,
  1001.                     LOCK_TEST,imsg.mpntr))
  1002.                     break;
  1003. #endif
  1004.         ctio(CTWRITE,ctnum,imsg.mpntr,srvdat,imsg.mdlen);
  1005.  
  1006.         if (imsg.mseqn == 0 && ucon->ucsgop == CTWRITE)
  1007.              wakcon(cur_usrid,filno,CTWRITE);
  1008.         else if (imsg.mseqn > 0)
  1009.             setcon(cur_usrid,filno,CTWRITE,imsg.mvlen,usrmsg);
  1010.         break;
  1011.  
  1012. case CNT_RECOUT:
  1013.         if (ctnum->ucwrt > 0 && chkcon(cur_usrid,filno,CTWRITE) > -1) {
  1014.             if (imsg.mretc == CMBREDAT) {
  1015.             (ausrcon + cur_usrid)->ucslep = -2;
  1016.             rmsg->mretc              = CMBREDCN;
  1017.             uerr_cod              = NO_ERROR;
  1018.             break;
  1019.             } else {
  1020.             uerr_cod = STRY_ERR;
  1021.             break;
  1022.             }
  1023.         }
  1024.  
  1025.         if (imsg.mseqn == 0) { /* 1st request: must determine len */
  1026.             if (ctnum->clstyp == DAT_CLOSE || imsg.mvlen == 0)
  1027.                 temp = ctnum->reclen;
  1028. #ifdef VARLDATA
  1029.             else {
  1030.                 if (getvhdr(ctnum,imsg.mpntr,&tvhdr))
  1031.                     break;
  1032.                 if ((temp = tvhdr.urclen) > imsg.mvlen) {
  1033.                     uerr_cod = VBSZ_ERR;
  1034.                     break;
  1035.                 }
  1036.             }
  1037. #endif
  1038.             rmsg->mvlen = temp;            
  1039.         } else
  1040.             rmsg->mvlen = temp = imsg.mvlen;
  1041.  
  1042.         if (imsg.mretc == CMBREDAT) {
  1043.             if (temp > (usrsiz - sizeof(MESSAGE) - rmsg->mdlen))
  1044.                 terr(969);
  1045.             ctio(CTREAD,ctnum,rmsg->mpntr,usrdat + rmsg->mdlen,
  1046.                 temp);
  1047.             rmsg->mdlen += temp;
  1048.             break;
  1049.         }
  1050.  
  1051.         ctio(CTREAD,ctnum,imsg.mpntr,usrdat,rmsg->mdlen =
  1052.             min(temp,usrsiz - sizeof(MESSAGE)));
  1053.  
  1054.         if (rmsg->mdlen == temp && ucon->ucsgop == CTREAD)
  1055.             wakcon(cur_usrid,filno,CTREAD);
  1056.         else if (rmsg->mdlen < temp)
  1057.             setcon(cur_usrid,filno,CTREAD,temp,usrmsg);
  1058.         break;
  1059.  
  1060. default:
  1061.         srvmesg("Illegal function number at server:",
  1062.             imsg.mfunc,uerr_cod = SFUN_ERR);
  1063.     }
  1064.  
  1065.     /* set error return code */
  1066.     rmsg->merrn = uerr_cod;
  1067.  
  1068.     /* for output keys, get key length */
  1069.     if (imsg.mfunc >= FN_FLOWKEY && imsg.mfunc <= FN_LLOWKEY) {
  1070.         rmsg->mdlen = ctnum->length;
  1071.         if (imsg.mfunc >= FN_FTWOKEY)
  1072.             cpybuf(usrdat,outval,rmsg->mdlen);
  1073.     }
  1074.  
  1075.     if (rmsg->merrn == ARDO_ERR) {
  1076.         usrsiz        = sizeof(MESSAGE);
  1077.         rmsg->mdlen = imsg.mdlen;
  1078.         redo++;
  1079.     } else if (rmsg->merrn == STRY_ERR) {
  1080.         retry++;
  1081. #ifndef CTS_CPLD
  1082.         imsg.merrn = STRY_ERR;
  1083.         cpybuf(umsg + cur_usrid,&imsg,sizeof(MESSAGE));
  1084.         return;
  1085. #else
  1086.         usrsiz        = sizeof(MESSAGE);
  1087.         rmsg->mdlen = imsg.mdlen;
  1088. #endif
  1089.     }
  1090.  
  1091.     if (rmsg->mretc == CMBREDLK || rmsg->mretc == (CMBREDLK + 1)) {
  1092.         prmchk = ENABLE + (rmsg->mretc - CMBREDLK) * (READREC - ENABLE);
  1093.         rmsg->mretc = CMBREDWO;
  1094.         if (rmsg->merrn == 0 && rmsg->mpntr != DRNZERO)
  1095.         rmsg->merrn = LOKREC(afilmap[cur_usrid][imsg.mseqn],
  1096.             prmchk,rmsg->mpntr);
  1097.     }
  1098.     if (rmsg->mretc == CMBREDWO) {
  1099.         rmsg->mretc = imsg.mretc = CMBREDAT;
  1100.         if (rmsg->merrn == 0) {
  1101.         imsg.mfunc  = CNT_RECOUT;
  1102.         imsg.mfiln  = imsg.mseqn;
  1103.         imsg.mdlen  = rmsg->mdlen;
  1104.         imsg.mseqn  = 0;
  1105.         imsg.mvlen  = 0;
  1106.         if ((imsg.mpntr = rmsg->mpntr) == DRNZERO)
  1107.             rmsg->merrn = INOT_ERR;
  1108.         else
  1109.             goto cmbloop;
  1110.         }
  1111.     }
  1112.  
  1113.     if (usrsiz > sizeof(MESSAGE))
  1114.         usrsiz = sizeof(MESSAGE) + rmsg->mdlen;
  1115.  
  1116.     if (ctrspn(usrmsg,rmsg,usrsiz,cur_usrid))
  1117.         srvmesg("Could not send response:",cur_usrid,uerr_cod);
  1118.  
  1119.     return;
  1120. }
  1121.  
  1122. /* end of ctsrvr.c */
  1123.  
  1124.