blob: e60fb38e3e0eff506db120f2ce20514671b52be0 [file] [log] [blame]
Lennart Poettering7892e9b2008-07-28 20:50:57 +02001/***
2 This file is part of libdaemon.
Lennart Poetteringc73f5e42004-12-18 22:22:54 +00003
Lennart Poettering7892e9b2008-07-28 20:50:57 +02004 Copyright 2003-2008 Lennart Poettering
5
Brandon Philips0630da02012-08-29 17:42:24 -07006 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
Lennart Poettering7892e9b2008-07-28 20:50:57 +020012
Brandon Philips0630da02012-08-29 17:42:24 -070013 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
Lennart Poettering7892e9b2008-07-28 20:50:57 +020015
Brandon Philips0630da02012-08-29 17:42:24 -070016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23
Lennart Poettering7892e9b2008-07-28 20:50:57 +020024***/
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000025
Lennart Poettering191905c2004-08-23 18:52:43 +000026#ifdef HAVE_CONFIG_H
27#include <config.h>
28#endif
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000029
30#include <fcntl.h>
31#include <unistd.h>
32#include <errno.h>
33#include <string.h>
34#include <stdarg.h>
35#include <signal.h>
36
37#include "dsignal.h"
38#include "dlog.h"
39#include "dnonblock.h"
40
41static int _signal_pipe[2] = { -1, -1 };
42
43static void _sigfunc(int s) {
Lennart Poettering2c8a7472007-10-30 18:36:41 +000044 int saved_errno = errno;
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000045 write(_signal_pipe[1], &s, sizeof(s));
Lennart Poettering2c8a7472007-10-30 18:36:41 +000046 errno = saved_errno;
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000047}
48
49static int _init(void) {
50
51 if (_signal_pipe[0] < 0 || _signal_pipe[1] < 0) {
52 if (pipe(_signal_pipe) < 0) {
53 daemon_log(LOG_ERR, "pipe(): %s", strerror(errno));
54 return -1;
55 }
56
Lennart Poettering6c6fee02008-07-28 23:20:07 +020057 if (daemon_nonblock(_signal_pipe[0], 1) < 0 || daemon_nonblock(_signal_pipe[1], 1) < 0) {
58 daemon_signal_done();
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000059 return -1;
Lennart Poettering6c6fee02008-07-28 23:20:07 +020060 }
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000061 }
62
63 return 0;
64}
65
66int daemon_signal_install(int s){
Lennart Poettering3b92cbb2005-10-30 21:07:55 +000067 sigset_t ss;
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000068 struct sigaction sa;
69
70 if (_init() < 0)
71 return -1;
Lennart Poettering7892e9b2008-07-28 20:50:57 +020072
Lennart Poettering3b92cbb2005-10-30 21:07:55 +000073 if (sigemptyset(&ss) < 0) {
Lennart Poetteringfff36c82004-02-08 20:17:39 +000074 daemon_log(LOG_ERR, "sigemptyset(): %s", strerror(errno));
75 return -1;
76 }
77
Lennart Poettering3b92cbb2005-10-30 21:07:55 +000078 if (sigaddset(&ss, s) < 0) {
Lennart Poetteringc7352582006-07-06 21:03:15 +000079 daemon_log(LOG_ERR, "sigaddset(): %s", strerror(errno));
Lennart Poetteringfff36c82004-02-08 20:17:39 +000080 return -1;
81 }
82
Lennart Poettering3b92cbb2005-10-30 21:07:55 +000083 if (sigprocmask(SIG_UNBLOCK, &ss, NULL) < 0) {
Lennart Poetteringfff36c82004-02-08 20:17:39 +000084 daemon_log(LOG_ERR, "sigprocmask(): %s", strerror(errno));
85 return -1;
86 }
87
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000088 memset(&sa, 0, sizeof(sa));
89 sa.sa_handler = _sigfunc;
90 sigemptyset(&sa.sa_mask);
91 sa.sa_flags = SA_RESTART;
Lennart Poettering7892e9b2008-07-28 20:50:57 +020092
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000093 if (sigaction(s, &sa, NULL) < 0) {
Lennart Poetteringfff36c82004-02-08 20:17:39 +000094 daemon_log(LOG_ERR, "sigaction(%s, ...) failed: %s", strsignal(s), strerror(errno));
Lennart Poetteringe774e8e2003-07-31 14:18:41 +000095 return -1;
96 }
97
98 return 0;
99}
100
101int daemon_signal_init(int s, ...) {
102 int sig, r = 0;
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000103 va_list ap;
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000104
105 if (_init() < 0)
106 return -1;
107
Lennart Poettering255e56d2008-07-28 23:21:11 +0200108 va_start(ap, s);
109
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000110 sig = s;
111 while (sig > 0) {
Lennart Poettering255e56d2008-07-28 23:21:11 +0200112 if ((r = daemon_signal_install(sig)) < 0)
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000113 break;
Lennart Poettering7892e9b2008-07-28 20:50:57 +0200114
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000115 sig = va_arg(ap, int);
116 }
Lennart Poettering7892e9b2008-07-28 20:50:57 +0200117
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000118 va_end(ap);
Lennart Poettering7892e9b2008-07-28 20:50:57 +0200119
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000120 return r;
121}
122
123void daemon_signal_done(void) {
Lennart Poetteringa2dc8192008-07-28 23:21:31 +0200124 int saved_errno = errno;
125
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000126 if (_signal_pipe[0] != -1)
127 close(_signal_pipe[0]);
Lennart Poettering7892e9b2008-07-28 20:50:57 +0200128
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000129 if (_signal_pipe[1] != -1)
130 close(_signal_pipe[1]);
131
132 _signal_pipe[0] = _signal_pipe[1] = -1;
Lennart Poetteringa2dc8192008-07-28 23:21:31 +0200133
134 errno = saved_errno;
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000135}
136
137int daemon_signal_next(void) {
138 int s;
139 ssize_t r;
140
141 if ((r = read(_signal_pipe[0], &s, sizeof(s))) == sizeof(s))
142 return s;
Lennart Poettering7892e9b2008-07-28 20:50:57 +0200143
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000144 if (r < 0) {
145
146 if (errno == EAGAIN)
147 return 0;
148 else {
149 daemon_log(LOG_ERR, "read(signal_pipe[0], ...): %s", strerror(errno));
150 return -1;
151 }
152 }
Lennart Poettering7892e9b2008-07-28 20:50:57 +0200153
Lennart Poetteringe774e8e2003-07-31 14:18:41 +0000154 daemon_log(LOG_ERR, "Short read() on signal pipe.");
155 return -1;
156}
157
158int daemon_signal_fd(void) {
159 return _signal_pipe[0];
160}