]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - 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
index 9c5b6991f5d236916fa61d7356fe75ecfb9d3976..2127937f2bd7acc6c692169d19e6d4915a2048a4 100644 (file)
@@ -1,28 +1,16 @@
 /*
- * "$Id: cups-deviced.c 7011 2007-10-10 21:13:35Z mike $"
+ * "$Id$"
  *
- *   Device scanning mini-daemon for the Common UNIX Printing System (CUPS).
+ * Device scanning mini-daemon for CUPS.
  *
- *   Copyright 2007-2008 by Apple Inc.
- *   Copyright 1997-2006 by Easy Software Products.
+ * Copyright 2007-2014 by Apple Inc.
+ * Copyright 1997-2006 by Easy Software Products.
  *
- *   These coded instructions, statements, and computer programs are the
- *   property of Apple Inc. and are protected by Federal copyright
- *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
- *   which should have been included with this file.  If this file is
- *   file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * Contents:
- *
- *   main()                 - Scan for devices and return an IPP response.
- *   add_device()           - Add a new device to the list.
- *   compare_devices()      - Compare device names to eliminate duplicates.
- *   create_strings_array() - Create a CUPS array of strings.
- *   get_current_time()     - Get the current time as a double value in seconds.
- *   get_device()           - Get a device from a backend.
- *   process_children()     - Process all dead children...
- *   sigchld_handler()      - Handle 'child' signals from old processes.
- *   start_backend()        - Run a backend to gather the available devices.
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file.  If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
  */
 
 /*
@@ -65,10 +53,8 @@ typedef struct
 typedef struct
 {
   char device_class[128],              /* Device class */
-       device_make_and_model[128],     /* Make and model, if known */
        device_info[128],               /* Device info/description */
-       device_uri[1024],               /* Device URI */
-       device_id[1024];                /* 1284 Device ID */
+       device_uri[1024];               /* Device URI */
 } cupsd_device_t;
 
 
@@ -85,14 +71,15 @@ static cupsd_backend_t      backends[MAX_BACKENDS];
 static struct pollfd   backend_fds[MAX_BACKENDS];
                                        /* Array for poll() */
 static cups_array_t    *devices;       /* Array of devices */
-static int             normal_user;    /* Normal user ID */
+static uid_t           normal_user;    /* Normal user ID */
 static int             device_limit;   /* Maximum number of devices */
 static int             send_class,     /* Send device-class attribute? */
                        send_info,      /* Send device-info attribute? */
                        send_make_and_model,
                                        /* Send device-make-and-model attribute? */
                        send_uri,       /* Send device-uri attribute? */
-                       send_id;        /* Send device-id attribute? */
+                       send_id,        /* Send device-id attribute? */
+                       send_location;  /* Send device-location attribute? */
 static int             dead_children = 0;
                                        /* Dead children? */
 
@@ -105,10 +92,10 @@ static int         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_id,
+                                  const char *device_location);
 static int             compare_devices(cupsd_device_t *p0,
                                        cupsd_device_t *p1);
-static cups_array_t    *create_strings_array(const char *s);
 static double          get_current_time(void);
 static int             get_device(cupsd_backend_t *backend);
 static void            process_children(void);
