Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 376021 | Differences between
and this patch

Collapse All | Expand All

(-)a/Makedefs.in (+2 lines)
Lines 143-148 CXXFLAGS = @CPPFLAGS@ @CXXFLAGS@ Link Here
143
CXXLIBS		=	@CXXLIBS@
143
CXXLIBS		=	@CXXLIBS@
144
DBUS_NOTIFIER	=	@DBUS_NOTIFIER@
144
DBUS_NOTIFIER	=	@DBUS_NOTIFIER@
145
DBUS_NOTIFIERLIBS =	@DBUS_NOTIFIERLIBS@
145
DBUS_NOTIFIERLIBS =	@DBUS_NOTIFIERLIBS@
146
SYSTEMD_UNITS   =       @SYSTEMD_UNITS@
146
DNSSD_BACKEND	=	@DNSSD_BACKEND@
147
DNSSD_BACKEND	=	@DNSSD_BACKEND@
147
DSOFLAGS	=	-L../cups @DSOFLAGS@
148
DSOFLAGS	=	-L../cups @DSOFLAGS@
148
DSOLIBS		=	@DSOLIBS@ $(COMMONLIBS)
149
DSOLIBS		=	@DSOLIBS@ $(COMMONLIBS)
Lines 267-272 PAMFILE = @PAMFILE@ Link Here
267
268
268
DEFAULT_LAUNCHD_CONF =	@DEFAULT_LAUNCHD_CONF@
269
DEFAULT_LAUNCHD_CONF =	@DEFAULT_LAUNCHD_CONF@
269
DBUSDIR		=	@DBUSDIR@
270
DBUSDIR		=	@DBUSDIR@
271
SYSTEMDUNITDIR  =       $(BUILDROOT)@systemdsystemunitdir@
270
272
271
273
272
#
274
#
(-)a/config-scripts/cups-systemd.m4 (+25 lines)
Line 0 Link Here
1
dnl
2
dnl "$Id$"
3
dnl
4
dnl   systemd stuff for CUPS.
5
6
dnl Find whether systemd is available
7
8
AC_ARG_WITH([systemdsystemunitdir],
9
        AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
10
        [], [with_systemdsystemunitdir=$($PKGCONFIG --variable=systemdsystemunitdir systemd)])
11
if test "x$with_systemdsystemunitdir" != xno; then
12
        AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
13
fi
14
15
if test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ; then
16
        SYSTEMD_UNITS="cups.service cups.socket cups.path"
17
else
18
        SYSTEMD_UNITS=""
