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