|
|
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: */ ! 109: ! 110: locknrm(resource, pid) ! 111: char *resource; ! 112: int pid; ! 113: { ! 114: int lockfd; /* pointer to file to read */ ! 115: int chars_read; /* Number of characters read(). */ ! 116: ! 117: char gotpid[PIDLEN + 1]; /* String value of the PID that should be stored ! 118: * in the lock file pointed to by *lockfp. ! 119: */ ! 120: char lockfn[LOKFLEN]; ! 121: ! 122: if ( resource == NULL ) { ! 123: #ifdef UUCP ! 124: plog(M_CALL, "Unlocking NULL resource."); ! 125: #endif /* UUCP */ ! 126: return( 0 ); ! 127: } ! 128: ! 129: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource); ! 130: ! 131: /* open the lock file for read, abort on failure */ ! 132: if(-1 == (lockfd = (open(lockfn, 0)))){ ! 133: #ifdef UUCP ! 134: printmsg(M_DEBUG, "Error opening lock file for PID verify"); ! 135: plog(M_CALL, "Error opening lock file for PID verify"); ! 136: #endif /* UUCP */ ! 137: close(lockfd); ! 138: return(-1); ! 139: } ! 140: ! 141: /* read the contents of the file. Abort if empty */ ! 142: if ( -1 == (chars_read = read(lockfd, gotpid, PIDLEN))) { ! 143: #ifdef UUCP ! 144: printmsg(M_DEBUG, "Lockrm: Error reading lock file for PID verify"); ! 145: plog(M_CALL, "Lockrm: Error reading lock file for PID verify"); ! 146: #endif /* UUCP */ ! 147: close(lockfd); ! 148: return(-1); ! 149: } ! 150: ! 151: gotpid[chars_read] = '\0'; /* NUL terminate the string. */ ! 152: if (atoi(gotpid) != pid){ ! 153: #ifdef UUCP ! 154: printmsg(M_DEBUG, "Lockrm: PID verify failed. PID read was %s.", ! 155: gotpid); ! 156: plog(M_CALL, "Lockrm: PID verify failed. PID read was %s", gotpid); ! 157: #endif /* UUCP */ ! 158: close(lockfd); ! 159: return(-1); ! 160: }else{ ! 161: #ifdef UUCP ! 162: printmsg(M_DEBUG, "Lockrm: PID verify successful, removing lock."); ! 163: plog(M_CALL, "Lockrm: PID verify successful, removing lock."); ! 164: #endif /* UUCP */ ! 165: ! 166: if ( unlink(lockfn) < 0 ) { ! 167: #ifdef UUCP ! 168: printmsg(M_DEBUG, "Lockrm: Error unlocking: %s", lockfn); ! 169: plog(M_CALL, "Lockrm: Error unlocking: %s", lockfn); ! 170: #endif /* UUCP */ ! 171: close(lockfd); ! 172: return( -1 ); ! 173: } ! 174: #ifdef UUCP ! 175: printmsg(M_DEBUG, "Just unlocked: %s", lockfn); ! 176: #endif /* UUCP */ ! 177: close(lockfd); ! 178: return( 0 ); ! 179: } ! 180: #ifdef UUCP ! 181: plog(M_CALL, "Unreachable code in locknrm()."); ! 182: #endif /* UUCP */ ! 183: } ! 184: ! 185: /* ! 186: * lockexist(resource) char *resource; ! 187: * ! 188: * Test for existance of a lock on the given resource. ! 189: * ! 190: * Returns: (1) Resource is locked. ! 191: * (0) Resource is not locked. ! 192: */ ! 193: ! 194: lockexist(resource) ! 195: char *resource; ! 196: { ! 197: char lockfn[LOKFLEN]; ! 198: ! 199: if ( resource == NULL ) ! 200: return(0); ! 201: sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource); ! 202: ! 203: return (!access(lockfn, AEXISTS)); ! 204: } ! 205: ! 206: ! 207: /* ! 208: * Attempt to lock a tty device. Takes the name of the tty itself, ! 209: * otherwise behaves like lockit(). ! 210: */ ! 211: locktty(ttyname) ! 212: { ! 213: char resource[LOKFLEN]; ! 214: char filename[LOKFLEN]; ! 215: ! 216: sprintf(filename, "/dev/%s", ttyname); ! 217: if (NULL == gen_res_name(filename, resource)){ ! 218: return(-1); ! 219: } ! 220: return(lockit(resource)); ! 221: ! 222: } /* locktty() */ ! 223: ! 224: /* ! 225: * Unlock a tty device. Takes the name of the tty itself, ! 226: * otherwise behaves like lockrm(). ! 227: */ ! 228: unlocktty(ttyname) ! 229: char *ttyname; ! 230: { ! 231: return(unlockntty(ttyname, getpid())); ! 232: } /* unlocktty() */ ! 233: ! 234: /* ! 235: * Unlock a tty device. Takes the name of the tty itself, ! 236: * otherwise behaves like locknrm(). ! 237: */ ! 238: unlockntty(ttyname, pid) ! 239: char *ttyname; ! 240: int pid; ! 241: { ! 242: char resource[LOKFLEN]; ! 243: char filename[LOKFLEN]; ! 244: ! 245: sprintf(filename, "/dev/%s", ttyname); ! 246: if (NULL == gen_res_name(filename, resource)){ ! 247: #ifdef UUCP ! 248: plog(M_CALL, "Can't generate resource for %s.", ttyname); ! 249: #endif /* UUCP */ ! 250: return(-1); ! 251: } ! 252: return(locknrm(resource, pid)); ! 253: } /* unlockntty() */ ! 254: ! 255: /* ! 256: * Attempt to lock a tty device. Takes the name of the tty itself, ! 257: * otherwise behaves like lockit(). ! 258: */ ! 259: lockttyexist(ttyname) ! 260: { ! 261: char resource[LOKFLEN]; ! 262: char filename[LOKFLEN]; ! 263: ! 264: sprintf(filename, "/dev/%s", ttyname); ! 265: if (NULL == gen_res_name(filename, resource)){ ! 266: return(0); /* Non-existent tty can not be locked :-) */ ! 267: } ! 268: ! 269: return(lockexist(resource)); ! 270: } /* lockttyexist() */ ! 271: ! 272: /* ! 273: * Generates a resource name for locking, based on the major number ! 274: * and the lower 4 bits of the minor number of the tty device. ! 275: * ! 276: * Builds the name in buff as two "." separated decimal numbers. ! 277: * Returns NULL on failure, buff on success. ! 278: */ ! 279: char * ! 280: gen_res_name(path, buff) ! 281: char *path; ! 282: char *buff; ! 283: { ! 284: struct stat sbuf; ! 285: int status; ! 286: ! 287: if (0 != (status = stat(path, &sbuf))) { ! 288: /* Can't stat the file. */ ! 289: return (NULL); ! 290: } ! 291: ! 292: if (PE_DRIVER == major(sbuf.st_rdev)) { ! 293: sprintf(buff, "%d.%d", major(sbuf.st_rdev), ! 294: PE_DEVMASK & minor(sbuf.st_rdev)); ! 295: } else { ! 296: sprintf(buff, "%d.%d", major(sbuf.st_rdev), ! 297: DEVMASK & minor(sbuf.st_rdev)); ! 298: } ! 299: ! 300: return(buff); ! 301: } /* gen_res_name */ ! 302: ! 303: #ifdef TEST ! 304: #include <stdio.h> ! 305: ! 306: #define LOCKSIG 9 /* Significant Chars of Lockable Resources. */ ! 307: ! 308: main(argc, argv) ! 309: int argc; ! 310: char *argv[]; ! 311: { ! 312: char buffer[LOCKSIG + 1]; ! 313: char path[LOKFLEN]; ! 314: ! 315: if (argc != 2) { ! 316: fprintf(stderr, "Usage: %s ttyname\n", argv[0]); ! 317: exit(1); ! 318: } ! 319: ! 320: sprintf(path, "/dev/%s", argv[1]); ! 321: ! 322: if (NULL == gen_res_name(path, buffer)) { ! 323: fprintf(stderr, "%s: Can't stat %s.\n", argv[0], argv[1]); ! 324: exit(1); ! 325: } ! 326: ! 327: printf("Resource to lock: %s\n", buffer); ! 328: ! 329: if (-1 == locktty(argv[1])) { ! 330: fprintf(stderr, "%s: Can't lock %s.\n", argv[0], argv[1]); ! 331: exit(1); ! 332: } ! 333: ! 334: printf("I think I've locked %s.\n", argv[1]); ! 335: ! 336: if (lockttyexist(argv[1])) { ! 337: printf("Yep, %s is locked.\n", argv[1]); ! 338: } else { ! 339: fprintf(stderr, "%s: Failed to lock %s.\n", argv[0], argv[1]); ! 340: exit(1); ! 341: } ! 342: ! 343: ! 344: sprintf(path, "cat /usr/spool/uucp/LCK..%s", buffer); ! 345: printf("Contents of lock file: "); ! 346: fflush(stdout); ! 347: system(path); ! 348: printf("\n"); ! 349: ! 350: if (-1 == unlocktty(argv[1])) { ! 351: fprintf(stderr, "%s: Problem removing lock on %s.\n", argv[0], argv[1]); ! 352: exit(1); ! 353: } ! 354: ! 355: printf("I think I've unlocked %s.\n", argv[1]); ! 356: ! 357: if (lockttyexist(argv[1])) { ! 358: fprintf(stderr, "%s: Failed to unlock %s.\n", argv[0], argv[1]); ! 359: exit(1); ! 360: } else { ! 361: printf("Successfully unlocked %s.\n", argv[1]); ! 362: } ! 363: ! 364: ! 365: exit(0); ! 366: } ! 367: #endif /* TEST */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.