19
fi
20
21
AC_SUBST(SYSTEMD_UNITS)
22
23
dnl
24
dnl "$Id$"
25
dnl
(-)a/configure.in (+4 lines)
Lines 37-42 sinclude(config-scripts/cups-pam.m4) Link Here
37
sinclude(config-scripts/cups-largefile.m4)
37
sinclude(config-scripts/cups-largefile.m4)
38
sinclude(config-scripts/cups-dnssd.m4)
38
sinclude(config-scripts/cups-dnssd.m4)
39
sinclude(config-scripts/cups-launchd.m4)
39
sinclude(config-scripts/cups-launchd.m4)
40
sinclude(config-scripts/cups-systemd.m4)
40
sinclude(config-scripts/cups-defaults.m4)
41
sinclude(config-scripts/cups-defaults.m4)
41
sinclude(config-scripts/cups-pdf.m4)
42
sinclude(config-scripts/cups-pdf.m4)
42
sinclude(config-scripts/cups-scripting.m4)
43
sinclude(config-scripts/cups-scripting.m4)
Lines 71-76 AC_OUTPUT(Makedefs Link Here
71
	  conf/snmp.conf
72
	  conf/snmp.conf
72
	  cups-config
73
	  cups-config
73
	  data/testprint
74
	  data/testprint
75
          data/cups.service
76
          data/cups.socket
77
          data/cups.path
74
	  desktop/cups.desktop
78
	  desktop/cups.desktop
75
	  doc/help/ref-cupsd-conf.html
79
	  doc/help/ref-cupsd-conf.html
76
	  doc/help/standard.html
80
	  doc/help/standard.html
(-)a/data/Makefile (+9 lines)
Lines 112-117 install-data: Link Here
112
		$(INSTALL_DATA) $$file $(DATADIR)/ppdc; \
112
		$(INSTALL_DATA) $$file $(DATADIR)/ppdc; \
113
	done
113
	done
114
	$(INSTALL_DIR) -m 755 $(DATADIR)/profiles
114
	$(INSTALL_DIR) -m 755 $(DATADIR)/profiles
115
	if test "x$(SYSTEMD_UNITS)" != "x" ; then \
116
		$(INSTALL_DIR) -m 755 $(SYSTEMDUNITDIR); \
117
		for file in $(SYSTEMD_UNITS); do \
118
			$(INSTALL_DATA) $$file $(SYSTEMDUNITDIR); \
119
		done; \
120
	fi
115
121
116
122
117
#
123
#
Lines 159-164 uninstall: Link Here
159
	-$(RMDIR) $(DATADIR)/charsets
165
	-$(RMDIR) $(DATADIR)/charsets
160
	-$(RMDIR) $(DATADIR)/banners
166
	-$(RMDIR) $(DATADIR)/banners
161
	-$(RMDIR) $(DATADIR)
167
	-$(RMDIR) $(DATADIR)
168
	for file in $(SYSTEMD_UNITS); do \
169
		$(RM) $(SYSTEMDUNITDIR)/$$file; \
170
	done
162
171
163
172
164
#
173
#
(-)a/data/cups.path.in (+8 lines)
Line 0 Link Here
1
[Unit]
2
Description=CUPS Printer Service Spool
3
4
[Path]
5
DirectoryNotEmpty=@CUPS_REQUESTS@
6
7
[Install]
8
WantedBy=multi-user.target
(-)a/data/cups.service.in (+9 lines)
Line 0 Link Here
1
[Unit]
2
Description=CUPS Printing Service
3
4
[Service]
5
ExecStart=@sbindir@/cupsd -f
6
7
[Install]
8
Also=cups.socket cups.path
9
WantedBy=printer.target
(-)a/data/cups.socket.in (+9 lines)
Line 0 Link Here
1
[Unit]
2
Description=CUPS Printing Service Sockets
3
4
[Socket]
5
ListenStream=@CUPS_DEFAULT_DOMAINSOCKET@
6
ListenStream=631
7
8
[Install]
9
WantedBy=sockets.target
(-)a/scheduler/Makefile (+9 lines)
Lines 39-44 CUPSDOBJS = \ Link Here
39
		server.o \
39
		server.o \
40
		statbuf.o \
40
		statbuf.o \
41
		subscriptions.o \
41
		subscriptions.o \
42
		sd-daemon.o \
42
		sysman.o
43
		sysman.o
43
LIBOBJS =	\
44
LIBOBJS =	\
44
		filter.o \
45
		filter.o \
Lines 568-573 sloc: Link Here
568
569
569
570
570
#
571
#
572
# Update sd-daemon.[ch] drop-in file from upstream git
573
#
574
575
update-systemd:
576
	curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c > sd-daemon.c
577
	curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h > sd-daemon.h
578
579
#
571
# Dependencies...
580
# Dependencies...
572
#
581
#
573
582
(-)a/scheduler/main.c (+107 lines)
Lines 26-31 Link Here
26
 *   launchd_checkin()     - Check-in with launchd and collect the listening
26
 *   launchd_checkin()     - Check-in with launchd and collect the listening
27
 *                           fds.
27
 *                           fds.
28
 *   launchd_checkout()    - Update the launchd KeepAlive file as needed.
28
 *   launchd_checkout()    - Update the launchd KeepAlive file as needed.
29
 *   systemd_checkin()     - Check-in with systemd and collect the
30
 *                           listening fds.
29
 *   parent_handler()      - Catch USR1/CHLD signals...
31
 *   parent_handler()      - Catch USR1/CHLD signals...
30
 *   process_children()    - Process all dead children...
32
 *   process_children()    - Process all dead children...
31
 *   select_timeout()      - Calculate the select timeout value.
33
 *   select_timeout()      - Calculate the select timeout value.
Lines 62-67 Link Here
62
#  endif /* !LAUNCH_JOBKEY_SERVICEIPC */
64
#  endif /* !LAUNCH_JOBKEY_SERVICEIPC */
63
#endif /* HAVE_LAUNCH_H */
65
#endif /* HAVE_LAUNCH_H */
64
66
67
#include "sd-daemon.h"
68
65
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
69
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
66
#  include <malloc.h>
70
#  include <malloc.h>
67
#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */
71
#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */
Lines 78-83 Link Here
78
static void		launchd_checkin(void);
82
static void		launchd_checkin(void);
79
static void		launchd_checkout(void);
83
static void		launchd_checkout(void);
80
#endif /* HAVE_LAUNCHD */
84
#endif /* HAVE_LAUNCHD */
85
static void		systemd_checkin(void);
81
static void		parent_handler(int sig);
86
static void		parent_handler(int sig);
82
static void		process_children(void);
87
static void		process_children(void);
83
static void		sigchld_handler(int sig);
88
static void		sigchld_handler(int sig);
Lines 520-525 main(int argc, /* I - Number of command-line args */ Link Here
520
#endif /* HAVE_LAUNCHD */
525
#endif /* HAVE_LAUNCHD */
521
526
522
 /*
527
 /*
528
  * If we were started by systemd get the listen sockets file descriptors...
529
  */
530
  systemd_checkin();
531
532
 /*
523
  * Startup the server...
533
  * Startup the server...
524
  */
534
  */
525
535
Lines 731-736 main(int argc, /* I - Number of command-line args */ Link Here
731
#endif /* HAVE_LAUNCHD */
741
#endif /* HAVE_LAUNCHD */
732
742
733
       /*
743
       /*
744
        * If we were started by systemd get the listen sockets file descriptors...
745
        */
746
747
        systemd_checkin();
748
749
       /*
734
        * Startup the server...
750
        * Startup the server...
735
        */
751
        */
736
752
Lines 1535-1540 launchd_checkout(void) Link Here
1535
}
1551
}
1536
#endif /* HAVE_LAUNCHD */
1552
#endif /* HAVE_LAUNCHD */
1537
1553
1554
static void
1555
systemd_checkin(void)
1556
{
1557
  int n, fd;
1558
1559
  n = sd_listen_fds(1);
1560
  if (n < 0)
1561
  {
1562
    cupsdLogMessage(CUPSD_LOG_ERROR,
1563
           "systemd_checkin: Failed to acquire sockets from systemd - %s",
1564
           strerror(-n));
1565
    exit(EXIT_FAILURE);
1566
    return;
1567
  }
1568
1569
  if (n == 0)
1570
    return;
1571
1572
  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1573
  {
1574
    http_addr_t addr;
1575
    socklen_t addrlen;
1576
    int r;
1577
    cupsd_listener_t *lis;
1578
    char s[256];
1579
1580
    r = sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1);
1581
    if (r < 0) {
1582
      cupsdLogMessage(CUPSD_LOG_ERROR,
1583
             "systemd_checkin: Unable to verify socket type - %s",
1584
             strerror(-r));
1585
      continue;
1586
    }
1587
1588
    if (!r) {
1589
      cupsdLogMessage(CUPSD_LOG_ERROR,
1590
             "systemd_checkin: Socket not of the right type");
1591
      continue;
1592
    }
1593
1594
    if (getsockname(fd, (struct sockaddr*) &addr, &addrlen))
1595
    {
1596
      cupsdLogMessage(CUPSD_LOG_ERROR,
1597
             "systemd_checkin: Unable to get local address - %s",
1598
             strerror(errno));
1599
      continue;
1600
    }
1601
1602
     /*
1603
    * Try to match the systemd socket address to one of the listeners...
1604
    */
1605
1606
    for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
1607
       lis;
1608
       lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
1609
      if (httpAddrEqual(&lis->address, &addr))
1610
      break;
1611
1612
    if (lis)
1613
    {
1614
      cupsdLogMessage(CUPSD_LOG_DEBUG,
1615
                      "systemd_checkin: Matched existing listener %s with fd %d...",
1616
                      httpAddrString(&(lis->address), s, sizeof(s)), fd);
1617
    }
1618
    else
1619
    {
1620
      cupsdLogMessage(CUPSD_LOG_DEBUG,
1621
                      "systemd_checkin: Adding new listener %s with fd %d...",
1622
                      httpAddrString(&addr, s, sizeof(s)), fd);
1623
1624
      if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
1625
      {
1626
        cupsdLogMessage(CUPSD_LOG_ERROR,
1627
                        "systemd_checkin: Unable to allocate listener - "
1628
                        "%s.", strerror(errno));
1629
        exit(EXIT_FAILURE);
1630
      }
1631
1632
      cupsArrayAdd(Listeners, lis);
1633
1634
      memcpy(&lis->address, &addr, sizeof(lis->address));
1635
    }
1636
1637
    lis->fd = fd;
1638
1639
#  ifdef HAVE_SSL
1640
    if (_httpAddrPort(&(lis->address)) == 443)
1641
      lis->encryption = HTTP_ENCRYPT_ALWAYS;
1642
#  endif /* HAVE_SSL */
1643
  }
1644
}
1538
1645
1539
/*
1646
/*
1540
 * 'parent_handler()' - Catch USR1/CHLD signals...
1647
 * 'parent_handler()' - Catch USR1/CHLD signals...
(-)a/scheduler/sd-daemon.c (+520 lines)
Line 0 Link Here
1
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3
/***
4
  Copyright 2010 Lennart Poettering
5
6
  Permission is hereby granted, free of charge, to any person
7
  obtaining a copy of this software and associated documentation files
8
  (the "Software"), to deal in the Software without restriction,
9
  including without limitation the rights to use, copy, modify, merge,
10
  publish, distribute, sublicense, and/or sell copies of the Software,
11
  and to permit persons to whom the Software is furnished to do so,
12
  subject to the following conditions:
13
14
  The above copyright notice and this permission notice shall be
15
  included in all copies or substantial portions of the Software.
16
17
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
  SOFTWARE.
25
***/
26
27
#ifndef _GNU_SOURCE
28
#define _GNU_SOURCE
29
#endif
30
31
#include <sys/types.h>
32
#include <sys/stat.h>
33
#include <sys/socket.h>
34
#include <sys/un.h>
35
#include <sys/fcntl.h>
36
#include <netinet/in.h>
37
#include <stdlib.h>
38
#include <errno.h>
39
#include <unistd.h>
40
#include <string.h>
41
#include <stdarg.h>
42
#include <stdio.h>
43
#include <stddef.h>
44
#include <limits.h>
45
46
#if defined(__linux__)
47
#include <mqueue.h>
48
#endif
49
50
#include "sd-daemon.h"
51
52
#if (__GNUC__ >= 4) && !defined(SD_EXPORT_SYMBOLS)
53
#define _sd_hidden_ __attribute__ ((visibility("hidden")))
54
#else
55
#define _sd_hidden_
56
#endif
57
58
_sd_hidden_ int sd_listen_fds(int unset_environment) {
59
60
#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
61
        return 0;
62
#else
63
        int r, fd;
64
        const char *e;
65
        char *p = NULL;
66
        unsigned long l;
67
68
        if (!(e = getenv("LISTEN_PID"))) {
69
                r = 0;
70
                goto finish;
71
        }
72
73
        errno = 0;
74
        l = strtoul(e, &p, 10);
75
76
        if (errno != 0) {
77
                r = -errno;
78
                goto finish;
79
        }
80
81
        if (!p || *p || l <= 0) {
82
                r = -EINVAL;
83
                goto finish;
84
        }
85
86
        /* Is this for us? */
87
        if (getpid() != (pid_t) l) {
88
                r = 0;
89
                goto finish;
90
        }
91
92
        if (!(e = getenv("LISTEN_FDS"))) {
93
                r = 0;
94
                goto finish;
95
        }
96
97
        errno = 0;
98
        l = strtoul(e, &p, 10);
99
100
        if (errno != 0) {
101
                r = -errno;
102
                goto finish;
103
        }
104
105
        if (!p || *p) {
106
                r = -EINVAL;
107
                goto finish;
108
        }
109
110
        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) {
111
                int flags;
112
113
                if ((flags = fcntl(fd, F_GETFD)) < 0) {
114
                        r = -errno;
115
                        goto finish;
116
                }
117
118
                if (flags & FD_CLOEXEC)
119
                        continue;
120
121
                if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
122
                        r = -errno;
123
                        goto finish;
124
                }
