1: #if !defined(lint) && defined(DOSCCS) 2: static char sccsid[] = "@(#)ulockf.c 5.5.1 (2.11BSD) 1997/10/2"; 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 = (char *)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: extern int errno; 119: #ifdef VMS 120: fd = creat(name, LCKMODE, "1version"); 121: #else !VMS 122: fd = creat(tempfile, LCKMODE); 123: #endif !VMS 124: if (fd < 0) { 125: DEBUG(1,"Can't creat temp file %s ", tempfile); 126: DEBUG(1,"-- errno %d", errno); 127: return FAIL; 128: } 129: ret = write(fd, (char *)&pid, sizeof(int)); 130: (void) close(fd); 131: 132: if (ret != sizeof(int)) { 133: DEBUG(1,"Temp file write failed -- errno %d\n", errno); 134: #ifdef VMS 135: (void) unlink(name); 136: #else !VMS 137: (void) unlink(tempfile); 138: #endif !VMS 139: return FAIL; 140: } 141: #ifndef VMS 142: if (link(tempfile, name) < 0) { 143: (void) unlink(tempfile); 144: return FAIL; 145: } 146: unlink(tempfile); 147: #endif !VMS 148: return SUCCESS; 149: } 150: 151: #if !defined(BSD4_2) && !defined(USG) 152: /* 153: * update 'change' time for lock files 154: * 155: * Only update ctime, not mtime or atime. 156: * The 'chmod' method permits cu(I)-like programs 157: * to determine how long uucp has been on the line. 158: * The old "change access, mod, and change time" method 159: * can be had by defining OLDTOUCH 160: * 161: * return code - none 162: */ 163: 164: ultouch() 165: { 166: static time_t lasttouch = 0; 167: register int i; 168: struct ut { 169: time_t actime; 170: time_t modtime; 171: } ut; 172: 173: #ifdef USG 174: time(&Now.time); 175: t1.millitm = 0; 176: #else !USG 177: ftime(&Now); 178: #endif !USG 179: ut.actime = ut.modtime = Now.time; 180: /* Do not waste time touching locking files too often */ 181: /* (But, defend against backward time changes) */ 182: if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 183: return; 184: lasttouch = ut.actime; 185: DEBUG(4, "ultouch\n", 0); 186: 187: for (i = 0; i < Nlocks; i++) { 188: if (Lockfile[i] == NULL) 189: continue; 190: #ifdef OLDTOUCH 191: utime(Lockfile[i], &ut); 192: #else !OLDTOUCH 193: chmod(Lockfile[i], LCKMODE); 194: #endif !OLDTOUCH 195: } 196: } 197: #endif !BSD4_2 && ! USG