113673Ssam #ifndef lint 2*25138Sbloom static char sccsid[] = "@(#)ulockf.c 5.5 (Berkeley) 10/09/85"; 313673Ssam #endif 413673Ssam 513673Ssam #include "uucp.h" 613673Ssam #include <sys/stat.h> 7*25138Sbloom #include <errno.h> 813673Ssam 9*25138Sbloom #define LCKMODE 0444 /* File mode for lock files */ 10*25138Sbloom #define MAXLOCKS 16 /* Maximum number of lock files */ 1113673Ssam 12*25138Sbloom char *Lockfile[MAXLOCKS]; 13*25138Sbloom char *LockDirectory = LOCKDIR; 14*25138Sbloom int Nlocks = 0; 15*25138Sbloom 1623677Sbloom /*LINTLIBRARY*/ 1723677Sbloom 1817839Sralph /* 19*25138Sbloom * This routine will attempt to create a lock file (file). 20*25138Sbloom * It makes sure that the lock file is valid if it already exists. 2113673Ssam * 2223677Sbloom * return codes: SUCCESS | FAIL 2313673Ssam */ 2418623Sralph ulockf(hfile, atime) 2518623Sralph char *hfile; 2613673Ssam time_t atime; 2713673Ssam { 28*25138Sbloom register char *p; 29*25138Sbloom register int i; 3013673Ssam static char tempfile[NAMESIZE]; 3118623Sralph char file[NAMESIZE]; 32*25138Sbloom static int pid = -1; 33*25138Sbloom extern int errno; 3413673Ssam 3513673Ssam if (pid < 0) { 3613673Ssam pid = getpid(); 37*25138Sbloom sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid); 3813673Ssam } 39*25138Sbloom sprintf(file, "%s/LCK..%s", LockDirectory, hfile); 40*25138Sbloom i = 0; 41*25138Sbloom while (onelock(pid, tempfile, file) == -1) { /* lock file exists */ 42*25138Sbloom #if !defined(BSD4_2) && !defined(USG) 43*25138Sbloom struct stat stbuf; 44*25138Sbloom time_t ptime; 4513673Ssam /* get status to check age of the lock file */ 46*25138Sbloom if (stat(file, &stbuf) == 0) { 47*25138Sbloom (void) time(&ptime); 48*25138Sbloom if ((ptime - stbuf.st_ctime) < atime) 49*25138Sbloom return FAIL; /* file not old enough to delete */ 5013673Ssam } 51*25138Sbloom #else BSD4_2 || USG 52*25138Sbloom register int fd; 53*25138Sbloom fd = open(file, 0); 54*25138Sbloom if (fd >= 0) { 55*25138Sbloom int upid, ret; 56*25138Sbloom ret = read(fd, &upid, sizeof upid); 57*25138Sbloom close(fd); 58*25138Sbloom if (ret == sizeof upid && (kill(upid, 0) == 0 59*25138Sbloom || errno != ESRCH)) 60*25138Sbloom return FAIL; /* process is still running */ 61*25138Sbloom } 62*25138Sbloom #endif BSD4_2 || USG 63*25138Sbloom assert("DEAD LOCK", file, errno); 64*25138Sbloom logent(file, "DEAD LOCK"); 65*25138Sbloom (void) unlink(file); 66*25138Sbloom sleep(5); /* avoid a possible race */ 67*25138Sbloom ASSERT(i++ < 5, "CAN'T GET LOCKFILE", tempfile, errno); 6813673Ssam } 6913673Ssam 7013673Ssam for (i = 0; i < Nlocks; i++) { 7113673Ssam if (Lockfile[i] == NULL) 7213673Ssam break; 7313673Ssam } 7417839Sralph ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i); 7513673Ssam if (i >= Nlocks) 7613673Ssam i = Nlocks++; 77*25138Sbloom p = malloc((unsigned)(strlen(file)+1)); 78*25138Sbloom ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", file, 0); 79*25138Sbloom strcpy(p, file); 8013673Ssam Lockfile[i] = p; 81*25138Sbloom 82*25138Sbloom return SUCCESS; 8313673Ssam } 8413673Ssam 8517839Sralph /* 86*25138Sbloom * remove all lock files in list or name 8713673Ssam */ 8813673Ssam rmlock(name) 8913673Ssam register char *name; 9013673Ssam { 9113673Ssam register int i; 92*25138Sbloom char file[MAXFULLNAME]; 9313673Ssam 94*25138Sbloom if (name != NULL) { 95*25138Sbloom sprintf(file, "%s/LCK..%s", LockDirectory, name); 96*25138Sbloom name = file; 97*25138Sbloom } 9813673Ssam for (i = 0; i < Nlocks; i++) { 9913673Ssam if (Lockfile[i] == NULL) 10013673Ssam continue; 10117839Sralph if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 10213673Ssam unlink(Lockfile[i]); 10313673Ssam free(Lockfile[i]); 10413673Ssam Lockfile[i] = NULL; 10513673Ssam } 10613673Ssam } 10713673Ssam } 10813673Ssam 10913673Ssam /* 110*25138Sbloom * makes lock a name on behalf of pid. Tempfile must be in the same 11113673Ssam * file system as name. 11213673Ssam */ 11323677Sbloom onelock(pid, tempfile, name) 11423677Sbloom int pid; 115*25138Sbloom char *tempfile, *name; 11617839Sralph { 117*25138Sbloom register int fd, ret; 11817839Sralph #ifdef VMS 11917839Sralph fd = creat(name, LCKMODE, "1version"); 12017839Sralph #else !VMS 12117839Sralph fd = creat(tempfile, LCKMODE); 12217839Sralph #endif !VMS 123*25138Sbloom if (fd < 0) { 124*25138Sbloom DEBUG(1,"Can't creat temp file %s ", tempfile); 125*25138Sbloom DEBUG(1,"-- errno %d", errno); 12617839Sralph return FAIL; 127*25138Sbloom } 128*25138Sbloom ret = write(fd, (char *)&pid, sizeof(int)); 129*25138Sbloom (void) close(fd); 130*25138Sbloom 131*25138Sbloom if (ret != sizeof(int)) { 132*25138Sbloom DEBUG(1,"Temp file write failed -- errno %d\n", errno); 133*25138Sbloom #ifdef VMS 134*25138Sbloom (void) unlink(name); 135*25138Sbloom #else !VMS 136*25138Sbloom (void) unlink(tempfile); 137*25138Sbloom #endif !VMS 138*25138Sbloom return FAIL; 139*25138Sbloom } 140*25138Sbloom #ifndef VMS 14117839Sralph if (link(tempfile, name) < 0) { 142*25138Sbloom (void) unlink(tempfile); 14317839Sralph return FAIL; 14413673Ssam } 14513673Ssam unlink(tempfile); 146*25138Sbloom #endif !VMS 14717839Sralph return SUCCESS; 14813673Ssam } 14917839Sralph 150*25138Sbloom #if !defined(BSD4_2) && !defined(USG) 15117839Sralph /* 15217839Sralph * update 'change' time for lock files 15313673Ssam * 15413673Ssam * Only update ctime, not mtime or atime. 15513673Ssam * The 'chmod' method permits cu(I)-like programs 15613673Ssam * to determine how long uucp has been on the line. 15713673Ssam * The old "change access, mod, and change time" method 15813673Ssam * can be had by defining OLDTOUCH 15913673Ssam * 16013673Ssam * return code - none 16113673Ssam */ 16213673Ssam 16313673Ssam ultouch() 16413673Ssam { 16513673Ssam static time_t lasttouch = 0; 16613673Ssam register int i; 16713673Ssam struct ut { 16813673Ssam time_t actime; 16913673Ssam time_t modtime; 17013673Ssam } ut; 17113673Ssam 172*25138Sbloom #ifdef USG 173*25138Sbloom time(&Now.time); 174*25138Sbloom t1.millitm = 0; 175*25138Sbloom #else !USG 176*25138Sbloom ftime(&Now); 177*25138Sbloom #endif !USG 178*25138Sbloom ut.actime = ut.modtime = Now.time; 17913673Ssam /* Do not waste time touching locking files too often */ 18013673Ssam /* (But, defend against backward time changes) */ 18113673Ssam if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 18213673Ssam return; 18313673Ssam lasttouch = ut.actime; 18413673Ssam DEBUG(4, "ultouch\n", 0); 18513673Ssam 18613673Ssam for (i = 0; i < Nlocks; i++) { 18713673Ssam if (Lockfile[i] == NULL) 18813673Ssam continue; 18913673Ssam #ifdef OLDTOUCH 19013673Ssam utime(Lockfile[i], &ut); 19117839Sralph #else !OLDTOUCH 19213673Ssam chmod(Lockfile[i], LCKMODE); 19317839Sralph #endif !OLDTOUCH 19413673Ssam } 19513673Ssam } 196*25138Sbloom #endif !BSD4_2 && ! USG 197