Annotation of coherent/g/usr/lib/misc/lock.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * lock.c
        !             3:  *
        !             4:  * Provide a locking mechanism for devices that may be used by
        !             5:  * UUCP. This is infact used by UUCP.
        !             6:  *
        !             7:  * Lock files are created in SPOOLDIR with the name LCK..resource.  The
        !             8:  * contents of the lock file are a decimal representation of the pid of
        !             9:  * the process that created the lock.
        !            10:  *
        !            11:  * For a tty device, the "resource" is a string composed of a
        !            12:  * decimal representation of its major number, a decimal point, and
        !            13:  * the lower five bits of its minor number.  This conversion is done
        !            14:  * by gen_res_name().
        !            15:  *
        !            16:  * Each routine takes a string which names a resource to be locked or
        !            17:  * unlocked.  The tty routines want the base name of the tty to be locked
        !            18:  * (without the "/dev/" part).
        !            19:  *
        !            20:  * These routines all return 0 on failure and 1 on success.
        !            21:  *
        !            22:  * It is possible to provide an alternate pid by using one of the "n"
        !            23:  * routines.  A pid of 0 provided to one of the unlocking routines
        !            24:  * is treated as an over-ride--the lock will be removed no matter
        !            25:  * what the pid of its creating process.
        !            26:  *
        !            27:  * Here are the lock/unlock pairs:
        !            28:  *
        !            29:  * locktty(ttyname)            /       unlocktty(ttyname)
        !            30:  * lockntty(ttyname, pid)      /       unlockntty(ttyname, pid)
        !            31:  * lockit(resource)            /       lockrm(resource)
        !            32:  * nlockit(resource, pid)      /       locknrm(resource, pid)
        !            33:  *
        !            34:  * These are for checking for the existence of locks:
        !            35:  * lockexist(resource)
        !            36:  * lockttyexist(ttyname)
        !            37:  */
        !            38: 
        !            39: #include <stdio.h>
        !            40: #include <sys/stat.h>
        !            41: #include <unistd.h>
        !            42: 
        !            43: static char *gen_res_name();
        !            44: 
        !            45: #ifdef UUCP
        !            46: #include "dcp.h"
        !            47: #else
        !            48: #define SPOOLDIR       "/usr/spool/uucp"
        !            49: #define LOCKSIG                9       /* Significant Chars of Lockable Resources.  */
        !            50: #define LOKFLEN                64      /* Max Length of UUCP Lock File Name.        */
        !            51: #endif /* UUCP */
        !            52: 
        !            53: #define LOCKDIR        SPOOLDIR
        !            54: #define        LOCKPRE "LCK.."
        !            55: #define PIDLEN 6       /* Maximum length of string representing a pid.  */
        !            56: 
        !            57: /* There is a special version of DEVMASK for the PE multiport driver
        !            58:  * because of the peculiar way it uses the minor device number.  For
        !            59:  * all other drivers, the lower 5 bits describe the physical port--
        !            60:  * the upper 3 bits give attributes for the port.
        !            61:  */
        !            62: 
        !            63: #define PE_DRIVER 21   /* Major device number for the PE driver.  */
        !            64: #define PE_DEVMASK 0x3f        /* PE driver minor device mask.  */
        !            65: #define DEVMASK 0x1f   /* Minor device mask.  */
        !            66: 
        !            67: 
        !            68: /*
        !            69:  *  lockit(resource)  char *resource;
        !            70:  *
        !            71:  *  Lock the given resource--just like nlockit, but uses the current pid.
        !            72:  *  Returns (0) if already locked or error in locking.
        !            73:  *          (1) if all ok, resource locked.
        !            74:  */
        !            75: int
        !            76: lockit(resource)
        !            77: char *resource;
        !            78: {
        !            79:        return(nlockit(resource, getpid()));
        !            80: } /* lockit() */
        !            81: 
        !            82: /*
        !            83:  *  nlockit(resource, pid)  char *resource; int pid;
        !            84:  *
        !            85:  *  Lock the given resource.
        !            86:  *  Returns (0) if already locked or error in locking.
        !            87:  *          (1) if all ok, resource locked.
        !            88:  */
        !            89: int
        !            90: nlockit(resource, pid)
        !            91: char *resource;
        !            92: int pid;
        !            93: {
        !            94: 
        !            95:        int lockfd;
        !            96:        char lockfn[LOKFLEN];
        !            97:        char pidstring[PIDLEN];
        !            98: 
        !            99:        sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource);
        !           100:        if ( (access(lockfn, F_OK) == 0) ||
        !           101:             ((lockfd=creat(lockfn, 0644)) == -1) ) {
        !           102: #ifdef UUCP
        !           103:                printmsg(M_DEBUG, "Can't lock: %s", lockfn);
        !           104: #endif /* UUCP */
        !           105:                close(lockfd);
        !           106:                unlink(lockfn);
        !           107:                return(0);
        !           108:        }
        !           109: #ifdef UUCP
        !           110:        printmsg(M_DEBUG, "Just created lock: %s", lockfn);
        !           111: #endif /* UUCP */
        !           112:        sprintf(pidstring, "%d", pid);
        !           113:        if (-1 == write(lockfd, pidstring, strlen(pidstring))) {
        !           114:                close(lockfd);
        !           115:                unlink(lockfn);
        !           116:                return(0);
        !           117:        }
        !           118:        close(lockfd);
        !           119:        return(1);
        !           120: } /* nlockit() */
        !           121: /*
        !           122:  *  lockrm(resource)  char *resource;
        !           123:  *
        !           124:  *  Simply remove the lock on the given resource.
        !           125:  *  Returns (0) if not locked or error in unlocking.
        !           126:  *          (1) if all ok, resource lock removed.
        !           127:  *
        !           128:  *
        !           129:  * Open the lock file for read operations to try to read the pid
        !           130:  * stored in the file. If the open fails, abort. If the read fails, 
        !           131:  * abort. if the read pid does not match our pid, abort. We will only
        !           132:  * remove the lock if our pid matches the pid written to the file.
        !           133: */
        !           134: 
        !           135: lockrm(resource)
        !           136: char *resource;
        !           137: {
        !           138:        return(locknrm(resource, getpid()));
        !           139: } /* lockrm() */
        !           140: 
        !           141: 
        !           142: /*
        !           143:  *  locknrm(resource, pid)  char *resource;
        !           144:  *
        !           145:  *  Remove the lock on the given resource, using pid as the process id to
        !           146:  *  look for.
        !           147:  *
        !           148:  *  Returns (0) if not locked or error in unlocking.
        !           149:  *          (1) if all ok, resource lock removed.
        !           150:  *
        !           151:  *  Open the lock file for read operations to try to read the pid
        !           152:  *  stored in the file. If the open fails, abort. If the read fails, 
        !           153:  *  abort. If the read pid does not match our pid, abort. We will only
        !           154:  *  remove the lock if the passed matches the pid written to the file, or
        !           155:  *  if the passed pid is
        !           156:  */
        !           157: 
        !           158: locknrm(resource, pid)
        !           159: char *resource;
        !           160: int pid;
        !           161: {
        !           162:        int lockfd;     /* pointer to file to read */
        !           163:        int chars_read; /* Number of characters read().  */
        !           164: 
        !           165:        char gotpid[PIDLEN + 1];        /* String value of the pid that should be stored
        !           166:                                 * in the lock file pointed to by *lockfp.
        !           167:                                 */
        !           168:        char lockfn[LOKFLEN];
        !           169: 
        !           170:        if (resource == NULL) {
        !           171: #ifdef UUCP
        !           172:                plog(M_CALL, "Unlocking NULL resource.");
        !           173: #endif /* UUCP */
        !           174:                return(1);
        !           175:        }
        !           176: 
        !           177:        sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource);
        !           178: 
        !           179:        /* open the lock file for read, abort on failure */
        !           180:        if(-1 == (lockfd = (open(lockfn, 0)))){
        !           181: #ifdef UUCP
        !           182:                printmsg(M_DEBUG, "Error opening lock file for pid verify");
        !           183:                plog(M_CALL, "Error opening lock file for pid verify");
        !           184: #endif /* UUCP */
        !           185:                close(lockfd);
        !           186:                return(0);
        !           187:        }
        !           188: 
        !           189:        /* read the contents of the file. Abort if empty */
        !           190:        if ( -1 == (chars_read = read(lockfd, gotpid, PIDLEN))) {
        !           191: #ifdef UUCP
        !           192:                printmsg(M_DEBUG, "Lockrm: Error reading lock file for pid verify");
        !           193:                plog(M_CALL, "Lockrm: Error reading lock file for pid verify");
        !           194: #endif /* UUCP */
        !           195:                close(lockfd);
        !           196:                return(0);
        !           197:        }
        !           198: 
        !           199:        gotpid[chars_read] = '\0';      /* NUL terminate the string.  */
        !           200:        if (pid != 0 && atoi(gotpid) != pid){
        !           201: #ifdef UUCP
        !           202:                printmsg(M_DEBUG, "Lockrm: pid verify failed. pid read was %s.", 
        !           203:                        gotpid);
        !           204:                plog(M_CALL, "Lockrm: pid verify failed. pid read was %s", gotpid);
        !           205: #endif /* UUCP */
        !           206:                close(lockfd);
        !           207:                return(0);
        !           208:        }else{
        !           209: #ifdef UUCP
        !           210:                printmsg(M_DEBUG, "Lockrm: pid verify successful, removing lock.");
        !           211:                plog(M_CALL, "Lockrm: pid verify successful, removing lock.");
        !           212: #endif /* UUCP */
        !           213: 
        !           214:                if (unlink(lockfn) < 0) {
        !           215: #ifdef UUCP
        !           216:                        printmsg(M_DEBUG, "Lockrm: Error unlocking: %s", lockfn);
        !           217:                        plog(M_CALL, "Lockrm: Error unlocking: %s", lockfn);
        !           218: #endif /* UUCP */
        !           219:                        close(lockfd);
        !           220:                        return(0);
        !           221:                }
        !           222: #ifdef UUCP
        !           223:                printmsg(M_DEBUG, "Just unlocked: %s", lockfn);
        !           224: #endif /* UUCP */
        !           225:                close(lockfd);
        !           226:                return(1);
        !           227:        }
        !           228: #ifdef UUCP
        !           229:        plog(M_CALL, "Unreachable code in locknrm().");
        !           230: #endif /* UUCP */
        !           231: } /* locknrm() */
        !           232: 
        !           233: /*
        !           234:  *  lockexist(resource)  char *resource;
        !           235:  *
        !           236:  *  Test for existance of a lock on the given resource.
        !           237:  *
        !           238:  *  Returns:  (1)  Resource is locked.
        !           239:  *           (0)  Resource is not locked.
        !           240:  */
        !           241: 
        !           242: lockexist(resource)
        !           243: char   *resource;
        !           244: {
        !           245:        char lockfn[LOKFLEN];
        !           246: 
        !           247:        if ( resource == NULL )
        !           248:                return(0);
        !           249:        sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource);
        !           250: 
        !           251:        return (!access(lockfn, F_OK));
        !           252: } /* lockexist() */
        !           253: 
        !           254: 
        !           255: /*
        !           256:  * Attempt to lock a tty device.  Takes the name of the tty itself
        !           257:  * otherwise behaves like lockit().
        !           258:  */
        !           259: locktty(ttyname)
        !           260:        char *ttyname;
        !           261: {
        !           262:        return(lockntty(ttyname, getpid()));
        !           263: } /* locktty() */
        !           264: 
        !           265: /*
        !           266:  * Attempt to lock a tty device.  Takes the name of the tty itself and
        !           267:  * a pid, otherwise behaves like nlockit().
        !           268:  */
        !           269: lockntty(ttyname, pid)
        !           270: char *ttyname;
        !           271: int pid;
        !           272: {
        !           273:        char resource[LOKFLEN];
        !           274:        char filename[LOKFLEN];
        !           275: 
        !           276:        sprintf(filename, "/dev/%s", ttyname);
        !           277:        if (NULL == gen_res_name(filename, resource)){
        !           278:                return(0);
        !           279:        }
        !           280:        return(nlockit(resource, pid));
        !           281: 
        !           282: } /* lockntty() */
        !           283: 
        !           284: /*
        !           285:  * Unlock a tty device.  Takes the name of the tty itself,
        !           286:  * otherwise behaves like lockrm().
        !           287:  */
        !           288: unlocktty(ttyname)
        !           289: char *ttyname;
        !           290: {
        !           291:        return(unlockntty(ttyname, getpid()));
        !           292: } /* unlocktty() */
        !           293: 
        !           294: /*
        !           295:  * Unlock a tty device.  Takes the name of the tty itself,
        !           296:  * otherwise behaves like locknrm().
        !           297:  */
        !           298: unlockntty(ttyname, pid)
        !           299:        char *ttyname;
        !           300:        int pid;
        !           301: {
        !           302:        char resource[LOKFLEN];
        !           303:        char filename[LOKFLEN];
        !           304: 
        !           305:        sprintf(filename, "/dev/%s", ttyname);
        !           306:        if (NULL == gen_res_name(filename, resource)){
        !           307: #ifdef UUCP
        !           308:                plog(M_CALL, "Can't generate resource for %s.", ttyname);
        !           309: #endif /* UUCP */
        !           310:                return(0);
        !           311:        }
        !           312:        return(locknrm(resource, pid));
        !           313: } /* unlockntty() */
        !           314: 
        !           315: /*
        !           316:  *  lockttyexist(ttyname)  char *ttyname;
        !           317:  *
        !           318:  *  Test for existance of a lock on the given tty.
        !           319:  *
        !           320:  *  Returns:  (1)  Resource is locked.
        !           321:  *           (0)  Resource is not locked.
        !           322:  */
        !           323: lockttyexist(ttyname)
        !           324: char *ttyname;
        !           325: {
        !           326:        char resource[LOKFLEN];
        !           327:        char filename[LOKFLEN];
        !           328: 
        !           329:        sprintf(filename, "/dev/%s", ttyname);
        !           330:        if (NULL == gen_res_name(filename, resource)){
        !           331:                return(0);      /* Non-existent tty can not be locked :-) */
        !           332:        }
        !           333: 
        !           334:        return(lockexist(resource));
        !           335: } /* lockttyexist() */
        !           336: 
        !           337: /*
        !           338:  * Generates a resource name for locking, based on the major number
        !           339:  * and the lower 4 bits of the minor number of the tty device.
        !           340:  *
        !           341:  * Builds the name in buff as two "." separated decimal numbers.
        !           342:  * Returns NULL on failure, buff on success.
        !           343:  */
        !           344: static char *
        !           345: gen_res_name(path, buff)
        !           346: char *path;
        !           347: char *buff;
        !           348: {
        !           349:        struct stat sbuf;
        !           350:        int status;
        !           351:        
        !           352:        if (0 != (status = stat(path, &sbuf))) {
        !           353:                /* Can't stat the file.  */
        !           354:                return (NULL);
        !           355:        }
        !           356: 
        !           357:        if (PE_DRIVER == major(sbuf.st_rdev)) {
        !           358:                sprintf(buff, "%d.%d", major(sbuf.st_rdev),
        !           359:                                       PE_DEVMASK & minor(sbuf.st_rdev));
        !           360:        } else {
        !           361:                sprintf(buff, "%d.%d", major(sbuf.st_rdev),
        !           362:                                       DEVMASK & minor(sbuf.st_rdev));
        !           363:        }
        !           364: 
        !           365:        return(buff);
        !           366: } /* gen_res_name */
        !           367: 
        !           368: 
        !           369: #ifdef PGM
        !           370: static char _version[]="lock version 1.0";
        !           371: /*
        !           372:  * executable file to lock and unlock uucp resources.
        !           373:  * must be owned by uucp and setuid.
        !           374:  */
        !           375: main(argc, argv)
        !           376: int argc;
        !           377: char *argv[];
        !           378: {
        !           379:        int c, rc;
        !           380:        extern char *optarg;
        !           381:        extern int optind;
        !           382:        static char umsg[] = "lock [-l dev][-u dev][-t dev]";
        !           383: 
        !           384:        for (rc = 0; EOF != (c = getopt(argc, argv, "l:u:t:"));) {
        !           385:                if (NULL == optarg || !*optarg)
        !           386:                        usage(umsg);
        !           387:                /*
        !           388:                 * Strip off a possible leading "/dev/".
        !           389:                 */
        !           390:                if (0 == strncmp(optarg, "/dev/", strlen("/dev/") )) {
        !           391:                        optarg += strlen("/dev/");
        !           392:                }
        !           393: 
        !           394:                switch (c) {
        !           395:                case 'l':
        !           396:                        if (0 == lockntty(optarg, 0)) {
        !           397:                                fprintf(stderr, "%s locked\n", optarg);
        !           398:                                rc |= 1;
        !           399:                        }
        !           400:                        break;
        !           401:                case 'u':
        !           402:                        unlockntty(optarg, 0);
        !           403:                        break;
        !           404:                case 't':
        !           405:                        rc |= lockttyexist(optarg);
        !           406:                        break;
        !           407:                default:
        !           408:                        usage(umsg);
        !           409:                }
        !           410:        }
        !           411:        if (optind < argc)
        !           412:                usage(umsg);
        !           413:        exit(rc);
        !           414: }
        !           415: #endif
        !           416: 
        !           417: #ifdef TEST
        !           418: #include <stdio.h>
        !           419: #define LOCKSIG 9      /* Significant Chars of Lockable Resources.  */
        !           420: main(argc, argv)
        !           421: int argc;
        !           422: char *argv[];
        !           423: {
        !           424:        char buffer[LOCKSIG + 1];
        !           425:        char path[LOKFLEN];
        !           426: 
        !           427:        if (argc != 2) {
        !           428:                fprintf(stderr, "Usage: %s ttyname\n", argv[0]);
        !           429:                exit(1);
        !           430:        }
        !           431: 
        !           432:        sprintf(path, "/dev/%s", argv[1]);
        !           433: 
        !           434:        if (NULL == gen_res_name(path, buffer)) {
        !           435:                fprintf(stderr, "%s: Can't stat %s.\n", argv[0], argv[1]);
        !           436:                exit(1);
        !           437:        }
        !           438: 
        !           439:        printf("Resource to lock: %s\n", buffer);
        !           440: 
        !           441:        if (-1 == locktty(argv[1])) {
        !           442:                fprintf(stderr, "%s: Can't lock %s.\n", argv[0], argv[1]);
        !           443:                exit(1);
        !           444:        }
        !           445: 
        !           446:        printf("I think I've locked %s.\n", argv[1]);
        !           447: 
        !           448:        if (lockttyexist(argv[1])) {
        !           449:                printf("Yep, %s is locked.\n", argv[1]);
        !           450:        } else {
        !           451:                fprintf(stderr, "%s: Failed to lock %s.\n", argv[0], argv[1]);
        !           452:                exit(1);
        !           453:        }
        !           454: 
        !           455: 
        !           456:        sprintf(path, "cat /usr/spool/uucp/LCK..%s", buffer);
        !           457:        printf("Contents of lock file: ");
        !           458:        fflush(stdout);
        !           459:        system(path);
        !           460:        printf("\n");
        !           461: 
        !           462:        if (-1 == unlocktty(argv[1])) {
        !           463:                fprintf(stderr, "%s: Problem removing lock on %s.\n", argv[0], argv[1]);
        !           464:                exit(1);
        !           465:        }
        !           466: 
        !           467:        printf("I think I've unlocked %s.\n", argv[1]);
        !           468: 
        !           469:        if (lockttyexist(argv[1])) {
        !           470:                fprintf(stderr, "%s: Failed to unlock %s.\n", argv[0], argv[1]);
        !           471:                exit(1);
        !           472:        } else {
        !           473:                printf("Successfully unlocked %s.\n", argv[1]);
        !           474:        }
        !           475:        
        !           476:        exit(0);
        !           477: }
        !           478: #endif /* TEST */

unix.superglobalmegacorp.com

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