Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / support / pop / mmdfII / pop / RCS / lock.c,v
1 head     1.4;
2 branch   ;
3 access   ;
4 symbols  ;
5 locks    ; strict;
6 comment  @ * @;
7
8
9 1.4
10 date     90.04.05.15.34.26;  author sources;  state Exp;
11 branches ;
12 next     1.3;
13
14 1.3
15 date     90.04.05.14.53.44;  author sources;  state Exp;
16 branches ;
17 next     1.2;
18
19 1.2
20 date     90.01.29.15.22.04;  author sources;  state Exp;
21 branches ;
22 next     1.1;
23
24 1.1
25 date     90.01.29.15.21.54;  author sources;  state Exp;
26 branches ;
27 next     ;
28
29
30 desc
31 @@
32
33
34 1.4
35 log
36 @add ID
37 @
38 text
39 @/* lock.c - universal locking routines */
40 #ifndef lint
41 static char ident[] = "@@(#)$Id:$";
42 #endif  lint
43
44 #ifdef  MMDFONLY
45 #define LOCKONLY
46 #endif  MMDFONLY
47
48 #include <stdio.h>
49 #ifndef LOCKONLY
50 #include "../h/strings.h"
51 #include "mts.h"
52 #else   LOCKONLY
53 #include "strings.h"
54 #ifdef  MMDFONLY
55 #include "mmdfonly.h"
56 #include "mts.h"
57 #else   not MMDFONLY
58 #include "lockonly.h"
59 #endif  not MMDFONLY
60 #endif  LOCKONLY
61 #include <sys/types.h>
62 #include <sys/stat.h>
63
64
65 #define NOTOK   (-1)
66 #define OK      0
67
68 #define NULLCP  ((char *) 0)
69
70 #ifdef  SYS5
71 #define index   strchr
72 #define rindex  strrchr
73 #endif  SYS5
74
75
76 extern int  errno;
77
78 #ifdef  LOCKONLY
79 #ifndef MMDFONLY
80 char   *lockldir = "/usr/spool/locks";
81 #endif  not MMDFONLY
82 #endif  LOCKONLY
83
84
85 long    time ();
86
87 /* \f */
88
89 int     lkopen (file, access)
90 register char   *file;
91 register int     access;
92 {
93     mts_init ("mts");
94     switch (lockstyle) {
95         case LOK_UNIX:
96 #ifdef  BSD42
97             return f_lkopen (file, access);
98 #endif  BSD42
99
100         default:
101             return b_lkopen (file, access);
102         }
103 }
104
105 /* \f */
106
107 static int  b_lkopen (file, access)
108 register char   *file;
109 register int     access;
110 {
111     register int    i,
112                     j;
113     long    curtime;
114     char    curlock[BUFSIZ],
115             tmplock[BUFSIZ];
116     struct stat st;
117
118     if (stat (file, &st) == NOTOK)
119         return NOTOK;
120     lockname (curlock, tmplock, file, (int) st.st_dev, (int) st.st_ino);
121
122     for (i = 0;;)
123         switch (lockit (tmplock, curlock)) {
124             case OK: 
125                 if ((i = open (file, access)) == NOTOK) {
126                     j = errno;
127                     (void) unlink (curlock);
128                     errno = j;
129                 }
130                 timerON (curlock, i);
131                 return i;
132
133             case NOTOK: 
134                 if (stat (curlock, &st) == NOTOK) {
135                     if (i++ > 5)
136                         return NOTOK;
137                     sleep (5);
138                     break;
139                 }
140
141                 i = 0;
142                 (void) time (&curtime);
143                 if (curtime < st.st_ctime + 60L)
144                     sleep (5);
145                 else
146                     (void) unlink (curlock);
147                 break;
148         }
149 }
150
151
152 static int  lockit (tmp, file)
153 register char   *tmp,
154                 *file;
155 {
156     register int    fd;
157
158     if ((fd = creat (tmp, 0400)) == NOTOK)
159         return NOTOK;
160     (void) close (fd);
161
162     fd = link (tmp, file);
163     (void) unlink (tmp);
164
165     return (fd != NOTOK ? OK : NOTOK);
166 }
167
168 /* \f */
169
170 static  lockname (curlock, tmplock, file, dev, ino)
171 register char   *curlock,
172                 *tmplock,
173                 *file;
174 register int     dev,
175                  ino;
176 {
177     register char  *bp,
178                    *cp;
179
180     bp = curlock;
181     if ((cp = rindex (file, '/')) == NULL || *++cp == NULL)
182         cp = file;
183     if (lockldir == NULL || *lockldir == NULL) {
184         if (cp != file) {
185             (void) sprintf (bp, "%.*s", cp - file, file);
186             bp += strlen (bp);
187         }
188     }
189     else {
190         (void) sprintf (bp, "%s/", lockldir);
191         bp += strlen (bp);
192     }
193
194     switch (lockstyle) {
195         case LOK_BELL: 
196         default: 
197             (void) sprintf (bp, "%s.lock", cp);
198             break;
199
200         case LOK_MMDF: 
201             (void) sprintf (bp, "LCK%05d.%05d", dev, ino);
202             break;
203     }
204
205     if (tmplock) {
206         if ((cp = rindex (curlock, '/')) == NULL || *++cp == NULL)
207             (void) strcpy (tmplock, ",LCK.XXXXXX");
208         else
209             (void) sprintf (tmplock, "%.*s,LCK.XXXXXX",
210                 cp - curlock, curlock);
211         (void) unlink (mktemp (tmplock));
212     }
213 }
214
215 /* \f */
216
217 #ifdef  BSD42
218
219 #include <sys/file.h>
220 #ifdef  SUN40
221 #include <sys/fcntl.h>
222 #endif  SUN40
223
224 static int  f_lkopen (file, access)
225 register char   *file;
226 register int     access;
227 {
228     register int    fd,
229                     i,
230                     j;
231
232     for (i = 0; i < 5; i++) {
233         if ((fd = open (file, access | O_NDELAY)) == NOTOK)
234             return NOTOK;
235         if (flock (fd, LOCK_EX | LOCK_NB) != NOTOK)
236             return fd;
237         j = errno;
238         (void) close (fd);
239
240         sleep (5);
241     }
242
243     (void) close (fd);
244     errno = j;
245     return NOTOK;
246 }
247 #endif  BSD42
248
249 /* \f */
250
251 /* ARGSUSED */
252
253 int     lkclose (fd, file)
254 register int     fd;
255 register char   *file;
256 {
257     char    curlock[BUFSIZ];
258     struct stat st;
259
260     if (fd == NOTOK)
261         return OK;
262     switch (lockstyle) {
263         case LOK_UNIX: 
264 #ifdef  BSD42
265             break;
266 #endif  BSD42
267
268         default: 
269             if (fstat (fd, &st) != NOTOK) {
270                 lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
271                 (void) unlink (curlock);
272                 timerOFF (fd);
273             }
274     }
275
276     return (close (fd));
277 }
278
279
280 /* \f */
281
282 FILE    *lkfopen (file, mode)
283 register char   *file,
284                 *mode;
285 {
286     register int    fd;
287     register FILE  *fp;
288
289     if ((fd = lkopen (file, strcmp (mode, "r") ? 2 : 0)) == NOTOK)
290         return NULL;
291
292     if ((fp = fdopen (fd, mode)) == NULL) {
293         (void) close (fd);
294         return NULL;
295     }
296
297     return fp;
298 }
299
300
301 /* ARGSUSED */
302
303 int     lkfclose (fp, file)
304 register FILE   *fp;
305 register char   *file;
306 {
307     char    curlock[BUFSIZ];
308     struct stat st;
309
310     if (fp == NULL)
311         return OK;
312
313     switch (lockstyle) {
314         case LOK_UNIX: 
315 #ifdef  BSD42
316             break;
317 #endif  BSD42
318
319         default: 
320             if (fstat (fileno (fp), &st) != NOTOK) {
321                 lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
322                 (void) unlink (curlock);
323             }
324     }
325
326     return (fclose (fp));
327 }
328
329 /* \f */
330
331 #include <signal.h>
332
333 #define NSECS   ((unsigned) 20)
334
335
336 struct lock {
337     int          l_fd;
338     char        *l_lock;
339     struct lock *l_next;
340 };
341 #define NULLP   ((struct lock *) 0)
342
343 static struct lock *l_top = NULLP;
344
345
346 /* ARGSUSED */
347
348 static alrmser (sig)
349 int     sig;
350 {
351     register int    j;
352     register char  *cp;
353     register struct lock   *lp;
354
355 #ifndef BSD42
356     (void) signal (SIGALRM, alrmser);
357 #endif  BSD42
358
359     for (lp = l_top; lp; lp = lp -> l_next)
360         if (*(cp = lp -> l_lock) && (j = creat (cp, 0400)) != NOTOK)
361             (void) close (j);
362
363     (void) alarm (NSECS);
364 }
365
366 /* \f */
367
368 static timerON (lock, fd)
369 char   *lock;
370 int     fd;
371 {
372     register struct lock   *lp;
373
374     if ((lp = (struct lock *) malloc ((unsigned) (sizeof *lp))) == NULLP)
375         return;                 /* XXX */
376
377     lp -> l_fd = fd;
378     if ((lp -> l_lock = malloc ((unsigned) (strlen (lock) + 1))) == NULLCP) {
379         free ((char *) lp);
380         return;                 /* XXX */
381     }
382     (void) strcpy (lp -> l_lock, lock);
383     lp -> l_next = NULLP;
384
385     if (l_top)
386         lp -> l_next = l_top -> l_next;
387     else {
388         (void) signal (SIGALRM, alrmser);/* perhaps SIGT{STP,TIN,TOU} */
389         (void) alarm (NSECS);
390     }
391     l_top = lp;
392 }
393
394
395 static timerOFF (fd)
396 int     fd;
397 {
398     register struct lock   *pp,
399                            *lp;
400
401     (void) alarm (0);
402
403     if (l_top) {
404         for (pp = lp = l_top; lp; pp = lp, lp = lp -> l_next)
405             if (lp -> l_fd == fd)
406                 break;
407         if (lp) {
408             if (lp == l_top)
409                 l_top = lp -> l_next;
410             else
411                 pp -> l_next = lp -> l_next;
412
413             free (lp -> l_lock);
414             free ((char *) lp);
415         }
416     }
417
418     if (l_top)
419         (void) alarm (NSECS);
420 }
421 @
422
423
424 1.3
425 log
426 @add ID
427 @
428 text
429 @d3 1
430 a3 1
431 static char ident[] = "@@(#)$Id:";
432 @
433
434
435 1.2
436 log
437 @fix for null pointer
438 @
439 text
440 @d2 3
441 @
442
443
444 1.1
445 log
446 @Initial revision
447 @
448 text
449 @d179 3
450 @