113673Ssam #ifndef lint 2*34095Sbostic static char sccsid[] = "@(#)ulockf.c 5.7 (Berkeley) 04/24/88"; 313673Ssam #endif 413673Ssam 513673Ssam #include "uucp.h" 613673Ssam #include <sys/stat.h> 725138Sbloom #include <errno.h> 813673Ssam 925138Sbloom #define LCKMODE 0444 /* File mode for lock files */ 1025138Sbloom #define MAXLOCKS 16 /* Maximum number of lock files */ 1113673Ssam 1225138Sbloom char *Lockfile[MAXLOCKS]; 1325138Sbloom char *LockDirectory = LOCKDIR; 1425138Sbloom int Nlocks = 0; 15*34095Sbostic extern int errno; 1625138Sbloom 1723677Sbloom /*LINTLIBRARY*/ 1823677Sbloom 1917839Sralph /* 2025138Sbloom * This routine will attempt to create a lock file (file). 2125138Sbloom * It makes sure that the lock file is valid if it already exists. 2213673Ssam * 2323677Sbloom * return codes: SUCCESS | FAIL 2413673Ssam */ 2518623Sralph ulockf(hfile, atime) 2618623Sralph char *hfile; 2713673Ssam time_t atime; 2813673Ssam { 2925138Sbloom register char *p; 3025138Sbloom register int i; 3113673Ssam static char tempfile[NAMESIZE]; 3218623Sralph char file[NAMESIZE]; 3325138Sbloom static int pid = -1; 3413673Ssam 3513673Ssam if (pid < 0) { 3613673Ssam pid = getpid(); 3725138Sbloom sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid); 3813673Ssam } 3925138Sbloom sprintf(file, "%s/LCK..%s", LockDirectory, hfile); 4025138Sbloom i = 0; 4125138Sbloom while (onelock(pid, tempfile, file) == -1) { /* lock file exists */ 4225138Sbloom #if !defined(BSD4_2) && !defined(USG) 4325138Sbloom struct stat stbuf; 4425138Sbloom time_t ptime; 4513673Ssam /* get status to check age of the lock file */ 4625138Sbloom if (stat(file, &stbuf) == 0) { 4725138Sbloom (void) time(&ptime); 4825138Sbloom if ((ptime - stbuf.st_ctime) < atime) 4925138Sbloom return FAIL; /* file not old enough to delete */ 5013673Ssam } 5125138Sbloom #else BSD4_2 || USG 5225138Sbloom register int fd; 5325138Sbloom fd = open(file, 0); 5425138Sbloom if (fd >= 0) { 5525138Sbloom int upid, ret; 5625138Sbloom ret = read(fd, &upid, sizeof upid); 5725138Sbloom close(fd); 5825138Sbloom if (ret == sizeof upid && (kill(upid, 0) == 0 5925138Sbloom || errno != ESRCH)) 6025138Sbloom return FAIL; /* process is still running */ 6125138Sbloom } 6225138Sbloom #endif BSD4_2 || USG 6333958Srick syslog(LOG_WARNING, "%s: dead lock %s", Rmtname, file); 6425138Sbloom logent(file, "DEAD LOCK"); 6525138Sbloom (void) unlink(file); 6625138Sbloom sleep(5); /* avoid a possible race */ 6733958Srick if (i++ >= 5) { 6833958Srick syslog(LOG_ERR, "%s: can't get lockfile %s: %m", 6933958Srick Rmtname, tempfile); 7033958Srick cleanup(FAIL); 7133958Srick } 7213673Ssam } 7313673Ssam 7413673Ssam for (i = 0; i < Nlocks; i++) { 7513673Ssam if (Lockfile[i] == NULL) 7613673Ssam break; 7713673Ssam } 7833958Srick if (i >= MAXLOCKS) { 7933958Srick syslog(LOG_ERR, "Too many locks"); 8033958Srick cleanup(FAIL); 8133958Srick } 8213673Ssam if (i >= Nlocks) 8313673Ssam i = Nlocks++; 8425138Sbloom p = malloc((unsigned)(strlen(file)+1)); 8533958Srick if (p == NULL) { 8633958Srick syslog(LOG_ERR, "malloc failed: %m"); 8733958Srick cleanup(FAIL); 8833958Srick } 8925138Sbloom strcpy(p, file); 9013673Ssam Lockfile[i] = p; 9125138Sbloom 9225138Sbloom return SUCCESS; 9313673Ssam } 9413673Ssam 9517839Sralph /* 9625138Sbloom * remove all lock files in list or name 9713673Ssam */ 9813673Ssam rmlock(name) 9913673Ssam register char *name; 10013673Ssam { 10113673Ssam register int i; 10225138Sbloom char file[MAXFULLNAME]; 10313673Ssam 10425138Sbloom if (name != NULL) { 10525138Sbloom sprintf(file, "%s/LCK..%s", LockDirectory, name); 10625138Sbloom name = file; 10725138Sbloom } 10813673Ssam for (i = 0; i < Nlocks; i++) { 10913673Ssam if (Lockfile[i] == NULL) 11013673Ssam continue; 11117839Sralph if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 11213673Ssam unlink(Lockfile[i]); 11313673Ssam free(Lockfile[i]); 11413673Ssam Lockfile[i] = NULL; 11513673Ssam } 11613673Ssam } 11713673Ssam } 11813673Ssam 11913673Ssam /* 12025138Sbloom * makes lock a name on behalf of pid. Tempfile must be in the same 12113673Ssam * file system as name. 12213673Ssam */ 12323677Sbloom onelock(pid, tempfile, name) 12423677Sbloom int pid; 12525138Sbloom char *tempfile, *name; 12617839Sralph { 12725138Sbloom register int fd, ret; 12817839Sralph #ifdef VMS 12917839Sralph fd = creat(name, LCKMODE, "1version"); 13017839Sralph #else !VMS 13117839Sralph fd = creat(tempfile, LCKMODE); 13217839Sralph #endif !VMS 13325138Sbloom if (fd < 0) { 13425138Sbloom DEBUG(1,"Can't creat temp file %s ", tempfile); 13525138Sbloom DEBUG(1,"-- errno %d", errno); 13617839Sralph return FAIL; 13725138Sbloom } 13825138Sbloom ret = write(fd, (char *)&pid, sizeof(int)); 13925138Sbloom (void) close(fd); 14025138Sbloom 14125138Sbloom if (ret != sizeof(int)) { 14225138Sbloom DEBUG(1,"Temp file write failed -- errno %d\n", errno); 14325138Sbloom #ifdef VMS 14425138Sbloom (void) unlink(name); 14525138Sbloom #else !VMS 14625138Sbloom (void) unlink(tempfile); 14725138Sbloom #endif !VMS 14825138Sbloom return FAIL; 14925138Sbloom } 15025138Sbloom #ifndef VMS 15117839Sralph if (link(tempfile, name) < 0) { 15225138Sbloom (void) unlink(tempfile); 15317839Sralph return FAIL; 15413673Ssam } 15513673Ssam unlink(tempfile); 15625138Sbloom #endif !VMS 15717839Sralph return SUCCESS; 15813673Ssam } 15917839Sralph 16025138Sbloom #if !defined(BSD4_2) && !defined(USG) 16117839Sralph /* 16217839Sralph * update 'change' time for lock files 16313673Ssam * 16413673Ssam * Only update ctime, not mtime or atime. 16513673Ssam * The 'chmod' method permits cu(I)-like programs 16613673Ssam * to determine how long uucp has been on the line. 16713673Ssam * The old "change access, mod, and change time" method 16813673Ssam * can be had by defining OLDTOUCH 16913673Ssam * 17013673Ssam * return code - none 17113673Ssam */ 17213673Ssam 17313673Ssam ultouch() 17413673Ssam { 17513673Ssam static time_t lasttouch = 0; 17613673Ssam register int i; 17713673Ssam struct ut { 17813673Ssam time_t actime; 17913673Ssam time_t modtime; 18013673Ssam } ut; 18113673Ssam 18225138Sbloom #ifdef USG 18325138Sbloom time(&Now.time); 18425138Sbloom t1.millitm = 0; 18525138Sbloom #else !USG 18625138Sbloom ftime(&Now); 18725138Sbloom #endif !USG 18825138Sbloom ut.actime = ut.modtime = Now.time; 18913673Ssam /* Do not waste time touching locking files too often */ 19013673Ssam /* (But, defend against backward time changes) */ 19113673Ssam if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 19213673Ssam return; 19313673Ssam lasttouch = ut.actime; 19413673Ssam DEBUG(4, "ultouch\n", 0); 19513673Ssam 19613673Ssam for (i = 0; i < Nlocks; i++) { 19713673Ssam if (Lockfile[i] == NULL) 19813673Ssam continue; 19913673Ssam #ifdef OLDTOUCH 20013673Ssam utime(Lockfile[i], &ut); 20117839Sralph #else !OLDTOUCH 20213673Ssam chmod(Lockfile[i], LCKMODE); 20317839Sralph #endif !OLDTOUCH 20413673Ssam } 20513673Ssam } 20625138Sbloom #endif !BSD4_2 && ! USG 207