1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * Device scanning mini-daemon for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2018 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright © 1997-2006 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker * information.
9*5e7646d2SAndroid Build Coastguard Worker */
10*5e7646d2SAndroid Build Coastguard Worker
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker */
14*5e7646d2SAndroid Build Coastguard Worker
15*5e7646d2SAndroid Build Coastguard Worker #include "util.h"
16*5e7646d2SAndroid Build Coastguard Worker #include <cups/array.h>
17*5e7646d2SAndroid Build Coastguard Worker #include <cups/dir.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <fcntl.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <sys/wait.h>
20*5e7646d2SAndroid Build Coastguard Worker #include <poll.h>
21*5e7646d2SAndroid Build Coastguard Worker
22*5e7646d2SAndroid Build Coastguard Worker
23*5e7646d2SAndroid Build Coastguard Worker /*
24*5e7646d2SAndroid Build Coastguard Worker * Constants...
25*5e7646d2SAndroid Build Coastguard Worker */
26*5e7646d2SAndroid Build Coastguard Worker
27*5e7646d2SAndroid Build Coastguard Worker #define MAX_BACKENDS 200 /* Maximum number of backends we'll run */
28*5e7646d2SAndroid Build Coastguard Worker
29*5e7646d2SAndroid Build Coastguard Worker
30*5e7646d2SAndroid Build Coastguard Worker /*
31*5e7646d2SAndroid Build Coastguard Worker * Backend information...
32*5e7646d2SAndroid Build Coastguard Worker */
33*5e7646d2SAndroid Build Coastguard Worker
34*5e7646d2SAndroid Build Coastguard Worker typedef struct
35*5e7646d2SAndroid Build Coastguard Worker {
36*5e7646d2SAndroid Build Coastguard Worker char *name; /* Name of backend */
37*5e7646d2SAndroid Build Coastguard Worker int pid, /* Process ID */
38*5e7646d2SAndroid Build Coastguard Worker status; /* Exit status */
39*5e7646d2SAndroid Build Coastguard Worker cups_file_t *pipe; /* Pipe from backend stdout */
40*5e7646d2SAndroid Build Coastguard Worker int count; /* Number of devices found */
41*5e7646d2SAndroid Build Coastguard Worker } cupsd_backend_t;
42*5e7646d2SAndroid Build Coastguard Worker
43*5e7646d2SAndroid Build Coastguard Worker
44*5e7646d2SAndroid Build Coastguard Worker /*
45*5e7646d2SAndroid Build Coastguard Worker * Device information structure...
46*5e7646d2SAndroid Build Coastguard Worker */
47*5e7646d2SAndroid Build Coastguard Worker
48*5e7646d2SAndroid Build Coastguard Worker typedef struct
49*5e7646d2SAndroid Build Coastguard Worker {
50*5e7646d2SAndroid Build Coastguard Worker char device_class[128], /* Device class */
51*5e7646d2SAndroid Build Coastguard Worker device_info[128], /* Device info/description */
52*5e7646d2SAndroid Build Coastguard Worker device_uri[1024]; /* Device URI */
53*5e7646d2SAndroid Build Coastguard Worker } cupsd_device_t;
54*5e7646d2SAndroid Build Coastguard Worker
55*5e7646d2SAndroid Build Coastguard Worker
56*5e7646d2SAndroid Build Coastguard Worker /*
57*5e7646d2SAndroid Build Coastguard Worker * Local globals...
58*5e7646d2SAndroid Build Coastguard Worker */
59*5e7646d2SAndroid Build Coastguard Worker
60*5e7646d2SAndroid Build Coastguard Worker static int num_backends = 0,
61*5e7646d2SAndroid Build Coastguard Worker /* Total backends */
62*5e7646d2SAndroid Build Coastguard Worker active_backends = 0;
63*5e7646d2SAndroid Build Coastguard Worker /* Active backends */
64*5e7646d2SAndroid Build Coastguard Worker static cupsd_backend_t backends[MAX_BACKENDS];
65*5e7646d2SAndroid Build Coastguard Worker /* Array of backends */
66*5e7646d2SAndroid Build Coastguard Worker static struct pollfd backend_fds[MAX_BACKENDS];
67*5e7646d2SAndroid Build Coastguard Worker /* Array for poll() */
68*5e7646d2SAndroid Build Coastguard Worker static cups_array_t *devices; /* Array of devices */
69*5e7646d2SAndroid Build Coastguard Worker static uid_t normal_user; /* Normal user ID */
70*5e7646d2SAndroid Build Coastguard Worker static int device_limit; /* Maximum number of devices */
71*5e7646d2SAndroid Build Coastguard Worker static int send_class, /* Send device-class attribute? */
72*5e7646d2SAndroid Build Coastguard Worker send_info, /* Send device-info attribute? */
73*5e7646d2SAndroid Build Coastguard Worker send_make_and_model,
74*5e7646d2SAndroid Build Coastguard Worker /* Send device-make-and-model attribute? */
75*5e7646d2SAndroid Build Coastguard Worker send_uri, /* Send device-uri attribute? */
76*5e7646d2SAndroid Build Coastguard Worker send_id, /* Send device-id attribute? */
77*5e7646d2SAndroid Build Coastguard Worker send_location; /* Send device-location attribute? */
78*5e7646d2SAndroid Build Coastguard Worker static int dead_children = 0;
79*5e7646d2SAndroid Build Coastguard Worker /* Dead children? */
80*5e7646d2SAndroid Build Coastguard Worker
81*5e7646d2SAndroid Build Coastguard Worker
82*5e7646d2SAndroid Build Coastguard Worker /*
83*5e7646d2SAndroid Build Coastguard Worker * Local functions...
84*5e7646d2SAndroid Build Coastguard Worker */
85*5e7646d2SAndroid Build Coastguard Worker
86*5e7646d2SAndroid Build Coastguard Worker static int add_device(const char *device_class,
87*5e7646d2SAndroid Build Coastguard Worker const char *device_make_and_model,
88*5e7646d2SAndroid Build Coastguard Worker const char *device_info,
89*5e7646d2SAndroid Build Coastguard Worker const char *device_uri,
90*5e7646d2SAndroid Build Coastguard Worker const char *device_id,
91*5e7646d2SAndroid Build Coastguard Worker const char *device_location);
92*5e7646d2SAndroid Build Coastguard Worker static int compare_devices(cupsd_device_t *p0,
93*5e7646d2SAndroid Build Coastguard Worker cupsd_device_t *p1);
94*5e7646d2SAndroid Build Coastguard Worker static double get_current_time(void);
95*5e7646d2SAndroid Build Coastguard Worker static int get_device(cupsd_backend_t *backend);
96*5e7646d2SAndroid Build Coastguard Worker static void process_children(void);
97*5e7646d2SAndroid Build Coastguard Worker static void sigchld_handler(int sig);
98*5e7646d2SAndroid Build Coastguard Worker static int start_backend(const char *backend, int root);
99*5e7646d2SAndroid Build Coastguard Worker
100*5e7646d2SAndroid Build Coastguard Worker
101*5e7646d2SAndroid Build Coastguard Worker /*
102*5e7646d2SAndroid Build Coastguard Worker * 'main()' - Scan for devices and return an IPP response.
103*5e7646d2SAndroid Build Coastguard Worker *
104*5e7646d2SAndroid Build Coastguard Worker * Usage:
105*5e7646d2SAndroid Build Coastguard Worker *
106*5e7646d2SAndroid Build Coastguard Worker * cups-deviced request_id limit options
107*5e7646d2SAndroid Build Coastguard Worker */
108*5e7646d2SAndroid Build Coastguard Worker
109*5e7646d2SAndroid Build Coastguard Worker int /* O - Exit code */
main(int argc,char * argv[])110*5e7646d2SAndroid Build Coastguard Worker main(int argc, /* I - Number of command-line args */
111*5e7646d2SAndroid Build Coastguard Worker char *argv[]) /* I - Command-line arguments */
112*5e7646d2SAndroid Build Coastguard Worker {
113*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
114*5e7646d2SAndroid Build Coastguard Worker int request_id; /* Request ID */
115*5e7646d2SAndroid Build Coastguard Worker int timeout; /* Timeout in seconds */
116*5e7646d2SAndroid Build Coastguard Worker const char *server_bin; /* CUPS_SERVERBIN environment variable */
117*5e7646d2SAndroid Build Coastguard Worker char filename[1024]; /* Backend directory filename */
118*5e7646d2SAndroid Build Coastguard Worker cups_dir_t *dir; /* Directory pointer */
119*5e7646d2SAndroid Build Coastguard Worker cups_dentry_t *dent; /* Directory entry */
120*5e7646d2SAndroid Build Coastguard Worker double current_time, /* Current time */
121*5e7646d2SAndroid Build Coastguard Worker end_time; /* Ending time */
122*5e7646d2SAndroid Build Coastguard Worker int num_options; /* Number of options */
123*5e7646d2SAndroid Build Coastguard Worker cups_option_t *options; /* Options */
124*5e7646d2SAndroid Build Coastguard Worker cups_array_t *requested, /* requested-attributes values */
125*5e7646d2SAndroid Build Coastguard Worker *exclude, /* exclude-schemes values */
126*5e7646d2SAndroid Build Coastguard Worker *include; /* include-schemes values */
127*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
128*5e7646d2SAndroid Build Coastguard Worker struct sigaction action; /* Actions for POSIX signals */
129*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
130*5e7646d2SAndroid Build Coastguard Worker
131*5e7646d2SAndroid Build Coastguard Worker
132*5e7646d2SAndroid Build Coastguard Worker setbuf(stderr, NULL);
133*5e7646d2SAndroid Build Coastguard Worker
134*5e7646d2SAndroid Build Coastguard Worker /*
135*5e7646d2SAndroid Build Coastguard Worker * Check the command-line...
136*5e7646d2SAndroid Build Coastguard Worker */
137*5e7646d2SAndroid Build Coastguard Worker
138*5e7646d2SAndroid Build Coastguard Worker if (argc != 6)
139*5e7646d2SAndroid Build Coastguard Worker {
140*5e7646d2SAndroid Build Coastguard Worker fputs("Usage: cups-deviced request-id limit timeout user-id options\n", stderr);
141*5e7646d2SAndroid Build Coastguard Worker
142*5e7646d2SAndroid Build Coastguard Worker return (1);
143*5e7646d2SAndroid Build Coastguard Worker }
144*5e7646d2SAndroid Build Coastguard Worker
145*5e7646d2SAndroid Build Coastguard Worker request_id = atoi(argv[1]);
146*5e7646d2SAndroid Build Coastguard Worker if (request_id < 1)
147*5e7646d2SAndroid Build Coastguard Worker {
148*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: [cups-deviced] Bad request ID %d!\n", request_id);
149*5e7646d2SAndroid Build Coastguard Worker
150*5e7646d2SAndroid Build Coastguard Worker return (1);
151*5e7646d2SAndroid Build Coastguard Worker }
152*5e7646d2SAndroid Build Coastguard Worker
153*5e7646d2SAndroid Build Coastguard Worker device_limit = atoi(argv[2]);
154*5e7646d2SAndroid Build Coastguard Worker if (device_limit < 0)
155*5e7646d2SAndroid Build Coastguard Worker {
156*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: [cups-deviced] Bad limit %d!\n", device_limit);
157*5e7646d2SAndroid Build Coastguard Worker
158*5e7646d2SAndroid Build Coastguard Worker return (1);
159*5e7646d2SAndroid Build Coastguard Worker }
160*5e7646d2SAndroid Build Coastguard Worker
161*5e7646d2SAndroid Build Coastguard Worker timeout = atoi(argv[3]);
162*5e7646d2SAndroid Build Coastguard Worker if (timeout < 1)
163*5e7646d2SAndroid Build Coastguard Worker {
164*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: [cups-deviced] Bad timeout %d!\n", timeout);
165*5e7646d2SAndroid Build Coastguard Worker
166*5e7646d2SAndroid Build Coastguard Worker return (1);
167*5e7646d2SAndroid Build Coastguard Worker }
168*5e7646d2SAndroid Build Coastguard Worker
169*5e7646d2SAndroid Build Coastguard Worker normal_user = (uid_t)atoi(argv[4]);
170*5e7646d2SAndroid Build Coastguard Worker if (normal_user <= 0)
171*5e7646d2SAndroid Build Coastguard Worker {
172*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: [cups-deviced] Bad user %d!\n", normal_user);
173*5e7646d2SAndroid Build Coastguard Worker
174*5e7646d2SAndroid Build Coastguard Worker return (1);
175*5e7646d2SAndroid Build Coastguard Worker }
176*5e7646d2SAndroid Build Coastguard Worker
177*5e7646d2SAndroid Build Coastguard Worker num_options = cupsParseOptions(argv[5], 0, &options);
178*5e7646d2SAndroid Build Coastguard Worker requested = cupsdCreateStringsArray(cupsGetOption("requested-attributes",
179*5e7646d2SAndroid Build Coastguard Worker num_options, options));
180*5e7646d2SAndroid Build Coastguard Worker exclude = cupsdCreateStringsArray(cupsGetOption("exclude-schemes",
181*5e7646d2SAndroid Build Coastguard Worker num_options, options));
182*5e7646d2SAndroid Build Coastguard Worker include = cupsdCreateStringsArray(cupsGetOption("include-schemes",
183*5e7646d2SAndroid Build Coastguard Worker num_options, options));
184*5e7646d2SAndroid Build Coastguard Worker
185*5e7646d2SAndroid Build Coastguard Worker if (!requested || cupsArrayFind(requested, "all") != NULL)
186*5e7646d2SAndroid Build Coastguard Worker {
187*5e7646d2SAndroid Build Coastguard Worker send_class = send_info = send_make_and_model = send_uri = send_id =
188*5e7646d2SAndroid Build Coastguard Worker send_location = 1;
189*5e7646d2SAndroid Build Coastguard Worker }
190*5e7646d2SAndroid Build Coastguard Worker else
191*5e7646d2SAndroid Build Coastguard Worker {
192*5e7646d2SAndroid Build Coastguard Worker send_class = cupsArrayFind(requested, "device-class") != NULL;
193*5e7646d2SAndroid Build Coastguard Worker send_info = cupsArrayFind(requested, "device-info") != NULL;
194*5e7646d2SAndroid Build Coastguard Worker send_make_and_model = cupsArrayFind(requested, "device-make-and-model") != NULL;
195*5e7646d2SAndroid Build Coastguard Worker send_uri = cupsArrayFind(requested, "device-uri") != NULL;
196*5e7646d2SAndroid Build Coastguard Worker send_id = cupsArrayFind(requested, "device-id") != NULL;
197*5e7646d2SAndroid Build Coastguard Worker send_location = cupsArrayFind(requested, "device-location") != NULL;
198*5e7646d2SAndroid Build Coastguard Worker }
199*5e7646d2SAndroid Build Coastguard Worker
200*5e7646d2SAndroid Build Coastguard Worker /*
201*5e7646d2SAndroid Build Coastguard Worker * Listen to child signals...
202*5e7646d2SAndroid Build Coastguard Worker */
203*5e7646d2SAndroid Build Coastguard Worker
204*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
205*5e7646d2SAndroid Build Coastguard Worker sigset(SIGCHLD, sigchld_handler);
206*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_SIGACTION)
207*5e7646d2SAndroid Build Coastguard Worker memset(&action, 0, sizeof(action));
208*5e7646d2SAndroid Build Coastguard Worker
209*5e7646d2SAndroid Build Coastguard Worker sigemptyset(&action.sa_mask);
210*5e7646d2SAndroid Build Coastguard Worker sigaddset(&action.sa_mask, SIGCHLD);
211*5e7646d2SAndroid Build Coastguard Worker action.sa_handler = sigchld_handler;
212*5e7646d2SAndroid Build Coastguard Worker sigaction(SIGCHLD, &action, NULL);
213*5e7646d2SAndroid Build Coastguard Worker #else
214*5e7646d2SAndroid Build Coastguard Worker signal(SIGCLD, sigchld_handler); /* No, SIGCLD isn't a typo... */
215*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGSET */
216*5e7646d2SAndroid Build Coastguard Worker
217*5e7646d2SAndroid Build Coastguard Worker /*
218*5e7646d2SAndroid Build Coastguard Worker * Try opening the backend directory...
219*5e7646d2SAndroid Build Coastguard Worker */
220*5e7646d2SAndroid Build Coastguard Worker
221*5e7646d2SAndroid Build Coastguard Worker if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL)
222*5e7646d2SAndroid Build Coastguard Worker server_bin = CUPS_SERVERBIN;
223*5e7646d2SAndroid Build Coastguard Worker
224*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/backend", server_bin);
225*5e7646d2SAndroid Build Coastguard Worker
226*5e7646d2SAndroid Build Coastguard Worker if ((dir = cupsDirOpen(filename)) == NULL)
227*5e7646d2SAndroid Build Coastguard Worker {
228*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: [cups-deviced] Unable to open backend directory "
229*5e7646d2SAndroid Build Coastguard Worker "\"%s\": %s", filename, strerror(errno));
230*5e7646d2SAndroid Build Coastguard Worker
231*5e7646d2SAndroid Build Coastguard Worker return (1);
232*5e7646d2SAndroid Build Coastguard Worker }
233*5e7646d2SAndroid Build Coastguard Worker
234*5e7646d2SAndroid Build Coastguard Worker /*
235*5e7646d2SAndroid Build Coastguard Worker * Setup the devices array...
236*5e7646d2SAndroid Build Coastguard Worker */
237*5e7646d2SAndroid Build Coastguard Worker
238*5e7646d2SAndroid Build Coastguard Worker devices = cupsArrayNew((cups_array_func_t)compare_devices, NULL);
239*5e7646d2SAndroid Build Coastguard Worker
240*5e7646d2SAndroid Build Coastguard Worker /*
241*5e7646d2SAndroid Build Coastguard Worker * Loop through all of the device backends...
242*5e7646d2SAndroid Build Coastguard Worker */
243*5e7646d2SAndroid Build Coastguard Worker
244*5e7646d2SAndroid Build Coastguard Worker while ((dent = cupsDirRead(dir)) != NULL)
245*5e7646d2SAndroid Build Coastguard Worker {
246*5e7646d2SAndroid Build Coastguard Worker /*
247*5e7646d2SAndroid Build Coastguard Worker * Skip entries that are not executable files...
248*5e7646d2SAndroid Build Coastguard Worker */
249*5e7646d2SAndroid Build Coastguard Worker
250*5e7646d2SAndroid Build Coastguard Worker if (!S_ISREG(dent->fileinfo.st_mode) ||
251*5e7646d2SAndroid Build Coastguard Worker !isalnum(dent->filename[0] & 255) ||
252*5e7646d2SAndroid Build Coastguard Worker (dent->fileinfo.st_mode & (S_IRUSR | S_IXUSR)) != (S_IRUSR | S_IXUSR))
253*5e7646d2SAndroid Build Coastguard Worker continue;
254*5e7646d2SAndroid Build Coastguard Worker
255*5e7646d2SAndroid Build Coastguard Worker /*
256*5e7646d2SAndroid Build Coastguard Worker * Skip excluded or not included backends...
257*5e7646d2SAndroid Build Coastguard Worker */
258*5e7646d2SAndroid Build Coastguard Worker
259*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayFind(exclude, dent->filename) ||
260*5e7646d2SAndroid Build Coastguard Worker (include && !cupsArrayFind(include, dent->filename)))
261*5e7646d2SAndroid Build Coastguard Worker continue;
262*5e7646d2SAndroid Build Coastguard Worker
263*5e7646d2SAndroid Build Coastguard Worker /*
264*5e7646d2SAndroid Build Coastguard Worker * Backends without permissions for normal users run as root,
265*5e7646d2SAndroid Build Coastguard Worker * all others run as the unprivileged user...
266*5e7646d2SAndroid Build Coastguard Worker */
267*5e7646d2SAndroid Build Coastguard Worker
268*5e7646d2SAndroid Build Coastguard Worker start_backend(dent->filename, !(dent->fileinfo.st_mode & (S_IWGRP | S_IWOTH | S_IXOTH)));
269*5e7646d2SAndroid Build Coastguard Worker }
270*5e7646d2SAndroid Build Coastguard Worker
271*5e7646d2SAndroid Build Coastguard Worker cupsDirClose(dir);
272*5e7646d2SAndroid Build Coastguard Worker
273*5e7646d2SAndroid Build Coastguard Worker /*
274*5e7646d2SAndroid Build Coastguard Worker * Collect devices...
275*5e7646d2SAndroid Build Coastguard Worker */
276*5e7646d2SAndroid Build Coastguard Worker
277*5e7646d2SAndroid Build Coastguard Worker if (getenv("SOFTWARE"))
278*5e7646d2SAndroid Build Coastguard Worker puts("Content-Type: application/ipp\n");
279*5e7646d2SAndroid Build Coastguard Worker
280*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPHeader(IPP_OK, request_id);
281*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPGroup(IPP_TAG_OPERATION);
282*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
283*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US");
284*5e7646d2SAndroid Build Coastguard Worker
285*5e7646d2SAndroid Build Coastguard Worker end_time = get_current_time() + timeout;
286*5e7646d2SAndroid Build Coastguard Worker
287*5e7646d2SAndroid Build Coastguard Worker while (active_backends > 0 && (current_time = get_current_time()) < end_time)
288*5e7646d2SAndroid Build Coastguard Worker {
289*5e7646d2SAndroid Build Coastguard Worker /*
290*5e7646d2SAndroid Build Coastguard Worker * Collect the output from the backends...
291*5e7646d2SAndroid Build Coastguard Worker */
292*5e7646d2SAndroid Build Coastguard Worker
293*5e7646d2SAndroid Build Coastguard Worker timeout = (int)(1000 * (end_time - current_time));
294*5e7646d2SAndroid Build Coastguard Worker
295*5e7646d2SAndroid Build Coastguard Worker if (poll(backend_fds, (nfds_t)num_backends, timeout) > 0)
296*5e7646d2SAndroid Build Coastguard Worker {
297*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < num_backends; i ++)
298*5e7646d2SAndroid Build Coastguard Worker if (backend_fds[i].revents && backends[i].pipe)
299*5e7646d2SAndroid Build Coastguard Worker {
300*5e7646d2SAndroid Build Coastguard Worker cups_file_t *bpipe = backends[i].pipe;
301*5e7646d2SAndroid Build Coastguard Worker /* Copy of pipe for backend... */
302*5e7646d2SAndroid Build Coastguard Worker
303*5e7646d2SAndroid Build Coastguard Worker do
304*5e7646d2SAndroid Build Coastguard Worker {
305*5e7646d2SAndroid Build Coastguard Worker if (get_device(backends + i))
306*5e7646d2SAndroid Build Coastguard Worker {
307*5e7646d2SAndroid Build Coastguard Worker backend_fds[i].fd = 0;
308*5e7646d2SAndroid Build Coastguard Worker backend_fds[i].events = 0;
309*5e7646d2SAndroid Build Coastguard Worker break;
310*5e7646d2SAndroid Build Coastguard Worker }
311*5e7646d2SAndroid Build Coastguard Worker }
312*5e7646d2SAndroid Build Coastguard Worker while (_cupsFilePeekAhead(bpipe, '\n'));
313*5e7646d2SAndroid Build Coastguard Worker }
314*5e7646d2SAndroid Build Coastguard Worker }
315*5e7646d2SAndroid Build Coastguard Worker
316*5e7646d2SAndroid Build Coastguard Worker /*
317*5e7646d2SAndroid Build Coastguard Worker * Get exit status from children...
318*5e7646d2SAndroid Build Coastguard Worker */
319*5e7646d2SAndroid Build Coastguard Worker
320*5e7646d2SAndroid Build Coastguard Worker if (dead_children)
321*5e7646d2SAndroid Build Coastguard Worker process_children();
322*5e7646d2SAndroid Build Coastguard Worker }
323*5e7646d2SAndroid Build Coastguard Worker
324*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPTrailer();
325*5e7646d2SAndroid Build Coastguard Worker
326*5e7646d2SAndroid Build Coastguard Worker /*
327*5e7646d2SAndroid Build Coastguard Worker * Terminate any remaining backends and exit...
328*5e7646d2SAndroid Build Coastguard Worker */
329*5e7646d2SAndroid Build Coastguard Worker
330*5e7646d2SAndroid Build Coastguard Worker if (active_backends > 0)
331*5e7646d2SAndroid Build Coastguard Worker {
332*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < num_backends; i ++)
333*5e7646d2SAndroid Build Coastguard Worker if (backends[i].pid)
334*5e7646d2SAndroid Build Coastguard Worker kill(backends[i].pid, SIGTERM);
335*5e7646d2SAndroid Build Coastguard Worker }
336*5e7646d2SAndroid Build Coastguard Worker
337*5e7646d2SAndroid Build Coastguard Worker return (0);
338*5e7646d2SAndroid Build Coastguard Worker }
339*5e7646d2SAndroid Build Coastguard Worker
340*5e7646d2SAndroid Build Coastguard Worker
341*5e7646d2SAndroid Build Coastguard Worker /*
342*5e7646d2SAndroid Build Coastguard Worker * 'add_device()' - Add a new device to the list.
343*5e7646d2SAndroid Build Coastguard Worker */
344*5e7646d2SAndroid Build Coastguard Worker
345*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on error */
add_device(const char * device_class,const char * device_make_and_model,const char * device_info,const char * device_uri,const char * device_id,const char * device_location)346*5e7646d2SAndroid Build Coastguard Worker add_device(
347*5e7646d2SAndroid Build Coastguard Worker const char *device_class, /* I - Device class */
348*5e7646d2SAndroid Build Coastguard Worker const char *device_make_and_model, /* I - Device make and model */
349*5e7646d2SAndroid Build Coastguard Worker const char *device_info, /* I - Device information */
350*5e7646d2SAndroid Build Coastguard Worker const char *device_uri, /* I - Device URI */
351*5e7646d2SAndroid Build Coastguard Worker const char *device_id, /* I - 1284 device ID */
352*5e7646d2SAndroid Build Coastguard Worker const char *device_location) /* I - Physical location */
353*5e7646d2SAndroid Build Coastguard Worker {
354*5e7646d2SAndroid Build Coastguard Worker cupsd_device_t *device; /* New device */
355*5e7646d2SAndroid Build Coastguard Worker
356*5e7646d2SAndroid Build Coastguard Worker
357*5e7646d2SAndroid Build Coastguard Worker /*
358*5e7646d2SAndroid Build Coastguard Worker * Allocate memory for the device record...
359*5e7646d2SAndroid Build Coastguard Worker */
360*5e7646d2SAndroid Build Coastguard Worker
361*5e7646d2SAndroid Build Coastguard Worker if ((device = calloc(1, sizeof(cupsd_device_t))) == NULL)
362*5e7646d2SAndroid Build Coastguard Worker {
363*5e7646d2SAndroid Build Coastguard Worker fputs("ERROR: [cups-deviced] Ran out of memory allocating a device!\n",
364*5e7646d2SAndroid Build Coastguard Worker stderr);
365*5e7646d2SAndroid Build Coastguard Worker return (-1);
366*5e7646d2SAndroid Build Coastguard Worker }
367*5e7646d2SAndroid Build Coastguard Worker
368*5e7646d2SAndroid Build Coastguard Worker /*
369*5e7646d2SAndroid Build Coastguard Worker * Copy the strings over...
370*5e7646d2SAndroid Build Coastguard Worker */
371*5e7646d2SAndroid Build Coastguard Worker
372*5e7646d2SAndroid Build Coastguard Worker strlcpy(device->device_class, device_class, sizeof(device->device_class));
373*5e7646d2SAndroid Build Coastguard Worker strlcpy(device->device_info, device_info, sizeof(device->device_info));
374*5e7646d2SAndroid Build Coastguard Worker strlcpy(device->device_uri, device_uri, sizeof(device->device_uri));
375*5e7646d2SAndroid Build Coastguard Worker
376*5e7646d2SAndroid Build Coastguard Worker /*
377*5e7646d2SAndroid Build Coastguard Worker * Add the device to the array and return...
378*5e7646d2SAndroid Build Coastguard Worker */
379*5e7646d2SAndroid Build Coastguard Worker
380*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayFind(devices, device))
381*5e7646d2SAndroid Build Coastguard Worker {
382*5e7646d2SAndroid Build Coastguard Worker /*
383*5e7646d2SAndroid Build Coastguard Worker * Avoid duplicates!
384*5e7646d2SAndroid Build Coastguard Worker */
385*5e7646d2SAndroid Build Coastguard Worker
386*5e7646d2SAndroid Build Coastguard Worker free(device);
387*5e7646d2SAndroid Build Coastguard Worker }
388*5e7646d2SAndroid Build Coastguard Worker else
389*5e7646d2SAndroid Build Coastguard Worker {
390*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(devices, device);
391*5e7646d2SAndroid Build Coastguard Worker
392*5e7646d2SAndroid Build Coastguard Worker if (device_limit <= 0 || cupsArrayCount(devices) < device_limit)
393*5e7646d2SAndroid Build Coastguard Worker {
394*5e7646d2SAndroid Build Coastguard Worker /*
395*5e7646d2SAndroid Build Coastguard Worker * Send device info...
396*5e7646d2SAndroid Build Coastguard Worker */
397*5e7646d2SAndroid Build Coastguard Worker
398*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPGroup(IPP_TAG_PRINTER);
399*5e7646d2SAndroid Build Coastguard Worker if (send_class)
400*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPString(IPP_TAG_KEYWORD, "device-class",
401*5e7646d2SAndroid Build Coastguard Worker device_class);
402*5e7646d2SAndroid Build Coastguard Worker if (send_info)
403*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPString(IPP_TAG_TEXT, "device-info", device_info);
404*5e7646d2SAndroid Build Coastguard Worker if (send_make_and_model)
405*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPString(IPP_TAG_TEXT, "device-make-and-model",
406*5e7646d2SAndroid Build Coastguard Worker device_make_and_model);
407*5e7646d2SAndroid Build Coastguard Worker if (send_uri)
408*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPString(IPP_TAG_URI, "device-uri", device_uri);
409*5e7646d2SAndroid Build Coastguard Worker if (send_id)
410*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPString(IPP_TAG_TEXT, "device-id",
411*5e7646d2SAndroid Build Coastguard Worker device_id ? device_id : "");
412*5e7646d2SAndroid Build Coastguard Worker if (send_location)
413*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPString(IPP_TAG_TEXT, "device-location",
414*5e7646d2SAndroid Build Coastguard Worker device_location ? device_location : "");
415*5e7646d2SAndroid Build Coastguard Worker
416*5e7646d2SAndroid Build Coastguard Worker fflush(stdout);
417*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Flushed attributes...\n", stderr);
418*5e7646d2SAndroid Build Coastguard Worker }
419*5e7646d2SAndroid Build Coastguard Worker }
420*5e7646d2SAndroid Build Coastguard Worker
421*5e7646d2SAndroid Build Coastguard Worker return (0);
422*5e7646d2SAndroid Build Coastguard Worker }
423*5e7646d2SAndroid Build Coastguard Worker
424*5e7646d2SAndroid Build Coastguard Worker
425*5e7646d2SAndroid Build Coastguard Worker /*
426*5e7646d2SAndroid Build Coastguard Worker * 'compare_devices()' - Compare device names to eliminate duplicates.
427*5e7646d2SAndroid Build Coastguard Worker */
428*5e7646d2SAndroid Build Coastguard Worker
429*5e7646d2SAndroid Build Coastguard Worker static int /* O - Result of comparison */
compare_devices(cupsd_device_t * d0,cupsd_device_t * d1)430*5e7646d2SAndroid Build Coastguard Worker compare_devices(cupsd_device_t *d0, /* I - First device */
431*5e7646d2SAndroid Build Coastguard Worker cupsd_device_t *d1) /* I - Second device */
432*5e7646d2SAndroid Build Coastguard Worker {
433*5e7646d2SAndroid Build Coastguard Worker int diff; /* Difference between strings */
434*5e7646d2SAndroid Build Coastguard Worker
435*5e7646d2SAndroid Build Coastguard Worker
436*5e7646d2SAndroid Build Coastguard Worker /*
437*5e7646d2SAndroid Build Coastguard Worker * Sort devices by device-info, device-class, and device-uri...
438*5e7646d2SAndroid Build Coastguard Worker */
439*5e7646d2SAndroid Build Coastguard Worker
440*5e7646d2SAndroid Build Coastguard Worker if ((diff = cupsdCompareNames(d0->device_info, d1->device_info)) != 0)
441*5e7646d2SAndroid Build Coastguard Worker return (diff);
442*5e7646d2SAndroid Build Coastguard Worker else if ((diff = _cups_strcasecmp(d0->device_class, d1->device_class)) != 0)
443*5e7646d2SAndroid Build Coastguard Worker return (diff);
444*5e7646d2SAndroid Build Coastguard Worker else
445*5e7646d2SAndroid Build Coastguard Worker return (_cups_strcasecmp(d0->device_uri, d1->device_uri));
446*5e7646d2SAndroid Build Coastguard Worker }
447*5e7646d2SAndroid Build Coastguard Worker
448*5e7646d2SAndroid Build Coastguard Worker
449*5e7646d2SAndroid Build Coastguard Worker /*
450*5e7646d2SAndroid Build Coastguard Worker * 'get_current_time()' - Get the current time as a double value in seconds.
451*5e7646d2SAndroid Build Coastguard Worker */
452*5e7646d2SAndroid Build Coastguard Worker
453*5e7646d2SAndroid Build Coastguard Worker static double /* O - Time in seconds */
get_current_time(void)454*5e7646d2SAndroid Build Coastguard Worker get_current_time(void)
455*5e7646d2SAndroid Build Coastguard Worker {
456*5e7646d2SAndroid Build Coastguard Worker struct timeval curtime; /* Current time */
457*5e7646d2SAndroid Build Coastguard Worker
458*5e7646d2SAndroid Build Coastguard Worker
459*5e7646d2SAndroid Build Coastguard Worker gettimeofday(&curtime, NULL);
460*5e7646d2SAndroid Build Coastguard Worker
461*5e7646d2SAndroid Build Coastguard Worker return (curtime.tv_sec + 0.000001 * curtime.tv_usec);
462*5e7646d2SAndroid Build Coastguard Worker }
463*5e7646d2SAndroid Build Coastguard Worker
464*5e7646d2SAndroid Build Coastguard Worker
465*5e7646d2SAndroid Build Coastguard Worker /*
466*5e7646d2SAndroid Build Coastguard Worker * 'get_device()' - Get a device from a backend.
467*5e7646d2SAndroid Build Coastguard Worker */
468*5e7646d2SAndroid Build Coastguard Worker
469*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on error */
get_device(cupsd_backend_t * backend)470*5e7646d2SAndroid Build Coastguard Worker get_device(cupsd_backend_t *backend) /* I - Backend to read from */
471*5e7646d2SAndroid Build Coastguard Worker {
472*5e7646d2SAndroid Build Coastguard Worker char line[2048], /* Line from backend */
473*5e7646d2SAndroid Build Coastguard Worker temp[2048], /* Copy of line */
474*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into line */
475*5e7646d2SAndroid Build Coastguard Worker *dclass, /* Device class */
476*5e7646d2SAndroid Build Coastguard Worker *uri, /* Device URI */
477*5e7646d2SAndroid Build Coastguard Worker *make_model, /* Make and model */
478*5e7646d2SAndroid Build Coastguard Worker *info, /* Device info */
479*5e7646d2SAndroid Build Coastguard Worker *device_id, /* 1284 device ID */
480*5e7646d2SAndroid Build Coastguard Worker *location; /* Physical location */
481*5e7646d2SAndroid Build Coastguard Worker
482*5e7646d2SAndroid Build Coastguard Worker
483*5e7646d2SAndroid Build Coastguard Worker if (cupsFileGets(backend->pipe, line, sizeof(line)))
484*5e7646d2SAndroid Build Coastguard Worker {
485*5e7646d2SAndroid Build Coastguard Worker /*
486*5e7646d2SAndroid Build Coastguard Worker * Each line is of the form:
487*5e7646d2SAndroid Build Coastguard Worker *
488*5e7646d2SAndroid Build Coastguard Worker * class URI "make model" "name" ["1284 device ID"] ["location"]
489*5e7646d2SAndroid Build Coastguard Worker */
490*5e7646d2SAndroid Build Coastguard Worker
491*5e7646d2SAndroid Build Coastguard Worker strlcpy(temp, line, sizeof(temp));
492*5e7646d2SAndroid Build Coastguard Worker
493*5e7646d2SAndroid Build Coastguard Worker /*
494*5e7646d2SAndroid Build Coastguard Worker * device-class
495*5e7646d2SAndroid Build Coastguard Worker */
496*5e7646d2SAndroid Build Coastguard Worker
497*5e7646d2SAndroid Build Coastguard Worker dclass = temp;
498*5e7646d2SAndroid Build Coastguard Worker
499*5e7646d2SAndroid Build Coastguard Worker for (ptr = temp; *ptr; ptr ++)
500*5e7646d2SAndroid Build Coastguard Worker if (isspace(*ptr & 255))
501*5e7646d2SAndroid Build Coastguard Worker break;
502*5e7646d2SAndroid Build Coastguard Worker
503*5e7646d2SAndroid Build Coastguard Worker while (isspace(*ptr & 255))
504*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
505*5e7646d2SAndroid Build Coastguard Worker
506*5e7646d2SAndroid Build Coastguard Worker /*
507*5e7646d2SAndroid Build Coastguard Worker * device-uri
508*5e7646d2SAndroid Build Coastguard Worker */
509*5e7646d2SAndroid Build Coastguard Worker
510*5e7646d2SAndroid Build Coastguard Worker if (!*ptr)
511*5e7646d2SAndroid Build Coastguard Worker goto error;
512*5e7646d2SAndroid Build Coastguard Worker
513*5e7646d2SAndroid Build Coastguard Worker for (uri = ptr; *ptr; ptr ++)
514*5e7646d2SAndroid Build Coastguard Worker if (isspace(*ptr & 255))
515*5e7646d2SAndroid Build Coastguard Worker break;
516*5e7646d2SAndroid Build Coastguard Worker
517*5e7646d2SAndroid Build Coastguard Worker while (isspace(*ptr & 255))
518*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
519*5e7646d2SAndroid Build Coastguard Worker
520*5e7646d2SAndroid Build Coastguard Worker /*
521*5e7646d2SAndroid Build Coastguard Worker * device-make-and-model
522*5e7646d2SAndroid Build Coastguard Worker */
523*5e7646d2SAndroid Build Coastguard Worker
524*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
525*5e7646d2SAndroid Build Coastguard Worker goto error;
526*5e7646d2SAndroid Build Coastguard Worker
527*5e7646d2SAndroid Build Coastguard Worker for (ptr ++, make_model = ptr; *ptr && *ptr != '\"'; ptr ++)
528*5e7646d2SAndroid Build Coastguard Worker {
529*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\\' && ptr[1])
530*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
531*5e7646d2SAndroid Build Coastguard Worker }
532*5e7646d2SAndroid Build Coastguard Worker
533*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
534*5e7646d2SAndroid Build Coastguard Worker goto error;
535*5e7646d2SAndroid Build Coastguard Worker
536*5e7646d2SAndroid Build Coastguard Worker for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0');
537*5e7646d2SAndroid Build Coastguard Worker
538*5e7646d2SAndroid Build Coastguard Worker /*
539*5e7646d2SAndroid Build Coastguard Worker * device-info
540*5e7646d2SAndroid Build Coastguard Worker */
541*5e7646d2SAndroid Build Coastguard Worker
542*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
543*5e7646d2SAndroid Build Coastguard Worker goto error;
544*5e7646d2SAndroid Build Coastguard Worker
545*5e7646d2SAndroid Build Coastguard Worker for (ptr ++, info = ptr; *ptr && *ptr != '\"'; ptr ++)
546*5e7646d2SAndroid Build Coastguard Worker {
547*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\\' && ptr[1])
548*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
549*5e7646d2SAndroid Build Coastguard Worker }
550*5e7646d2SAndroid Build Coastguard Worker
551*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
552*5e7646d2SAndroid Build Coastguard Worker goto error;
553*5e7646d2SAndroid Build Coastguard Worker
554*5e7646d2SAndroid Build Coastguard Worker for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0');
555*5e7646d2SAndroid Build Coastguard Worker
556*5e7646d2SAndroid Build Coastguard Worker /*
557*5e7646d2SAndroid Build Coastguard Worker * device-id
558*5e7646d2SAndroid Build Coastguard Worker */
559*5e7646d2SAndroid Build Coastguard Worker
560*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\"')
561*5e7646d2SAndroid Build Coastguard Worker {
562*5e7646d2SAndroid Build Coastguard Worker for (ptr ++, device_id = ptr; *ptr && *ptr != '\"'; ptr ++)
563*5e7646d2SAndroid Build Coastguard Worker {
564*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\\' && ptr[1])
565*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
566*5e7646d2SAndroid Build Coastguard Worker }
567*5e7646d2SAndroid Build Coastguard Worker
568*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
569*5e7646d2SAndroid Build Coastguard Worker goto error;
570*5e7646d2SAndroid Build Coastguard Worker
571*5e7646d2SAndroid Build Coastguard Worker for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0');
572*5e7646d2SAndroid Build Coastguard Worker
573*5e7646d2SAndroid Build Coastguard Worker /*
574*5e7646d2SAndroid Build Coastguard Worker * device-location
575*5e7646d2SAndroid Build Coastguard Worker */
576*5e7646d2SAndroid Build Coastguard Worker
577*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\"')
578*5e7646d2SAndroid Build Coastguard Worker {
579*5e7646d2SAndroid Build Coastguard Worker for (ptr ++, location = ptr; *ptr && *ptr != '\"'; ptr ++)
580*5e7646d2SAndroid Build Coastguard Worker {
581*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\\' && ptr[1])
582*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
583*5e7646d2SAndroid Build Coastguard Worker }
584*5e7646d2SAndroid Build Coastguard Worker
585*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
586*5e7646d2SAndroid Build Coastguard Worker goto error;
587*5e7646d2SAndroid Build Coastguard Worker
588*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
589*5e7646d2SAndroid Build Coastguard Worker }
590*5e7646d2SAndroid Build Coastguard Worker else
591*5e7646d2SAndroid Build Coastguard Worker location = NULL;
592*5e7646d2SAndroid Build Coastguard Worker }
593*5e7646d2SAndroid Build Coastguard Worker else
594*5e7646d2SAndroid Build Coastguard Worker {
595*5e7646d2SAndroid Build Coastguard Worker device_id = NULL;
596*5e7646d2SAndroid Build Coastguard Worker location = NULL;
597*5e7646d2SAndroid Build Coastguard Worker }
598*5e7646d2SAndroid Build Coastguard Worker
599*5e7646d2SAndroid Build Coastguard Worker /*
600*5e7646d2SAndroid Build Coastguard Worker * Add the device to the array of available devices...
601*5e7646d2SAndroid Build Coastguard Worker */
602*5e7646d2SAndroid Build Coastguard Worker
603*5e7646d2SAndroid Build Coastguard Worker if (!add_device(dclass, make_model, info, uri, device_id, location))
604*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: [cups-deviced] Found device \"%s\"...\n", uri);
605*5e7646d2SAndroid Build Coastguard Worker
606*5e7646d2SAndroid Build Coastguard Worker return (0);
607*5e7646d2SAndroid Build Coastguard Worker }
608*5e7646d2SAndroid Build Coastguard Worker
609*5e7646d2SAndroid Build Coastguard Worker /*
610*5e7646d2SAndroid Build Coastguard Worker * End of file...
611*5e7646d2SAndroid Build Coastguard Worker */
612*5e7646d2SAndroid Build Coastguard Worker
613*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(backend->pipe);
614*5e7646d2SAndroid Build Coastguard Worker backend->pipe = NULL;
615*5e7646d2SAndroid Build Coastguard Worker
616*5e7646d2SAndroid Build Coastguard Worker return (-1);
617*5e7646d2SAndroid Build Coastguard Worker
618*5e7646d2SAndroid Build Coastguard Worker /*
619*5e7646d2SAndroid Build Coastguard Worker * Bad format; strip trailing newline and write an error message.
620*5e7646d2SAndroid Build Coastguard Worker */
621*5e7646d2SAndroid Build Coastguard Worker
622*5e7646d2SAndroid Build Coastguard Worker error:
623*5e7646d2SAndroid Build Coastguard Worker
624*5e7646d2SAndroid Build Coastguard Worker if (line[strlen(line) - 1] == '\n')
625*5e7646d2SAndroid Build Coastguard Worker line[strlen(line) - 1] = '\0';
626*5e7646d2SAndroid Build Coastguard Worker
627*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n",
628*5e7646d2SAndroid Build Coastguard Worker backend->name, line);
629*5e7646d2SAndroid Build Coastguard Worker return (0);
630*5e7646d2SAndroid Build Coastguard Worker }
631*5e7646d2SAndroid Build Coastguard Worker
632*5e7646d2SAndroid Build Coastguard Worker
633*5e7646d2SAndroid Build Coastguard Worker /*
634*5e7646d2SAndroid Build Coastguard Worker * 'process_children()' - Process all dead children...
635*5e7646d2SAndroid Build Coastguard Worker */
636*5e7646d2SAndroid Build Coastguard Worker
637*5e7646d2SAndroid Build Coastguard Worker static void
process_children(void)638*5e7646d2SAndroid Build Coastguard Worker process_children(void)
639*5e7646d2SAndroid Build Coastguard Worker {
640*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
641*5e7646d2SAndroid Build Coastguard Worker int status; /* Exit status of child */
642*5e7646d2SAndroid Build Coastguard Worker int pid; /* Process ID of child */
643*5e7646d2SAndroid Build Coastguard Worker cupsd_backend_t *backend; /* Current backend */
644*5e7646d2SAndroid Build Coastguard Worker const char *name; /* Name of process */
645*5e7646d2SAndroid Build Coastguard Worker
646*5e7646d2SAndroid Build Coastguard Worker
647*5e7646d2SAndroid Build Coastguard Worker /*
648*5e7646d2SAndroid Build Coastguard Worker * Reset the dead_children flag...
649*5e7646d2SAndroid Build Coastguard Worker */
650*5e7646d2SAndroid Build Coastguard Worker
651*5e7646d2SAndroid Build Coastguard Worker dead_children = 0;
652*5e7646d2SAndroid Build Coastguard Worker
653*5e7646d2SAndroid Build Coastguard Worker /*
654*5e7646d2SAndroid Build Coastguard Worker * Collect the exit status of some children...
655*5e7646d2SAndroid Build Coastguard Worker */
656*5e7646d2SAndroid Build Coastguard Worker
657*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_WAITPID
658*5e7646d2SAndroid Build Coastguard Worker while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
659*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_WAIT3)
660*5e7646d2SAndroid Build Coastguard Worker while ((pid = wait3(&status, WNOHANG, NULL)) > 0)
661*5e7646d2SAndroid Build Coastguard Worker #else
662*5e7646d2SAndroid Build Coastguard Worker if ((pid = wait(&status)) > 0)
663*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_WAITPID */
664*5e7646d2SAndroid Build Coastguard Worker {
665*5e7646d2SAndroid Build Coastguard Worker if (status == SIGTERM)
666*5e7646d2SAndroid Build Coastguard Worker status = 0;
667*5e7646d2SAndroid Build Coastguard Worker
668*5e7646d2SAndroid Build Coastguard Worker for (i = num_backends, backend = backends; i > 0; i --, backend ++)
669*5e7646d2SAndroid Build Coastguard Worker if (backend->pid == pid)
670*5e7646d2SAndroid Build Coastguard Worker break;
671*5e7646d2SAndroid Build Coastguard Worker
672*5e7646d2SAndroid Build Coastguard Worker if (i > 0)
673*5e7646d2SAndroid Build Coastguard Worker {
674*5e7646d2SAndroid Build Coastguard Worker name = backend->name;
675*5e7646d2SAndroid Build Coastguard Worker backend->pid = 0;
676*5e7646d2SAndroid Build Coastguard Worker backend->status = status;
677*5e7646d2SAndroid Build Coastguard Worker
678*5e7646d2SAndroid Build Coastguard Worker active_backends --;
679*5e7646d2SAndroid Build Coastguard Worker }
680*5e7646d2SAndroid Build Coastguard Worker else
681*5e7646d2SAndroid Build Coastguard Worker name = "Unknown";
682*5e7646d2SAndroid Build Coastguard Worker
683*5e7646d2SAndroid Build Coastguard Worker if (status)
684*5e7646d2SAndroid Build Coastguard Worker {
685*5e7646d2SAndroid Build Coastguard Worker if (WIFEXITED(status))
686*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr,
687*5e7646d2SAndroid Build Coastguard Worker "ERROR: [cups-deviced] PID %d (%s) stopped with status %d!\n",
688*5e7646d2SAndroid Build Coastguard Worker pid, name, WEXITSTATUS(status));
689*5e7646d2SAndroid Build Coastguard Worker else
690*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr,
691*5e7646d2SAndroid Build Coastguard Worker "ERROR: [cups-deviced] PID %d (%s) crashed on signal %d!\n",
692*5e7646d2SAndroid Build Coastguard Worker pid, name, WTERMSIG(status));
693*5e7646d2SAndroid Build Coastguard Worker }
694*5e7646d2SAndroid Build Coastguard Worker else
695*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr,
696*5e7646d2SAndroid Build Coastguard Worker "DEBUG: [cups-deviced] PID %d (%s) exited with no errors.\n",
697*5e7646d2SAndroid Build Coastguard Worker pid, name);
698*5e7646d2SAndroid Build Coastguard Worker }
699*5e7646d2SAndroid Build Coastguard Worker }
700*5e7646d2SAndroid Build Coastguard Worker
701*5e7646d2SAndroid Build Coastguard Worker
702*5e7646d2SAndroid Build Coastguard Worker /*
703*5e7646d2SAndroid Build Coastguard Worker * 'sigchld_handler()' - Handle 'child' signals from old processes.
704*5e7646d2SAndroid Build Coastguard Worker */
705*5e7646d2SAndroid Build Coastguard Worker
706*5e7646d2SAndroid Build Coastguard Worker static void
sigchld_handler(int sig)707*5e7646d2SAndroid Build Coastguard Worker sigchld_handler(int sig) /* I - Signal number */
708*5e7646d2SAndroid Build Coastguard Worker {
709*5e7646d2SAndroid Build Coastguard Worker (void)sig;
710*5e7646d2SAndroid Build Coastguard Worker
711*5e7646d2SAndroid Build Coastguard Worker /*
712*5e7646d2SAndroid Build Coastguard Worker * Flag that we have dead children...
713*5e7646d2SAndroid Build Coastguard Worker */
714*5e7646d2SAndroid Build Coastguard Worker
715*5e7646d2SAndroid Build Coastguard Worker dead_children = 1;
716*5e7646d2SAndroid Build Coastguard Worker
717*5e7646d2SAndroid Build Coastguard Worker /*
718*5e7646d2SAndroid Build Coastguard Worker * Reset the signal handler as needed...
719*5e7646d2SAndroid Build Coastguard Worker */
720*5e7646d2SAndroid Build Coastguard Worker
721*5e7646d2SAndroid Build Coastguard Worker #if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
722*5e7646d2SAndroid Build Coastguard Worker signal(SIGCLD, sigchld_handler);
723*5e7646d2SAndroid Build Coastguard Worker #endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
724*5e7646d2SAndroid Build Coastguard Worker }
725*5e7646d2SAndroid Build Coastguard Worker
726*5e7646d2SAndroid Build Coastguard Worker
727*5e7646d2SAndroid Build Coastguard Worker /*
728*5e7646d2SAndroid Build Coastguard Worker * 'start_backend()' - Run a backend to gather the available devices.
729*5e7646d2SAndroid Build Coastguard Worker */
730*5e7646d2SAndroid Build Coastguard Worker
731*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 on success, -1 on error */
start_backend(const char * name,int root)732*5e7646d2SAndroid Build Coastguard Worker start_backend(const char *name, /* I - Backend to run */
733*5e7646d2SAndroid Build Coastguard Worker int root) /* I - Run as root? */
734*5e7646d2SAndroid Build Coastguard Worker {
735*5e7646d2SAndroid Build Coastguard Worker const char *server_bin; /* CUPS_SERVERBIN environment variable */
736*5e7646d2SAndroid Build Coastguard Worker char program[1024]; /* Full path to backend */
737*5e7646d2SAndroid Build Coastguard Worker cupsd_backend_t *backend; /* Current backend */
738*5e7646d2SAndroid Build Coastguard Worker char *argv[2]; /* Command-line arguments */
739*5e7646d2SAndroid Build Coastguard Worker
740*5e7646d2SAndroid Build Coastguard Worker
741*5e7646d2SAndroid Build Coastguard Worker if (num_backends >= MAX_BACKENDS)
742*5e7646d2SAndroid Build Coastguard Worker {
743*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: Too many backends (%d)!\n", num_backends);
744*5e7646d2SAndroid Build Coastguard Worker return (-1);
745*5e7646d2SAndroid Build Coastguard Worker }
746*5e7646d2SAndroid Build Coastguard Worker
747*5e7646d2SAndroid Build Coastguard Worker if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL)
748*5e7646d2SAndroid Build Coastguard Worker server_bin = CUPS_SERVERBIN;
749*5e7646d2SAndroid Build Coastguard Worker
750*5e7646d2SAndroid Build Coastguard Worker snprintf(program, sizeof(program), "%s/backend/%s", server_bin, name);
751*5e7646d2SAndroid Build Coastguard Worker
752*5e7646d2SAndroid Build Coastguard Worker if (_cupsFileCheck(program, _CUPS_FILE_CHECK_PROGRAM, !geteuid(),
753*5e7646d2SAndroid Build Coastguard Worker _cupsFileCheckFilter, NULL))
754*5e7646d2SAndroid Build Coastguard Worker return (-1);
755*5e7646d2SAndroid Build Coastguard Worker
756*5e7646d2SAndroid Build Coastguard Worker backend = backends + num_backends;
757*5e7646d2SAndroid Build Coastguard Worker
758*5e7646d2SAndroid Build Coastguard Worker argv[0] = (char *)name;
759*5e7646d2SAndroid Build Coastguard Worker argv[1] = NULL;
760*5e7646d2SAndroid Build Coastguard Worker
761*5e7646d2SAndroid Build Coastguard Worker if ((backend->pipe = cupsdPipeCommand(&(backend->pid), program, argv,
762*5e7646d2SAndroid Build Coastguard Worker root ? 0 : normal_user)) == NULL)
763*5e7646d2SAndroid Build Coastguard Worker {
764*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: [cups-deviced] Unable to execute \"%s\" - %s\n",
765*5e7646d2SAndroid Build Coastguard Worker program, strerror(errno));
766*5e7646d2SAndroid Build Coastguard Worker return (-1);
767*5e7646d2SAndroid Build Coastguard Worker }
768*5e7646d2SAndroid Build Coastguard Worker
769*5e7646d2SAndroid Build Coastguard Worker /*
770*5e7646d2SAndroid Build Coastguard Worker * Fill in the rest of the backend information...
771*5e7646d2SAndroid Build Coastguard Worker */
772*5e7646d2SAndroid Build Coastguard Worker
773*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: [cups-deviced] Started backend %s (PID %d)\n",
774*5e7646d2SAndroid Build Coastguard Worker program, backend->pid);
775*5e7646d2SAndroid Build Coastguard Worker
776*5e7646d2SAndroid Build Coastguard Worker backend_fds[num_backends].fd = cupsFileNumber(backend->pipe);
777*5e7646d2SAndroid Build Coastguard Worker backend_fds[num_backends].events = POLLIN;
778*5e7646d2SAndroid Build Coastguard Worker
779*5e7646d2SAndroid Build Coastguard Worker backend->name = strdup(name);
780*5e7646d2SAndroid Build Coastguard Worker backend->status = 0;
781*5e7646d2SAndroid Build Coastguard Worker backend->count = 0;
782*5e7646d2SAndroid Build Coastguard Worker
783*5e7646d2SAndroid Build Coastguard Worker active_backends ++;
784*5e7646d2SAndroid Build Coastguard Worker num_backends ++;
785*5e7646d2SAndroid Build Coastguard Worker
786*5e7646d2SAndroid Build Coastguard Worker return (0);
787*5e7646d2SAndroid Build Coastguard Worker }
788