]> Pileus Git - ~andy/fetchmail/blob - lock.c
After refactoring.
[~andy/fetchmail] / lock.c
1 /*
2  * lock.c -- cross-platform concurrency locking for fetchmail
3  *
4  * For license terms, see the file COPYING in this directory.
5  */
6 #include "config.h"
7
8 #include <stdio.h>
9 #if defined(STDC_HEADERS)
10 #include <stdlib.h>
11 #endif
12 #if defined(HAVE_UNISTD_H)
13 #include <unistd.h>
14 #endif
15 #include <fcntl.h>
16
17 #include "fetchmail.h"
18 #include "i18n.h"
19
20 static char *lockfile;          /* name of lockfile */
21 static int lock_acquired;       /* have we acquired a lock */
22
23 void lock_setup(void)
24 /* set up the global lockfile name */
25 {
26     /* set up to do lock protocol */
27 #define FETCHMAIL_PIDFILE       "fetchmail.pid"
28     if (!getuid()) {
29         xalloca(lockfile, char *,
30                 sizeof(PID_DIR) + sizeof(FETCHMAIL_PIDFILE));
31         sprintf(lockfile, "%s/%s", PID_DIR, FETCHMAIL_PIDFILE);
32     } else {
33         xalloca(lockfile, char *, strlen(fmhome) + sizeof(FETCHMAIL_PIDFILE) + 2);
34         strcpy(lockfile, fmhome);
35         strcat(lockfile, "/");
36         if (fmhome == home)
37            strcat(lockfile, ".");
38         strcat(lockfile, FETCHMAIL_PIDFILE);
39     }
40 #undef FETCHMAIL_PIDFILE
41 }
42
43 #ifdef HAVE_ON_EXIT
44 static void unlockit(int n, void *p)
45 #else
46 static void unlockit(void)
47 #endif
48 /* must-do actions for exit (but we can't count on being able to do malloc) */
49 {
50     if (lockfile && lock_acquired)
51         unlink(lockfile);
52 }
53
54 void lock_dispose(void)
55 /* arrange for a lock to be removed on process exit */
56 {
57 #ifdef HAVE_ATEXIT
58     atexit(unlockit);
59 #endif
60 #ifdef HAVE_ON_EXIT
61     on_exit(unlockit, (char *)NULL);
62 #endif
63 }
64
65 int lock_state(void)
66 {
67     int         pid, st;
68     FILE        *lockfp;
69     int         bkgd = FALSE;
70
71     pid = 0;
72     if ((lockfp = fopen(lockfile, "r")) != NULL )
73     {
74         bkgd = (fscanf(lockfp, "%d %d", &pid, &st) == 2);
75
76         if (kill(pid, 0) == -1) {
77             fprintf(stderr,_("fetchmail: removing stale lockfile\n"));
78             pid = 0;
79             unlink(lockfile);
80         }
81         fclose(lockfp); /* not checking should be safe, file mode was "r" */
82     }
83
84     return(bkgd ? -pid : pid);
85 }
86
87 void lock_assert(void)
88 /* assert that we already posess a lock */
89 {
90     lock_acquired = TRUE;
91 }
92
93 void lock_or_die(void)
94 /* get a lock on a given host or exit */
95 {
96     int fd;
97     char        tmpbuf[20];
98
99 #ifndef O_SYNC
100 #define O_SYNC  0       /* use it if we have it */
101 #endif
102     if (!lock_acquired)
103     {
104       if ((fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_SYNC, 0666)) != -1)
105       {
106           sprintf(tmpbuf,"%d", getpid());
107           write(fd, tmpbuf, strlen(tmpbuf));
108           if (run.poll_interval)
109           {
110               sprintf(tmpbuf," %d", run.poll_interval);
111               write(fd, tmpbuf, strlen(tmpbuf));
112           }
113           close(fd);    /* should be safe, fd was opened with O_SYNC */
114           lock_acquired = TRUE;
115       }
116       else
117       {
118           fprintf(stderr,       _("fetchmail: lock creation failed.\n"));
119           exit(PS_EXCLUDE);
120       }
121     }
122 }
123
124 void lock_release(void)
125 /* release a lock on a given host */
126 {
127     unlink(lockfile);
128 }
129
130 /* lock.c ends here */