# 2.11BSD#431 - /usr/src/new/nntp/xmit/shlock.c

##### Functions

    cklock            X
    errmsg            X
    main              X
    mklock            X
    p_exists          X
    xtmpfile          X

##### Variables

    Debug             X
    Pname             X
    USAGE             X

##### Macros

    FAIL              X
    FALSE             X
    LOCK_FAIL         X
    LOCK_SET          X
    TRUE              X
    dprintf           X
    index             X
    rindex            X

       1: /*
       2: ** Program to produce reliable locks for shell scripts.
       3: ** Algorithmn suggested by Peter Honeyman, January 1984,
       4: ** in connection with HoneyDanBer UUCP.
       5: **
       6: ** I tried extending this to handle shared locks in November 1987,
       7: ** and ran into to some fundamental problems:
       8: **
       9: **	Neither 4.3 BSD nor System V have an open(2) with locking,
      10: **	so that you can open a file and have it locked as soon as
      11: **	it's real; you have to make two system calls, and there's
      12: **	a race...
      13: **
      14: **	When removing dead process id's from a list in a file,
      15: **	you need to truncate the file (you don't want to create a
      16: **	new one; see above); unfortunately for the portability of
      17: **	this program, only 4.3 BSD has ftruncate(2).
      18: **
      19: ** Erik E. Fair <fair@ucbarpa.berkeley.edu>, November 8, 1987
      20: */
      21:
      22: #include <stdio.h>
      23: #include <sys/types.h>
      24: #include <fcntl.h>          /* Needed on hpux */
      25: #include <sys/file.h>
      26: #include <errno.h>
      27:
      28: #define LOCK_SET    0
      29: #define LOCK_FAIL   1
      30:
      31: #define FAIL        (-1)
      32:
      33: #define TRUE    1
      34: #define FALSE   0
      35:
      36: #ifdef USG
      37: #define index   strchr
      38: #define rindex  strrchr
      39: #endif
      40:
      41: int Debug = FALSE;
      42: char    *Pname;
      43: char    *USAGE = "%s: USAGE: shlock -f file -p pid [-d]\n";
      44: char    *errmsg();
      45: char    *xtmpfile();
      46:
      47: #define dprintf if (Debug) printf
      48:
      49: extern  int errno;
      50: extern  char    *rindex();
      51: extern  char    *strcpy();
      52: extern  char    *strcat();
      53:
      54: main(ac, av)
      55: int ac;
      56: char    *av[];
      57: {
      58:     register int    x;
      59:     char    *file;
      60:     int pid;
      61:
      62:     Pname = ((Pname = rindex(av[0], '/')) ? Pname + 1 : av[0]);
      63:
      64:     for(x = 1; x < ac; x++) {
      65:         if (av[x][0] == '-') {
      66:             switch(av[x][1]) {
      67:             case 'd':
      68:                 Debug = TRUE;
      69:                 break;
      70:             case 'p':
      71:                 if (strlen(av[x]) > 2) {
      72:                     pid = atoi(&av[x][2]);
      73:                 } else {
      74:                     pid = atoi(av[++x]);
      75:                 }
      76:                 break;
      77:             case 'f':
      78:                 if (strlen(av[x]) > 2) {
      79:                     file = &av[x][2];
      80:                 } else {
      81:                     file = av[++x];
      82:                 }
      83:                 break;
      84:             default:
      85:                 fprintf(stderr, USAGE, Pname);
      86:                 exit(LOCK_FAIL);
      87:             }
      88:         }
      89:     }
      90:     if (pid == 0 || file == (char *)NULL) {
      91:         fprintf(stderr, USAGE, Pname);
      92:         exit(LOCK_FAIL);
      93:     }
      94:
      95:     exit(mklock(file, pid) ? LOCK_SET : LOCK_FAIL);
      96: }
      97:
      98: char *
      99: errmsg(n)
     100: register int    n;
     101: {
     102:     return(strerror(n));
     103: }
     104:
     105: mklock(file, pid)
     106: char    *file;
     107: int pid;
     108: {
     109:     register char   *tmp;
     110:     register int    retcode = FALSE;
     111:     char    *e_unlk = "%s: unlink(%s): %s\n";
     112:
     113:     dprintf("%s: trying lock <%s> for process %d\n", Pname, file, pid);
     114:     if ((tmp = xtmpfile(file, pid)) == (char *)NULL)
     115:         return(FALSE);
     116:
     117: linkloop:
     118:     if (link(tmp, file) < 0) {
     119:         switch(errno) {
     120:         case EEXIST:
     121:             dprintf("%s: lock <%s> already exists\n", Pname, file);
     122:             if (cklock(file)) {
     123:                 dprintf("%s: extant lock is valid\n", Pname);
     124:                 break;
     125:             } else {
     126:                 dprintf("%s: lock is invalid, removing\n",
     127:                     Pname);
     128:                 if (unlink(file) < 0) {
     129:                     fprintf(stderr, e_unlk,
     130:                         Pname, file, errmsg(errno));
     131:                     break;
     132:                 }
     133:             }
     134:             /*
     135: 			** I hereby profane the god of structured programming,
     136: 			** Edsgar Dijkstra
     137: 			*/
     138:             goto linkloop;
     139:         default:
     140:             fprintf(stderr, "%s: link(%s, %s): %s\n",
     141:                 Pname, tmp, file, errmsg(errno));
     142:             break;
     143:         }
     144:     } else {
     145:         dprintf("%s: got lock <%s>\n", Pname, file);
     146:         retcode = TRUE;
     147:     }
     148:     if (unlink(tmp) < 0) {
     149:         fprintf(stderr, e_unlk, Pname, tmp, errmsg(errno));
     150:     }
     151:     return(retcode);
     152: }
     153:
     154: /*
     155: ** Does the PID exist?
     156: ** Send null signal to find out.
     157: */
     158: p_exists(pid)
     159: int pid;
     160: {
     161:     dprintf("%s: process %d is ", Pname, pid);
     162:     if (pid <= 0) {
     163:         dprintf("invalid\n");
     164:         return(FALSE);
     165:     }
     166:     if (kill(pid, 0) < 0) {
     167:         switch(errno) {
     168:         case ESRCH:
     169:             dprintf("dead\n");
     170:             return(FALSE);  /* pid does not exist */
     171:         case EPERM:
     172:             dprintf("alive\n");
     173:             return(TRUE);   /* pid exists */
     174:         default:
     175:             dprintf("state unknown: %s\n", errmsg(errno));
     176:             return(TRUE);   /* be conservative */
     177:         }
     178:     }
     179:     dprintf("alive\n");
     180:     return(TRUE);   /* pid exists */
     181: }
     182:
     183: /*
     184: ** Check the validity of an existing lock file.
     185: **
     186: **	Read the PID out of the lock
     187: **	Send a null signal to determine whether that PID still exists
     188: **	Existence (or not) determines the validity of the lock.
     189: **
     190: **	Two bigs wins to this algorithmn:
     191: **
     192: **	o	Locks do not survive crashes of either the system or the
     193: **			application by any appreciable period of time.
     194: **
     195: **	o	No clean up to do if the system or application crashes.
     196: **
     197: */
     198:
     199: cklock(file)
     200: char    *file;
     201: {
     202:     register int    fd = open(file, O_RDONLY);
     203:     register int    len;
     204:     char    buf[BUFSIZ];
     205:
     206:     dprintf("%s: checking extant lock <%s>\n", Pname, file);
     207:     if (fd < 0) {
     208:         fprintf(stderr,"%s: open(%s): %s\n", Pname, file, errmsg(errno));
     209:         return(TRUE);   /* might or might not; conservatism */
     210:     }
     211:
     212:     if ((len = read(fd, buf, sizeof(buf))) <= 0) {
     213:         close(fd);
     214:         dprintf("%s: lock file format error\n", Pname);
     215:         return(FALSE);
     216:     }
     217:     close(fd);
     218:     buf[len + 1] = '\0';
     219:     return(p_exists(atoi(buf)));
     220: }
     221:
     222: /*
     223: ** Create a temporary file, all ready to lock with.
     224: ** The file arg is so we get the filename right, if he
     225: ** gave us a full path, instead of using the current directory
     226: ** which might not be in the same filesystem.
     227: */
     228: char *
     229: xtmpfile(file, pid)
     230: char    *file;
     231: int pid;
     232: {
     233:     register int    fd;
     234:     register int    len;
     235:     char    *cp, buf[BUFSIZ];
     236:     static char tempname[BUFSIZ];
     237:
     238:     sprintf(buf, "shlock%d", getpid());
     239:     if ((cp = rindex(strcpy(tempname, file), '/')) != (char *)NULL) {
     240:         *++cp = '\0';
     241:         (void) strcat(tempname, buf);
     242:     } else
     243:         (void) strcpy(tempname, buf);
     244:     dprintf("%s: temporary filename: %s\n", Pname, tempname);
     245:
     246:     sprintf(buf, "%d\n", pid);
     247:     len = strlen(buf);
     248: openloop:
     249:     if ((fd = open(tempname, O_RDWR|O_CREAT|O_EXCL, 0644)) < 0) {
     250:         switch(errno) {
     251:         case EEXIST:
     252:             dprintf("%s: file %s exists already.\n",
     253:                 Pname, tempname);
     254:             if (unlink(tempname) < 0) {
     255:                 fprintf(stderr, "%s: unlink(%s): %s\n",
     256:                     Pname, tempname, errmsg(errno));
     257:                 return((char *)NULL);
     258:             }
     259:             /*
     260: 			** Further profanity
     261: 			*/
     262:             goto openloop;
     263:         default:
     264:             fprintf(stderr, "%s: open(%s): %s\n",
     265:                 Pname, tempname, errmsg(errno));
     266:             return((char *)NULL);
     267:         }
     268:     }
     269:
     270:     /*
     271: 	** Write the PID into the temporary file before attempting to link
     272: 	** to the actual lock file. That way we have a valid lock the instant
     273: 	** the link succeeds.
     274: 	*/
     275:     if (write(fd, buf, len) < 0) {
     276:         fprintf(stderr, "%s: write(%s,%d): %s\n",
     277:             Pname, tempname, pid, errmsg(errno));
     278:         (void) close(fd);
     279:         return((char *)NULL);
     280:     }
     281:     (void) close(fd);
     282:     return(tempname);
     283: }

