|
|
1.1 ! root 1: /* ! 2: * lock.c ! 3: * ! 4: * Provide a locking mechanism for UUCP ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <access.h> ! 9: #include <sys/stat.h> ! 10: ! 11: char *gen_res_name(); ! 12: ! 13: #ifdef UUCP ! 14: #include "dcp.h" ! 15: #else ! 16: #define SPOOLDIR "/usr/spool/uucp" ! 17: #define LOCKSIG 9 /* Significant Chars of Lockable Resources. */ ! 18: #define LOKFLEN 64 /* Max Length of UUCP Lock File Name. */ ! 19: #endif /* UUCP */ ! 20: ! 21: #define LOCKDIR SPOOLDIR ! 22: #define LOCKPRE "LCK.." ! 23: #define PIDLEN 6 /* Maximum length of string representing a PID. */ ! 24: ! 25: /* There is a special version of DEVMASK for the PE multiport driver ! 26: * because of the peculiar way it uses the minor device number. For ! 27: * all other drivers, the lower 5 bits describe the physical port-- ! 28: * the upper 3 bits give attributes for the port. ! 29: */ ! 30: ! 31: #define PE_DRIVER 21 /* Major device number for the PE driver. */ ! 32: #define PE_DEVMASK 0x3f /* PE driver minor device mask. */ ! 33: #define DEVMASK 0x1f /* Minor device mask. */ ! 34: ! 35: ! 36: /* ! 37: * lockit(resource) char *resource; ! 38: * ! 39: * Lock the given resource. ! 40: * Returns (-1) if already locked or error in locking. ! 41: * ( 0) if all ok, resource locked. ! 42: */ ! 43: ! 44: lockit(resource) ! 45: char *resource; ! 46: { ! 47: ! 48: int lockfd; ! 49: char lockfn[LOKFLEN]; ! 50: char pidstring[PIDLEN]; ! 51: ! 52: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource); ! 53: if ( (access(lockfn, AEXISTS) == 0) || ! 54: ((lockfd=creat(lockfn, 0644)) == -1) ) { ! 55: #ifdef UUCP ! 56: printmsg(M_DEBUG, "Can't lock: %s", lockfn); ! 57: #endif /* UUCP */ ! 58: return( -1 ); ! 59: } ! 60: #ifdef UUCP ! 61: printmsg(M_DEBUG, "Just created lock: %s", lockfn); ! 62: #endif /* UUCP */ ! 63: sprintf(pidstring, "%d", getpid()); ! 64: if(-1 == write(lockfd, pidstring, strlen(pidstring))){ ! 65: close(lockfd); ! 66: unlink(lockfn); ! 67: return(-1); ! 68: } ! 69: ! 70: close(lockfd); ! 71: return( 0 ); ! 72: } ! 73: ! 74: /* ! 75: * lockrm(resource) char *resource; ! 76: * ! 77: * Simply remove the lock on the given resource. ! 78: * Returns (-1) if not locked or error in unlocking. ! 79: * ( 0) if all ok, resource lock removed. ! 80: * ! 81: * ! 82: * Open the lock file for read operations to try to read the PID ! 83: * stored in the file. If the open fails, abort. If the read fails, ! 84: * abort. If the read PID does not match our PID, abort. We will only ! 85: * remove the lock if our PID matches the PID written to the file. ! 86: */ ! 87: ! 88: lockrm(resource) ! 89: char *resource; ! 90: { ! 91: return(locknrm(resource, getpid())); ! 92: } ! 93: ! 94: ! 95: /* ! 96: * locknrm(resource, pid) char *resource; ! 97: * ! 98: * Remove the lock on the given resource, using pid as the process id to ! 99: * look for. ! 100: * ! 101: * Returns (-1) if not locked or error in unlocking. ! 102: * ( 0) if all ok, resource lock removed. ! 103: * ! 104: * Open the lock file for read operations to try to read the PID ! 105: * stored in the file. If the open fails, abort. If the read fails, ! 106: * abort. If the read PID does not match our PID, abort. We will only ! 107: * remove the lock if the passed matches the PID written to the file, ! 108: * or if the pid we are passed was 0. ! 109: * ! 110: */ ! 111: ! 112: locknrm(resource, pid) ! 113: char *resource; ! 114: int pid; ! 115: { ! 116: int lockfd; /* pointer to file to read */ ! 117: int chars_read; /* Number of characters read(). */ ! 118: ! 119: char gotpid[PIDLEN + 1]; /* String value of the PID that should be stored ! 120: * in the lock file pointed to by *lockfp. ! 121: */ ! 122: char lockfn[LOKFLEN]; ! 123: ! 124: if ( resource == NULL ) { ! 125: #ifdef UUCP ! 126: plog(M_CALL, "Unlocking NULL resource."); ! 127: #endif /* UUCP */ ! 128: return( 0 ); ! 129: } ! 130: ! 131: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource); ! 132: ! 133: /* open the lock file for read, abort on failure */ ! 134: if(-1 == (lockfd = (open(lockfn, 0)))){ ! 135: #ifdef UUCP ! 136: printmsg(M_DEBUG, "Error opening lock file for PID verify"); ! 137: plog(M_CALL, "Error opening lock file for PID verify"); ! 138: #endif /* UUCP */ ! 139: close(lockfd); ! 140: return(-1); ! 141: } ! 142: ! 143: /* read the contents of the file. Abort if empty */ ! 144: if ( -1 == (chars_read = read(lockfd, gotpid, PIDLEN))) { ! 145: #ifdef UUCP ! 146: printmsg(M_DEBUG, "Lockrm: Error reading lock file for PID verify"); ! 147: plog(M_CALL, "Lockrm: Error reading lock file for PID verify"); ! 148: #endif /* UUCP */ ! 149: close(lockfd); ! 150: return(-1); ! 151: } ! 152: ! 153: gotpid[chars_read] = '\0'; /* NUL terminate the string. */ ! 154: if ( (0 != pid) && (atoi(gotpid) != pid) ){ ! 155: #ifdef UUCP ! 156: printmsg(M_DEBUG, "Lockrm: PID verify failed. PID read was %s.", ! 157: gotpid); ! 158: plog(M_CALL, "Lockrm: PID verify failed. PID read was %s", gotpid); ! 159: #endif /* UUCP */ ! 160: close(lockfd); ! 161: return(-1); ! 162: } else { ! 163: #ifdef UUCP ! 164: printmsg(M_DEBUG, "Lockrm: PID verify successful, removing lock."); ! 165: plog(M_CALL, "Lockrm: PID verify successful, removing lock."); ! 166: #endif /* UUCP */ ! 167: ! 168: if ( unlink(lockfn) < 0 ) { ! 169: #ifdef UUCP ! 170: printmsg(M_DEBUG, "Lockrm: Error unlocking: %s", lockfn); ! 171: plog(M_CALL, "Lockrm: Error unlocking: %s", lockfn); ! 172: #endif /* UUCP */ ! 173: close(lockfd); ! 174: return( -1 ); ! 175: } ! 176: #ifdef UUCP ! 177: printmsg(M_DEBUG, "Just unlocked: %s", lockfn); ! 178: #endif /* UUCP */ ! 179: close(lockfd); ! 180: return( 0 ); ! 181: } ! 182: #ifdef UUCP ! 183: plog(M_CALL, "Unreachable code in locknrm()."); ! 184: #endif /* UUCP */ ! 185: } ! 186: ! 187: /* ! 188: * lockexist(resource) char *resource; ! 189: * ! 190: * Test for existance of a lock on the given resource. ! 191: * ! 192: * Returns: (1) Resource is locked. ! 193: * (0) Resource is not locked. ! 194: */ ! 195: ! 196: lockexist(resource) ! 197: char *resource; ! 198: { ! 199: char lockfn[LOKFLEN]; ! 200: ! 201: if ( resource == NULL ) ! 202: return(0); ! 203: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource); ! 204: ! 205: return (!access(lockfn, AEXISTS)); ! 206: } ! 207: ! 208: ! 209: /* ! 210: * Attempt to lock a tty device. Takes the name of the tty itself, ! 211: * otherwise behaves like lockit(). ! 212: */ ! 213: locktty(ttyname) ! 214: { ! 215: char resource[LOKFLEN]; ! 216: char filename[LOKFLEN]; ! 217: ! 218: sprintf(filename, "/dev/%s", ttyname); ! 219: if (NULL == gen_res_name(filename, resource)){ ! 220: return(-1); ! 221: } ! 222: return(lockit(resource)); ! 223: ! 224: } /* locktty() */ ! 225: ! 226: /* ! 227: * Unlock a tty device. Takes the name of the tty itself, ! 228: * otherwise behaves like lockrm(). ! 229: */ ! 230: unlocktty(ttyname) ! 231: char *ttyname; ! 232: { ! 233: return(unlockntty(ttyname, getpid())); ! 234: } /* unlocktty() */ ! 235: ! 236: /* ! 237: * Unlock a tty device. Takes the name of the tty itself, ! 238: * otherwise behaves like locknrm(). ! 239: */ ! 240: unlockntty(ttyname, pid) ! 241: char *ttyname; ! 242: int pid; ! 243: { ! 244: char resource[LOKFLEN]; ! 245: char filename[LOKFLEN]; ! 246: ! 247: sprintf(filename, "/dev/%s", ttyname); ! 248: if (NULL == gen_res_name(filename, resource)){ ! 249: #ifdef UUCP ! 250: plog(M_CALL, "Can't generate resource for %s.", ttyname); ! 251: #endif /* UUCP */ ! 252: return(-1); ! 253: } ! 254: return(locknrm(resource, pid)); ! 255: } /* unlockntty() */ ! 256: ! 257: /* ! 258: * Attempt to lock a tty device. Takes the name of the tty itself, ! 259: * otherwise behaves like lockit(). ! 260: */ ! 261: lockttyexist(ttyname) ! 262: { ! 263: char resource[LOKFLEN]; ! 264: char filename[LOKFLEN]; ! 265: ! 266: sprintf(filename, "/dev/%s", ttyname); ! 267: if (NULL == gen_res_name(filename, resource)){ ! 268: return(0); /* Non-existent tty can not be locked :-) */ ! 269: } ! 270: ! 271: return(lockexist(resource)); ! 272: } /* lockttyexist() */ ! 273: ! 274: /* ! 275: * Generates a resource name for locking, based on the major number ! 276: * and the lower 4 bits of the minor number of the tty device. ! 277: * ! 278: * Builds the name in buff as two "." separated decimal numbers. ! 279: * Returns NULL on failure, buff on success. ! 280: */ ! 281: char * ! 282: gen_res_name(path, buff) ! 283: char *path; ! 284: char *buff; ! 285: { ! 286: struct stat sbuf; ! 287: int status; ! 288: ! 289: if (0 != (status = stat(path, &sbuf))) { ! 290: /* Can't stat the file. */ ! 291: return (NULL); ! 292: } ! 293: ! 294: if (PE_DRIVER == major(sbuf.st_rdev)) { ! 295: sprintf(buff, "%d.%d", major(sbuf.st_rdev), ! 296: PE_DEVMASK & minor(sbuf.st_rdev)); ! 297: } else { ! 298: sprintf(buff, "%d.%d", major(sbuf.st_rdev), ! 299: DEVMASK & minor(sbuf.st_rdev)); ! 300: } ! 301: ! 302: return(buff); ! 303: } /* gen_res_name */ ! 304: ! 305: #ifdef TEST ! 306: #include <stdio.h> ! 307: ! 308: #define LOCKSIG 9 /* Significant Chars of Lockable Resources. */ ! 309: ! 310: main(argc, argv) ! 311: int argc; ! 312: char *argv[]; ! 313: { ! 314: char buffer[LOCKSIG + 1]; ! 315: char path[LOKFLEN]; ! 316: ! 317: if (argc != 2) { ! 318: fprintf(stderr, "Usage: %s ttyname\n", argv[0]); ! 319: exit(1); ! 320: } ! 321: ! 322: sprintf(path, "/dev/%s", argv[1]); ! 323: ! 324: if (NULL == gen_res_name(path, buffer)) { ! 325: fprintf(stderr, "%s: Can't stat %s.\n", argv[0], argv[1]); ! 326: exit(1); ! 327: } ! 328: ! 329: printf("Resource to lock: %s\n", buffer); ! 330: ! 331: if (-1 == locktty(argv[1])) { ! 332: fprintf(stderr, "%s: Can't lock %s.\n", argv[0], argv[1]); ! 333: exit(1); ! 334: } ! 335: ! 336: printf("I think I've locked %s.\n", argv[1]); ! 337: ! 338: if (lockttyexist(argv[1])) { ! 339: printf("Yep, %s is locked.\n", argv[1]); ! 340: } else { ! 341: fprintf(stderr, "%s: Failed to lock %s.\n", argv[0], argv[1]); ! 342: exit(1); ! 343: } ! 344: ! 345: ! 346: sprintf(path, "cat /usr/spool/uucp/LCK..%s", buffer); ! 347: printf("Contents of lock file: "); ! 348: fflush(stdout); ! 349: system(path); ! 350: printf("\n"); ! 351: ! 352: if (-1 == unlocktty(argv[1])) { ! 353: fprintf(stderr, "%s: Problem removing lock on %s.\n", argv[0], argv[1]); ! 354: exit(1); ! 355: } ! 356: ! 357: printf("I think I've unlocked %s.\n", argv[1]); ! 358: ! 359: if (lockttyexist(argv[1])) { ! 360: fprintf(stderr, "%s: Failed to unlock %s.\n", argv[0], argv[1]); ! 361: exit(1); ! 362: } else { ! 363: printf("Successfully unlocked %s.\n", argv[1]); ! 364: } ! 365: ! 366: ! 367: exit(0); ! 368: } ! 369: #endif /* TEST */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.