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