Annotation of coherent/g/usr/lib/misc/lock.c, revision 1.1.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.