125
        }
126
127
        r = (int) l;
128
129
finish:
130
        if (unset_environment) {
131
                unsetenv("LISTEN_PID");
132
                unsetenv("LISTEN_FDS");
133
        }
134
135
        return r;
136
#endif
137
}
138
139
_sd_hidden_ int sd_is_fifo(int fd, const char *path) {
140
        struct stat st_fd;
141
142
        if (fd < 0)
143
                return -EINVAL;
144
145
        memset(&st_fd, 0, sizeof(st_fd));
146
        if (fstat(fd, &st_fd) < 0)
147
                return -errno;
148
149
        if (!S_ISFIFO(st_fd.st_mode))
150
                return 0;
151
152
        if (path) {
153
                struct stat st_path;
154
155
                memset(&st_path, 0, sizeof(st_path));
156
                if (stat(path, &st_path) < 0) {
157
158
                        if (errno == ENOENT || errno == ENOTDIR)
159
                                return 0;
160
161
                        return -errno;
162
                }
163
164
                return
165
                        st_path.st_dev == st_fd.st_dev &&
166
                        st_path.st_ino == st_fd.st_ino;
167
        }
168
169
        return 1;
170
}
171
172
_sd_hidden_ int sd_is_special(int fd, const char *path) {
173
        struct stat st_fd;
174
175
        if (fd < 0)
176
                return -EINVAL;
177
178
        if (fstat(fd, &st_fd) < 0)
179
                return -errno;
180
181
        if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
182
                return 0;
183
184
        if (path) {
185
                struct stat st_path;
186
187
                if (stat(path, &st_path) < 0) {
188
189
                        if (errno == ENOENT || errno == ENOTDIR)
190
                                return 0;
191
192
                        return -errno;
193
                }
194
195
                if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
196
                        return
197
                                st_path.st_dev == st_fd.st_dev &&
198
                                st_path.st_ino == st_fd.st_ino;
199
                else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
200
                        return st_path.st_rdev == st_fd.st_rdev;
201
                else
202
                        return 0;
203
        }
204
205
        return 1;
206
}
207
208
static int sd_is_socket_internal(int fd, int type, int listening) {
209
        struct stat st_fd;
210
211
        if (fd < 0 || type < 0)
212
                return -EINVAL;
213
214
        if (fstat(fd, &st_fd) < 0)
215
                return -errno;
216
217
        if (!S_ISSOCK(st_fd.st_mode))
218
                return 0;
219
220
        if (type != 0) {
221
                int other_type = 0;
222
                socklen_t l = sizeof(other_type);
223
224
                if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
225
                        return -errno;
226
227
                if (l != sizeof(other_type))
228
                        return -EINVAL;
229
230
                if (other_type != type)
231
                        return 0;
232
        }
233
234
        if (listening >= 0) {
235
                int accepting = 0;
236
                socklen_t l = sizeof(accepting);
237
238
                if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
239
                        return -errno;
240
241
                if (l != sizeof(accepting))
242
                        return -EINVAL;
243
244
                if (!accepting != !listening)
245
                        return 0;
246
        }
247
248
        return 1;
249
}
250
251
union sockaddr_union {
252
        struct sockaddr sa;
253
        struct sockaddr_in in4;
254
        struct sockaddr_in6 in6;
255
        struct sockaddr_un un;
256
        struct sockaddr_storage storage;
257
};
258
259
_sd_hidden_ int sd_is_socket(int fd, int family, int type, int listening) {
260
        int r;
261
262
        if (family < 0)
263
                return -EINVAL;
264
265
        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
266
                return r;
267
268
        if (family > 0) {
269
                union sockaddr_union sockaddr;
270
                socklen_t l;
271
272
                memset(&sockaddr, 0, sizeof(sockaddr));
273
                l = sizeof(sockaddr);
274
275
                if (getsockname(fd, &sockaddr.sa, &l) < 0)
276
                        return -errno;
277
278
                if (l < sizeof(sa_family_t))
279
                        return -EINVAL;
280
281
                return sockaddr.sa.sa_family == family;
282
        }
283
284
        return 1;
285
}
286
287
_sd_hidden_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
288
        union sockaddr_union sockaddr;
