|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.