xref: /aosp_15_r20/external/libcups/scheduler/cups-deviced.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
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