113673Ssam #ifndef lint 2*17839Sralph static char sccsid[] = "@(#)ulockf.c 5.2 (Berkeley) 01/22/85"; 313673Ssam #endif 413673Ssam 513673Ssam #include "uucp.h" 613673Ssam #include <sys/types.h> 713673Ssam #include <sys/stat.h> 813673Ssam 913673Ssam extern time_t time(); 1013673Ssam 1113673Ssam /* File mode for lock files */ 1213673Ssam #define LCKMODE 0444 1313673Ssam 14*17839Sralph /* 1513673Ssam * ulockf - this routine will create a lock file (file). 1613673Ssam * If one already exists, the create time is checked for 1713673Ssam * older than the age time (atime). 1813673Ssam * If it is older, an attempt will be made to unlink it 1913673Ssam * and create a new one. 2013673Ssam * 2113673Ssam * return codes: 0 | FAIL 2213673Ssam */ 2313673Ssam 2413673Ssam ulockf(file, atime) 2513673Ssam register char *file; 2613673Ssam time_t atime; 2713673Ssam { 2813673Ssam struct stat stbuf; 2913673Ssam time_t ptime; 3013673Ssam register int ret; 3113673Ssam static int pid = -1; 3213673Ssam static char tempfile[NAMESIZE]; 3313673Ssam 3413673Ssam if (pid < 0) { 3513673Ssam pid = getpid(); 36*17839Sralph sprintf(tempfile, "%s/LTMP.%d", LOCKDIR, pid); 3713673Ssam } 3813673Ssam if (onelock(pid, tempfile, file) == -1) { 3913673Ssam /* lock file exists */ 4013673Ssam /* get status to check age of the lock file */ 4113673Ssam ret = stat(file, &stbuf); 4213673Ssam if (ret != -1) { 4313673Ssam time(&ptime); 4413673Ssam if ((ptime - stbuf.st_ctime) < atime) { 4513673Ssam /* file not old enough to delete */ 46*17839Sralph return FAIL; 4713673Ssam } 48*17839Sralph ret = unlink(file); 49*17839Sralph logent(file, "DEAD LOCK"); 50*17839Sralph sleep(5); /* rti!trt: avoid a race */ 51*17839Sralph ret = onelock(pid, tempfile, file); 5213673Ssam } 5313673Ssam if (ret != 0) 54*17839Sralph return FAIL; 5513673Ssam } 5613673Ssam stlock(file); 57*17839Sralph return SUCCESS; 5813673Ssam } 5913673Ssam 6013673Ssam 6113673Ssam #define MAXLOCKS 10 /* maximum number of lock files */ 6213673Ssam char *Lockfile[MAXLOCKS]; 6313673Ssam int Nlocks = 0; 6413673Ssam 6513673Ssam /*** 6613673Ssam * stlock(name) put name in list of lock files 6713673Ssam * char *name; 6813673Ssam * 6913673Ssam * return codes: none 7013673Ssam */ 7113673Ssam 7213673Ssam stlock(name) 7313673Ssam register char *name; 7413673Ssam { 7513673Ssam register char *p; 7613673Ssam register int i; 7713673Ssam 7813673Ssam for (i = 0; i < Nlocks; i++) { 7913673Ssam if (Lockfile[i] == NULL) 8013673Ssam break; 8113673Ssam } 82*17839Sralph ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i); 8313673Ssam if (i >= Nlocks) 8413673Ssam i = Nlocks++; 8513673Ssam p = calloc((unsigned)(strlen(name)+1), sizeof (char)); 8613673Ssam ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", name, 0); 8713673Ssam strcpy(p, name); 8813673Ssam Lockfile[i] = p; 8913673Ssam return; 9013673Ssam } 9113673Ssam 9213673Ssam 93*17839Sralph /* 94*17839Sralph * remove all lock files in list * or name 9513673Ssam * 9613673Ssam * return codes: none 9713673Ssam */ 9813673Ssam 9913673Ssam rmlock(name) 10013673Ssam register char *name; 10113673Ssam { 10213673Ssam register int i; 10313673Ssam 10413673Ssam for (i = 0; i < Nlocks; i++) { 10513673Ssam if (Lockfile[i] == NULL) 10613673Ssam continue; 107*17839Sralph if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 10813673Ssam unlink(Lockfile[i]); 10913673Ssam free(Lockfile[i]); 11013673Ssam Lockfile[i] = NULL; 11113673Ssam } 11213673Ssam } 11313673Ssam } 11413673Ssam 11513673Ssam /* 11613673Ssam * isalock(name) returns 0 if the name is a lock. 11713673Ssam * unlock(name) unlocks name if it is a lock. 11813673Ssam * onelock(pid,tempfile,name) makes lock a name 11913673Ssam * on behalf of pid. Tempfile must be in the same 12013673Ssam * file system as name. 12113673Ssam * lock(pid,tempfile,names) either locks all the 12213673Ssam * names or none of them. 12313673Ssam */ 124*17839Sralph isalock(name) 125*17839Sralph char *name; 12613673Ssam { 12713673Ssam struct stat xstat; 128*17839Sralph if (stat(name,&xstat) < 0) 129*17839Sralph return 0; 130*17839Sralph if (xstat.st_size != sizeof(int)) 131*17839Sralph return 0; 132*17839Sralph return 1; 13313673Ssam } 134*17839Sralph unlock(name) 135*17839Sralph char *name; 13613673Ssam { 137*17839Sralph if (isalock(name)) 138*17839Sralph return unlink(name); 139*17839Sralph else 140*17839Sralph return -1; 14113673Ssam } 142*17839Sralph onelock(pid,tempfile,name) 143*17839Sralph char *tempfile,*name; 144*17839Sralph { 145*17839Sralph register int fd; 146*17839Sralph #ifdef VMS 147*17839Sralph fd = creat(name, LCKMODE, "1version"); 148*17839Sralph #else !VMS 149*17839Sralph fd = creat(tempfile, LCKMODE); 150*17839Sralph #endif !VMS 151*17839Sralph if (fd<0) 152*17839Sralph return FAIL; 153*17839Sralph write(fd, (char *) &pid, sizeof(int)); 15413673Ssam close(fd); 155*17839Sralph #ifndef VMS 156*17839Sralph if (link(tempfile, name) < 0) { 157*17839Sralph unlink(tempfile); 158*17839Sralph return FAIL; 15913673Ssam } 16013673Ssam unlink(tempfile); 161*17839Sralph #endif 162*17839Sralph return SUCCESS; 16313673Ssam } 164*17839Sralph 165*17839Sralph 166*17839Sralph lock(pid, tempfile, names) 167*17839Sralph char *tempfile; 16813673Ssam register char **names; 169*17839Sralph { 170*17839Sralph register int i, j; 171*17839Sralph 172*17839Sralph for(i=0; names[i] != 0; i++) { 173*17839Sralph if (onelock(pid, tempfile, names[i]) == 0) 174*17839Sralph continue; 175*17839Sralph for(j=0; j < i ;j++) 176*17839Sralph unlink(names[j]); 177*17839Sralph return FAIL; 17813673Ssam } 179*17839Sralph return SUCCESS; 18013673Ssam } 18113673Ssam 18213673Ssam #define LOCKPRE "LCK." 18313673Ssam 184*17839Sralph /* 185*17839Sralph * remove a lock file 18613673Ssam */ 18713673Ssam delock(s) 18813673Ssam char *s; 18913673Ssam { 190*17839Sralph char ln[NAMESIZE]; 19113673Ssam 192*17839Sralph sprintf(ln, "%s/%s.%s", LOCKDIR, LOCKPRE, s); 19313673Ssam rmlock(ln); 19413673Ssam } 19513673Ssam 196*17839Sralph /* 197*17839Sralph * create system lock 19813673Ssam * 199*17839Sralph * return codes: SUCCESS | FAIL 20013673Ssam */ 20113673Ssam mlock(sys) 20213673Ssam char *sys; 20313673Ssam { 204*17839Sralph char lname[NAMESIZE]; 205*17839Sralph 206*17839Sralph sprintf(lname, "%s/%s.%s", LOCKDIR, LOCKPRE, sys); 207*17839Sralph return ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : SUCCESS; 20813673Ssam } 20913673Ssam 21013673Ssam /*** 211*17839Sralph * update 'change' time for lock files 21213673Ssam * 21313673Ssam * Only update ctime, not mtime or atime. 21413673Ssam * The 'chmod' method permits cu(I)-like programs 21513673Ssam * to determine how long uucp has been on the line. 21613673Ssam * The old "change access, mod, and change time" method 21713673Ssam * can be had by defining OLDTOUCH 21813673Ssam * 21913673Ssam * return code - none 22013673Ssam */ 22113673Ssam 22213673Ssam ultouch() 22313673Ssam { 22413673Ssam time_t time(); 22513673Ssam static time_t lasttouch = 0; 22613673Ssam register int i; 22713673Ssam struct ut { 22813673Ssam time_t actime; 22913673Ssam time_t modtime; 23013673Ssam } ut; 23113673Ssam 23213673Ssam ut.actime = time(&ut.modtime); 23313673Ssam /* Do not waste time touching locking files too often */ 23413673Ssam /* (But, defend against backward time changes) */ 23513673Ssam if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 23613673Ssam return; 23713673Ssam lasttouch = ut.actime; 23813673Ssam DEBUG(4, "ultouch\n", 0); 23913673Ssam 24013673Ssam for (i = 0; i < Nlocks; i++) { 24113673Ssam if (Lockfile[i] == NULL) 24213673Ssam continue; 24313673Ssam #ifdef OLDTOUCH 24413673Ssam utime(Lockfile[i], &ut); 245*17839Sralph #else !OLDTOUCH 24613673Ssam chmod(Lockfile[i], LCKMODE); 247*17839Sralph #endif !OLDTOUCH 248*17839Sralph /* 249*17839Sralph * set 'nologinflag' if the file /etc/nologin exists. 250*17839Sralph * This permits graceful shutdown of uucp. 251*17839Sralph */ 252*17839Sralph if (nologinflag == 0 && access(NOLOGIN, 0) == 0) 253*17839Sralph nologinflag = 1; 25413673Ssam } 25513673Ssam } 256