Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / support / bboards / mmdfII / bboards / RCS / lock.c,v
1 head    2.2;
2 access;
3 symbols;
4 locks
5         shettich:2.2; strict;
6 comment @ * @;
7
8
9 2.2
10 date    90.04.05.15.32.41;      author sources; state Exp;
11 branches;
12 next    2.1;
13
14 2.1
15 date    90.04.05.14.50.19;      author sources; state Exp;
16 branches;
17 next    2.0;
18
19 2.0
20 date    89.11.17.15.57.47;      author sources; state Exp;
21 branches;
22 next    1.1;
23
24 1.1
25 date    89.11.17.15.49.06;      author sources; state Exp;
26 branches;
27 next    ;
28
29
30 desc
31 @@
32
33
34 2.2
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 #ifdef  LOCKF
234         j = access;
235         access &= ! O_APPEND;   /* make sure we open at the beginning */
236 #endif  LOCKF
237         if ((fd = open (file, access | O_NDELAY)) == NOTOK)
238             return NOTOK;
239 #ifndef LOCKF
240         if (flock (fd, LOCK_EX | LOCK_NB) != NOTOK)
241             return fd;
242 #else   LOCKF
243         if (lockf (fd, F_TLOCK, 0L) != NOTOK) {
244             /* see if we should be at the end */
245             if (j & O_APPEND) lseek (fd, 0L, L_XTND);
246             return fd;
247         }
248         /* Fix errno - lockf screws it */
249         if (errno == EACCES) errno = EWOULDBLOCK;
250 #endif  LOCKF
251         j = errno;
252         (void) close (fd);
253
254         sleep (5);
255     }
256
257     (void) close (fd);
258     errno = j;
259     return NOTOK;
260 }
261 #endif  BSD42
262
263 /* \f */
264
265 /* ARGSUSED */
266
267 int     lkclose (fd, file)
268 register int     fd;
269 register char   *file;
270 {
271     char    curlock[BUFSIZ];
272     struct stat st;
273
274     if (fd == NOTOK)
275         return OK;
276     switch (lockstyle) {
277         case LOK_UNIX: 
278 #ifdef  BSD42
279 #ifndef LOCKF
280             flock (fd, LOCK_UN);
281 #else   LOCKF
282             lseek (fd, 0L, L_SET); /* make sure we unlock the whole thing */
283             lockf (fd, F_ULOCK, 0L);
284 #endif  LOCKF
285             break;
286 #endif  BSD42
287
288         default: 
289             if (fstat (fd, &st) != NOTOK) {
290                 lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
291                 (void) unlink (curlock);
292                 timerOFF (fd);
293             }
294     }
295
296     return (close (fd));
297 }
298
299
300 /* \f */
301
302 FILE    *lkfopen (file, mode)
303 register char   *file,
304                 *mode;
305 {
306     register int    fd;
307     register FILE  *fp;
308
309     if ((fd = lkopen (file, strcmp (mode, "r") ? 2 : 0)) == NOTOK)
310         return NULL;
311
312     if ((fp = fdopen (fd, mode)) == NULL) {
313         (void) close (fd);
314         return NULL;
315     }
316
317     return fp;
318 }
319
320
321 /* ARGSUSED */
322
323 int     lkfclose (fp, file)
324 register FILE   *fp;
325 register char   *file;
326 {
327     char    curlock[BUFSIZ];
328     struct stat st;
329
330     if (fp == NULL)
331         return OK;
332
333     switch (lockstyle) {
334         case LOK_UNIX: 
335 #ifdef  BSD42
336 #ifndef LOCKF
337             flock (fileno(fp), LOCK_UN);
338 #else   LOCKF
339             fseek (fp, 0L, 0); /* make sure we unlock the whole thing */
340             lockf (fileno(fp), F_ULOCK, 0L);
341 #endif  LOCKF
342             break;
343 #endif  BSD42
344
345         default: 
346             if (fstat (fileno (fp), &st) != NOTOK) {
347                 lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
348                 (void) unlink (curlock);
349             }
350     }
351
352     return (fclose (fp));
353 }
354
355 /* \f */
356
357 #include <signal.h>
358
359 #define NSECS   ((unsigned) 20)
360
361
362 struct lock {
363     int          l_fd;
364     char        *l_lock;
365     struct lock *l_next;
366 };
367 #define NULLP   ((struct lock *) 0)
368
369 static struct lock *l_top = NULLP;
370
371
372 /* ARGSUSED */
373
374 static alrmser (sig)
375 int     sig;
376 {
377     register int    j;
378     register char  *cp;
379     register struct lock   *lp;
380
381 #ifndef BSD42
382     (void) signal (SIGALRM, alrmser);
383 #endif  BSD42
384
385     for (lp = l_top; lp; lp = lp -> l_next)
386         if (*(cp = lp -> l_lock) && (j = creat (cp, 0400)) != NOTOK)
387             (void) close (j);
388
389     (void) alarm (NSECS);
390 }
391
392 /* \f */
393
394 static timerON (lock, fd)
395 char   *lock;
396 int     fd;
397 {
398     register struct lock   *lp;
399
400     if ((lp = (struct lock *) malloc ((unsigned) (sizeof *lp))) == NULLP)
401         return;                 /* XXX */
402
403     lp -> l_fd = fd;
404     if ((lp -> l_lock = malloc ((unsigned) (strlen (lock) + 1))) == NULLCP) {
405         free ((char *) lp);
406         return;                 /* XXX */
407     }
408     (void) strcpy (lp -> l_lock, lock);
409     lp -> l_next = NULLP;
410
411     if (l_top)
412         lp -> l_next = l_top -> l_next;
413     else {
414         (void) signal (SIGALRM, alrmser);/* perhaps SIGT{STP,TIN,TOU} */
415         (void) alarm (NSECS);
416     }
417     l_top = lp;
418 }
419
420
421 static timerOFF (fd)
422 int     fd;
423 {
424     register struct lock   *pp,
425                            *lp;
426
427     (void) alarm (0);
428
429     if (l_top) {
430         for (pp = lp = l_top; lp; pp = lp, lp = lp -> l_next)
431             if (lp -> l_fd == fd)
432                 break;
433         if (lp) {
434             if (lp == l_top)
435                 l_top = lp -> l_next;
436             else
437                 pp -> l_next = lp -> l_next;
438
439             free (lp -> l_lock);
440             free ((char *) lp);
441         }
442     }
443
444     if (l_top)
445         (void) alarm (NSECS);
446 }
447 @
448
449
450 2.1
451 log
452 @add ID
453 @
454 text
455 @d3 1
456 a3 1
457 static char ident[] = "$Id:";
458 @
459
460
461 2.0
462 log
463 @changes for SUN40 shared libraries and NNTP under bbc
464 @
465 text
466 @d2 3
467 @
468
469
470 1.1
471 log
472 @Initial revision
473 @
474 text
475 @d179 3
476 d192 4
477 d198 1
478 d201 9
479 d238 6
480 d295 6
481 @