Annotation of 43BSDTahoe/new/nntp/xmit/shlock.c, revision 1.1.1.1

1.1       root        1: /*
                      2: ** Program to produce reliable locks for shell scripts.
                      3: ** Algorithmn suggested by Peter Honeyman, January 1984, in connection
                      4: ** with HoneyDanBer UUCP.
                      5: **
                      6: ** Erik E. Fair <ucbvax!fair>
                      7: */
                      8: 
                      9: #include <stdio.h>
                     10: #include <sys/file.h>
                     11: #include <errno.h>
                     12: 
                     13: #define        LOCK_SET        0
                     14: #define        LOCK_FAIL       1
                     15: 
                     16: #define TRUE   1
                     17: #define        FALSE   0
                     18: 
                     19: int    Verbose = FALSE;
                     20: char   *Pname;
                     21: char   *USAGE = "%s: USAGE: shlock -f file -p pid [-v]\n";
                     22: char   *errmsg();
                     23: char   *tmpfile();
                     24: 
                     25: #define        vprintf if (Verbose) printf
                     26: 
                     27: extern int     errno;
                     28: extern char    *rindex();
                     29: extern char    *strcpy();
                     30: extern char    *strcat();
                     31: 
                     32: main(ac,av)
                     33: int    ac;
                     34: char   *av[];
                     35: {
                     36:        register int    x;
                     37:        char    *file;
                     38:        int     pid;
                     39: 
                     40:        Pname = ((Pname = rindex(av[0], '/')) ? Pname + 1 : av[0]);
                     41: 
                     42:        for(x = 1; x < ac; x++) {
                     43:                if (av[x][0] == '-') {
                     44:                        switch(av[x][1]) {
                     45:                        case 'v':
                     46:                                Verbose = TRUE;
                     47:                                break;
                     48:                        case 'p':
                     49:                                if (strlen(av[x]) > 2) {
                     50:                                        pid = atoi(&av[x][2]);
                     51:                                } else {
                     52:                                        pid = atoi(av[x + 1]);
                     53:                                        x++;
                     54:                                }
                     55:                                break;
                     56:                        case 'f':
                     57:                                if (strlen(av[x]) > 2) {
                     58:                                        file = &av[x][2];
                     59:                                } else {
                     60:                                        file = av[x + 1];
                     61:                                        x++;
                     62:                                }
                     63:                                break;
                     64:                        default:
                     65:                                fprintf(stderr, USAGE, Pname);
                     66:                                exit(LOCK_FAIL);
                     67:                        }
                     68:                }
                     69:        }
                     70:        if (pid == 0 || file == (char *)NULL) {
                     71:                fprintf(stderr, USAGE, Pname);
                     72:                exit(LOCK_FAIL);
                     73:        }
                     74:        if (mklock(file, pid))
                     75:                exit(LOCK_SET);
                     76:        exit(LOCK_FAIL);
                     77: }
                     78: 
                     79: mklock(file, pid)
                     80: char   *file;
                     81: int    pid;
                     82: {
                     83:        register int    fd;
                     84:        register int    len;
                     85:        register char   *tmp = tmpfile(file);
                     86:        char    *buf[BUFSIZ];
                     87: 
                     88:        vprintf("%s: attempting to get lock <%s> for process %d\n", Pname, file, pid);
                     89:        sprintf(buf, "%d\n", pid);
                     90:        len = strlen(buf);
                     91: loop:
                     92:        if ((fd = open(tmp, O_RDWR|O_CREAT|O_EXCL, 0644)) < 0) {
                     93:                switch(errno) {
                     94:                case EEXIST:
                     95:                        vprintf("%s: temporary file %s exists already.\n", Pname, tmp);
                     96:                        if (unlink(tmp) < 0) {
                     97:                                fprintf(stderr,"%s: unlink(%s): %s\n", Pname, tmp, errmsg(errno));
                     98:                                return(FALSE);
                     99:                        }
                    100:                        /*
                    101:                        ** I hereby profane the god of structured programming
                    102:                        ** Edsgar Djikstra
                    103:                        */
                    104:                        goto loop;
                    105:                default:
                    106:                        fprintf(stderr,"%s: open(%s): %s\n", Pname, tmp, errmsg(errno));
                    107:                        return(FALSE);
                    108:                }
                    109:        }
                    110: 
                    111:        /*
                    112:        ** Write the PID into the temporary file before attempting to link
                    113:        ** to the actual lock file. That way we have a valid lock the instant
                    114:        ** the link succeeds.
                    115:        */
                    116:        if (write(fd, buf, len) < 0) {
                    117:                fprintf(stderr, "%s: write(%s,%d): %s\n", Pname, tmp, pid, errmsg(errno));
                    118:                close(fd);
                    119:                return(FALSE);
                    120:        }
                    121:        close(fd);
                    122: 
                    123: loop2:
                    124:        if (link(tmp, file) < 0) {
                    125:                switch(errno) {
                    126:                case EEXIST:
                    127:                        vprintf("%s: lock <%s> already exists\n", Pname, file);
                    128:                        if (cklock(file)) {
                    129:                                vprintf("%s: extant lock is valid\n", Pname);
                    130:                                if (unlink(tmp) < 0) {
                    131:                                        fprintf(stderr,"%s: unlink(%s): %s\n", Pname, tmp, errmsg(errno));
                    132:                                }
                    133:                                return(FALSE);
                    134:                        } else {
                    135:                                vprintf("%s: extant lock is invalid, removing\n", Pname);
                    136:                                if (unlink(file) < 0) {
                    137:                                        fprintf(stderr,"%s: unlink(%s): %s\n", Pname, file, errmsg(errno));
                    138:                                        return(FALSE);
                    139:                                }
                    140:                        }
                    141:                        goto loop2;
                    142:                default:
                    143:                        fprintf(stderr,"%s: link(%s, %s): %s\n", Pname, tmp, file, errmsg(errno));
                    144:                        return(FALSE);
                    145:                }
                    146:        }
                    147:        if (unlink(tmp) < 0) {
                    148:                fprintf(stderr,"%s: unlink(%s): %s\n", Pname, tmp, errmsg(errno));
                    149:        }
                    150:        vprintf("%s: got lock <%s>\n", Pname, file);
                    151:        return(TRUE);
                    152: }
                    153: 
                    154: /*
                    155: ** Check the validity of an existing lock file.
                    156: **
                    157: **     Read the PID out of the lock
                    158: **     Send a null signal to determine whether that PID still exists
                    159: **     Existence (or not) determines the validity of the lock.
                    160: **
                    161: **     Two bigs wins to this algorithmn:
                    162: **
                    163: **     o       Locks do not survive crashes of either the system or the
                    164: **                     application by any appreciable period of time.
                    165: **
                    166: **     o       No clean up to do if the system or application crashes.
                    167: **
                    168: */
                    169: 
                    170: cklock(file)
                    171: char   *file;
                    172: {
                    173:        register int    fd = open(file, O_RDONLY);
                    174:        register int    len;
                    175:        char    buf[BUFSIZ];
                    176: 
                    177:        vprintf("%s: checking extant lock <%s>\n", Pname, file);
                    178:        if (fd < 0) {
                    179:                fprintf(stderr,"%s: open(%s): %s\n", Pname, file, errmsg(errno));
                    180:                return(TRUE);   /* might or might not; conservatism */
                    181:        }
                    182:        
                    183:        if ((len = read(fd, buf, sizeof(buf))) <= 0) {
                    184:                close(fd);
                    185:                vprintf("%s: lock file format error\n", Pname);
                    186:                return(FALSE);
                    187:        }
                    188:        close(fd);
                    189:        buf[len + 1] = '\0';
                    190:        return(p_exists(atoi(buf)));
                    191: }
                    192: 
                    193: /*
                    194: ** Does the PID exist?
                    195: ** Send null signal to find out.
                    196: */
                    197: 
                    198: p_exists(pid)
                    199: int    pid;
                    200: {
                    201:        vprintf("%s: locking process %d is ", Pname, pid);
                    202:        if (kill(pid, 0) < 0) {
                    203:                switch(errno) {
                    204:                case ESRCH:
                    205:                        vprintf("dead\n");
                    206:                        return(FALSE);  /* pid does not exist */
                    207:                case EPERM:
                    208:                        vprintf("alive\n");
                    209:                        return(TRUE);   /* pid exists */
                    210:                default:
                    211:                        vprintf("state unknown: %s\n", errmsg(errno));
                    212:                        return(TRUE);   /* be conservative */
                    213:                }
                    214:        }
                    215:        vprintf("alive\n");
                    216:        return(TRUE);   /* pid exists */
                    217: }
                    218: 
                    219: char *
                    220: errmsg(n)
                    221: register int   n;
                    222: {
                    223:        extern  int     sys_nerr;
                    224:        extern  char    *sys_errlist[];
                    225: 
                    226:        return((n >= 0 && n < sys_nerr) ? sys_errlist[n] : "unknown error");
                    227: }
                    228: 
                    229: char *
                    230: tmpfile(file)
                    231: char *file;
                    232: {
                    233:        register char   *cp;
                    234:        static char     buf[BUFSIZ];
                    235:        char    tempname[BUFSIZ];
                    236: 
                    237:        if ((cp = rindex(strcpy(buf, file), '/')) != (char *)NULL) {
                    238:                *(cp + 1) = '\0';
                    239:        } else
                    240:                buf[0] = '\0';
                    241:        sprintf(tempname, "shlock%d", getpid());
                    242:        vprintf("%s: temporary filename: %s\n", Pname, tempname);
                    243:        return(strcat(buf, tempname));
                    244: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.