#### Defined functions

cklock defined in line 199; used 1 times

- in line 122

errmsg defined in line 98; used 14 times

- in line 44, 130, 141, 149, 175, 208, 256, 265, 277
- in /usr/src/new/nntp/xmit/get_tcp_conn.c line 28, 314
- in /usr/src/new/nntp/xmit/remote.c line 53, 207, 214

main defined in line 54; never used
mklock defined in line 105; used 1 times

- in line 95

p_exists defined in line 158; used 1 times

- in line 219

xtmpfile defined in line 228; used 2 times

- in line 45, 114

#### Defined variables

Debug defined in line 41; used 2 times

- in line 47, 68

Pname defined in line 42; used 23 times

- in line 62(3), 85, 91, 113, 121-130(4), 141-149(3), 161, 206-208(2), 214, 244, 253-256(2), 265, 277
- in /usr/src/new/nntp/xmit/get_tcp_conn.c line 313

USAGE defined in line 43; used 2 times

- in line 85, 91

#### Defined macros

FAIL defined in line 31; never used
FALSE defined in line 34; used 6 times

- in line 41, 110-115(2), 164, 170, 215

LOCK_FAIL defined in line 29; used 3 times

- in line 86, 92-95(2)

LOCK_SET defined in line 28; used 1 times

- in line 95

TRUE defined in line 33; used 6 times

- in line 68, 146, 173-180(3), 209

dprintf defined in line 47; used 15 times

- in line 113, 121-126(3), 145, 161-163(2), 169-179(4), 206, 214, 244, 252

index defined in line 37; never used
rindex defined in line 38; used 3 times

- in line 50, 62, 239

Last modified: 1996-03-22 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1863 |