@@ -140,7 +127,8 @@ main(int  argc,                             /* I - Number of command-line args */
   int          num_options;            /* Number of options */
   cups_option_t        *options;               /* Options */
   cups_array_t *requested,             /* requested-attributes values */
-               *exclude;               /* exclude-schemes values */
+               *exclude,               /* exclude-schemes values */
+               *include;               /* include-schemes values */
 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
   struct sigaction action;             /* Actions for POSIX signals */
 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
@@ -183,7 +171,7 @@ main(int  argc,                             /* I - Number of command-line args */
     return (1);
   }
 
-  normal_user = atoi(argv[4]);
+  normal_user = (uid_t)atoi(argv[4]);
   if (normal_user <= 0)
   {
     fprintf(stderr, "ERROR: [cups-deviced] Bad user %d!\n", normal_user);
@@ -192,13 +180,18 @@ main(int  argc,                           /* I - Number of command-line args */
   }
 
   num_options = cupsParseOptions(argv[5], 0, &options);
-  requested   = create_strings_array(cupsGetOption("requested-attributes",
-                                                   num_options, options));
-  exclude     = create_strings_array(cupsGetOption("exclude-schemes",
-                                                   num_options, options));
+  requested   = cupsdCreateStringsArray(cupsGetOption("requested-attributes",
+                                                      num_options, options));
+  exclude     = cupsdCreateStringsArray(cupsGetOption("exclude-schemes",
+                                                      num_options, options));
+  include     = cupsdCreateStringsArray(cupsGetOption("include-schemes",
+                                                      num_options, options));
 
   if (!requested || cupsArrayFind(requested, "all") != NULL)
-    send_class = send_info = send_make_and_model = send_uri = send_id = 1;
+  {
+    send_class = send_info = send_make_and_model = send_uri = send_id =
+        send_location = 1;
+  }
   else
   {
     send_class          = cupsArrayFind(requested, "device-class") != NULL;
@@ -206,6 +199,7 @@ main(int  argc,                             /* I - Number of command-line args */
     send_make_and_model = cupsArrayFind(requested, "device-make-and-model") != NULL;
     send_uri            = cupsArrayFind(requested, "device-uri") != NULL;
     send_id             = cupsArrayFind(requested, "device-id") != NULL;
+    send_location       = cupsArrayFind(requested, "device-location") != NULL;
   }
 
  /*
@@ -263,7 +257,12 @@ main(int  argc,                            /* I - Number of command-line args */
         (dent->fileinfo.st_mode & (S_IRUSR | S_IXUSR)) != (S_IRUSR | S_IXUSR))
       continue;
 
-    if (cupsArrayFind(exclude, dent->filename))
+   /*
+    * Skip excluded or not included backends...
+    */
+
+    if (cupsArrayFind(exclude, dent->filename) ||
+        (include && !cupsArrayFind(include, dent->filename)))
       continue;
 
    /*
@@ -299,15 +298,25 @@ main(int  argc,                           /* I - Number of command-line args */
 
     timeout = (int)(1000 * (end_time - current_time));
 
-    if (poll(backend_fds, num_backends, timeout) > 0)
+    if (poll(backend_fds, (nfds_t)num_backends, timeout) > 0)
     {
       for (i = 0; i < num_backends; i ++)
         if (backend_fds[i].revents && backends[i].pipe)
-         if (get_device(backends + i))
+       {
+         cups_file_t *bpipe = backends[i].pipe;
+                                       /* Copy of pipe for backend... */
+
+         do
          {
-           backend_fds[i].fd     = 0;
-           backend_fds[i].events = 0;
+           if (get_device(backends + i))
+           {
+             backend_fds[i].fd     = 0;
+             backend_fds[i].events = 0;
+             break;
+           }
          }
+         while (bpipe->ptr && memchr(bpipe->ptr, '\n', (size_t)(bpipe->end - bpipe->ptr)));
+        }
     }
 
    /*
@@ -345,10 +354,10 @@ add_device(
     const char *device_make_and_model, /* I - Device make and model */
     const char *device_info,           /* I - Device information */
     const char *device_uri,            /* I - Device URI */
-    const char *device_id)             /* I - 1284 device ID */
+    const char *device_id,             /* I - 1284 device ID */
+    const char *device_location)       /* I - Physical location */
 {
-  cupsd_device_t       *device,        /* New device */
-                       *temp;          /* Found device */
+  cupsd_device_t       *device;        /* New device */
 
 
  /*
@@ -367,17 +376,14 @@ add_device(
   */
 
   strlcpy(device->device_class, device_class, sizeof(device->device_class));
-  strlcpy(device->device_make_and_model, device_make_and_model,
-          sizeof(device->device_make_and_model));
   strlcpy(device->device_info, device_info, sizeof(device->device_info));
   strlcpy(device->device_uri, device_uri, sizeof(device->device_uri));
-  strlcpy(device->device_id, device_id, sizeof(device->device_id));
 
  /*
   * Add the device to the array and return...
   */
 
-  if ((temp = cupsArrayFind(devices, device)) != NULL)
+  if (cupsArrayFind(devices, device))
   {
    /*
     * Avoid duplicates!
@@ -398,16 +404,20 @@ add_device(
       cupsdSendIPPGroup(IPP_TAG_PRINTER);
       if (send_class)
        cupsdSendIPPString(IPP_TAG_KEYWORD, "device-class",
-                          device->device_class);
+                          device_class);
       if (send_info)
-       cupsdSendIPPString(IPP_TAG_TEXT, "device-info", device->device_info);
+       cupsdSendIPPString(IPP_TAG_TEXT, "device-info", device_info);
       if (send_make_and_model)
        cupsdSendIPPString(IPP_TAG_TEXT, "device-make-and-model",
-                          device->device_make_and_model);
+                          device_make_and_model);
       if (send_uri)
-       cupsdSendIPPString(IPP_TAG_URI, "device-uri", device->device_uri);
+       cupsdSendIPPString(IPP_TAG_URI, "device-uri", device_uri);
       if (send_id)
-       cupsdSendIPPString(IPP_TAG_TEXT, "device-id", device->device_id);
+       cupsdSendIPPString(IPP_TAG_TEXT, "device-id",
+                          device_id ? device_id : "");
+      if (send_location)
+       cupsdSendIPPString(IPP_TAG_TEXT, "device-location",
+                          device_location ? device_location : "");
 
       fflush(stdout);
       fputs("DEBUG: Flushed attributes...\n", stderr);
@@ -435,53 +445,10 @@ compare_devices(cupsd_device_t *d0,       /* I - First device */
 
   if ((diff = cupsdCompareNames(d0->device_info, d1->device_info)) != 0)
     return (diff);
-  else if ((diff = strcasecmp(d0->device_class, d1->device_class)) != 0)
+  else if ((diff = _cups_strcasecmp(d0->device_class, d1->device_class)) != 0)
     return (diff);
   else
-    return (strcasecmp(d0->device_uri, d1->device_uri));
-}
-
-
-/*
- * 'create_strings_array()' - Create a CUPS array of strings.
- */
-
-static cups_array_t *                  /* O - CUPS array */
-create_strings_array(const char *s)    /* I - Comma-delimited strings */
-{
-  cups_array_t *a;                     /* CUPS array */
-  const char   *start,                 /* Start of string */
-               *end;                   /* End of string */
-  char         *ptr;                   /* New string */
-
-
-  if (!s)
-    return (NULL);
-
-  if ((a = cupsArrayNew((cups_array_func_t)strcmp, NULL)) != NULL)
-  {
-    for (start = end = s; *end; start = end + 1)
-    {
-     /*
-      * Find the end of the current delimited string...
-      */
-
-      if ((end = strchr(start, ',')) == NULL)
-        end = start + strlen(start);
-
-     /*
-      * Duplicate the string and add it to the array...
-      */
-
-      if ((ptr = calloc(1, end - start + 1)) == NULL)
-        break;
-
-      memcpy(ptr, start, end - start);
-      cupsArrayAdd(a, ptr);
-    }
-  }
-
-  return (a);
+    return (_cups_strcasecmp(d0->device_uri, d1->device_uri));
 }
 
 
@@ -509,11 +476,14 @@ static int                                /* O - 0 on success, -1 on error */
 get_device(cupsd_backend_t *backend)   /* I - Backend to read from */
 {
   char line[2048],                     /* Line from backend */
-       dclass[64],                     /* Device class */
-       uri[1024],                      /* Device URI */
-       info[128],                      /* Device info */
-       make_model[256],                /* Make and model */
-       device_id[1024];                /* 1284 device ID */
+       temp[2048],                     /* Copy of line */
+       *ptr,                           /* Pointer into line */
+       *dclass,                        /* Device class */
+       *uri,                           /* Device URI */
+       *make_model,                    /* Make and model */
+       *info,                          /* Device info */
+       *device_id,                     /* 1284 device ID */
+       *location;                      /* Physical location */
 
 
   if (cupsFileGets(backend->pipe, line, sizeof(line)))
@@ -521,36 +491,124 @@ get_device(cupsd_backend_t *backend)     /* I - Backend to read from */
    /*
     * Each line is of the form:
     *
-    *   class URI "make model" "name" ["1284 device ID"]
+    *   class URI "make model" "name" ["1284 device ID"] ["location"]
+    */
+
+    strlcpy(temp, line, sizeof(temp));
+
+   /*
+    * device-class
     */
 
-    device_id[0] = '\0';
+    dclass = temp;
+
+    for (ptr = temp; *ptr; ptr ++)
+      if (isspace(*ptr & 255))
+        break;
 
-    if (sscanf(line,
-              "%63s%1023s%*[ \t]\"%255[^\"]\"%*[ \t]\"%127[^\"]\""
-              "%*[ \t]\"%1023[^\"]",
-              dclass, uri, make_model, info, device_id) < 4)
+    while (isspace(*ptr & 255))
+      *ptr++ = '\0';
+
+   /*
+    * device-uri
+    */
+
+    if (!*ptr)
+      goto error;
+
+    for (uri = ptr; *ptr; ptr ++)
+      if (isspace(*ptr & 255))
+        break;
+
+    while (isspace(*ptr & 255))
+      *ptr++ = '\0';
+
+   /*
+    * device-make-and-model
+    */
+
+    if (*ptr != '\"')
+      goto error;
+
+    for (ptr ++, make_model = ptr; *ptr && *ptr != '\"'; ptr ++)
     {
-     /*
-      * Bad format; strip trailing newline and write an error message.
-      */
+      if (*ptr == '\\' && ptr[1])
+        _cups_strcpy(ptr, ptr + 1);
+    }
+
+    if (*ptr != '\"')
+      goto error;
 
-      if (line[strlen(line) - 1] == '\n')
-       line[strlen(line) - 1] = '\0';
+    for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0');
 
-      fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n",
-             backend->name, line);
+   /*
+    * device-info
+    */
+
+    if (*ptr != '\"')
+      goto error;
+
+    for (ptr ++, info = ptr; *ptr && *ptr != '\"'; ptr ++)
+    {
+      if (*ptr == '\\' && ptr[1])
+        _cups_strcpy(ptr, ptr + 1);
     }
-    else
+
+    if (*ptr != '\"')
+      goto error;
+
+    for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0');
+
+   /*
+    * device-id
+    */
+
+    if (*ptr == '\"')
     {
+      for (ptr ++, device_id = ptr; *ptr && *ptr != '\"'; ptr ++)
+      {
+       if (*ptr == '\\' && ptr[1])
+         _cups_strcpy(ptr, ptr + 1);
+      }
+
+      if (*ptr != '\"')
+       goto error;
+
+      for (*ptr++ = '\0'; isspace(*ptr & 255); *ptr++ = '\0');
+
      /*
-      * Add the device to the array of available devices...
+      * device-location
       */
 
-      if (!add_device(dclass, make_model, info, uri, device_id))
-        fprintf(stderr, "DEBUG: [cups-deviced] Found device \"%s\"...\n", uri);
+      if (*ptr == '\"')
+      {
+       for (ptr ++, location = ptr; *ptr && *ptr != '\"'; ptr ++)
+       {
+         if (*ptr == '\\' && ptr[1])
+           _cups_strcpy(ptr, ptr + 1);
+       }
+
+       if (*ptr != '\"')
+         goto error;
+
+       *ptr = '\0';
+      }
+      else
+        location = NULL;
+    }
+    else
+    {
+      device_id = NULL;
+      location  = NULL;
     }
 
+   /*
+    * Add the device to the array of available devices...
+    */
+
+    if (!add_device(dclass, make_model, info, uri, device_id, location))
+      fprintf(stderr, "DEBUG: [cups-deviced] Found device \"%s\"...\n", uri);
+
     return (0);
   }
 