289
        socklen_t l;
290
        int r;
291
292
        if (family != 0 && family != AF_INET && family != AF_INET6)
293
                return -EINVAL;
294
295
        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
296
                return r;
297
298
        memset(&sockaddr, 0, sizeof(sockaddr));
299
        l = sizeof(sockaddr);
300
301
        if (getsockname(fd, &sockaddr.sa, &l) < 0)
302
                return -errno;
303
304
        if (l < sizeof(sa_family_t))
305
                return -EINVAL;
306
307
        if (sockaddr.sa.sa_family != AF_INET &&
308
            sockaddr.sa.sa_family != AF_INET6)
309
                return 0;
310
311
        if (family > 0)
312
                if (sockaddr.sa.sa_family != family)
313
                        return 0;
314
315
        if (port > 0) {
316
                if (sockaddr.sa.sa_family == AF_INET) {
317
                        if (l < sizeof(struct sockaddr_in))
318
                                return -EINVAL;
319
320
                        return htons(port) == sockaddr.in4.sin_port;
321
                } else {
322
                        if (l < sizeof(struct sockaddr_in6))
323
                                return -EINVAL;
324
325
                        return htons(port) == sockaddr.in6.sin6_port;
326
                }
327
        }
328
329
        return 1;
330
}
331
332
_sd_hidden_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
333
        union sockaddr_union sockaddr;
