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.
6
* Version: @(#)dotlockfile.c 1.0 10-Jun-1999 miquels@cistron.nl
8
* Copyright (C) Miquel van Smoorenburg 1999.
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.
18
#include <sys/types.h>
20
#include <sys/param.h>
45
extern int eaccess(char *, gid_t, struct stat *);
48
* Sleep for an amout of time while regulary checking if
49
* our parent is still alive.
51
int check_sleep(int sleeptime)
56
if (ppid == 0) ppid = getppid();
58
for (i = 0; i < sleeptime; i += 5) {
60
if (kill(ppid, 0) < 0 && errno == ESRCH)
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.
72
int ismaillock(char *lockfile, char *username)
79
sprintf(tmp, "%.120s.lock", username);
80
if ((p = strrchr(lockfile, '/')) != NULL)
85
if (strcmp(p, tmp) != 0)
88
len = strlen(lockfile);
89
if (len > sizeof(tmp) || len < 5)
91
strncpy(tmp, lockfile, len - 5);
93
if (stat(tmp, &st) != 0 || st.st_uid != geteuid())
101
* Split a filename up in file and directory.
103
void fn_split(char *fn, char **fn_p, char **dir_p)
105
static char buf[MAXPATHLEN];
109
if ((p = strrchr(buf, '/')) != NULL) {
121
* Return name of lockfile for mail.
123
char *mlockname(char *user)
125
static char buf[MAXPATHLEN];
128
if ((e = getenv("MAIL")) != NULL && strlen(e) + 6 < MAXPATHLEN)
129
sprintf(buf, "%s.lock", e);
131
sprintf(buf, "%s%.120s.lock", MAILDIR, user);
137
* Print usage mesage and exit.
141
fprintf(stderr, "Usage: dotlockfile [-p] [-l|-u] [-r retries] [-c] [-m|lockfile]\n");
146
int main(int argc, char **argv)
151
char *dir, *file, *lockfile = NULL;
160
* Get username for mailbox-locks.
162
if ((pwd = getpwuid(getuid())) == NULL) {
163
fprintf(stderr, "dotlockfile: You don't exist. Go away.\n");
168
* Process the options.
170
while ((c = getopt(argc, argv, "qpNr:mlu")) != EOF) switch(c) {
181
retries = atoi(optarg);
184
lockfile = mlockname(pwd->pw_name);
201
* Need a lockfile, ofcourse.
203
if (lockfile && optind < argc) usage();
204
if (lockfile == NULL) {
205
if (optind != argc - 1) usage();
206
lockfile = argv[optind];
208
if (strlen(lockfile) >= MAXPATHLEN) {
209
fprintf(stderr, "dotlockfile: %s: name too long\n", lockfile);
214
* See if we can write into the lock directory.
216
fn_split(lockfile, &file, &dir);
218
if (eaccess(dir, gid, &st) < 0) {
219
if (errno == ENOENT) {
221
if (!quiet) fprintf(stderr,
222
"dotlockfile: %s: no such directory\n", dir);
225
if ((r = eaccess(dir, getegid(), &st) < 0) && errno == ENOENT)
227
if (r < 0 || !ismaillock(lockfile, pwd->pw_name)) {
228
if (!quiet) fprintf(stderr,
229
"dotlockfile: %s: permission denied\n", lockfile);
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.
240
if (chdir(dir) < 0 || stat(".", &st2) < 0) {
241
if (!quiet) fprintf(stderr,
242
"dotlockfile: %s: cannot access directory\n", dir);
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);
252
* Simple check for a valid lockfile ?
255
return (lockfile_check(file, flags) < 0) ? 0 : 1;
261
return (lockfile_remove(file) == 0) ? 0 : 1;
266
return lockfile_create(file, retries, flags);