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