148652Sbostic /*-
2*62386Sbostic * Copyright (c) 1985, 1993
3*62386Sbostic * The Regents of the University of California. All rights reserved.
448652Sbostic *
548652Sbostic * %sccs.include.proprietary.c%
648652Sbostic */
748652Sbostic
813673Ssam #ifndef lint
9*62386Sbostic static char sccsid[] = "@(#)ulockf.c 8.1 (Berkeley) 06/06/93";
1048652Sbostic #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 */
ulockf(hfile,atime)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 */
rmlock(name)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 */
onelock(pid,tempfile,name)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
ultouch()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