@@ -562,6 +620,19 @@ get_device(cupsd_backend_t *backend)       /* I - Backend to read from */
   backend->pipe = NULL;
 
   return (-1);
+
+ /*
+  * Bad format; strip trailing newline and write an error message.
+  */
+
+  error:
+
+  if (line[strlen(line) - 1] == '\n')
+    line[strlen(line) - 1] = '\0';
+
+  fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n",
+         backend->name, line);
+  return (0);
 }
 
 
@@ -669,8 +740,8 @@ start_backend(const char *name,             /* I - Backend to run */
 {
   const char           *server_bin;    /* CUPS_SERVERBIN environment variable */
   char                 program[1024];  /* Full path to backend */
-  int                  fds[2];         /* Pipe file descriptors */
   cupsd_backend_t      *backend;       /* Current backend */
+  char                 *argv[2];       /* Command-line arguments */
 
 
   if (num_backends >= MAX_BACKENDS)
@@ -679,72 +750,40 @@ start_backend(const char *name,           /* I - Backend to run */
     return (-1);
   }
 
-  if (pipe(fds))
-  {
-    fprintf(stderr, "ERROR: Unable to create a pipe for \"%s\" - %s\n",
-            name, strerror(errno));
-    return (-1);
-  }
-
   if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL)
     server_bin = CUPS_SERVERBIN;
 
   snprintf(program, sizeof(program), "%s/backend/%s", server_bin, name);
 
-  backend = backends + num_backends;
-
-  if ((backend->pid = fork()) < 0)
-  {
-   /*
-    * Error!
-    */
-
-    fprintf(stderr, "ERROR: [cups-deviced] Unable to fork for \"%s\" - %s\n",
-            program, strerror(errno));
-    close(fds[0]);
-    close(fds[1]);
+  if (_cupsFileCheck(program, _CUPS_FILE_CHECK_PROGRAM, !geteuid(),
+                     _cupsFileCheckFilter, NULL))
     return (-1);
-  }
-  else if (!backend->pid)
-  {
-   /*
-    * Child comes here...
-    */
 
-    if (!getuid() && !root)
-      setuid(normal_user);             /* Run as restricted user */
-
-    close(0);                          /* </dev/null */
-    open("/dev/null", O_RDONLY);
-
-    close(1);                          /* >pipe */
-    dup(fds[1]);
+  backend = backends + num_backends;
 
-    close(fds[0]);                     /* Close copies of pipes */
-    close(fds[1]);
+  argv[0] = (char *)name;
+  argv[1] = NULL;
 
-    execl(program, name, (char *)0);   /* Run it! */
+  if ((backend->pipe = cupsdPipeCommand(&(backend->pid), program, argv,
+                                        root ? 0 : normal_user)) == NULL)
+  {
     fprintf(stderr, "ERROR: [cups-deviced] Unable to execute \"%s\" - %s\n",
             program, strerror(errno));
-    exit(1);
+    return (-1);
   }
 
  /*
-  * Parent comes here, allocate a backend and open the input side of the
-  * pipe...
+  * Fill in the rest of the backend information...
   */
 
   fprintf(stderr, "DEBUG: [cups-deviced] Started backend %s (PID %d)\n",
           program, backend->pid);
 
-  close(fds[1]);
-
-  backend_fds[num_backends].fd     = fds[0];
+  backend_fds[num_backends].fd     = cupsFileNumber(backend->pipe);
   backend_fds[num_backends].events = POLLIN;
 
   backend->name   = strdup(name);
   backend->status = 0;
-  backend->pipe   = cupsFileOpenFd(fds[0], "r");
   backend->count  = 0;
 
   active_backends ++;
@@ -755,5 +794,5 @@ start_backend(const char *name,             /* I - Backend to run */
 
 
 /*
- * End of "$Id: cups-deviced.c 7011 2007-10-10 21:13:35Z mike $".
+ * End of "$Id$".
  */