home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / BWNFSD.TAR / bwnfsd / bwlock.c next >
Encoding:
C/C++ Source or Header  |  1993-02-14  |  16.0 KB  |  644 lines

  1. /*
  2. VERSION  2.3a
  3. MODIFIED 1/31/92
  4.  
  5.     BWNFSD is an RPC daemon used in conjunction with BWNFS ( a client
  6. NFS for DOS based PCs. BWNFSD provides Authentication, Print Spooling,
  7. DOS 3.1 Locking, DOS 3.1 Sharing, GID name mapping, UID name mapping
  8. services for BWNFS and associated applications on the PC. BWNFSD is being
  9. used also by Macintosh NFS clients.
  10.  
  11.     The BWNFSD code is originally copyright Beame & Whiteside Software
  12. Ltd. and now is released to the Public Domain. The intent is that all server
  13. vendors included a version of BWNFSD with their operating system. BWNFSD can
  14. run simultantiously with PCNFSD, but provides many more features.
  15.  
  16.     Please send modifications to:
  17.  
  18.         Beame & Whiteside Software Ltd.
  19.         P.O. Box 8130
  20.         Dundas, Ontario
  21.         Canada L9H 5E7
  22.         +1 (416) 765-0822
  23.  
  24.     Please modify by including "ifdefs" for your particular operating
  25. system, with appropriate modifications to the "makefile".
  26.  
  27. BWLOCK.C provides the locking and sharing service for BWNFS. This should be
  28. used if rpc.lockd does not include the extensions for DOS 3.1 locking or
  29. sharing, or if your system has the regular distribution of the rpc.lockd as
  30. the extensions most likely will not work.
  31.  
  32. One might want to make operating system calls to lock and unlock the files
  33. so that locking occurs not only against other BWNFS clients, but native
  34. clients as well.
  35.  
  36. Modified 02/14/93, Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>,
  37. to use #define macros for pathnames and such.  Much cleaner...
  38.  
  39. */
  40. /*
  41.   HASH_LOCATION is a number between 0 and 31 inclusive. It should be set to
  42.   the position in the file handle 32 bytes structure which changes the most
  43.   between different files.
  44. */
  45. #define HASH_LOCATION 17
  46.  
  47. #include <stdio.h>
  48. #include <signal.h>
  49. #ifdef SYSV32
  50. #   include <string.h>
  51. #   define  memcmp(a,b,c) bcmp((b),(a),(c))
  52. #   define  memcpy(a,b,c) bcopy((b),(a),(c))
  53. #else
  54. #   include <memory.h>
  55. #   include <strings.h>
  56. #endif
  57.  
  58. #define LOCK_DMP    "/tmp/bwlocks.dmp"
  59.  
  60.  
  61. #define LOCK     'L'
  62. #define SHARE   'S'
  63.               /*              1st Open             */
  64.                       /* ALL     DR     DW     DRW   COMP  */
  65.                       /* I O B  I O B  I O B  I O B  I O B */
  66. char shares[15][15] = { {1,1,1, 0,0,0, 1,1,1, 0,0,0, 0,0,0}, /* I */
  67.             {1,1,1, 1,1,1, 0,0,0, 0,0,0, 0,0,0}, /* O  ALL */
  68.             {1,1,1, 0,0,0, 0,0,0, 0,0,0, 0,0,0}, /* B */
  69.             {0,1,0, 0,0,0, 0,1,0, 0,0,0, 0,0,0}, /* I */
  70.                  {0,1,0, 0,1,0, 0,0,0, 0,0,0, 0,0,0}, /* O  DR */
  71.             {0,1,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0}, /* B */
  72.             {1,0,0, 0,0,0, 1,0,0, 0,0,0, 0,0,0}, /* I */
  73.             {1,0,0, 1,0,0, 0,0,0, 0,0,0, 0,0,0}, /* O DW 2nd Open */
  74.             {1,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0}, /* B */
  75.             {0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0}, /* I */
  76.             {0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0}, /* O  DRW */
  77.             {0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0}, /* B */
  78.             {0,0,0, 0,0,0, 0,0,0, 0,0,0, 1,1,1}, /* I */
  79.             {0,0,0, 0,0,0, 0,0,0, 0,0,0, 1,1,1}, /* O  COMP */
  80.             {0,0,0, 0,0,0, 0,0,0, 0,0,0, 1,1,1}};/* B */
  81.  
  82. struct LK
  83.     {
  84.         char type;
  85.         struct LK *nxt;
  86.         struct LK *prv;
  87.         struct LK *nxt_fh;
  88.         struct LK *prv_fh;
  89.         struct FH *fh;
  90.         struct PC *pc;
  91.         union {
  92.              struct {
  93.                 char mode;
  94.                 char access;
  95.              } s;
  96.              struct {
  97.                 unsigned long offset;
  98.                 unsigned long length;
  99.              } l;
  100.               } lock;
  101.     };
  102.  
  103. struct FH
  104.     {
  105.         char fh[32];
  106.         struct LK *lock;
  107.         struct FH *nxt;
  108.         struct FH *prv;
  109.     };
  110.  
  111. struct PC
  112.     {
  113.         char  *owner;
  114.         struct PC *nxt;
  115.         struct PC *prv;
  116.         struct LK *lock;
  117.         unsigned long    last_cookie;
  118.         int    last_result;
  119.     };
  120.  
  121. struct PC *pcs[256];
  122. struct FH *fhs[256];
  123. int       debugmode;
  124.  
  125.  
  126. char *my_strdup(p)
  127.     char *p;
  128. {
  129.     char *p1;
  130.     if ( (p1 = (char *) malloc(strlen(p)+1)) == NULL) return(NULL);
  131.     return(strcpy(p1,p));
  132. }
  133.  
  134.  
  135. void display_locks()
  136. {
  137.     int i,j;
  138.     struct PC *pc1;
  139.     struct LK *lk1;
  140.     struct FH *fh1;
  141.     FILE *lock_file;
  142.  
  143. #ifdef    SIGUSR1
  144.   (void) signal(SIGUSR1,display_locks);
  145. #endif
  146.    if ( (lock_file = fopen(LOCK_DMP,"w")) == NULL) return;
  147.    for ( i = 0 ; i < 256;i++)
  148.    {
  149.       pc1 = pcs[i];
  150.       while ( pc1 != NULL)
  151.       {
  152.      j = 0;
  153.      (void) fprintf( lock_file,"%3d %s -> ", i, pc1->owner );
  154.      lk1 = pc1->lock;
  155.      while ( lk1 != NULL)
  156.      {
  157.         (void) fprintf( lock_file, "%c/%3u/",
  158.                         lk1->type, (lk1->fh)->fh[HASH_LOCATION] & 0xff);
  159.         if ( lk1->type == SHARE)
  160.         {
  161.            (void) fprintf( lock_file, "%1d -> ", lk1->lock.s.mode );
  162.            j+=11;
  163.         }
  164.         else
  165.         {
  166.                (void) fprintf( lock_file, "%3ld+%3ld -> ",
  167.                                lk1->lock.l.offset, lk1->lock.l.length );
  168.            j+=17;
  169.         }
  170.         if ( j > 70)
  171.         {
  172.            (void) fprintf( lock_file, "\n                ");
  173.            j=0;
  174.         }
  175.         lk1=lk1->nxt;
  176.      }
  177.      (void) fprintf( lock_file, "NULL\n" );
  178.      pc1=pc1->nxt;
  179.       }
  180.    }
  181.    (void) fprintf( lock_file, "File Handles\n");
  182.    for ( i = 0 ; i < 256;i++)
  183.    {
  184.       fh1 = fhs[i];
  185.       while ( fh1 != NULL)
  186.       {
  187.      (void) fprintf( lock_file, "%3d ", i );
  188.      for (j=0;j<32;j++)
  189.        (void) fprintf( lock_file, "%02X", fh1->fh[j] & 0xff );
  190.      (void) fprintf( lock_file, " -> " );
  191.      j   = 0;
  192.      lk1 = fh1->lock;
  193.      while ( lk1 != NULL)
  194.      {
  195.         (void) fprintf( lock_file, "%c/%3u/",lk1->type,*(lk1->pc)->owner & 0xff);
  196.         if ( lk1->type == SHARE)
  197.         {
  198.            (void) fprintf( lock_file, "%1d -> ", lk1->lock.s.mode );
  199.            j+=11;
  200.         }
  201.         else
  202.         {
  203.                (void) fprintf( lock_file, "%3ld+%3ld -> ",
  204.                                lk1->lock.l.offset, lk1->lock.l.length );
  205.            j+=17;
  206.         }
  207.         if ( j > 70)
  208.         {
  209.            (void) fprintf( lock_file, "\n                ");
  210.            j=0;
  211.         }
  212.         lk1=lk1->nxt_fh;
  213.      }
  214.      (void) fprintf( lock_file, "NULL\n" );
  215.      fh1=fh1->nxt;
  216.       }
  217.    }
  218.    fclose(lock_file);
  219. }
  220.  
  221.  
  222. void init_locks()
  223. {
  224.     int    i;
  225.  
  226.         if (debugmode)
  227.           (void) fprintf( stdout, "bwnfds: [init_locks] called\n" );
  228.     for ( i = 0 ; i < 256;i++)
  229.        pcs[i] = NULL;
  230.     for ( i = 0 ; i < 256;i++)
  231.        fhs[i] = NULL;
  232. #ifdef    SIGUSR1
  233.   (void) signal(SIGUSR1,display_locks);
  234. #endif
  235. }
  236.  
  237. #define TRUE  1
  238. #define FALSE 0
  239.  
  240. static    int    pc_ptr,fh_ptr;
  241.  
  242. struct PC *locate_by_owner(owner)
  243. char *owner;
  244. {
  245.     struct PC *p;
  246.  
  247.         if (debugmode)
  248.           (void) fprintf( stdout, "bwnfsd: [locate_by_owner] called for %s\n",
  249.                           owner );
  250.     p = pcs[pc_ptr];
  251.     while ( p != NULL)
  252.     {
  253.        if (debugmode)
  254.          (void) fprintf (stdout, "bwnfsd: [locate_by_owner] owner is %s\n",
  255.                         p->owner );
  256.        if ( strcmp(p->owner,owner) == 0)
  257.           return(p);
  258.        else
  259.           p = p->nxt;
  260.     }
  261.     return(p);
  262. }
  263.  
  264. struct FH *locate_by_handle(fh)
  265. char *fh;
  266. {
  267.     struct FH *p;
  268.  
  269.         if (debugmode)
  270.           (void) fprintf( stdout, "bwnfsd: [locate_by_handle] called\n" );
  271.     p = fhs[fh_ptr];
  272.     while ( p != NULL)
  273.        if ( memcmp(p->fh,fh,32) == 0)
  274.           return(p);
  275.        else
  276.           p = p->nxt;
  277.     return(p);
  278. }
  279.  
  280.  
  281. int process_lock_request(request,owner,fh,access,mode,offset,length,cookie)
  282. int    request;
  283. char    *fh,*owner;
  284. int    access,mode;
  285. unsigned long    length,offset;
  286. unsigned long   cookie;
  287. {
  288.     struct PC *pc1;
  289.     struct LK *lk1;
  290.     struct LK *lk2;
  291.     struct FH *fh1;
  292.     int      j;
  293.  
  294.         if (debugmode)
  295.         {
  296.           (void) fprintf( stdout, "bwnfsd: [process_lock_request] called with\n" );
  297.           (void) fprintf( stdout, "bwnfsd: request     = %d\n", request );
  298.           (void) fprintf( stdout, "bwnfsd: owner       = %s\n", owner );
  299.           (void) fprintf( stdout, "bwnfsd: file_handle = " );
  300.           for(j=0;j<32;j++)
  301.             (void) fprintf( stdout, "%02X", fh[j] & 0xff );
  302.       fprintf(stdout,"\n");
  303.           (void) fprintf( stdout, "bwnfsd: access      = %d\n", access );
  304.           (void) fprintf( stdout, "bwnfsd: mode        = %d\n", mode );
  305.           (void) fprintf( stdout, "bwnfsd: offset      = %ld\n", offset );
  306.           (void) fprintf( stdout, "bwnfsd: length      = %ld\n", length );
  307.           (void) fprintf( stdout, "bwnfsd: cookie      = %ld\n", cookie );
  308.         }
  309.     {
  310.         int len;
  311.         if ( owner == NULL)
  312.             len = 0;
  313.         else
  314.             len = strlen(owner);
  315.         if ( len ==0)
  316.             pc_ptr =0;
  317.         else if ( len == 1)
  318.             pc_ptr = *(owner+len-1) & 0xff;
  319.         else
  320.             pc_ptr = (*(owner+len-1) ^ *(owner+len-2)) & 0xff;
  321.     }
  322.  
  323.     if ( request != 23)
  324.     {
  325.            if ( (pc1 = locate_by_owner(owner)) == NULL)
  326.            {
  327.                   if ( (pc1 = (struct PC *) malloc(sizeof(struct PC))) == NULL)
  328.                  return(FALSE);
  329.                   pc1->owner  = my_strdup(owner);
  330.                   pc1->lock   = NULL;
  331.                   pc1->prv    = NULL;
  332.                   pc1->nxt    = pcs[pc_ptr];
  333.             pc1->last_cookie = cookie-1;
  334.                   pcs[pc_ptr] = pc1;
  335.                   if ( (pc1->nxt) != NULL)
  336.                 (pc1->nxt)->prv = pc1;
  337.            }
  338.         if ( pc1->last_cookie == cookie ) return(pc1->last_result);
  339.             pc1->last_cookie = cookie;
  340.     }
  341.     switch(request)
  342.     {
  343.     case 20: /* share */
  344.        fh_ptr = fh[HASH_LOCATION] & 0xff;
  345.  
  346.        if ( (fh1 = locate_by_handle(fh)) == NULL)
  347.        {
  348.           if ( (fh1 = (struct FH *) malloc(sizeof(struct FH))) == NULL)
  349.           {
  350.          pc1->last_result = FALSE;
  351.          return(FALSE);
  352.           }
  353.           (void) memcpy(fh1->fh,fh,32);
  354.           fh1->lock   = NULL;
  355.           fh1->prv    = NULL;
  356.           fh1->nxt    = fhs[fh_ptr];
  357.           fhs[fh_ptr] = fh1;
  358.           if ( (fh1->nxt) != NULL)
  359.         (fh1->nxt)->prv = fh1;
  360.        }
  361.        lk1 = fh1->lock;
  362.        while ( lk1 != NULL)
  363.        {
  364.         if ( lk1->type == SHARE)
  365.         {
  366.            if ( !shares[mode*3+access-1][lk1->lock.s.mode*3+
  367.             lk1->lock.s.access-1])
  368.             {
  369.                pc1->last_result = FALSE;
  370.                return(FALSE);
  371.             }
  372.                 }
  373.         lk1=lk1->nxt_fh;
  374.        }
  375.        if ( (lk1 = (struct LK *) malloc(sizeof(struct LK))) == NULL)
  376.        {
  377.           pc1->last_result = FALSE;
  378.           return(FALSE);
  379.        }
  380.        lk1->fh            = fh1;
  381.        lk1->pc            = pc1;
  382.        lk1->type          = SHARE;
  383.        lk1->lock.s.mode   = mode;
  384.        lk1->lock.s.access = access;
  385.        lk1->prv           = NULL;
  386.        lk1->prv_fh        = NULL;
  387.        if ( ( lk1->nxt = pc1->lock) != NULL)
  388.           (lk1->nxt)->prv = lk1;
  389.        pc1->lock = lk1;
  390.        if ( ( lk1->nxt_fh = fh1->lock) != NULL)
  391.           (lk1->nxt_fh)->prv_fh = lk1;
  392.        fh1->lock = lk1;
  393.        pc1->last_result = TRUE;
  394.        return(TRUE);
  395.     case 21: /* unshare */
  396.        fh_ptr = fh[HASH_LOCATION] & 0xff;
  397.        if ( (fh1 = locate_by_handle(fh)) == NULL)
  398.        {
  399.         pc1->last_result = TRUE;
  400.             return(TRUE);
  401.        }
  402.        lk1=fh1->lock;
  403.        while ( lk1 != NULL)
  404.        {
  405.           if ( (lk1->pc == pc1) && ( lk1->type == SHARE) &&
  406.            ( mode == lk1->lock.s.mode) && ( access == lk1->lock.s.access))
  407.           {
  408.              if ( (lk1->prv_fh) == NULL)
  409.              {
  410.             if ((fh1->lock = lk1->nxt_fh) == NULL)
  411.             {
  412.                    if ( fh1->prv == NULL)
  413.                   {
  414.                       if ( (fhs[fh_ptr] = fh1->nxt) != NULL)
  415.                      (fh1->nxt)->prv = NULL;
  416.                  }
  417.                    else
  418.                   {
  419.                         if (((fh1->prv)->nxt = fh1->nxt) != NULL)
  420.                          (fh1->nxt)->prv = fh1->prv;
  421.                    }
  422.                free(fh1);
  423.  
  424.             }
  425.             else
  426.                (fh1->lock)->prv_fh = NULL;
  427.              }
  428.              else
  429.              {
  430.                 if ( ((lk1->prv_fh)->nxt_fh = lk1->nxt_fh) != NULL)
  431.                    (lk1->nxt_fh)->prv_fh = lk1->prv_fh;
  432.              }
  433.              if ( (lk1->prv) == NULL)
  434.              {
  435.             if ((pc1->lock = lk1->nxt) == NULL)
  436.             {
  437.                    if ( pc1->prv == NULL)
  438.                   {
  439.                       if ( (pcs[pc_ptr] = pc1->nxt) != NULL)
  440.                      (pc1->nxt)->prv = NULL;
  441.                  }
  442.                    else
  443.                   {
  444.                         if ( ((pc1->prv)->nxt = pc1->nxt) != NULL)
  445.                          (pc1->nxt)->prv = pc1->prv;
  446.                    }
  447.                free(pc1->owner);
  448.                free(pc1);
  449.                pc1 = NULL;
  450.             }
  451.             else
  452.                (pc1->lock)->prv = NULL;
  453.              }
  454.              else
  455.              {
  456.                 if (((lk1->prv)->nxt = lk1->nxt) != NULL)
  457.                    (lk1->nxt)->prv = lk1->prv;
  458.              }
  459.          free(lk1);
  460.          if ( pc1 != NULL) pc1->last_result = TRUE;
  461.          return(TRUE);
  462.           }
  463.           lk1 = lk1->nxt_fh;
  464.        }
  465.            if ( pc1 != NULL) pc1->last_result = TRUE;
  466.        return(TRUE);
  467.     case 22: /* lock */
  468.        fh_ptr = fh[HASH_LOCATION] & 0xff;
  469.        if ( (fh1 = locate_by_handle(fh)) == NULL)
  470.        {
  471.           if ( (fh1 = (struct FH *) malloc(sizeof(struct FH))) == NULL)
  472.           {
  473.          pc1->last_result = FALSE;
  474.          return(FALSE);
  475.           }
  476.           (void) memcpy(fh1->fh,fh,32);
  477.           fh1->lock   = NULL;
  478.           fh1->prv    = NULL;
  479.           fh1->nxt    = fhs[fh_ptr];
  480.           fhs[fh_ptr] = fh1;
  481.           if ( (fh1->nxt) != NULL)
  482.         (fh1->nxt)->prv = fh1;
  483.        }
  484.        lk1 = fh1->lock;
  485.        while ( lk1 != NULL)
  486.        {
  487.         if ( lk1->type == LOCK)
  488.            if ( ((lk1->lock.l.offset >= offset) &&
  489.              (offset+length > lk1->lock.l.offset)) ||
  490.             ((lk1->lock.l.offset < offset) &&
  491.              (lk1->lock.l.offset + lk1->lock.l.length > offset)))
  492.               {
  493.                pc1->last_result = FALSE;
  494.                return(FALSE);
  495.               }
  496.         lk1=lk1->nxt_fh;
  497.        }
  498.        if ( (lk1 = (struct LK *) malloc(sizeof(struct LK))) == NULL)
  499.        {
  500.           pc1->last_result = FALSE;
  501.           return(FALSE);
  502.            }
  503.        lk1->fh            = fh1;
  504.        lk1->pc            = pc1;
  505.        lk1->type          = LOCK;
  506.        lk1->lock.l.offset = offset;
  507.        lk1->lock.l.length = length;
  508.        lk1->prv           = NULL;
  509.        lk1->prv_fh        = NULL;
  510.        if ( ( lk1->nxt = pc1->lock) != NULL)
  511.           (lk1->nxt)->prv = lk1;
  512.        pc1->lock = lk1;
  513.        if ( ( lk1->nxt_fh = fh1->lock) != NULL)
  514.           (lk1->nxt_fh)->prv_fh = lk1;
  515.        fh1->lock = lk1;
  516.        pc1->last_result = TRUE;
  517.        return(TRUE);
  518.     case 23: /* remove all */
  519.            if (  (pc1 = locate_by_owner(owner)) == NULL)
  520.           return(TRUE);
  521.        if ( pc1->prv == NULL)
  522.        {
  523.           if ( (pcs[pc_ptr] = pc1->nxt) != NULL)
  524.          (pc1->nxt)->prv = NULL;
  525.        }
  526.        else
  527.        {
  528.           if ( ((pc1->prv)->nxt = pc1->nxt) != NULL)
  529.              (pc1->nxt)->prv = pc1->prv;
  530.        }
  531.        lk1 = pc1->lock;
  532.        while ( lk1 != NULL)
  533.        {
  534.           if ( (lk1->prv_fh) == NULL)
  535.           {
  536.            fh1 = lk1->fh;
  537.          if ((fh1->lock = lk1->nxt_fh) == NULL)
  538.          {
  539.                 if ( fh1->prv == NULL)
  540.                {
  541.                fh_ptr = fh1->fh[HASH_LOCATION] & 0xff;
  542.                    if ( (fhs[fh_ptr] = fh1->nxt) != NULL)
  543.                   (fh1->nxt)->prv = NULL;
  544.               }
  545.                 else
  546.                {
  547.                      if (((fh1->prv)->nxt = fh1->nxt) != NULL)
  548.                       (fh1->nxt)->prv = fh1->prv;
  549.                 }
  550.             free(fh1);
  551.  
  552.          }
  553.          else
  554.             (fh1->lock)->prv_fh = NULL;
  555.           }
  556.           else
  557.           {
  558.              if ( ((lk1->prv_fh)->nxt_fh = lk1->nxt_fh) != NULL)
  559.                 (lk1->nxt_fh)->prv_fh = lk1->prv_fh;
  560.           }
  561.           lk2 = lk1->nxt;
  562.           free(lk1);
  563.           lk1=lk2;
  564.        }
  565.        free(pc1->owner);
  566.        free(pc1);
  567.        return(TRUE);
  568.     case 24: /* unlock */
  569.        fh_ptr = fh[HASH_LOCATION] & 0xff;
  570.        if ( (fh1 = locate_by_handle(fh)) == NULL)
  571.        {
  572.           pc1->last_result = TRUE;
  573.           return(TRUE);
  574.        }
  575.        lk1=fh1->lock;
  576.        while ( lk1 != NULL)
  577.        {
  578.           if ( (lk1->pc == pc1) && (lk1->type == LOCK) &&
  579.           ( offset == lk1->lock.l.offset) && (length == lk1->lock.l.length))
  580.           {
  581.              if ( (lk1->prv_fh) == NULL)
  582.              {
  583.             if ((fh1->lock = lk1->nxt_fh) == NULL)
  584.             {
  585.                    if ( fh1->prv == NULL)
  586.                   {
  587.                       if ( (fhs[fh_ptr] = fh1->nxt) != NULL)
  588.                      (fh1->nxt)->prv = NULL;
  589.                  }
  590.                    else
  591.                   {
  592.                         if ( ((fh1->prv)->nxt = fh1->nxt) != NULL)
  593.                          (fh1->nxt)->prv = fh1->prv;
  594.                    }
  595.                free(fh1);
  596.  
  597.             }
  598.             else
  599.                (fh1->lock)->prv_fh = NULL;
  600.              }
  601.              else
  602.              {
  603.                 if ( ((lk1->prv_fh)->nxt_fh = lk1->nxt_fh) != NULL)
  604.                    (lk1->nxt_fh)->prv_fh = lk1->prv_fh;
  605.              }
  606.              if ( (lk1->prv) == NULL)
  607.              {
  608.             if ((pc1->lock = lk1->nxt) == NULL)
  609.             {
  610.                    if ( pc1->prv == NULL)
  611.                   {
  612.                       if ( (pcs[pc_ptr] = pc1->nxt) != NULL)
  613.                      (pc1->nxt)->prv = NULL;
  614.                  }
  615.                    else
  616.                   {
  617.                         if ( ((pc1->prv)->nxt = pc1->nxt) != NULL)
  618.                          (pc1->nxt)->prv = pc1->prv;
  619.                    }
  620.                  free(pc1->owner);
  621.                free(pc1);
  622.                pc1 = NULL;
  623.             }
  624.             else
  625.                (pc1->lock)->prv = NULL;
  626.              }
  627.              else
  628.              {
  629.                 if ( ((lk1->prv)->nxt = lk1->nxt) != NULL)
  630.                    (lk1->nxt)->prv = lk1->prv;
  631.              }
  632.          free(lk1);
  633.          if ( pc1 != NULL) pc1->last_result = TRUE;
  634.          return(TRUE);
  635.           }
  636.           lk1 = lk1->nxt_fh;
  637.        }
  638.        if ( pc1 != NULL) pc1->last_result = TRUE;
  639.        return(TRUE);
  640.     }
  641.     if ( pc1 != NULL) pc1->last_result = FALSE;
  642.     return(FALSE);
  643. }
  644.