334
        socklen_t l;
335
        int r;
336
337
        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
338
                return r;
339
340
        memset(&sockaddr, 0, sizeof(sockaddr));
341
        l = sizeof(sockaddr);
342
343
        if (getsockname(fd, &sockaddr.sa, &l) < 0)
344
                return -errno;
345
346
        if (l < sizeof(sa_family_t))
347
                return -EINVAL;
348
349
        if (sockaddr.sa.sa_family != AF_UNIX)
350
                return 0;
351
352
        if (path) {
353
                if (length <= 0)
354
                        length = strlen(path);
355
356
                if (length <= 0)
357
                        /* Unnamed socket */
358
                        return l == offsetof(struct sockaddr_un, sun_path);
359
360
                if (path[0])
361
                        /* Normal path socket */
362
                        return
363
                                (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
364
                                memcmp(path, sockaddr.un.sun_path, length+1) == 0;
365
                else
366
                        /* Abstract namespace socket */
367
                        return
368
                                (l == offsetof(struct sockaddr_un, sun_path) + length) &&
369
                                memcmp(path, sockaddr.un.sun_path, length) == 0;
370
        }
371
372
        return 1;
373
}
374
375
_sd_hidden_ int sd_is_mq(int fd, const char *path) {
376
#if !defined(__linux__)
377
        return 0;
378
#else
379
        struct mq_attr attr;
380
381
        if (fd < 0)
382
                return -EINVAL;
383
384
        if (mq_getattr(fd, &attr) < 0)
385
                return -errno;
386
387
        if (path) {
388
                char fpath[PATH_MAX];
389
                struct stat a, b;
390
391
                if (path[0] != '/')
392
                        return -EINVAL;
393
394
                if (fstat(fd, &a) < 0)
395
                        return -errno;
396
397
                strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
398
                fpath[sizeof(fpath)-1] = 0;
399
400
                if (stat(fpath, &b) < 0)
401
                        return -errno;
402
403
                if (a.st_dev != b.st_dev ||
404
                    a.st_ino != b.st_ino)
405
                        return 0;
406
        }
407
408
        return 1;
409
#endif
410
}
411
412
_sd_hidden_ int sd_notify(int unset_environment, const char *state) {
413
#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
414
        return 0;
415
#else
416
        int fd = -1, r;
417
        struct msghdr msghdr;
418
        struct iovec iovec;
419
        union sockaddr_union sockaddr;
420
        const char *e;
421
422
        if (!state) {
423
                r = -EINVAL;
424
                goto finish;
425
        }
426
427
        if (!(e = getenv("NOTIFY_SOCKET")))
428
                return 0;
429
430
        /* Must be an abstract socket, or an absolute path */
431
        if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
432
                r = -EINVAL;
433
                goto finish;
434
        }
