1: #ifndef lint 2: static char sccsid[] = "@(#)ulockf.c 5.1 (Berkeley) 7/2/83"; 3: #endif 4: 5: #include "uucp.h" 6: #include <sys/types.h> 7: #include <sys/stat.h> 8: 9: 10: extern time_t time(); 11: 12: /* File mode for lock files */ 13: #define LCKMODE 0444 14: 15: /******* 16: * ulockf(file, atime) 17: * char *file; 18: * time_t atime; 19: * 20: * ulockf - this routine will create a lock file (file). 21: * If one already exists, the create time is checked for 22: * older than the age time (atime). 23: * If it is older, an attempt will be made to unlink it 24: * and create a new one. 25: * 26: * return codes: 0 | FAIL 27: */ 28: 29: ulockf(file, atime) 30: register char *file; 31: time_t atime; 32: { 33: struct stat stbuf; 34: time_t ptime; 35: register int ret; 36: static int pid = -1; 37: static char tempfile[NAMESIZE]; 38: 39: if (pid < 0) { 40: pid = getpid(); 41: sprintf(tempfile, "LTMP.%d", pid); 42: } 43: if (onelock(pid, tempfile, file) == -1) { 44: /* lock file exists */ 45: /* get status to check age of the lock file */ 46: ret = stat(file, &stbuf); 47: if (ret != -1) { 48: time(&ptime); 49: if ((ptime - stbuf.st_ctime) < atime) { 50: /* file not old enough to delete */ 51: return(FAIL); 52: } 53: } 54: ret = unlink(file); 55: ret = onelock(pid, tempfile, file); 56: if (ret != 0) 57: return(FAIL); 58: } 59: stlock(file); 60: return(0); 61: } 62: 63: 64: #define MAXLOCKS 10 /* maximum number of lock files */ 65: char *Lockfile[MAXLOCKS]; 66: int Nlocks = 0; 67: 68: /*** 69: * stlock(name) put name in list of lock files 70: * char *name; 71: * 72: * return codes: none 73: */ 74: 75: stlock(name) 76: register char *name; 77: { 78: register char *p; 79: register int i; 80: 81: for (i = 0; i < Nlocks; i++) { 82: if (Lockfile[i] == NULL) 83: break; 84: } 85: ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", "", i); 86: if (i >= Nlocks) 87: i = Nlocks++; 88: p = calloc((unsigned)(strlen(name)+1), sizeof (char)); 89: ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", name, 0); 90: strcpy(p, name); 91: Lockfile[i] = p; 92: return; 93: } 94: 95: 96: /*** 97: * rmlock(name) remove all lock files in list 98: * char *name; or name 99: * 100: * return codes: none 101: */ 102: 103: rmlock(name) 104: register char *name; 105: { 106: register int i; 107: 108: for (i = 0; i < Nlocks; i++) { 109: if (Lockfile[i] == NULL) 110: continue; 111: if (name == NULL 112: || strcmp(name, Lockfile[i]) == SAME) { 113: unlink(Lockfile[i]); 114: free(Lockfile[i]); 115: Lockfile[i] = NULL; 116: } 117: } 118: return; 119: } 120: 121: 122: /* 123: * this stuff from pjw 124: * /usr/pjw/bin/recover - Check pids to remove unnecessary locks. 125: * isalock(name) returns 0 if the name is a lock. 126: * unlock(name) unlocks name if it is a lock. 127: * onelock(pid,tempfile,name) makes lock a name 128: * on behalf of pid. Tempfile must be in the same 129: * file system as name. 130: * lock(pid,tempfile,names) either locks all the 131: * names or none of them. 132: */ 133: isalock(name) char *name; 134: { 135: struct stat xstat; 136: if(stat(name,&xstat)<0) return(0); 137: if(xstat.st_size!=sizeof(int)) return(0); 138: return(1); 139: } 140: unlock(name) char *name; 141: { 142: if(isalock(name)) return(unlink(name)); 143: else return(-1); 144: } 145: onelock(pid,tempfile,name) char *tempfile,*name; 146: { register int fd; 147: fd=creat(tempfile,LCKMODE); 148: if(fd<0) return(-1); 149: write(fd,(char *) &pid,sizeof(int)); 150: close(fd); 151: if(link(tempfile,name)<0) 152: { unlink(tempfile); 153: return(-1); 154: } 155: unlink(tempfile); 156: return(0); 157: } 158: lock(pid,tempfile,names) char *tempfile; 159: register char **names; 160: { register int i,j; 161: for(i=0;names[i]!=0;i++) 162: { if(onelock(pid,tempfile,names[i])==0) continue; 163: for(j=0;j<i;j++) unlink(names[j]); 164: return(-1); 165: } 166: return(0); 167: } 168: 169: #define LOCKPRE "LCK." 170: 171: /*** 172: * delock(s) remove a lock file 173: * char *s; 174: * 175: * return codes: 0 | FAIL 176: */ 177: 178: delock(s) 179: char *s; 180: { 181: char ln[30]; 182: 183: sprintf(ln, "%s.%s", LOCKPRE, s); 184: rmlock(ln); 185: } 186: 187: 188: /*** 189: * mlock(sys) create system lock 190: * char *sys; 191: * 192: * return codes: 0 | FAIL 193: */ 194: 195: mlock(sys) 196: char *sys; 197: { 198: char lname[30]; 199: sprintf(lname, "%s.%s", LOCKPRE, sys); 200: return(ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : 0); 201: } 202: 203: 204: /*** 205: * ultouch() update 'change' time for lock files 206: * 207: * -- mod by rti!trt -- 208: * Only update ctime, not mtime or atime. 209: * The 'chmod' method permits cu(I)-like programs 210: * to determine how long uucp has been on the line. 211: * The old "change access, mod, and change time" method 212: * can be had by defining OLDTOUCH 213: * 214: * return code - none 215: */ 216: 217: ultouch() 218: { 219: time_t time(); 220: static time_t lasttouch = 0; 221: register int i; 222: struct ut { 223: time_t actime; 224: time_t modtime; 225: } ut; 226: 227: ut.actime = time(&ut.modtime); 228: /* Do not waste time touching locking files too often */ 229: /* (But, defend against backward time changes) */ 230: if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 231: return; 232: lasttouch = ut.actime; 233: DEBUG(4, "ultouch\n", 0); 234: 235: for (i = 0; i < Nlocks; i++) { 236: if (Lockfile[i] == NULL) 237: continue; 238: #ifdef OLDTOUCH 239: utime(Lockfile[i], &ut); 240: #else 241: chmod(Lockfile[i], LCKMODE); 242: #endif 243: } 244: }