~ubuntu-branches/ubuntu/quantal/liblockfile/quantal-proposed

« back to all changes in this revision

Viewing changes to dotlockfile.c

  • Committer: Bazaar Package Importer
  • Author(s): Miquel van Smoorenburg
  • Date: 2001-04-06 09:53:32 UTC
  • Revision ID: james.westby@ubuntu.com-20010406095332-xtysb4vtpotoa4fx
Tags: 1.03
* Some more manpage updates
* Set priority for liblockfile1 to "important" (closes: #92551)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * dotlockfile.c        Command line version of liblockfile.
 
3
 *                      Runs setgid mail so is able to lock mailboxes
 
4
 *                      as well. Liblockfile can call this command.
 
5
 *
 
6
 * Version:     @(#)dotlockfile.c  1.0  10-Jun-1999  miquels@cistron.nl
 
7
 *
 
8
 *              Copyright (C) Miquel van Smoorenburg 1999.
 
9
 *
 
10
 *              This program is free software; you can redistribute it and/or
 
11
 *              modify it under the terms of the GNU General Public License
 
12
 *              as published by the Free Software Foundation; either version 2
 
13
 *              of the License, or (at your option) any later version.
 
14
 */
 
15
 
 
16
#include "autoconf.h"
 
17
 
 
18
#include <sys/types.h>
 
19
#if HAVE_SYS_PARAM_H
 
20
#include <sys/param.h>
 
21
#endif
 
22
#include <sys/stat.h>
 
23
#include <stdio.h>
 
24
#include <string.h>
 
25
#include <pwd.h>
 
26
#include <fcntl.h>
 
27
#include <stdlib.h>
 
28
#include <unistd.h>
 
29
#include <signal.h>
 
30
#include <time.h>
 
31
#include <errno.h>
 
32
#include <maillock.h>
 
33
#include <lockfile.h>
 
34
 
 
35
#ifdef HAVE_GETOPT_H
 
36
#include <getopt.h>
 
37
#endif
 
38
 
 
39
#ifndef HAVE_GETOPT_H
 
40
extern int getopt();
 
41
extern char *optarg;
 
42
extern int optind;
 
43
#endif
 
44
 
 
45
extern int eaccess(char *, gid_t, struct stat *);
 
46
 
 
47
/*
 
48
 *      Sleep for an amout of time while regulary checking if
 
49
 *      our parent is still alive.
 
50
 */
 
51
int check_sleep(int sleeptime)
 
52
{
 
53
        int             i;
 
54
        static int      ppid = 0;
 
55
 
 
56
        if (ppid == 0) ppid = getppid();
 
57
 
 
58
        for (i = 0; i < sleeptime; i += 5) {
 
59
                sleep(5);
 
60
                if (kill(ppid, 0) < 0 && errno == ESRCH)
 
61
                        return L_ERROR;
 
62
        }
 
63
        return 0;
 
64
}
 
65
 
 
66
 
 
67
/*
 
68
 *      Is this a lock for a mailbox? We check if the filename
 
69
 *      is in ..../USERNAME.lock format, and if we own the file
 
70
 *      that we want to lock.
 
71
 */
 
72
int ismaillock(char *lockfile, char *username)
 
73
{
 
74
        struct stat     st;
 
75
        char            *p;
 
76
        char            tmp[1024];
 
77
        int             len;
 
78
 
 
79
        sprintf(tmp, "%.120s.lock", username);
 
80
        if ((p = strrchr(lockfile, '/')) != NULL)
 
81
                p++;
 
82
        else
 
83
                p = lockfile;
 
84
 
 
85
        if (strcmp(p, tmp) != 0)
 
86
                return 0;
 
87
 
 
88
        len = strlen(lockfile);
 
89
        if (len > sizeof(tmp) || len < 5)
 
90
                return 0;
 
91
        strncpy(tmp, lockfile, len - 5);
 
92
        tmp[len - 5] = 0;
 
93
        if (stat(tmp, &st) != 0 || st.st_uid != geteuid())
 
94
                return 0;
 
95
 
 
96
        return 1;
 
97
}
 
98
 
 
99
 
 
100
/*
 
101
 *      Split a filename up in  file and directory.
 
102
 */
 
103
void fn_split(char *fn, char **fn_p, char **dir_p)
 
104
{
 
105
        static char     buf[MAXPATHLEN];
 
106
        char            *p;
 
107
 
 
108
        strcpy(buf, fn);
 
109
        if ((p = strrchr(buf, '/')) != NULL) {
 
110
                *p++   = 0;
 
111
                *fn_p  = p;
 
112
                *dir_p = buf;
 
113
        } else {
 
114
                *fn_p  = fn;
 
115
                *dir_p = ".";
 
116
        }
 
117
}
 
118
 
 
119
 
 
120
/*
 
121
 *      Return name of lockfile for mail.
 
122
 */
 
123
char *mlockname(char *user)
 
124
{
 
125
        static char     buf[MAXPATHLEN];
 
126
        char            *e;
 
127
 
 
128
        if ((e = getenv("MAIL")) != NULL && strlen(e) + 6 < MAXPATHLEN)
 
129
                sprintf(buf, "%s.lock", e);
 
130
        else
 
131
                sprintf(buf, "%s%.120s.lock", MAILDIR, user);
 
132
        return buf;
 
133
}
 
134
 
 
135
 
 
136
/*
 
137
 *      Print usage mesage and exit.
 
138
 */
 
139
void usage(void)
 
140
{
 
141
        fprintf(stderr, "Usage: dotlockfile [-p] [-l|-u] [-r retries] [-c] [-m|lockfile]\n");
 
142
        exit(1);
 
143
}
 
144
 
 
145
 
 
146
int main(int argc, char **argv)
 
147
{
 
148
        struct passwd   *pwd;
 
149
        struct stat     st, st2;
 
150
        gid_t           gid;
 
151
        char            *dir, *file, *lockfile = NULL;
 
152
        int             c, r;
 
153
        int             retries = 5;
 
154
        int             flags = 0;
 
155
        int             unlock = 0;
 
156
        int             check = 0;
 
157
        int             quiet = 0;
 
158
 
 
159
        /*
 
160
         *      Get username for mailbox-locks.
 
161
         */
 
162
        if ((pwd = getpwuid(getuid())) == NULL) {
 
163
                fprintf(stderr, "dotlockfile: You don't exist. Go away.\n");
 
164
                return L_ERROR;
 
165
        }
 
166
 
 
167
        /*
 
168
         *      Process the options.
 
169
         */
 
170
        while ((c = getopt(argc, argv, "qpNr:mlu")) != EOF) switch(c) {
 
171
                case 'q':
 
172
                        quiet = 1;
 
173
                        break;
 
174
                case 'p':
 
175
                        flags |= L_PPID;
 
176
                        break;
 
177
                case 'N':
 
178
                        /* NOP */
 
179
                        break;
 
180
                case 'r':
 
181
                        retries = atoi(optarg);
 
182
                        break;
 
183
                case 'm':
 
184
                        lockfile = mlockname(pwd->pw_name);
 
185
                        break;
 
186
                case 'l':
 
187
                        /* default: lock */
 
188
                        break;
 
189
                case 'u':
 
190
                        unlock = 1;
 
191
                        break;
 
192
                case 'c':
 
193
                        check = 1;
 
194
                        break;
 
195
                default:
 
196
                        usage();
 
197
                        break;
 
198
        }
 
199
 
 
200
        /*
 
201
         *      Need a lockfile, ofcourse.
 
202
         */
 
203
        if (lockfile && optind < argc) usage();
 
204
        if (lockfile == NULL) {
 
205
                if (optind != argc - 1) usage();
 
206
                lockfile = argv[optind];
 
207
        }
 
208
        if (strlen(lockfile) >= MAXPATHLEN) {
 
209
                fprintf(stderr, "dotlockfile: %s: name too long\n", lockfile);
 
210
                return L_NAMELEN;
 
211
        }
 
212
 
 
213
        /*
 
214
         *      See if we can write into the lock directory.
 
215
         */
 
216
        fn_split(lockfile, &file, &dir);
 
217
        gid = getgid();
 
218
        if (eaccess(dir, gid, &st) < 0) {
 
219
                if (errno == ENOENT) {
 
220
enoent:
 
221
                        if (!quiet) fprintf(stderr,
 
222
                                "dotlockfile: %s: no such directory\n", dir);
 
223
                        return L_TMPLOCK;
 
224
                }
 
225
                if ((r = eaccess(dir, getegid(), &st) < 0) && errno == ENOENT)
 
226
                        goto enoent;
 
227
                if (r < 0 || !ismaillock(lockfile, pwd->pw_name)) {
 
228
                        if (!quiet) fprintf(stderr,
 
229
                                "dotlockfile: %s: permission denied\n", lockfile);
 
230
                        return L_TMPLOCK;
 
231
                }
 
232
        } else
 
233
                setgid(gid);
 
234
 
 
235
        /*
 
236
         *      Now we should be able to chdir() to the lock directory.
 
237
         *      When we stat("."), it should be the same as at the
 
238
         *      eaccess() check or someone played symlink() games on us.
 
239
         */
 
240
        if (chdir(dir) < 0 || stat(".", &st2) < 0) {
 
241
                if (!quiet) fprintf(stderr,
 
242
                        "dotlockfile: %s: cannot access directory\n", dir);
 
243
                return L_TMPLOCK;
 
244
        }
 
245
        if (st.st_ino != st2.st_ino || st.st_dev != st2.st_dev) {
 
246
                if (!quiet) fprintf(stderr,
 
247
                        "dotlockfile: %s: directory changed underneath us!\n", dir);
 
248
                return L_TMPLOCK;
 
249
        }
 
250
 
 
251
        /*
 
252
         *      Simple check for a valid lockfile ?
 
253
         */
 
254
        if (check)
 
255
                return (lockfile_check(file, flags) < 0) ? 0 : 1;
 
256
 
 
257
        /*
 
258
         *      Remove lockfile?
 
259
         */
 
260
        if (unlock)
 
261
                return (lockfile_remove(file) == 0) ? 0 : 1;
 
262
 
 
263
        /*
 
264
         *      No, lock.
 
265
         */
 
266
        return lockfile_create(file, retries, flags);
 
267
}
 
268