1/*	$OpenBSD: lockspool.c,v 1.23 2023/03/08 04:43:05 guenther Exp $	*/
2
3/*
4 * Copyright (c) 1998 Theo de Raadt <deraadt@theos.com>
5 * Copyright (c) 1998 Todd C. Miller <millert@openbsd.org>
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 <paths.h>
36#include <stdlib.h>
37#include <poll.h>
38#include <err.h>
39
40#include "mail.local.h"
41
42void unhold(int);
43void usage(void);
44
45extern char *__progname;
46
47int
48main(int argc, char *argv[])
49{
50	struct passwd *pw;
51	struct pollfd pfd;
52	ssize_t nread;
53	char *from, c;
54	int holdfd;
55
56	if (unveil(_PATH_MAILDIR, "rwc") == -1)
57		err(1, "unveil %s", _PATH_MAILDIR);
58	if (pledge("stdio rpath wpath getpw cpath fattr", NULL) == -1)
59		err(1, "pledge");
60
61	openlog(__progname, LOG_PERROR, LOG_MAIL);
62
63	if (argc != 1 && argc != 2)
64		usage();
65	if (argc == 2 && getuid() != 0)
66		merr(1, "you must be root to lock someone else's spool");
67
68	signal(SIGTERM, unhold);
69	signal(SIGINT, unhold);
70	signal(SIGHUP, unhold);
71	signal(SIGPIPE, unhold);
72
73	if (argc == 2)
74		pw = getpwnam(argv[1]);
75	else
76		pw = getpwuid(getuid());
77	if (pw == NULL)
78		exit (1);
79	from = pw->pw_name;
80
81	holdfd = getlock(from, pw);
82	if (holdfd == -1) {
83		write(STDOUT_FILENO, "0\n", 2);
84		exit (1);
85	}
86	write(STDOUT_FILENO, "1\n", 2);
87
88	/* wait for the other end of the pipe to close, then release the lock */
89	pfd.fd = STDIN_FILENO;
90	pfd.events = POLLIN;
91	do {
92		if (poll(&pfd, 1, INFTIM) == -1) {
93			if (errno != EINTR)
94				break;
95		}
96		do {
97			nread = read(STDIN_FILENO, &c, 1);
98		} while (nread == 1 || (nread == -1 && errno == EINTR));
99	} while (nread == -1 && errno == EAGAIN);
100	rellock();
101	exit (0);
102}
103
104void
105unhold(int signo)
106{
107
108	rellock();
109	_exit(0);
110}
111
112void
113usage(void)
114{
115
116	merr(1, "usage: %s [username]", __progname);
117}
118