1*48652Sbostic /*- 2*48652Sbostic * Copyright (c) 1985 The Regents of the University of California. 3*48652Sbostic * All rights reserved. 4*48652Sbostic * 5*48652Sbostic * %sccs.include.proprietary.c% 6*48652Sbostic */ 7*48652Sbostic 813673Ssam #ifndef lint 9*48652Sbostic static char sccsid[] = "@(#)ulockf.c 5.9 (Berkeley) 04/24/91"; 10*48652Sbostic #endif /* not lint */ 1113673Ssam 1213673Ssam #include "uucp.h" 1313673Ssam #include <sys/stat.h> 1425138Sbloom #include <errno.h> 1513673Ssam 1625138Sbloom #define LCKMODE 0444 /* File mode for lock files */ 1725138Sbloom #define MAXLOCKS 16 /* Maximum number of lock files */ 1813673Ssam 1925138Sbloom char *Lockfile[MAXLOCKS]; 2025138Sbloom char *LockDirectory = LOCKDIR; 2125138Sbloom int Nlocks = 0; 2234095Sbostic extern int errno; 2325138Sbloom 2423677Sbloom /*LINTLIBRARY*/ 2523677Sbloom 2617839Sralph /* 2725138Sbloom * This routine will attempt to create a lock file (file). 2825138Sbloom * It makes sure that the lock file is valid if it already exists. 2913673Ssam * 3023677Sbloom * return codes: SUCCESS | FAIL 3113673Ssam */ 3218623Sralph ulockf(hfile, atime) 3318623Sralph char *hfile; 3413673Ssam time_t atime; 3513673Ssam { 3625138Sbloom register char *p; 3725138Sbloom register int i; 3813673Ssam static char tempfile[NAMESIZE]; 3918623Sralph char file[NAMESIZE]; 4025138Sbloom static int pid = -1; 4113673Ssam 4213673Ssam if (pid < 0) { 4313673Ssam pid = getpid(); 4425138Sbloom sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid); 4513673Ssam } 4625138Sbloom sprintf(file, "%s/LCK..%s", LockDirectory, hfile); 4725138Sbloom i = 0; 4825138Sbloom while (onelock(pid, tempfile, file) == -1) { /* lock file exists */ 4925138Sbloom #if !defined(BSD4_2) && !defined(USG) 5025138Sbloom struct stat stbuf; 5125138Sbloom time_t ptime; 5213673Ssam /* get status to check age of the lock file */ 5325138Sbloom if (stat(file, &stbuf) == 0) { 5425138Sbloom (void) time(&ptime); 5525138Sbloom if ((ptime - stbuf.st_ctime) < atime) 5625138Sbloom return FAIL; /* file not old enough to delete */ 5713673Ssam } 5825138Sbloom #else BSD4_2 || USG 5925138Sbloom register int fd; 6025138Sbloom fd = open(file, 0); 6125138Sbloom if (fd >= 0) { 6225138Sbloom int upid, ret; 6325138Sbloom ret = read(fd, &upid, sizeof upid); 6425138Sbloom close(fd); 6525138Sbloom if (ret == sizeof upid && (kill(upid, 0) == 0 6625138Sbloom || errno != ESRCH)) 6725138Sbloom return FAIL; /* process is still running */ 6825138Sbloom } 6925138Sbloom #endif BSD4_2 || USG 7033958Srick syslog(LOG_WARNING, "%s: dead lock %s", Rmtname, file); 7125138Sbloom logent(file, "DEAD LOCK"); 7225138Sbloom (void) unlink(file); 7325138Sbloom sleep(5); /* avoid a possible race */ 7433958Srick if (i++ >= 5) { 7533958Srick syslog(LOG_ERR, "%s: can't get lockfile %s: %m", 7633958Srick Rmtname, tempfile); 7733958Srick cleanup(FAIL); 7833958Srick } 7913673Ssam } 8013673Ssam 8113673Ssam for (i = 0; i < Nlocks; i++) { 8213673Ssam if (Lockfile[i] == NULL) 8313673Ssam break; 8413673Ssam } 8533958Srick if (i >= MAXLOCKS) { 8633958Srick syslog(LOG_ERR, "Too many locks"); 8733958Srick cleanup(FAIL); 8833958Srick } 8913673Ssam if (i >= Nlocks) 9013673Ssam i = Nlocks++; 9125138Sbloom p = malloc((unsigned)(strlen(file)+1)); 9233958Srick if (p == NULL) { 9333958Srick syslog(LOG_ERR, "malloc failed: %m"); 9433958Srick cleanup(FAIL); 9533958Srick } 9625138Sbloom strcpy(p, file); 9713673Ssam Lockfile[i] = p; 9825138Sbloom 9925138Sbloom return SUCCESS; 10013673Ssam } 10113673Ssam 10217839Sralph /* 10325138Sbloom * remove all lock files in list or name 10413673Ssam */ 10513673Ssam rmlock(name) 10613673Ssam register char *name; 10713673Ssam { 10813673Ssam register int i; 10925138Sbloom char file[MAXFULLNAME]; 11013673Ssam 11125138Sbloom if (name != NULL) { 11225138Sbloom sprintf(file, "%s/LCK..%s", LockDirectory, name); 11325138Sbloom name = file; 11425138Sbloom } 11513673Ssam for (i = 0; i < Nlocks; i++) { 11613673Ssam if (Lockfile[i] == NULL) 11713673Ssam continue; 11817839Sralph if (name == NULL || strcmp(name, Lockfile[i]) == SAME) { 11913673Ssam unlink(Lockfile[i]); 12013673Ssam free(Lockfile[i]); 12113673Ssam Lockfile[i] = NULL; 12213673Ssam } 12313673Ssam } 12413673Ssam } 12513673Ssam 12613673Ssam /* 12725138Sbloom * makes lock a name on behalf of pid. Tempfile must be in the same 12813673Ssam * file system as name. 12913673Ssam */ 13023677Sbloom onelock(pid, tempfile, name) 13123677Sbloom int pid; 13225138Sbloom char *tempfile, *name; 13317839Sralph { 13425138Sbloom register int fd, ret; 13517839Sralph #ifdef VMS 13617839Sralph fd = creat(name, LCKMODE, "1version"); 13717839Sralph #else !VMS 13817839Sralph fd = creat(tempfile, LCKMODE); 13917839Sralph #endif !VMS 14025138Sbloom if (fd < 0) { 14125138Sbloom DEBUG(1,"Can't creat temp file %s ", tempfile); 14225138Sbloom DEBUG(1,"-- errno %d", errno); 14317839Sralph return FAIL; 14425138Sbloom } 14525138Sbloom ret = write(fd, (char *)&pid, sizeof(int)); 14625138Sbloom (void) close(fd); 14725138Sbloom 14825138Sbloom if (ret != sizeof(int)) { 14925138Sbloom DEBUG(1,"Temp file write failed -- errno %d\n", errno); 15025138Sbloom #ifdef VMS 15125138Sbloom (void) unlink(name); 15225138Sbloom #else !VMS 15325138Sbloom (void) unlink(tempfile); 15425138Sbloom #endif !VMS 15525138Sbloom return FAIL; 15625138Sbloom } 15725138Sbloom #ifndef VMS 15817839Sralph if (link(tempfile, name) < 0) { 15925138Sbloom (void) unlink(tempfile); 16017839Sralph return FAIL; 16113673Ssam } 16213673Ssam unlink(tempfile); 16325138Sbloom #endif !VMS 16417839Sralph return SUCCESS; 16513673Ssam } 16617839Sralph 16725138Sbloom #if !defined(BSD4_2) && !defined(USG) 16817839Sralph /* 16917839Sralph * update 'change' time for lock files 17013673Ssam * 17113673Ssam * Only update ctime, not mtime or atime. 17213673Ssam * The 'chmod' method permits cu(I)-like programs 17313673Ssam * to determine how long uucp has been on the line. 17413673Ssam * The old "change access, mod, and change time" method 17513673Ssam * can be had by defining OLDTOUCH 17613673Ssam * 17713673Ssam * return code - none 17813673Ssam */ 17913673Ssam 18013673Ssam ultouch() 18113673Ssam { 18213673Ssam static time_t lasttouch = 0; 18313673Ssam register int i; 18413673Ssam struct ut { 18513673Ssam time_t actime; 18613673Ssam time_t modtime; 18713673Ssam } ut; 18813673Ssam 18925138Sbloom #ifdef USG 19025138Sbloom time(&Now.time); 19125138Sbloom t1.millitm = 0; 19225138Sbloom #else !USG 19325138Sbloom ftime(&Now); 19425138Sbloom #endif !USG 19525138Sbloom ut.actime = ut.modtime = Now.time; 19613673Ssam /* Do not waste time touching locking files too often */ 19713673Ssam /* (But, defend against backward time changes) */ 19813673Ssam if (ut.actime >= lasttouch && ut.actime < lasttouch+60) 19913673Ssam return; 20013673Ssam lasttouch = ut.actime; 20113673Ssam DEBUG(4, "ultouch\n", 0); 20213673Ssam 20313673Ssam for (i = 0; i < Nlocks; i++) { 20413673Ssam if (Lockfile[i] == NULL) 20513673Ssam continue; 20613673Ssam #ifdef OLDTOUCH 20713673Ssam utime(Lockfile[i], &ut); 20817839Sralph #else !OLDTOUCH 20913673Ssam chmod(Lockfile[i], LCKMODE); 21017839Sralph #endif !OLDTOUCH 21113673Ssam } 21213673Ssam } 21325138Sbloom #endif !BSD4_2 && ! USG 214