435
436
        if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
437
                r = -errno;
438
                goto finish;
439
        }
440
441
        memset(&sockaddr, 0, sizeof(sockaddr));
442
        sockaddr.sa.sa_family = AF_UNIX;
443
        strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
444
445
        if (sockaddr.un.sun_path[0] == '@')
446
                sockaddr.un.sun_path[0] = 0;
447
448
        memset(&iovec, 0, sizeof(iovec));
449
        iovec.iov_base = (char*) state;
450
        iovec.iov_len = strlen(state);
451
452
        memset(&msghdr, 0, sizeof(msghdr));
453
        msghdr.msg_name = &sockaddr;
454
        msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
455
456
        if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
457
                msghdr.msg_namelen = sizeof(struct sockaddr_un);
458
459
        msghdr.msg_iov = &iovec;
460
        msghdr.msg_iovlen = 1;
461
462
        if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
463
                r = -errno;
464
                goto finish;
465
        }
466
467
        r = 1;
468
469
finish:
470
        if (unset_environment)
471
                unsetenv("NOTIFY_SOCKET");
472
473
        if (fd >= 0)
474
                close(fd);
475
476
        return r;
477
#endif
478
}
479
480
_sd_hidden_ int sd_notifyf(int unset_environment, const char *format, ...) {
481
#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
482
        return 0;
483
#else
484
        va_list ap;
485
        char *p = NULL;
486
        int r;
487
488
        va_start(ap, format);
489
        r = vasprintf(&p, format, ap);
490
        va_end(ap);
491
492
        if (r < 0 || !p)
493
                return -ENOMEM;
494
495
        r = sd_notify(unset_environment, p);
496
        free(p);
497
498
        return r;
499
#endif
500
}
501
502
_sd_hidden_ int sd_booted(void) {
503
#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
504
        return 0;
505
#else
506
507
        struct stat a, b;
508
509
        /* We simply test whether the systemd cgroup hierarchy is
510
         * mounted */
511
512
        if (lstat("/sys/fs/cgroup", &a) < 0)
513
                return 0;
514
515
        if (lstat("/sys/fs/cgroup/systemd", &b) < 0)
516
                return 0;
517
518
        return a.st_dev != b.st_dev;
519
#endif
520
}
(-)a/scheduler/sd-daemon.h (-1 / +277 lines)
Line 0 Link Here
0
- 
1
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3
#ifndef foosddaemonhfoo
4
#define foosddaemonhfoo
5
6
/***
7
  Copyright 2010 Lennart Poettering
8
9
  Permission is hereby granted, free of charge, to any person
10
  obtaining a copy of this software and associated documentation files
11
  (the "Software"), to deal in the Software without restriction,
12
  including without limitation the rights to use, copy, modify, merge,
13
  publish, distribute, sublicense, and/or sell copies of the Software,
14
  and to permit persons to whom the Software is furnished to do so,
15
  subject to the following conditions:
16
17
  The above copyright notice and this permission notice shall be
18
  included in all copies or substantial portions of the Software.
19
20
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
  SOFTWARE.
28
***/
29
30
#include <sys/types.h>
31
#include <inttypes.h>
32
33
#ifdef __cplusplus
34
extern "C" {
35
#endif
36
37
/*
38
  Reference implementation of a few systemd related interfaces for
39
  writing daemons. These interfaces are trivial to implement. To
40
  simplify porting we provide this reference implementation.
41
  Applications are welcome to reimplement the algorithms described
42
  here if they do not want to include these two source files.
43
44
  The following functionality is provided:
45
46
  - Support for logging with log levels on stderr
47
  - File descriptor passing for socket-based activation
48
  - Daemon startup and status notification
49
  - Detection of systemd boots
50
51
  You may compile this with -DDISABLE_SYSTEMD to disable systemd
52
  support. This makes all those calls NOPs that are directly related to
53
  systemd (i.e. only sd_is_xxx() will stay useful).
54
55
  Since this is drop-in code we don't want any of our symbols to be
56
  exported in any case. Hence we declare hidden visibility for all of
57
  them.
58
59
  You may find an up-to-date version of these source files online:
60
61
  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h
62
  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c
63
64
  This should compile on non-Linux systems, too, but with the
65
  exception of the sd_is_xxx() calls all functions will become NOPs.
66
67
  See sd-daemon(7) for more information.
68
*/
69
70
#ifndef _sd_printf_attr_
71
#if __GNUC__ >= 4
72
#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
73
#else
74
#define _sd_printf_attr_(a,b)
75
#endif
76
#endif
77
78
/*
79
  Log levels for usage on stderr:
80
81
          fprintf(stderr, SD_NOTICE "Hello World!\n");
82
83
  This is similar to printk() usage in the kernel.
84
*/
85
#define SD_EMERG   "<0>"  /* system is unusable */
86
#define SD_ALERT   "<1>"  /* action must be taken immediately */
87
#define SD_CRIT    "<2>"  /* critical conditions */
88
#define SD_ERR     "<3>"  /* error conditions */
89
#define SD_WARNING "<4>"  /* warning conditions */
90
#define SD_NOTICE  "<5>"  /* normal but significant condition */
91
#define SD_INFO    "<6>"  /* informational */
92
#define SD_DEBUG   "<7>"  /* debug-level messages */
93
94
/* The first passed file descriptor is fd 3 */
95
#define SD_LISTEN_FDS_START 3
96
97
/*
98
  Returns how many file descriptors have been passed, or a negative
99
  errno code on failure. Optionally, removes the $LISTEN_FDS and
100
  $LISTEN_PID file descriptors from the environment (recommended, but
101
  problematic in threaded environments). If r is the return value of
102
  this function you'll find the file descriptors passed as fds
103
  SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
104
  errno style error code on failure. This function call ensures that
105
  the FD_CLOEXEC flag is set for the passed file descriptors, to make
106
  sure they are not passed on to child processes. If FD_CLOEXEC shall
107
  not be set, the caller needs to unset it after this call for all file
108
  descriptors that are used.
109
110
  See sd_listen_fds(3) for more information.
111
*/
112
int sd_listen_fds(int unset_environment);
113
114
/*
115
  Helper call for identifying a passed file descriptor. Returns 1 if
116
  the file descriptor is a FIFO in the file system stored under the
117
  specified path, 0 otherwise. If path is NULL a path name check will
118
  not be done and the call only verifies if the file descriptor
119
  refers to a FIFO. Returns a negative errno style error code on
120
  failure.
121
122
  See sd_is_fifo(3) for more information.
123
*/
124
int sd_is_fifo(int fd, const char *path);
125
126
/*
127
  Helper call for identifying a passed file descriptor. Returns 1 if
128
  the file descriptor is a special character device on the file
129
  system stored under the specified path, 0 otherwise.
130
  If path is NULL a path name check will not be done and the call
131
  only verifies if the file descriptor refers to a special character.
132
  Returns a negative errno style error code on failure.
133
134
  See sd_is_special(3) for more information.
135
*/
136
int sd_is_special(int fd, const char *path);
137
138
/*
139
  Helper call for identifying a passed file descriptor. Returns 1 if
140
  the file descriptor is a socket of the specified family (AF_INET,
141
  ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
142
  family is 0 a socket family check will not be done. If type is 0 a
143
  socket type check will not be done and the call only verifies if
144
  the file descriptor refers to a socket. If listening is > 0 it is
145
  verified that the socket is in listening mode. (i.e. listen() has
146
  been called) If listening is == 0 it is verified that the socket is
147
  not in listening mode. If listening is < 0 no listening mode check
148
  is done. Returns a negative errno style error code on failure.
149
150
  See sd_is_socket(3) for more information.
151
*/
152
int sd_is_socket(int fd, int family, int type, int listening);
153
154
/*
155
  Helper call for identifying a passed file descriptor. Returns 1 if
156
  the file descriptor is an Internet socket, of the specified family
157
  (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM,
158
  SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
159
  check is not done. If type is 0 a socket type check will not be
160
  done. If port is 0 a socket port check will not be done. The
161
  listening flag is used the same way as in sd_is_socket(). Returns a
162
  negative errno style error code on failure.
163
164
  See sd_is_socket_inet(3) for more information.
165
*/
166
int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port);
167
168
/*
169
  Helper call for identifying a passed file descriptor. Returns 1 if
170
  the file descriptor is an AF_UNIX socket of the specified type
171
  (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0
172
  a socket type check will not be done. If path is NULL a socket path
173
  check will not be done. For normal AF_UNIX sockets set length to
174
  0. For abstract namespace sockets set length to the length of the
175
  socket name (including the initial 0 byte), and pass the full
176
  socket path in path (including the initial 0 byte). The listening
177
  flag is used the same way as in sd_is_socket(). Returns a negative
178
  errno style error code on failure.
179
180
  See sd_is_socket_unix(3) for more information.
181
*/
182
int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length);
183
184
/*
185
  Helper call for identifying a passed file descriptor. Returns 1 if
186
  the file descriptor is a POSIX Message Queue of the specified name,
187
  0 otherwise. If path is NULL a message queue name check is not
188
  done. Returns a negative errno style error code on failure.
189
*/
190
int sd_is_mq(int fd, const char *path);
191
192
/*
193
  Informs systemd about changed daemon state. This takes a number of
194
  newline separated environment-style variable assignments in a
195
  string. The following variables are known:
196
197
     READY=1      Tells systemd that daemon startup is finished (only
198
                  relevant for services of Type=notify). The passed
199
                  argument is a boolean "1" or "0". Since there is
200
                  little value in signaling non-readiness the only
201
                  value daemons should send is "READY=1".
202
203
     STATUS=...   Passes a single-line status string back to systemd
204
                  that describes the daemon state. This is free-from
205
                  and can be used for various purposes: general state
206
                  feedback, fsck-like programs could pass completion
207
                  percentages and failing programs could pass a human
208
                  readable error message. Example: "STATUS=Completed
209
                  66% of file system check..."
210
211
     ERRNO=...    If a daemon fails, the errno-style error code,
212
                  formatted as string. Example: "ERRNO=2" for ENOENT.
213
214
     BUSERROR=... If a daemon fails, the D-Bus error-style error
215
                  code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
216
217
     MAINPID=...  The main pid of a daemon, in case systemd did not
218
                  fork off the process itself. Example: "MAINPID=4711"
219
220
  Daemons can choose to send additional variables. However, it is
221
  recommended to prefix variable names not listed above with X_.
222
223
  Returns a negative errno-style error code on failure. Returns > 0
224
  if systemd could be notified, 0 if it couldn't possibly because
225
  systemd is not running.
226
227
  Example: When a daemon finished starting up, it could issue this
228
  call to notify systemd about it:
229
230
     sd_notify(0, "READY=1");
231
232
  See sd_notifyf() for more complete examples.
233
234
  See sd_notify(3) for more information.
235
*/
236
int sd_notify(int unset_environment, const char *state);
237
238
/*
239
  Similar to sd_notify() but takes a format string.
240
241
  Example 1: A daemon could send the following after initialization:
242
243
     sd_notifyf(0, "READY=1\n"
244
                   "STATUS=Processing requests...\n"
245
                   "MAINPID=%lu",
246
                   (unsigned long) getpid());
247
248
  Example 2: A daemon could send the following shortly before
249
  exiting, on failure:
250
251
     sd_notifyf(0, "STATUS=Failed to start up: %s\n"
252
                   "ERRNO=%i",
253
                   strerror(errno),
254
                   errno);
255
256
  See sd_notifyf(3) for more information.
257
*/
258
int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3);
259
260
/*
261
  Returns > 0 if the system was booted with systemd. Returns < 0 on
262
  error. Returns 0 if the system was not booted with systemd. Note
263
  that all of the functions above handle non-systemd boots just
264
  fine. You should NOT protect them with a call to this function. Also
265
  note that this function checks whether the system, not the user
266
  session is controlled by systemd. However the functions above work
267
  for both user and system services.
268
269
  See sd_booted(3) for more information.
270
*/
271
int sd_booted(void);
272
273
#ifdef __cplusplus
274
}
275
#endif
276
277
#endif

Return to bug 376021