BSD 4_3 release
[unix-history] / usr / src / usr.bin / uucp / ulockf.c
CommitLineData
758edcef 1#ifndef lint
95f51977 2static char sccsid[] = "@(#)ulockf.c 5.5 (Berkeley) 10/9/85";
758edcef
SL
3#endif
4
5#include "uucp.h"
758edcef 6#include <sys/stat.h>
4eac5393 7#include <errno.h>
758edcef 8
4eac5393
JB
9#define LCKMODE 0444 /* File mode for lock files */
10#define MAXLOCKS 16 /* Maximum number of lock files */
11
12char *Lockfile[MAXLOCKS];
13char *LockDirectory = LOCKDIR;
14int Nlocks = 0;
758edcef 15
a075b7ef
JB
16/*LINTLIBRARY*/
17
46b15d8a 18/*
4eac5393
JB
19 * This routine will attempt to create a lock file (file).
20 * It makes sure that the lock file is valid if it already exists.
758edcef 21 *
a075b7ef 22 * return codes: SUCCESS | FAIL
758edcef 23 */
1a85e9d2
RC
24ulockf(hfile, atime)
25char *hfile;
758edcef
SL
26time_t atime;
27{
4eac5393
JB
28 register char *p;
29 register int i;
758edcef 30 static char tempfile[NAMESIZE];
1a85e9d2 31 char file[NAMESIZE];
4eac5393
JB
32 static int pid = -1;
33 extern int errno;
758edcef
SL
34
35 if (pid < 0) {
36 pid = getpid();
4eac5393 37 sprintf(tempfile, "%s/LTMP.%d", LockDirectory, pid);
758edcef 38 }
4eac5393
JB
39 sprintf(file, "%s/LCK..%s", LockDirectory, hfile);
40 i = 0;
41 while (onelock(pid, tempfile, file) == -1) { /* lock file exists */
42#if !defined(BSD4_2) && !defined(USG)
43 struct stat stbuf;
44 time_t ptime;
758edcef 45 /* get status to check age of the lock file */
4eac5393
JB
46 if (stat(file, &stbuf) == 0) {
47 (void) time(&ptime);
48 if ((ptime - stbuf.st_ctime) < atime)
49 return FAIL; /* file not old enough to delete */
758edcef 50 }
4eac5393
JB
51#else BSD4_2 || USG
52 register int fd;
53 fd = open(file, 0);
54 if (fd >= 0) {
55 int upid, ret;
56 ret = read(fd, &upid, sizeof upid);
57 close(fd);
58 if (ret == sizeof upid && (kill(upid, 0) == 0
59 || errno != ESRCH))
60 return FAIL; /* process is still running */
61 }
62#endif BSD4_2 || USG
63 assert("DEAD LOCK", file, errno);
64 logent(file, "DEAD LOCK");
65 (void) unlink(file);
66 sleep(5); /* avoid a possible race */
67 ASSERT(i++ < 5, "CAN'T GET LOCKFILE", tempfile, errno);
758edcef 68 }
758edcef
SL
69
70 for (i = 0; i < Nlocks; i++) {
71 if (Lockfile[i] == NULL)
72 break;
73 }
46b15d8a 74 ASSERT(i < MAXLOCKS, "TOO MANY LOCKS", CNULL, i);
758edcef
SL
75 if (i >= Nlocks)
76 i = Nlocks++;
4eac5393
JB
77 p = malloc((unsigned)(strlen(file)+1));
78 ASSERT(p != NULL, "CAN NOT ALLOCATE FOR", file, 0);
79 strcpy(p, file);
758edcef 80 Lockfile[i] = p;
758edcef 81
4eac5393
JB
82 return SUCCESS;
83}
758edcef 84
46b15d8a 85/*
4eac5393 86 * remove all lock files in list or name
758edcef 87 */
758edcef
SL
88rmlock(name)
89register char *name;
90{
91 register int i;
4eac5393 92 char file[MAXFULLNAME];
758edcef 93
4eac5393
JB
94 if (name != NULL) {
95 sprintf(file, "%s/LCK..%s", LockDirectory, name);
96 name = file;
97 }
758edcef
SL
98 for (i = 0; i < Nlocks; i++) {
99 if (Lockfile[i] == NULL)
100 continue;
46b15d8a 101 if (name == NULL || strcmp(name, Lockfile[i]) == SAME) {
758edcef
SL
102 unlink(Lockfile[i]);
103 free(Lockfile[i]);
104 Lockfile[i] = NULL;
105 }
106 }
758edcef
SL
107}
108
758edcef 109/*
4eac5393 110 * makes lock a name on behalf of pid. Tempfile must be in the same
758edcef 111 * file system as name.
758edcef 112 */
a075b7ef
JB
113onelock(pid, tempfile, name)
114int pid;
4eac5393 115char *tempfile, *name;
46b15d8a 116{
4eac5393 117 register int fd, ret;
46b15d8a
RC
118#ifdef VMS
119 fd = creat(name, LCKMODE, "1version");
120#else !VMS
121 fd = creat(tempfile, LCKMODE);
122#endif !VMS
4eac5393
JB
123 if (fd < 0) {
124 DEBUG(1,"Can't creat temp file %s ", tempfile);
125 DEBUG(1,"-- errno %d", errno);
46b15d8a 126 return FAIL;
758edcef 127 }
4eac5393
JB
128 ret = write(fd, (char *)&pid, sizeof(int));
129 (void) close(fd);
46b15d8a 130
4eac5393
JB
131 if (ret != sizeof(int)) {
132 DEBUG(1,"Temp file write failed -- errno %d\n", errno);
133#ifdef VMS
134 (void) unlink(name);
135#else !VMS
136 (void) unlink(tempfile);
137#endif !VMS
138 return FAIL;
139 }
140#ifndef VMS
141 if (link(tempfile, name) < 0) {
142 (void) unlink(tempfile);
46b15d8a 143 return FAIL;
758edcef 144 }
4eac5393
JB
145 unlink(tempfile);
146#endif !VMS
46b15d8a 147 return SUCCESS;
758edcef
SL
148}
149
4eac5393 150#if !defined(BSD4_2) && !defined(USG)
46b15d8a 151/*
46b15d8a 152 * update 'change' time for lock files
758edcef 153 *
758edcef
SL
154 * Only update ctime, not mtime or atime.
155 * The 'chmod' method permits cu(I)-like programs
156 * to determine how long uucp has been on the line.
157 * The old "change access, mod, and change time" method
158 * can be had by defining OLDTOUCH
159 *
160 * return code - none
161 */
162
163ultouch()
164{
758edcef
SL
165 static time_t lasttouch = 0;
166 register int i;
167 struct ut {
168 time_t actime;
169 time_t modtime;
170 } ut;
171
4eac5393
JB
172#ifdef USG
173 time(&Now.time);
174 t1.millitm = 0;
175#else !USG
176 ftime(&Now);
177#endif !USG
178 ut.actime = ut.modtime = Now.time;
758edcef
SL
179 /* Do not waste time touching locking files too often */
180 /* (But, defend against backward time changes) */
181 if (ut.actime >= lasttouch && ut.actime < lasttouch+60)
182 return;
183 lasttouch = ut.actime;
184 DEBUG(4, "ultouch\n", 0);
185
186 for (i = 0; i < Nlocks; i++) {
187 if (Lockfile[i] == NULL)
188 continue;
189#ifdef OLDTOUCH
190 utime(Lockfile[i], &ut);
46b15d8a 191#else !OLDTOUCH
758edcef 192 chmod(Lockfile[i], LCKMODE);
46b15d8a 193#endif !OLDTOUCH
758edcef
SL
194 }
195}
4eac5393 196#endif !BSD4_2 && ! USG