lockspool.c revision 1.18
1/*	$OpenBSD: lockspool.c,v 1.18 2015/11/24 00:19:29 deraadt Exp $	*/
2
3/*
4 * Copyright (c) 1998 Theo de Raadt <deraadt@theos.com>
5 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <signal.h>
30#include <pwd.h>
31#include <syslog.h>
32#include <unistd.h>
33#include <errno.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <poll.h>
37#include <err.h>
38
39#include "mail.local.h"
40
41void unhold(int);
42void usage(void);
43
44extern char *__progname;
45
46int
47main(int argc, char *argv[])
48{
49	struct passwd *pw;
50	struct pollfd pfd;
51	ssize_t nread;
52	char *from, c;
53	int holdfd;
54
55	if (pledge("stdio rpath wpath getpw cpath fattr", NULL) == -1)
56		err(1, "pledge");
57
58	openlog(__progname, LOG_PERROR, LOG_MAIL);
59
60	if (argc != 1 && argc != 2)
61		usage();
62	if (argc == 2 && getuid() != 0)
63		merr(FATAL, "you must be root to lock someone else's spool");
64
65	signal(SIGTERM, unhold);
66	signal(SIGINT, unhold);
67	signal(SIGHUP, unhold);
68	signal(SIGPIPE, unhold);
69
70	if (argc == 2)
71		pw = getpwnam(argv[1]);
72	else
73		pw = getpwuid(getuid());
74	if (pw == NULL)
75		exit (1);
76	from = pw->pw_name;
77
78	holdfd = getlock(from, pw);
79	if (holdfd == -1) {
80		write(STDOUT_FILENO, "0\n", 2);
81		exit (1);
82	}
83	write(STDOUT_FILENO, "1\n", 2);
84
85	/* wait for the other end of the pipe to close, then release the lock */
86	pfd.fd = STDIN_FILENO;
87	pfd.events = POLLIN;
88	do {
89		if (poll(&pfd, 1, INFTIM) == -1) {
90			if (errno != EINTR)
91				break;
92		}
93		do {
94			nread = read(STDIN_FILENO, &c, 1);
95		} while (nread == 1 || (nread == -1 && errno == EINTR));
96	} while (nread == -1 && errno == EAGAIN);
97	rellock();
98	exit (0);
99}
100
101/*ARGSUSED*/
102void
103unhold(int signo)
104{
105
106	rellock();
107	_exit(0);
108}
109
110void
111usage(void)
112{
113
114	merr(FATAL, "usage: %s [username]", __progname);
115}
116