113673Ssam #ifndef lint 2*23677Sbloom static char sccsid[] = "@(#)ulockf.c 5.4 (Berkeley) 06/23/85"; 313673Ssam #endif 413673Ssam 513673Ssam #include "uucp.h" 613673Ssam #include <sys/stat.h> 713673Ssam 813673Ssam /* File mode for lock files */ 913673Ssam #define LCKMODE 0444 1013673Ssam 11*23677Sbloom /*LINTLIBRARY*/ 12*23677Sbloom 1317839Sralph /* 14*23677Sbloom * this routine will create a lock file (file). 1513673Ssam * If one already exists, the create time is checked for 1613673Ssam * older than the age time (atime). 1713673Ssam * If it is older, an attempt will be made to unlink it 1813673Ssam * and create a new one. 1913673Ssam * 20*23677Sbloom * return codes: SUCCESS | FAIL 2113673Ssam */ 2213673Ssam 2318623Sralph ulockf(hfile, atime) 2418623Sralph char *hfile; 2513673Ssam time_t atime; 2613673Ssam { 2713673Ssam struct stat stbuf; 2813673Ssam time_t ptime; 2913673Ssam register int ret; 3013673Ssam static int pid = -1; 3113673Ssam static char tempfile[NAMESIZE]; 3218623Sralph char file[NAMESIZE]; 3313673Ssam 3413673Ssam if (pid < 0) { 3513673Ssam pid = getpid(); 3617839Sralph sprintf(tempfile, "%s/LTMP.%d", LOCKDIR, pid); 3713673Ssam } 3818623Sralph sprintf(file, "%s/%s", LOCKDIR, hfile); 3913673Ssam if (onelock(pid, tempfile, file) == -1) { 4013673Ssam /* lock file exists */ 4113673Ssam /* get status to check age of the lock file */ 4213673Ssam ret = stat(file, &stbuf); 4313673Ssam if (ret != -1) { 4413673Ssam time(&ptime); 4513673Ssam if ((ptime - stbuf.st_ctime) < atime) { 4613673Ssam /* file not old enough to delete */ 4717839Sralph return FAIL; 4813673Ssam } 4917839Sralph ret = unlink(file); 5017839Sralph logent(file, "DEAD LOCK"); 5117839Sralph sleep(5); /* rti!trt: avoid a race */ 5217839Sralph ret = onelock(pid, tempfile, file); 5313673Ssam } 5413673Ssam if (ret != 0) 5517839Sralph return FAIL; 5613673Ssam } 5713673Ssam stlock(file); 5817839Sralph return SUCCESS; 5913673Ssam } 6013673Ssam 6113673Ssam 6213673Ssam #define MAXLOCKS 10 /* maximum number of lock files */ 6313673Ssam char *Lockfile[MAXLOCKS]; 6413673Ssam int Nlocks = 0; 6513673Ssam 6613673Ssam /*** 6713673Ssam * stlock(name) put name in list of lock files 6813673Ssam * char *name; 6913673Ssam * 7013673Ssam * return codes: none 7113673Ssam */ 7213673Ssam 7313673Ssam stlock(name) 7413673Ssam register char *name; 7513673Ssam { 7613673Ssam register char *p; 7713673Ssam register int i; 7813673Ssam 7913673Ssam for (i = 0; i < Nlocks; i++) { 8013673Ssam if (Lockfile[i] == NULL) 8113673Ssam break; 8213673Ssam } 8317839Sralph ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i); 8413673Ssam if (i >= Nlocks) 8513673Ssam i = Nlocks++; 8613673Ssam p = calloc((unsigned)(strlen(name)+1), sizeof (char)); 8713673Ssam ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", name, 0); 8813673Ssam strcpy(p, name); 8913673Ssam Lockfile[i] = p; 9013673Ssam } 9113673Ssam 9213673Ssam 9317839Sralph /* 9417839Sralph * 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; 10717839Sralph 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 */ 12417839Sralph isalock(name) 12517839Sralph char *name; 12613673Ssam { 12713673Ssam struct stat xstat; 12817839Sralph if (stat(name,&xstat) < 0) 12917839Sralph return 0; 13017839Sralph if (xstat.st_size != sizeof(int)) 13117839Sralph return 0; 13217839Sralph return 1; 13313673Ssam } 13417839Sralph unlock(name) 13517839Sralph char *name; 13613673Ssam { 13717839Sralph if (isalock(name)) 13817839Sralph return unlink(name); 13917839Sralph else 14017839Sralph return -1; 14113673Ssam } 142*23677Sbloom onelock(pid, tempfile, name) 143*23677Sbloom int pid; 14417839Sralph char *tempfile,*name; 14517839Sralph { 14617839Sralph register int fd; 14717839Sralph #ifdef VMS 14817839Sralph fd = creat(name, LCKMODE, "1version"); 14917839Sralph #else !VMS 15017839Sralph fd = creat(tempfile, LCKMODE); 15117839Sralph #endif !VMS 152*23677Sbloom if (fd < 0) 15317839Sralph return FAIL; 154*23677Sbloom write(fd, (char *)&pid, sizeof(int)); 15513673Ssam close(fd); 15617839Sralph #ifndef VMS 15717839Sralph if (link(tempfile, name) < 0) { 15817839Sralph unlink(tempfile); 15917839Sralph return FAIL; 16013673Ssam } 16113673Ssam unlink(tempfile); 16217839Sralph #endif 16317839Sralph return SUCCESS; 16413673Ssam } 16517839Sralph 16617839Sralph 16717839Sralph lock(pid, tempfile, names) 16817839Sralph char *tempfile; 16913673Ssam register char **names; 17017839Sralph { 17117839Sralph register int i, j; 17217839Sralph 17317839Sralph for(i=0; names[i] != 0; i++) { 17417839Sralph if (onelock(pid, tempfile, names[i]) == 0) 17517839Sralph continue; 17617839Sralph for(j=0; j < i ;j++) 17717839Sralph unlink(names[j]); 17817839Sralph return FAIL; 17913673Ssam } 18017839Sralph return SUCCESS; 18113673Ssam } 18213673Ssam 18313673Ssam #define LOCKPRE "LCK." 18413673Ssam 18517839Sralph /* 18617839Sralph * remove a lock file 18713673Ssam */ 18813673Ssam delock(s) 18913673Ssam char *s; 19013673Ssam { 19117839Sralph char ln[NAMESIZE]; 19213673Ssam 19317839Sralph sprintf(ln, "%s/%s.%s", LOCKDIR, LOCKPRE, s); 19413673Ssam rmlock(ln); 19513673Ssam } 19613673Ssam 19717839Sralph /* 19817839Sralph * create system lock 19913673Ssam * 20017839Sralph * return codes: SUCCESS | FAIL 20113673Ssam */ 20213673Ssam mlock(sys) 20313673Ssam char *sys; 20413673Ssam { 20517839Sralph char lname[NAMESIZE]; 20617839Sralph 20718623Sralph sprintf(lname, "%s.%s", LOCKPRE, sys); 20817839Sralph return ulockf(lname, (time_t) SLCKTIME ) < 0 ? FAIL : SUCCESS; 20913673Ssam } 21013673Ssam 21113673Ssam /*** 21217839Sralph * update 'change' time for lock files 21313673Ssam * 21413673Ssam * Only update ctime, not mtime or atime. 21513673Ssam * The 'chmod' method permits cu(I)-like programs 21613673Ssam * to determine how long uucp has been on the line. 21713673Ssam * The old "change access, mod, and change time" method 21813673Ssam * can be had by defining OLDTOUCH 21913673Ssam * 22013673Ssam * return code - none 22113673Ssam */ 22213673Ssam 22313673Ssam ultouch() 22413673Ssam { 22513673Ssam time_t time(); 22613673Ssam static time_t lasttouch = 0; 22713673Ssam register int i; 22813673Ssam struct ut { 22913673Ssam time_t actime; 23013673Ssam time_t modtime; 23113673Ssam } ut; 23213673Ssam 23313673Ssam ut.actime = time(&ut.modtime); 23413673Ssam /* Do not waste time touching locking files too often */ 23513673Ssam /* (But, defend against backward time changes) */ 23613673Ssam if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 23713673Ssam return; 23813673Ssam lasttouch = ut.actime; 23913673Ssam DEBUG(4, "ultouch\n", 0); 24013673Ssam 24113673Ssam for (i = 0; i < Nlocks; i++) { 24213673Ssam if (Lockfile[i] == NULL) 24313673Ssam continue; 24413673Ssam #ifdef OLDTOUCH 24513673Ssam utime(Lockfile[i], &ut); 24617839Sralph #else !OLDTOUCH 24713673Ssam chmod(Lockfile[i], LCKMODE); 24817839Sralph #endif !OLDTOUCH 24917839Sralph /* 25017839Sralph * set 'nologinflag' if the file /etc/nologin exists. 25117839Sralph * This permits graceful shutdown of uucp. 25217839Sralph */ 25317839Sralph if (nologinflag == 0 && access(NOLOGIN, 0) == 0) 25417839Sralph nologinflag = 1; 25513673Ssam } 25613673Ssam } 257