summaryrefslogtreecommitdiff
path: root/debian/patches/cupsd-upstart-support.patch
blob: cb85677ba7fd127a8451803b0d2fc1a414d5a946 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
Description: CUPS Upstart socket activation:
 Important to note:
 - Run by default in foreground (-f), not Foreground (-F). With -F CUPS
 closes all inherited file descriptors, which is not needed under
 upstart since it does that on our behalf, furthermore closing passed
 socket activation descriptors prevents us from using socket
 activation.
 - Force foreground (-f) mode if environment suggests that we are Upstart
 socket activated (similar to "-l" flag for launchd).
 - Initialize addrlen to sizeof(addr) to make getsockname() work.
 - Correct environment variable name used to check event type
 - Get UPSTART_FDS simply with atoi()
 - Perform explicit return code checking from getsockname function call
Author: Till Kamppeter <till.kamppeter@gmail.com>,
 Dimitri John Ledkov <xnox@ubuntu.com>
Bug: https://bugs.launchpad.net/ubuntu/+source/cups/+bug/1276713
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -71,6 +71,7 @@
 #ifdef HAVE_SYSTEMD
 static int		systemd_checkin(void);
 #endif /* HAVE_SYSTEMD */
+static void		upstart_checkin(void);
 static void		parent_handler(int sig);
 static void		process_children(void);
 static void		sigchld_handler(int sig);
@@ -342,6 +343,14 @@
       usage(1);
     }
 
+  /* force non-disconnecting foreground mode upon upstart socket
+   * activation, as otherwise all fd's are closed before we get to use
+   * them */
+  if (getenv("UPSTART_FDS"))
+  {
+    fg      = 1;
+  }
+
   if (!ConfigurationFile)
     cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf");
 
@@ -602,6 +611,11 @@
 #endif /* HAVE_SYSTEMD */
 
  /*
+  * If we were started by Upstart get the listen sockets file descriptors...
+  */
+  upstart_checkin();
+
+ /*
   * Startup the server...
   */
 
@@ -800,6 +814,13 @@
 #endif /* HAVE_SYSTEMD */
 
        /*
+        * If we were started by Upstart get the listen sockets file
+        * descriptors...
+        */
+
+        upstart_checkin();
+
+       /*
         * Startup the server...
         */
 
@@ -1681,6 +1702,94 @@
 }
 #endif /* HAVE_SYSTEMD */
 
+static void
+upstart_checkin(void)
+{
+  /*
+   * Example socket event environment:
+   *
+   * UPSTART_INSTANCE=
+   * PORT=34568
+   * PROTO=inet
+   * UPSTART_JOB=foo5
+   * UPSTART_FDS=43
+   * UPSTART_EVENTS=socket
+   * ADDR=127.0.0.1
+   *
+   */
+  int fd = 0;
+  const char *e;
+  http_addr_t addr;
+  socklen_t addrlen = sizeof(addr);
+  cupsd_listener_t *lis;
+  char s[256];
+
+  if (!(e = getenv("UPSTART_EVENTS")))
+    return;
+
+  if (strcasecmp(e, "socket"))
+    return;
+
+  if (!(e = getenv("UPSTART_FDS")))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+            "upstart_checkin: We got started via Upstart socket event but no environment variable UPSTART_FDS is not set");
+    return;
+  }
+
+  fd = atoi(e);
+
+  if (getsockname(fd, (struct sockaddr*) &addr, &addrlen) < 0)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+            "upstart_checkin: Unable to get local address - %s",
+            strerror(errno));
+    return;
+  }
+
+ /*
+  * Try to match the systemd socket address to one of the listeners...
+  */
+
+  for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
+       lis;
+       lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
+    if (httpAddrEqual(&lis->address, &addr))
+      break;
+
+  if (lis)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+            "upstart_checkin: Matched existing listener %s with fd %d...",
+            httpAddrString(&(lis->address), s, sizeof(s)), fd);
+  }
+  else
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+            "upstart_checkin: Adding new listener %s with fd %d...",
+            httpAddrString(&addr, s, sizeof(s)), fd);
+
+    if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+              "upstart_checkin: Unable to allocate listener - "
+              "%s.", strerror(errno));
+      exit(EXIT_FAILURE);
+    }
+
+    cupsArrayAdd(Listeners, lis);
+
+    memcpy(&lis->address, &addr, sizeof(lis->address));
+  }
+
+  lis->fd = fd;
+
+#  ifdef HAVE_SSL
+  if (_httpAddrPort(&(lis->address)) == 443)
+    lis->encryption = HTTP_ENCRYPT_ALWAYS;
+#  endif /* HAVE_SSL */
+}
+
 /*
  * 'parent_handler()' - Catch USR1/CHLD signals...
  */