Annotation of /trunk/cups/patches/cups-1.4.7-systemd-socket.patch
Parent Directory | Revision Log
Revision 1422 -
(hide annotations)
(download)
Mon Jul 18 12:24:57 2011 UTC (13 years, 2 months ago) by niro
File size: 35856 byte(s)
Mon Jul 18 12:24:57 2011 UTC (13 years, 2 months ago) by niro
File size: 35856 byte(s)
-added fedoras systemd socket patch
1 | niro | 1422 | From 1db0a48375836c7e93ac30649007c2391be8b3b2 Mon Sep 17 00:00:00 2001 |
2 | From: Lennart Poettering <lennart@poettering.net> | ||
3 | Date: Mon, 4 Jul 2011 01:37:01 +0200 | ||
4 | Subject: [PATCH] systemd: add systemd socket activation and unit files | ||
5 | |||
6 | On newer Linux machines systemd supports launchd-style socket | ||
7 | activation. This patch adds support for this mechanism and also adds | ||
8 | systemd unit files as appropriate to hook this up with systemd. | ||
9 | |||
10 | This includes an MIT-licensed drop-in file that implements the most | ||
11 | basic interfaces needed to get the file descriptors from systemd. Most | ||
12 | of the systemd and Linux-specific code compiles to NOPs on other | ||
13 | systems. | ||
14 | |||
15 | Three triggers to start CUPS are defined: a) if new printer hardware is | ||
16 | plugged in, b) when a client accesses the CUPS socket and c) when a | ||
17 | spool file resides in /var/spool/cups. | ||
18 | --- | ||
19 | Makedefs.in | 2 + | ||
20 | config-scripts/cups-systemd.m4 | 25 ++ | ||
21 | configure.in | 4 + | ||
22 | data/Makefile | 9 + | ||
23 | data/cups.path.in | 8 + | ||
24 | data/cups.service.in | 9 + | ||
25 | data/cups.socket.in | 9 + | ||
26 | scheduler/Makefile | 9 + | ||
27 | scheduler/main.c | 107 ++++++++ | ||
28 | scheduler/sd-daemon.c | 520 ++++++++++++++++++++++++++++++++++++++++ | ||
29 | scheduler/sd-daemon.h | 277 +++++++++++++++++++++ | ||
30 | 11 files changed, 979 insertions(+), 0 deletions(-) | ||
31 | create mode 100644 config-scripts/cups-systemd.m4 | ||
32 | create mode 100644 data/cups.path.in | ||
33 | create mode 100644 data/cups.service.in | ||
34 | create mode 100644 data/cups.socket.in | ||
35 | create mode 100644 scheduler/sd-daemon.c | ||
36 | create mode 100644 scheduler/sd-daemon.h | ||
37 | |||
38 | diff --git a/Makedefs.in b/Makedefs.in | ||
39 | index 654eea4..02c43b6 100644 | ||
40 | --- a/Makedefs.in | ||
41 | +++ b/Makedefs.in | ||
42 | @@ -143,6 +143,7 @@ CXXFLAGS = @CPPFLAGS@ @CXXFLAGS@ | ||
43 | CXXLIBS = @CXXLIBS@ | ||
44 | DBUS_NOTIFIER = @DBUS_NOTIFIER@ | ||
45 | DBUS_NOTIFIERLIBS = @DBUS_NOTIFIERLIBS@ | ||
46 | +SYSTEMD_UNITS = @SYSTEMD_UNITS@ | ||
47 | DNSSD_BACKEND = @DNSSD_BACKEND@ | ||
48 | DSOFLAGS = -L../cups @DSOFLAGS@ | ||
49 | DSOLIBS = @DSOLIBS@ $(COMMONLIBS) | ||
50 | @@ -267,6 +268,7 @@ PAMFILE = @PAMFILE@ | ||
51 | |||
52 | DEFAULT_LAUNCHD_CONF = @DEFAULT_LAUNCHD_CONF@ | ||
53 | DBUSDIR = @DBUSDIR@ | ||
54 | +SYSTEMDUNITDIR = $(BUILDROOT)@systemdsystemunitdir@ | ||
55 | |||
56 | |||
57 | # | ||
58 | diff --git a/config-scripts/cups-systemd.m4 b/config-scripts/cups-systemd.m4 | ||
59 | new file mode 100644 | ||
60 | index 0000000..fead8a9 | ||
61 | --- /dev/null | ||
62 | +++ b/config-scripts/cups-systemd.m4 | ||
63 | @@ -0,0 +1,25 @@ | ||
64 | +dnl | ||
65 | +dnl "$Id$" | ||
66 | +dnl | ||
67 | +dnl systemd stuff for CUPS. | ||
68 | + | ||
69 | +dnl Find whether systemd is available | ||
70 | + | ||
71 | +AC_ARG_WITH([systemdsystemunitdir], | ||
72 | + AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), | ||
73 | + [], [with_systemdsystemunitdir=$($PKGCONFIG --variable=systemdsystemunitdir systemd)]) | ||
74 | +if test "x$with_systemdsystemunitdir" != xno; then | ||
75 | + AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) | ||
76 | +fi | ||
77 | + | ||
78 | +if test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ; then | ||
79 | + SYSTEMD_UNITS="cups.service cups.socket cups.path" | ||
80 | +else | ||
81 | + SYSTEMD_UNITS="" | ||
82 | +fi | ||
83 | + | ||
84 | +AC_SUBST(SYSTEMD_UNITS) | ||
85 | + | ||
86 | +dnl | ||
87 | +dnl "$Id$" | ||
88 | +dnl | ||
89 | diff --git a/configure.in b/configure.in | ||
90 | index 560f4f8..b0c19a9 100644 | ||
91 | --- a/configure.in | ||
92 | +++ b/configure.in | ||
93 | @@ -37,6 +37,7 @@ sinclude(config-scripts/cups-pam.m4) | ||
94 | sinclude(config-scripts/cups-largefile.m4) | ||
95 | sinclude(config-scripts/cups-dnssd.m4) | ||
96 | sinclude(config-scripts/cups-launchd.m4) | ||
97 | +sinclude(config-scripts/cups-systemd.m4) | ||
98 | sinclude(config-scripts/cups-defaults.m4) | ||
99 | sinclude(config-scripts/cups-pdf.m4) | ||
100 | sinclude(config-scripts/cups-scripting.m4) | ||
101 | @@ -71,6 +72,9 @@ AC_OUTPUT(Makedefs | ||
102 | conf/snmp.conf | ||
103 | cups-config | ||
104 | data/testprint | ||
105 | + data/cups.service | ||
106 | + data/cups.socket | ||
107 | + data/cups.path | ||
108 | desktop/cups.desktop | ||
109 | doc/help/ref-cupsd-conf.html | ||
110 | doc/help/standard.html | ||
111 | diff --git a/data/Makefile b/data/Makefile | ||
112 | index b9de21a..cccab85 100644 | ||
113 | --- a/data/Makefile | ||
114 | +++ b/data/Makefile | ||
115 | @@ -112,6 +112,12 @@ install-data: | ||
116 | $(INSTALL_DATA) $$file $(DATADIR)/ppdc; \ | ||
117 | done | ||
118 | $(INSTALL_DIR) -m 755 $(DATADIR)/profiles | ||
119 | + if test "x$(SYSTEMD_UNITS)" != "x" ; then \ | ||
120 | + $(INSTALL_DIR) -m 755 $(SYSTEMDUNITDIR); \ | ||
121 | + for file in $(SYSTEMD_UNITS); do \ | ||
122 | + $(INSTALL_DATA) $$file $(SYSTEMDUNITDIR); \ | ||
123 | + done; \ | ||
124 | + fi | ||
125 | |||
126 | |||
127 | # | ||
128 | @@ -159,6 +165,9 @@ uninstall: | ||
129 | -$(RMDIR) $(DATADIR)/charsets | ||
130 | -$(RMDIR) $(DATADIR)/banners | ||
131 | -$(RMDIR) $(DATADIR) | ||
132 | + for file in $(SYSTEMD_UNITS); do \ | ||
133 | + $(RM) $(SYSTEMDUNITDIR)/$$file; \ | ||
134 | + done | ||
135 | |||
136 | |||
137 | # | ||
138 | diff --git a/data/cups.path.in b/data/cups.path.in | ||
139 | new file mode 100644 | ||
140 | index 0000000..c99e39b | ||
141 | --- /dev/null | ||
142 | +++ b/data/cups.path.in | ||
143 | @@ -0,0 +1,8 @@ | ||
144 | +[Unit] | ||
145 | +Description=CUPS Printer Service Spool | ||
146 | + | ||
147 | +[Path] | ||
148 | +DirectoryNotEmpty=@CUPS_REQUESTS@ | ||
149 | + | ||
150 | +[Install] | ||
151 | +WantedBy=multi-user.target | ||
152 | diff --git a/data/cups.service.in b/data/cups.service.in | ||
153 | new file mode 100644 | ||
154 | index 0000000..007d0e6 | ||
155 | --- /dev/null | ||
156 | +++ b/data/cups.service.in | ||
157 | @@ -0,0 +1,9 @@ | ||
158 | +[Unit] | ||
159 | +Description=CUPS Printing Service | ||
160 | + | ||
161 | +[Service] | ||
162 | +ExecStart=@sbindir@/cupsd -f | ||
163 | + | ||
164 | +[Install] | ||
165 | +Also=cups.socket cups.path | ||
166 | +WantedBy=printer.target | ||
167 | diff --git a/data/cups.socket.in b/data/cups.socket.in | ||
168 | new file mode 100644 | ||
169 | index 0000000..b940096 | ||
170 | --- /dev/null | ||
171 | +++ b/data/cups.socket.in | ||
172 | @@ -0,0 +1,9 @@ | ||
173 | +[Unit] | ||
174 | +Description=CUPS Printing Service Sockets | ||
175 | + | ||
176 | +[Socket] | ||
177 | +ListenStream=@CUPS_DEFAULT_DOMAINSOCKET@ | ||
178 | +ListenStream=631 | ||
179 | + | ||
180 | +[Install] | ||
181 | +WantedBy=sockets.target | ||
182 | diff --git a/scheduler/Makefile b/scheduler/Makefile | ||
183 | index 3c7da8e..05152a6 100644 | ||
184 | --- a/scheduler/Makefile | ||
185 | +++ b/scheduler/Makefile | ||
186 | @@ -39,6 +39,7 @@ CUPSDOBJS = \ | ||
187 | server.o \ | ||
188 | statbuf.o \ | ||
189 | subscriptions.o \ | ||
190 | + sd-daemon.o \ | ||
191 | sysman.o | ||
192 | LIBOBJS = \ | ||
193 | filter.o \ | ||
194 | @@ -568,6 +569,14 @@ sloc: | ||
195 | |||
196 | |||
197 | # | ||
198 | +# Update sd-daemon.[ch] drop-in file from upstream git | ||
199 | +# | ||
200 | + | ||
201 | +update-systemd: | ||
202 | + curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c > sd-daemon.c | ||
203 | + curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h > sd-daemon.h | ||
204 | + | ||
205 | +# | ||
206 | # Dependencies... | ||
207 | # | ||
208 | |||
209 | diff --git a/scheduler/main.c b/scheduler/main.c | ||
210 | index baaa3a1..5a4b8e1 100644 | ||
211 | --- a/scheduler/main.c | ||
212 | +++ b/scheduler/main.c | ||
213 | @@ -26,6 +26,8 @@ | ||
214 | * launchd_checkin() - Check-in with launchd and collect the listening | ||
215 | * fds. | ||
216 | * launchd_checkout() - Update the launchd KeepAlive file as needed. | ||
217 | + * systemd_checkin() - Check-in with systemd and collect the | ||
218 | + * listening fds. | ||
219 | * parent_handler() - Catch USR1/CHLD signals... | ||
220 | * process_children() - Process all dead children... | ||
221 | * select_timeout() - Calculate the select timeout value. | ||
222 | @@ -62,6 +64,8 @@ | ||
223 | # endif /* !LAUNCH_JOBKEY_SERVICEIPC */ | ||
224 | #endif /* HAVE_LAUNCH_H */ | ||
225 | |||
226 | +#include "sd-daemon.h" | ||
227 | + | ||
228 | #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) | ||
229 | # include <malloc.h> | ||
230 | #endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ | ||
231 | @@ -78,6 +82,7 @@ | ||
232 | static void launchd_checkin(void); | ||
233 | static void launchd_checkout(void); | ||
234 | #endif /* HAVE_LAUNCHD */ | ||
235 | +static void systemd_checkin(void); | ||
236 | static void parent_handler(int sig); | ||
237 | static void process_children(void); | ||
238 | static void sigchld_handler(int sig); | ||
239 | @@ -520,6 +525,11 @@ main(int argc, /* I - Number of command-line args */ | ||
240 | #endif /* HAVE_LAUNCHD */ | ||
241 | |||
242 | /* | ||
243 | + * If we were started by systemd get the listen sockets file descriptors... | ||
244 | + */ | ||
245 | + systemd_checkin(); | ||
246 | + | ||
247 | + /* | ||
248 | * Startup the server... | ||
249 | */ | ||
250 | |||
251 | @@ -731,6 +741,12 @@ main(int argc, /* I - Number of command-line args */ | ||
252 | #endif /* HAVE_LAUNCHD */ | ||
253 | |||
254 | /* | ||
255 | + * If we were started by systemd get the listen sockets file descriptors... | ||
256 | + */ | ||
257 | + | ||
258 | + systemd_checkin(); | ||
259 | + | ||
260 | + /* | ||
261 | * Startup the server... | ||
262 | */ | ||
263 | |||
264 | @@ -1535,6 +1551,97 @@ launchd_checkout(void) | ||
265 | } | ||
266 | #endif /* HAVE_LAUNCHD */ | ||
267 | |||
268 | +static void | ||
269 | +systemd_checkin(void) | ||
270 | +{ | ||
271 | + int n, fd; | ||
272 | + | ||
273 | + n = sd_listen_fds(1); | ||
274 | + if (n < 0) | ||
275 | + { | ||
276 | + cupsdLogMessage(CUPSD_LOG_ERROR, | ||
277 | + "systemd_checkin: Failed to acquire sockets from systemd - %s", | ||
278 | + strerror(-n)); | ||
279 | + exit(EXIT_FAILURE); | ||
280 | + return; | ||
281 | + } | ||
282 | + | ||
283 | + if (n == 0) | ||
284 | + return; | ||
285 | + | ||
286 | + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) | ||
287 | + { | ||
288 | + http_addr_t addr; | ||
289 | + socklen_t addrlen; | ||
290 | + int r; | ||
291 | + cupsd_listener_t *lis; | ||
292 | + char s[256]; | ||
293 | + | ||
294 | + r = sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1); | ||
295 | + if (r < 0) { | ||
296 | + cupsdLogMessage(CUPSD_LOG_ERROR, | ||
297 | + "systemd_checkin: Unable to verify socket type - %s", | ||
298 | + strerror(-r)); | ||
299 | + continue; | ||
300 | + } | ||
301 | + | ||
302 | + if (!r) { | ||
303 | + cupsdLogMessage(CUPSD_LOG_ERROR, | ||
304 | + "systemd_checkin: Socket not of the right type"); | ||
305 | + continue; | ||
306 | + } | ||
307 | + | ||
308 | + if (getsockname(fd, (struct sockaddr*) &addr, &addrlen)) | ||
309 | + { | ||
310 | + cupsdLogMessage(CUPSD_LOG_ERROR, | ||
311 | + "systemd_checkin: Unable to get local address - %s", | ||
312 | + strerror(errno)); | ||
313 | + continue; | ||
314 | + } | ||
315 | + | ||
316 | + /* | ||
317 | + * Try to match the systemd socket address to one of the listeners... | ||
318 | + */ | ||
319 | + | ||
320 | + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); | ||
321 | + lis; | ||
322 | + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) | ||
323 | + if (httpAddrEqual(&lis->address, &addr)) | ||
324 | + break; | ||
325 | + | ||
326 | + if (lis) | ||
327 | + { | ||
328 | + cupsdLogMessage(CUPSD_LOG_DEBUG, | ||
329 | + "systemd_checkin: Matched existing listener %s with fd %d...", | ||
330 | + httpAddrString(&(lis->address), s, sizeof(s)), fd); | ||
331 | + } | ||
332 | + else | ||
333 | + { | ||
334 | + cupsdLogMessage(CUPSD_LOG_DEBUG, | ||
335 | + "systemd_checkin: Adding new listener %s with fd %d...", | ||
336 | + httpAddrString(&addr, s, sizeof(s)), fd); | ||
337 | + | ||
338 | + if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) | ||
339 | + { | ||
340 | + cupsdLogMessage(CUPSD_LOG_ERROR, | ||
341 | + "systemd_checkin: Unable to allocate listener - " | ||
342 | + "%s.", strerror(errno)); | ||
343 | + exit(EXIT_FAILURE); | ||
344 | + } | ||
345 | + | ||
346 | + cupsArrayAdd(Listeners, lis); | ||
347 | + | ||
348 | + memcpy(&lis->address, &addr, sizeof(lis->address)); | ||
349 | + } | ||
350 | + | ||
351 | + lis->fd = fd; | ||
352 | + | ||
353 | +# ifdef HAVE_SSL | ||
354 | + if (_httpAddrPort(&(lis->address)) == 443) | ||
355 | + lis->encryption = HTTP_ENCRYPT_ALWAYS; | ||
356 | +# endif /* HAVE_SSL */ | ||
357 | + } | ||
358 | +} | ||
359 | |||
360 | /* | ||
361 | * 'parent_handler()' - Catch USR1/CHLD signals... | ||
362 | diff --git a/scheduler/sd-daemon.c b/scheduler/sd-daemon.c | ||
363 | new file mode 100644 | ||
364 | index 0000000..a2ec74c | ||
365 | --- /dev/null | ||
366 | +++ b/scheduler/sd-daemon.c | ||
367 | @@ -0,0 +1,520 @@ | ||
368 | +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ | ||
369 | + | ||
370 | +/*** | ||
371 | + Copyright 2010 Lennart Poettering | ||
372 | + | ||
373 | + Permission is hereby granted, free of charge, to any person | ||
374 | + obtaining a copy of this software and associated documentation files | ||
375 | + (the "Software"), to deal in the Software without restriction, | ||
376 | + including without limitation the rights to use, copy, modify, merge, | ||
377 | + publish, distribute, sublicense, and/or sell copies of the Software, | ||
378 | + and to permit persons to whom the Software is furnished to do so, | ||
379 | + subject to the following conditions: | ||
380 | + | ||
381 | + The above copyright notice and this permission notice shall be | ||
382 | + included in all copies or substantial portions of the Software. | ||
383 | + | ||
384 | + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
385 | + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
386 | + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
387 | + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
388 | + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
389 | + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
390 | + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
391 | + SOFTWARE. | ||
392 | +***/ | ||
393 | + | ||
394 | +#ifndef _GNU_SOURCE | ||
395 | +#define _GNU_SOURCE | ||
396 | +#endif | ||
397 | + | ||
398 | +#include <sys/types.h> | ||
399 | +#include <sys/stat.h> | ||
400 | +#include <sys/socket.h> | ||
401 | +#include <sys/un.h> | ||
402 | +#include <sys/fcntl.h> | ||
403 | +#include <netinet/in.h> | ||
404 | +#include <stdlib.h> | ||
405 | +#include <errno.h> | ||
406 | +#include <unistd.h> | ||
407 | +#include <string.h> | ||
408 | +#include <stdarg.h> | ||
409 | +#include <stdio.h> | ||
410 | +#include <stddef.h> | ||
411 | +#include <limits.h> | ||
412 | + | ||
413 | +#if defined(__linux__) | ||
414 | +#include <mqueue.h> | ||
415 | +#endif | ||
416 | + | ||
417 | +#include "sd-daemon.h" | ||
418 | + | ||
419 | +#if (__GNUC__ >= 4) && !defined(SD_EXPORT_SYMBOLS) | ||
420 | +#define _sd_hidden_ __attribute__ ((visibility("hidden"))) | ||
421 | +#else | ||
422 | +#define _sd_hidden_ | ||
423 | +#endif | ||
424 | + | ||
425 | +_sd_hidden_ int sd_listen_fds(int unset_environment) { | ||
426 | + | ||
427 | +#if defined(DISABLE_SYSTEMD) || !defined(__linux__) | ||
428 | + return 0; | ||
429 | +#else | ||
430 | + int r, fd; | ||
431 | + const char *e; | ||
432 | + char *p = NULL; | ||
433 | + unsigned long l; | ||
434 | + | ||
435 | + if (!(e = getenv("LISTEN_PID"))) { | ||
436 | + r = 0; | ||
437 | + goto finish; | ||
438 | + } | ||
439 | + | ||
440 | + errno = 0; | ||
441 | + l = strtoul(e, &p, 10); | ||
442 | + | ||
443 | + if (errno != 0) { | ||
444 | + r = -errno; | ||
445 | + goto finish; | ||
446 | + } | ||
447 | + | ||
448 | + if (!p || *p || l <= 0) { | ||
449 | + r = -EINVAL; | ||
450 | + goto finish; | ||
451 | + } | ||
452 | + | ||
453 | + /* Is this for us? */ | ||
454 | + if (getpid() != (pid_t) l) { | ||
455 | + r = 0; | ||
456 | + goto finish; | ||
457 | + } | ||
458 | + | ||
459 | + if (!(e = getenv("LISTEN_FDS"))) { | ||
460 | + r = 0; | ||
461 | + goto finish; | ||
462 | + } | ||
463 | + | ||
464 | + errno = 0; | ||
465 | + l = strtoul(e, &p, 10); | ||
466 | + | ||
467 | + if (errno != 0) { | ||
468 | + r = -errno; | ||
469 | + goto finish; | ||
470 | + } | ||
471 | + | ||
472 | + if (!p || *p) { | ||
473 | + r = -EINVAL; | ||
474 | + goto finish; | ||
475 | + } | ||
476 | + | ||
477 | + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) { | ||
478 | + int flags; | ||
479 | + | ||
480 | + if ((flags = fcntl(fd, F_GETFD)) < 0) { | ||
481 | + r = -errno; | ||
482 | + goto finish; | ||
483 | + } | ||
484 | + | ||
485 | + if (flags & FD_CLOEXEC) | ||
486 | + continue; | ||
487 | + | ||
488 | + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { | ||
489 | + r = -errno; | ||
490 | + goto finish; | ||
491 | + } | ||
492 | + } | ||
493 | + | ||
494 | + r = (int) l; | ||
495 | + | ||
496 | +finish: | ||
497 | + if (unset_environment) { | ||
498 | + unsetenv("LISTEN_PID"); | ||
499 | + unsetenv("LISTEN_FDS"); | ||
500 | + } | ||
501 | + | ||
502 | + return r; | ||
503 | +#endif | ||
504 | +} | ||
505 | + | ||
506 | +_sd_hidden_ int sd_is_fifo(int fd, const char *path) { | ||
507 | + struct stat st_fd; | ||
508 | + | ||
509 | + if (fd < 0) | ||
510 | + return -EINVAL; | ||
511 | + | ||
512 | + memset(&st_fd, 0, sizeof(st_fd)); | ||
513 | + if (fstat(fd, &st_fd) < 0) | ||
514 | + return -errno; | ||
515 | + | ||
516 | + if (!S_ISFIFO(st_fd.st_mode)) | ||
517 | + return 0; | ||
518 | + | ||
519 | + if (path) { | ||
520 | + struct stat st_path; | ||
521 | + | ||
522 | + memset(&st_path, 0, sizeof(st_path)); | ||
523 | + if (stat(path, &st_path) < 0) { | ||
524 | + | ||
525 | + if (errno == ENOENT || errno == ENOTDIR) | ||
526 | + return 0; | ||
527 | + | ||
528 | + return -errno; | ||
529 | + } | ||
530 | + | ||
531 | + return | ||
532 | + st_path.st_dev == st_fd.st_dev && | ||
533 | + st_path.st_ino == st_fd.st_ino; | ||
534 | + } | ||
535 | + | ||
536 | + return 1; | ||
537 | +} | ||
538 | + | ||
539 | +_sd_hidden_ int sd_is_special(int fd, const char *path) { | ||
540 | + struct stat st_fd; | ||
541 | + | ||
542 | + if (fd < 0) | ||
543 | + return -EINVAL; | ||
544 | + | ||
545 | + if (fstat(fd, &st_fd) < 0) | ||
546 | + return -errno; | ||
547 | + | ||
548 | + if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) | ||
549 | + return 0; | ||
550 | + | ||
551 | + if (path) { | ||
552 | + struct stat st_path; | ||
553 | + | ||
554 | + if (stat(path, &st_path) < 0) { | ||
555 | + | ||
556 | + if (errno == ENOENT || errno == ENOTDIR) | ||
557 | + return 0; | ||
558 | + | ||
559 | + return -errno; | ||
560 | + } | ||
561 | + | ||
562 | + if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) | ||
563 | + return | ||
564 | + st_path.st_dev == st_fd.st_dev && | ||
565 | + st_path.st_ino == st_fd.st_ino; | ||
566 | + else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) | ||
567 | + return st_path.st_rdev == st_fd.st_rdev; | ||
568 | + else | ||
569 | + return 0; | ||
570 | + } | ||
571 | + | ||
572 | + return 1; | ||
573 | +} | ||
574 | + | ||
575 | +static int sd_is_socket_internal(int fd, int type, int listening) { | ||
576 | + struct stat st_fd; | ||
577 | + | ||
578 | + if (fd < 0 || type < 0) | ||
579 | + return -EINVAL; | ||
580 | + | ||
581 | + if (fstat(fd, &st_fd) < 0) | ||
582 | + return -errno; | ||
583 | + | ||
584 | + if (!S_ISSOCK(st_fd.st_mode)) | ||
585 | + return 0; | ||
586 | + | ||
587 | + if (type != 0) { | ||
588 | + int other_type = 0; | ||
589 | + socklen_t l = sizeof(other_type); | ||
590 | + | ||
591 | + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) | ||
592 | + return -errno; | ||
593 | + | ||
594 | + if (l != sizeof(other_type)) | ||
595 | + return -EINVAL; | ||
596 | + | ||
597 | + if (other_type != type) | ||
598 | + return 0; | ||
599 | + } | ||
600 | + | ||
601 | + if (listening >= 0) { | ||
602 | + int accepting = 0; | ||
603 | + socklen_t l = sizeof(accepting); | ||
604 | + | ||
605 | + if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) | ||
606 | + return -errno; | ||
607 | + | ||
608 | + if (l != sizeof(accepting)) | ||
609 | + return -EINVAL; | ||
610 | + | ||
611 | + if (!accepting != !listening) | ||
612 | + return 0; | ||
613 | + } | ||
614 | + | ||
615 | + return 1; | ||
616 | +} | ||
617 | + | ||
618 | +union sockaddr_union { | ||
619 | + struct sockaddr sa; | ||
620 | + struct sockaddr_in in4; | ||
621 | + struct sockaddr_in6 in6; | ||
622 | + struct sockaddr_un un; | ||
623 | + struct sockaddr_storage storage; | ||
624 | +}; | ||
625 | + | ||
626 | +_sd_hidden_ int sd_is_socket(int fd, int family, int type, int listening) { | ||
627 | + int r; | ||
628 | + | ||
629 | + if (family < 0) | ||
630 | + return -EINVAL; | ||
631 | + | ||
632 | + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) | ||
633 | + return r; | ||
634 | + | ||
635 | + if (family > 0) { | ||
636 | + union sockaddr_union sockaddr; | ||
637 | + socklen_t l; | ||
638 | + | ||
639 | + memset(&sockaddr, 0, sizeof(sockaddr)); | ||
640 | + l = sizeof(sockaddr); | ||
641 | + | ||
642 | + if (getsockname(fd, &sockaddr.sa, &l) < 0) | ||
643 | + return -errno; | ||
644 | + | ||
645 | + if (l < sizeof(sa_family_t)) | ||
646 | + return -EINVAL; | ||
647 | + | ||
648 | + return sockaddr.sa.sa_family == family; | ||
649 | + } | ||
650 | + | ||
651 | + return 1; | ||
652 | +} | ||
653 | + | ||
654 | +_sd_hidden_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { | ||
655 | + union sockaddr_union sockaddr; | ||
656 | + socklen_t l; | ||
657 | + int r; | ||
658 | + | ||
659 | + if (family != 0 && family != AF_INET && family != AF_INET6) | ||
660 | + return -EINVAL; | ||
661 | + | ||
662 | + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) | ||
663 | + return r; | ||
664 | + | ||
665 | + memset(&sockaddr, 0, sizeof(sockaddr)); | ||
666 | + l = sizeof(sockaddr); | ||
667 | + | ||
668 | + if (getsockname(fd, &sockaddr.sa, &l) < 0) | ||
669 | + return -errno; | ||
670 | + | ||
671 | + if (l < sizeof(sa_family_t)) | ||
672 | + return -EINVAL; | ||
673 | + | ||
674 | + if (sockaddr.sa.sa_family != AF_INET && | ||
675 | + sockaddr.sa.sa_family != AF_INET6) | ||
676 | + return 0; | ||
677 | + | ||
678 | + if (family > 0) | ||
679 | + if (sockaddr.sa.sa_family != family) | ||
680 | + return 0; | ||
681 | + | ||
682 | + if (port > 0) { | ||
683 | + if (sockaddr.sa.sa_family == AF_INET) { | ||
684 | + if (l < sizeof(struct sockaddr_in)) | ||
685 | + return -EINVAL; | ||
686 | + | ||
687 | + return htons(port) == sockaddr.in4.sin_port; | ||
688 | + } else { | ||
689 | + if (l < sizeof(struct sockaddr_in6)) | ||
690 | + return -EINVAL; | ||
691 | + | ||
692 | + return htons(port) == sockaddr.in6.sin6_port; | ||
693 | + } | ||
694 | + } | ||
695 | + | ||
696 | + return 1; | ||
697 | +} | ||
698 | + | ||
699 | +_sd_hidden_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { | ||
700 | + union sockaddr_union sockaddr; | ||
701 | + socklen_t l; | ||
702 | + int r; | ||
703 | + | ||
704 | + if ((r = sd_is_socket_internal(fd, type, listening)) <= 0) | ||
705 | + return r; | ||
706 | + | ||
707 | + memset(&sockaddr, 0, sizeof(sockaddr)); | ||
708 | + l = sizeof(sockaddr); | ||
709 | + | ||
710 | + if (getsockname(fd, &sockaddr.sa, &l) < 0) | ||
711 | + return -errno; | ||
712 | + | ||
713 | + if (l < sizeof(sa_family_t)) | ||
714 | + return -EINVAL; | ||
715 | + | ||
716 | + if (sockaddr.sa.sa_family != AF_UNIX) | ||
717 | + return 0; | ||
718 | + | ||
719 | + if (path) { | ||
720 | + if (length <= 0) | ||
721 | + length = strlen(path); | ||
722 | + | ||
723 | + if (length <= 0) | ||
724 | + /* Unnamed socket */ | ||
725 | + return l == offsetof(struct sockaddr_un, sun_path); | ||
726 | + | ||
727 | + if (path[0]) | ||
728 | + /* Normal path socket */ | ||
729 | + return | ||
730 | + (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && | ||
731 | + memcmp(path, sockaddr.un.sun_path, length+1) == 0; | ||
732 | + else | ||
733 | + /* Abstract namespace socket */ | ||
734 | + return | ||
735 | + (l == offsetof(struct sockaddr_un, sun_path) + length) && | ||
736 | + memcmp(path, sockaddr.un.sun_path, length) == 0; | ||
737 | + } | ||
738 | + | ||
739 | + return 1; | ||
740 | +} | ||
741 | + | ||
742 | +_sd_hidden_ int sd_is_mq(int fd, const char *path) { | ||
743 | +#if !defined(__linux__) | ||
744 | + return 0; | ||
745 | +#else | ||
746 | + struct mq_attr attr; | ||
747 | + | ||
748 | + if (fd < 0) | ||
749 | + return -EINVAL; | ||
750 | + | ||
751 | + if (mq_getattr(fd, &attr) < 0) | ||
752 | + return -errno; | ||
753 | + | ||
754 | + if (path) { | ||
755 | + char fpath[PATH_MAX]; | ||
756 | + struct stat a, b; | ||
757 | + | ||
758 | + if (path[0] != '/') | ||
759 | + return -EINVAL; | ||
760 | + | ||
761 | + if (fstat(fd, &a) < 0) | ||
762 | + return -errno; | ||
763 | + | ||
764 | + strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); | ||
765 | + fpath[sizeof(fpath)-1] = 0; | ||
766 | + | ||
767 | + if (stat(fpath, &b) < 0) | ||
768 | + return -errno; | ||
769 | + | ||
770 | + if (a.st_dev != b.st_dev || | ||
771 | + a.st_ino != b.st_ino) | ||
772 | + return 0; | ||
773 | + } | ||
774 | + | ||
775 | + return 1; | ||
776 | +#endif | ||
777 | +} | ||
778 | + | ||
779 | +_sd_hidden_ int sd_notify(int unset_environment, const char *state) { | ||
780 | +#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC) | ||
781 | + return 0; | ||
782 | +#else | ||
783 | + int fd = -1, r; | ||
784 | + struct msghdr msghdr; | ||
785 | + struct iovec iovec; | ||
786 | + union sockaddr_union sockaddr; | ||
787 | + const char *e; | ||
788 | + | ||
789 | + if (!state) { | ||
790 | + r = -EINVAL; | ||
791 | + goto finish; | ||
792 | + } | ||
793 | + | ||
794 | + if (!(e = getenv("NOTIFY_SOCKET"))) | ||
795 | + return 0; | ||
796 | + | ||
797 | + /* Must be an abstract socket, or an absolute path */ | ||
798 | + if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { | ||
799 | + r = -EINVAL; | ||
800 | + goto finish; | ||
801 | + } | ||
802 | + | ||
803 | + if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { | ||
804 | + r = -errno; | ||
805 | + goto finish; | ||
806 | + } | ||
807 | + | ||
808 | + memset(&sockaddr, 0, sizeof(sockaddr)); | ||
809 | + sockaddr.sa.sa_family = AF_UNIX; | ||
810 | + strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); | ||
811 | + | ||
812 | + if (sockaddr.un.sun_path[0] == '@') | ||
813 | + sockaddr.un.sun_path[0] = 0; | ||
814 | + | ||
815 | + memset(&iovec, 0, sizeof(iovec)); | ||
816 | + iovec.iov_base = (char*) state; | ||
817 | + iovec.iov_len = strlen(state); | ||
818 | + | ||
819 | + memset(&msghdr, 0, sizeof(msghdr)); | ||
820 | + msghdr.msg_name = &sockaddr; | ||
821 | + msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); | ||
822 | + | ||
823 | + if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) | ||
824 | + msghdr.msg_namelen = sizeof(struct sockaddr_un); | ||
825 | + | ||
826 | + msghdr.msg_iov = &iovec; | ||
827 | + msghdr.msg_iovlen = 1; | ||
828 | + | ||
829 | + if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) { | ||
830 | + r = -errno; | ||
831 | + goto finish; | ||
832 | + } | ||
833 | + | ||
834 | + r = 1; | ||
835 | + | ||
836 | +finish: | ||
837 | + if (unset_environment) | ||
838 | + unsetenv("NOTIFY_SOCKET"); | ||
839 | + | ||
840 | + if (fd >= 0) | ||
841 | + close(fd); | ||
842 | + | ||
843 | + return r; | ||
844 | +#endif | ||
845 | +} | ||
846 | + | ||
847 | +_sd_hidden_ int sd_notifyf(int unset_environment, const char *format, ...) { | ||
848 | +#if defined(DISABLE_SYSTEMD) || !defined(__linux__) | ||
849 | + return 0; | ||
850 | +#else | ||
851 | + va_list ap; | ||
852 | + char *p = NULL; | ||
853 | + int r; | ||
854 | + | ||
855 | + va_start(ap, format); | ||
856 | + r = vasprintf(&p, format, ap); | ||
857 | + va_end(ap); | ||
858 | + | ||
859 | + if (r < 0 || !p) | ||
860 | + return -ENOMEM; | ||
861 | + | ||
862 | + r = sd_notify(unset_environment, p); | ||
863 | + free(p); | ||
864 | + | ||
865 | + return r; | ||
866 | +#endif | ||
867 | +} | ||
868 | + | ||
869 | +_sd_hidden_ int sd_booted(void) { | ||
870 | +#if defined(DISABLE_SYSTEMD) || !defined(__linux__) | ||
871 | + return 0; | ||
872 | +#else | ||
873 | + | ||
874 | + struct stat a, b; | ||
875 | + | ||
876 | + /* We simply test whether the systemd cgroup hierarchy is | ||
877 | + * mounted */ | ||
878 | + | ||
879 | + if (lstat("/sys/fs/cgroup", &a) < 0) | ||
880 | + return 0; | ||
881 | + | ||
882 | + if (lstat("/sys/fs/cgroup/systemd", &b) < 0) | ||
883 | + return 0; | ||
884 | + | ||
885 | + return a.st_dev != b.st_dev; | ||
886 | +#endif | ||
887 | +} | ||
888 | diff --git a/scheduler/sd-daemon.h b/scheduler/sd-daemon.h | ||
889 | new file mode 100644 | ||
890 | index 0000000..46dc7fd | ||
891 | --- /dev/null | ||
892 | +++ b/scheduler/sd-daemon.h | ||
893 | @@ -0,0 +1,277 @@ | ||
894 | +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ | ||
895 | + | ||
896 | +#ifndef foosddaemonhfoo | ||
897 | +#define foosddaemonhfoo | ||
898 | + | ||
899 | +/*** | ||
900 | + Copyright 2010 Lennart Poettering | ||
901 | + | ||
902 | + Permission is hereby granted, free of charge, to any person | ||
903 | + obtaining a copy of this software and associated documentation files | ||
904 | + (the "Software"), to deal in the Software without restriction, | ||
905 | + including without limitation the rights to use, copy, modify, merge, | ||
906 | + publish, distribute, sublicense, and/or sell copies of the Software, | ||
907 | + and to permit persons to whom the Software is furnished to do so, | ||
908 | + subject to the following conditions: | ||
909 | + | ||
910 | + The above copyright notice and this permission notice shall be | ||
911 | + included in all copies or substantial portions of the Software. | ||
912 | + | ||
913 | + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
914 | + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
915 | + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
916 | + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
917 | + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
918 | + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
919 | + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
920 | + SOFTWARE. | ||
921 | +***/ | ||
922 | + | ||
923 | +#include <sys/types.h> | ||
924 | +#include <inttypes.h> | ||
925 | + | ||
926 | +#ifdef __cplusplus | ||
927 | +extern "C" { | ||
928 | +#endif | ||
929 | + | ||
930 | +/* | ||
931 | + Reference implementation of a few systemd related interfaces for | ||
932 | + writing daemons. These interfaces are trivial to implement. To | ||
933 | + simplify porting we provide this reference implementation. | ||
934 | + Applications are welcome to reimplement the algorithms described | ||
935 | + here if they do not want to include these two source files. | ||
936 | + | ||
937 | + The following functionality is provided: | ||
938 | + | ||
939 | + - Support for logging with log levels on stderr | ||
940 | + - File descriptor passing for socket-based activation | ||
941 | + - Daemon startup and status notification | ||
942 | + - Detection of systemd boots | ||
943 | + | ||
944 | + You may compile this with -DDISABLE_SYSTEMD to disable systemd | ||
945 | + support. This makes all those calls NOPs that are directly related to | ||
946 | + systemd (i.e. only sd_is_xxx() will stay useful). | ||
947 | + | ||
948 | + Since this is drop-in code we don't want any of our symbols to be | ||
949 | + exported in any case. Hence we declare hidden visibility for all of | ||
950 | + them. | ||
951 | + | ||
952 | + You may find an up-to-date version of these source files online: | ||
953 | + | ||
954 | + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h | ||
955 | + http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c | ||
956 | + | ||
957 | + This should compile on non-Linux systems, too, but with the | ||
958 | + exception of the sd_is_xxx() calls all functions will become NOPs. | ||
959 | + | ||
960 | + See sd-daemon(7) for more information. | ||
961 | +*/ | ||
962 | + | ||
963 | +#ifndef _sd_printf_attr_ | ||
964 | +#if __GNUC__ >= 4 | ||
965 | +#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b))) | ||
966 | +#else | ||
967 | +#define _sd_printf_attr_(a,b) | ||
968 | +#endif | ||
969 | +#endif | ||
970 | + | ||
971 | +/* | ||
972 | + Log levels for usage on stderr: | ||
973 | + | ||
974 | + fprintf(stderr, SD_NOTICE "Hello World!\n"); | ||
975 | + | ||
976 | + This is similar to printk() usage in the kernel. | ||
977 | +*/ | ||
978 | +#define SD_EMERG "<0>" /* system is unusable */ | ||
979 | +#define SD_ALERT "<1>" /* action must be taken immediately */ | ||
980 | +#define SD_CRIT "<2>" /* critical conditions */ | ||
981 | +#define SD_ERR "<3>" /* error conditions */ | ||
982 | +#define SD_WARNING "<4>" /* warning conditions */ | ||
983 | +#define SD_NOTICE "<5>" /* normal but significant condition */ | ||
984 | +#define SD_INFO "<6>" /* informational */ | ||
985 | +#define SD_DEBUG "<7>" /* debug-level messages */ | ||
986 | + | ||
987 | +/* The first passed file descriptor is fd 3 */ | ||
988 | +#define SD_LISTEN_FDS_START 3 | ||
989 | + | ||
990 | +/* | ||
991 | + Returns how many file descriptors have been passed, or a negative | ||
992 | + errno code on failure. Optionally, removes the $LISTEN_FDS and | ||
993 | + $LISTEN_PID file descriptors from the environment (recommended, but | ||
994 | + problematic in threaded environments). If r is the return value of | ||
995 | + this function you'll find the file descriptors passed as fds | ||
996 | + SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative | ||
997 | + errno style error code on failure. This function call ensures that | ||
998 | + the FD_CLOEXEC flag is set for the passed file descriptors, to make | ||
999 | + sure they are not passed on to child processes. If FD_CLOEXEC shall | ||
1000 | + not be set, the caller needs to unset it after this call for all file | ||
1001 | + descriptors that are used. | ||
1002 | + | ||
1003 | + See sd_listen_fds(3) for more information. | ||
1004 | +*/ | ||
1005 | +int sd_listen_fds(int unset_environment); | ||
1006 | + | ||
1007 | +/* | ||
1008 | + Helper call for identifying a passed file descriptor. Returns 1 if | ||
1009 | + the file descriptor is a FIFO in the file system stored under the | ||
1010 | + specified path, 0 otherwise. If path is NULL a path name check will | ||
1011 | + not be done and the call only verifies if the file descriptor | ||
1012 | + refers to a FIFO. Returns a negative errno style error code on | ||
1013 | + failure. | ||
1014 | + | ||
1015 | + See sd_is_fifo(3) for more information. | ||
1016 | +*/ | ||
1017 | +int sd_is_fifo(int fd, const char *path); | ||
1018 | + | ||
1019 | +/* | ||
1020 | + Helper call for identifying a passed file descriptor. Returns 1 if | ||
1021 | + the file descriptor is a special character device on the file | ||
1022 | + system stored under the specified path, 0 otherwise. | ||
1023 | + If path is NULL a path name check will not be done and the call | ||
1024 | + only verifies if the file descriptor refers to a special character. | ||
1025 | + Returns a negative errno style error code on failure. | ||
1026 | + | ||
1027 | + See sd_is_special(3) for more information. | ||
1028 | +*/ | ||
1029 | +int sd_is_special(int fd, const char *path); | ||
1030 | + | ||
1031 | +/* | ||
1032 | + Helper call for identifying a passed file descriptor. Returns 1 if | ||
1033 | + the file descriptor is a socket of the specified family (AF_INET, | ||
1034 | + ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If | ||
1035 | + family is 0 a socket family check will not be done. If type is 0 a | ||
1036 | + socket type check will not be done and the call only verifies if | ||
1037 | + the file descriptor refers to a socket. If listening is > 0 it is | ||
1038 | + verified that the socket is in listening mode. (i.e. listen() has | ||
1039 | + been called) If listening is == 0 it is verified that the socket is | ||
1040 | + not in listening mode. If listening is < 0 no listening mode check | ||
1041 | + is done. Returns a negative errno style error code on failure. | ||
1042 | + | ||
1043 | + See sd_is_socket(3) for more information. | ||
1044 | +*/ | ||
1045 | +int sd_is_socket(int fd, int family, int type, int listening); | ||
1046 | + | ||
1047 | +/* | ||
1048 | + Helper call for identifying a passed file descriptor. Returns 1 if | ||
1049 | + the file descriptor is an Internet socket, of the specified family | ||
1050 | + (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, | ||
1051 | + SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version | ||
1052 | + check is not done. If type is 0 a socket type check will not be | ||
1053 | + done. If port is 0 a socket port check will not be done. The | ||
1054 | + listening flag is used the same way as in sd_is_socket(). Returns a | ||
1055 | + negative errno style error code on failure. | ||
1056 | + | ||
1057 | + See sd_is_socket_inet(3) for more information. | ||
1058 | +*/ | ||
1059 | +int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); | ||
1060 | + | ||
1061 | +/* | ||
1062 | + Helper call for identifying a passed file descriptor. Returns 1 if | ||
1063 | + the file descriptor is an AF_UNIX socket of the specified type | ||
1064 | + (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 | ||
1065 | + a socket type check will not be done. If path is NULL a socket path | ||
1066 | + check will not be done. For normal AF_UNIX sockets set length to | ||
1067 | + 0. For abstract namespace sockets set length to the length of the | ||
1068 | + socket name (including the initial 0 byte), and pass the full | ||
1069 | + socket path in path (including the initial 0 byte). The listening | ||
1070 | + flag is used the same way as in sd_is_socket(). Returns a negative | ||
1071 | + errno style error code on failure. | ||
1072 | + | ||
1073 | + See sd_is_socket_unix(3) for more information. | ||
1074 | +*/ | ||
1075 | +int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); | ||
1076 | + | ||
1077 | +/* | ||
1078 | + Helper call for identifying a passed file descriptor. Returns 1 if | ||
1079 | + the file descriptor is a POSIX Message Queue of the specified name, | ||
1080 | + 0 otherwise. If path is NULL a message queue name check is not | ||
1081 | + done. Returns a negative errno style error code on failure. | ||
1082 | +*/ | ||
1083 | +int sd_is_mq(int fd, const char *path); | ||
1084 | + | ||
1085 | +/* | ||
1086 | + Informs systemd about changed daemon state. This takes a number of | ||
1087 | + newline separated environment-style variable assignments in a | ||
1088 | + string. The following variables are known: | ||
1089 | + | ||
1090 | + READY=1 Tells systemd that daemon startup is finished (only | ||
1091 | + relevant for services of Type=notify). The passed | ||
1092 | + argument is a boolean "1" or "0". Since there is | ||
1093 | + little value in signaling non-readiness the only | ||
1094 | + value daemons should send is "READY=1". | ||
1095 | + | ||
1096 | + STATUS=... Passes a single-line status string back to systemd | ||
1097 | + that describes the daemon state. This is free-from | ||
1098 | + and can be used for various purposes: general state | ||
1099 | + feedback, fsck-like programs could pass completion | ||
1100 | + percentages and failing programs could pass a human | ||
1101 | + readable error message. Example: "STATUS=Completed | ||
1102 | + 66% of file system check..." | ||
1103 | + | ||
1104 | + ERRNO=... If a daemon fails, the errno-style error code, | ||
1105 | + formatted as string. Example: "ERRNO=2" for ENOENT. | ||
1106 | + | ||
1107 | + BUSERROR=... If a daemon fails, the D-Bus error-style error | ||
1108 | + code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" | ||
1109 | + | ||
1110 | + MAINPID=... The main pid of a daemon, in case systemd did not | ||
1111 | + fork off the process itself. Example: "MAINPID=4711" | ||
1112 | + | ||
1113 | + Daemons can choose to send additional variables. However, it is | ||
1114 | + recommended to prefix variable names not listed above with X_. | ||
1115 | + | ||
1116 | + Returns a negative errno-style error code on failure. Returns > 0 | ||
1117 | + if systemd could be notified, 0 if it couldn't possibly because | ||
1118 | + systemd is not running. | ||
1119 | + | ||
1120 | + Example: When a daemon finished starting up, it could issue this | ||
1121 | + call to notify systemd about it: | ||
1122 | + | ||
1123 | + sd_notify(0, "READY=1"); | ||
1124 | + | ||
1125 | + See sd_notifyf() for more complete examples. | ||
1126 | + | ||
1127 | + See sd_notify(3) for more information. | ||
1128 | +*/ | ||
1129 | +int sd_notify(int unset_environment, const char *state); | ||
1130 | + | ||
1131 | +/* | ||
1132 | + Similar to sd_notify() but takes a format string. | ||
1133 | + | ||
1134 | + Example 1: A daemon could send the following after initialization: | ||
1135 | + | ||
1136 | + sd_notifyf(0, "READY=1\n" | ||
1137 | + "STATUS=Processing requests...\n" | ||
1138 | + "MAINPID=%lu", | ||
1139 | + (unsigned long) getpid()); | ||
1140 | + | ||
1141 | + Example 2: A daemon could send the following shortly before | ||
1142 | + exiting, on failure: | ||
1143 | + | ||
1144 | + sd_notifyf(0, "STATUS=Failed to start up: %s\n" | ||
1145 | + "ERRNO=%i", | ||
1146 | + strerror(errno), | ||
1147 | + errno); | ||
1148 | + | ||
1149 | + See sd_notifyf(3) for more information. | ||
1150 | +*/ | ||
1151 | +int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3); | ||
1152 | + | ||
1153 | +/* | ||
1154 | + Returns > 0 if the system was booted with systemd. Returns < 0 on | ||
1155 | + error. Returns 0 if the system was not booted with systemd. Note | ||
1156 | + that all of the functions above handle non-systemd boots just | ||
1157 | + fine. You should NOT protect them with a call to this function. Also | ||
1158 | + note that this function checks whether the system, not the user | ||
1159 | + session is controlled by systemd. However the functions above work | ||
1160 | + for both user and system services. | ||
1161 | + | ||
1162 | + See sd_booted(3) for more information. | ||
1163 | +*/ | ||
1164 | +int sd_booted(void); | ||
1165 | + | ||
1166 | +#ifdef __cplusplus | ||
1167 | +} | ||
1168 | +#endif | ||
1169 | + | ||
1170 | +#endif | ||
1171 | -- | ||
1172 | 1.7.6 | ||
1173 |