Annotation of 43BSDTahoe/new/nntp/xmit/shlock.c, revision 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.