1: #ifndef lint 2: static char sccsid[] = "@(#)ulockf.c 5.5 (Berkeley) 10/9/85"; 3: #endif 4: 5: #include "uucp.h" 6: #include <sys/stat.h> 7: #include <errno.h> 8: 9: #define LCKMODE 0444 /* File mode for lock files */ 10: #define MAXLOCKS 16 /* Maximum number of lock files */ 11: 12: char *Lockfile[MAXLOCKS]; 13: char *LockDirectory = LOCKDIR; 14: int Nlocks = 0; 15: 16: /*LINTLIBRARY*/ 17: 18: /* 19: * This routine will attempt to create a lock file (file). 20: * It makes sure that the lock file is valid if it already exists. 21: * 22: * return codes: SUCCESS | FAIL 23: */ 24: ulockf(hfile, atime) 25: char *hfile; 26: time_t atime; 27: { 28: register char *p; 29: register int i; 30: static char tempfile[NAMESIZE]; 31: char file[NAMESIZE]; 32: static int pid = -1; 33: extern int errno; 34: 35: if (pid < 0) { 36: pid = getpid(); 37: sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid); 38: } 39: sprintf(file, "%s/LCK..%s", LockDirectory, hfile); 40: i = 0; 41: while (onelock(pid, tempfile, file) == -1) { /* lock file exists */ 42: #if !defined(BSD4_2) && !defined(USG) 43: struct stat stbuf; 44: time_t ptime; 45: /* get status to check age of the lock file */ 46: if (stat(file, &stbuf) == 0) { 47: (void) time(&ptime); 48: if ((ptime - stbuf.st_ctime) < atime) 49: return FAIL; /* file not old enough to delete */ 50: } 51: #else BSD4_2 || USG 52: register int fd; 53: fd = open(file, 0); 54: if (fd >= 0) { 55: int upid, ret; 56: ret = read(fd, &upid, sizeof upid); 57: close(fd); 58: if (ret == sizeof upid && (kill(upid, 0) == 0 59: || errno != ESRCH)) 60: return FAIL; /* process is still running */ 61: } 62: #endif BSD4_2 || USG 63: assert("DEAD LOCK", file, errno); 64: logent(file, "DEAD LOCK"); 65: (void) unlink(file); 66: sleep(5); /* avoid a possible race */ 67: ASSERT(i++ < 5, "CAN'T GET LOCKFILE", tempfile, errno); 68: } 69: 70: for (i = 0; i < Nlocks; i++) { 71: if (Lockfile[i] == NULL) 72: break; 73: } 74: ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i); 75: if (i >= Nlocks) 76: i = Nlocks++; 77: p = malloc((unsigned)(strlen(file)+1)); 78: ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", file, 0); 79: strcpy(p, file); 80: Lockfile[i] = p; 81: 82: return SUCCESS; 83: } 84: 85: /* 86: * remove all lock files in list or name 87: */ 88: rmlock(name) 89: register char *name; 90: { 91: register int i; 92: char file[MAXFULLNAME]; 93: 94: if (name != NULL) { 95: sprintf(file, "%s/LCK..%s", LockDirectory, name); 96: name = file; 97: } 98: for (i = 0; i < Nlocks; i++) { 99: if (Lockfile[i] == NULL) 100: continue; 101: if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 102: unlink(Lockfile[i]); 103: free(Lockfile[i]); 104: Lockfile[i] = NULL; 105: } 106: } 107: } 108: 109: /* 110: * makes lock a name on behalf of pid. Tempfile must be in the same 111: * file system as name. 112: */ 113: onelock(pid, tempfile, name) 114: int pid; 115: char *tempfile, *name; 116: { 117: register int fd, ret; 118: #ifdef VMS 119: fd = creat(name, LCKMODE, "1version"); 120: #else !VMS 121: fd = creat(tempfile, LCKMODE); 122: #endif !VMS 123: if (fd < 0) { 124: DEBUG(1,"Can't creat temp file %s ", tempfile); 125: DEBUG(1,"-- errno %d", errno); 126: return FAIL; 127: } 128: ret = write(fd, (char *)&pid, sizeof(int)); 129: (void) close(fd); 130: 131: if (ret != sizeof(int)) { 132: DEBUG(1,"Temp file write failed -- errno %d\n", errno); 133: #ifdef VMS 134: (void) unlink(name); 135: #else !VMS 136: (void) unlink(tempfile); 137: #endif !VMS 138: return FAIL; 139: } 140: #ifndef VMS 141: if (link(tempfile, name) < 0) { 142: (void) unlink(tempfile); 143: return FAIL; 144: } 145: unlink(tempfile); 146: #endif !VMS 147: return SUCCESS; 148: } 149: 150: #if !defined(BSD4_2) && !defined(USG) 151: /* 152: * update 'change' time for lock files 153: * 154: * Only update ctime, not mtime or atime. 155: * The 'chmod' method permits cu(I)-like programs 156: * to determine how long uucp has been on the line. 157: * The old "change access, mod, and change time" method 158: * can be had by defining OLDTOUCH 159: * 160: * return code - none 161: */ 162: 163: ultouch() 164: { 165: static time_t lasttouch = 0; 166: register int i; 167: struct ut { 168: time_t actime; 169: time_t modtime; 170: } ut; 171: 172: #ifdef USG 173: time(&Now.time); 174: t1.millitm = 0; 175: #else !USG 176: ftime(&Now); 177: #endif !USG 178: ut.actime = ut.modtime = Now.time; 179: /* Do not waste time touching locking files too often */ 180: /* (But, defend against backward time changes) */ 181: if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 182: return; 183: lasttouch = ut.actime; 184: DEBUG(4, "ultouch\n", 0); 185: 186: for (i = 0; i < Nlocks; i++) { 187: if (Lockfile[i] == NULL) 188: continue; 189: #ifdef OLDTOUCH 190: utime(Lockfile[i], &ut); 191: #else !OLDTOUCH 192: chmod(Lockfile[i], LCKMODE); 193: #endif !OLDTOUCH 194: } 195: } 196: #endif !BSD4_2 && ! USG