]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from CUPS 1.4svn-r7626.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Mon, 9 Jun 2008 15:59:44 +0000 (15:59 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Mon, 9 Jun 2008 15:59:44 +0000 (15:59 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@798 a1ca3aef-8c08-0410-bb20-df032aa958be

CHANGES-1.3.txt
scheduler/client.c
scheduler/conf.c
scheduler/cups-deviced.c
scheduler/cups-driverd.c
scheduler/printers.c
scheduler/util.c
scheduler/util.h
scripting/php/phpcups.c
systemv/lpstat.c

index a3f4184108a2cb562a9e9ba44c68aa7e43ed6bc5..90b02ac2042785d626227ba0cad14d349cc5eb96 100644 (file)
@@ -4,6 +4,16 @@ CHANGES-1.3.txt
 CHANGES IN CUPS V1.3.8
 
        - Documentation updates (STR #2785)
+       - The CUPS PHP extension was not thread-safe (STR #2828)
+       - The scheduler incorrectly added the document-format-default
+         attribute to the list of "common" printer attributes, which
+         over time would slow down the printing system (STR #2755,
+         STR #2836)
+       - The cups-deviced and cups-driverd helper programs did not set
+         the CFProcessPath environment variable on Mac OS X (STR #2837)
+       - "lpstat -p" could report the wrong job as printing (STR #2845)
+       - The scheduler would crash when some cupsd.conf directives
+         were missing values (STR #2849)
        - The web interface "move jobs" operation redirected users to
          the wrong URL (STR #2815)
        - The Polish web interface translation contained errors
@@ -22,7 +32,7 @@ CHANGES IN CUPS V1.3.8
          sockets (STR #2750)
        - The scheduler incorrectly logged errors for print filters
          when a job was canceled (STR #2806, #2808)
-       - The scheduler not long allows multiple RSS subscriptions
+       - The scheduler no longer allows multiple RSS subscriptions
          with the same URI (STR #2789)
        - The scheduler now supports Kerberized printing with
          multiple server names (STR #2783)
index bd45262cf19ea5e80bfcaba224ec55b1eb563933..f56ed64a267339a8de31393cd3135958319b75e0 100644 (file)
@@ -536,15 +536,15 @@ cupsdCloseClient(cupsd_client_t *con)     /* I - Client to close */
     switch (SSL_shutdown(conn))
     {
       case 1 :
-          cupsdLogMessage(CUPSD_LOG_INFO,
-                         "cupsdCloseClient: SSL shutdown successful!");
+          cupsdLogMessage(CUPSD_LOG_DEBUG,
+                         "SSL shutdown successful!");
          break;
       case -1 :
           cupsdLogMessage(CUPSD_LOG_ERROR,
-                         "cupsdCloseClient: Fatal error during SSL shutdown!");
+                         "Fatal error during SSL shutdown!");
       default :
          while ((error = ERR_get_error()) != 0)
-           cupsdLogMessage(CUPSD_LOG_ERROR, "cupsdCloseClient: %s",
+           cupsdLogMessage(CUPSD_LOG_ERROR, "SSL shutdown failed: %s",
                            ERR_error_string(error, NULL));
           break;
     }
@@ -560,12 +560,12 @@ cupsdCloseClient(cupsd_client_t *con)     /* I - Client to close */
     switch (error)
     {
       case GNUTLS_E_SUCCESS:
-       cupsdLogMessage(CUPSD_LOG_INFO,
-                       "cupsdCloseClient: SSL shutdown successful!");
+       cupsdLogMessage(CUPSD_LOG_DEBUG,
+                       "SSL shutdown successful!");
        break;
       default:
        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "cupsdCloseClient: %s", gnutls_strerror(error));
+                       "SSL shutdown failed: %s", gnutls_strerror(error));
        break;
     }
 
@@ -866,11 +866,14 @@ cupsdReadClient(cupsd_client_t *con)      /* I - Client to read from */
         switch (sscanf(line, "%63s%1023s%63s", operation, con->uri, version))
        {
          case 1 :
-             cupsdLogMessage(CUPSD_LOG_ERROR,
-                             "Bad request line \"%s\" from %s!", line,
-                             con->http.hostname);
-             cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE);
-             cupsdCloseClient(con);
+             if (line[0])
+             {
+               cupsdLogMessage(CUPSD_LOG_ERROR,
+                               "Bad request line \"%s\" from %s!", line,
+                               con->http.hostname);
+               cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE);
+               cupsdCloseClient(con);
+              }
              return;
          case 2 :
              con->http.version = HTTP_0_9;
index 29e43f7859ec4428f8b9a196762ab16d1e0fd173..20a5edd66f30c24c18b912416476d08d8b37a877 100644 (file)
@@ -2109,7 +2109,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
     * Decode the directive...
     */
 
-    if (!strcasecmp(line, "Include"))
+    if (!strcasecmp(line, "Include") && value)
     {
      /*
       * Include filename
@@ -2130,72 +2130,39 @@ read_configuration(cups_file_t *fp)     /* I - File to read from */
        cupsFileClose(incfile);
       }
     }
-    else if (!strcasecmp(line, "<Location"))
+    else if (!strcasecmp(line, "<Location") && value)
     {
      /*
       * <Location path>
       */
 
-      if (value)
-      {
-       linenum = read_location(fp, value, linenum);
-       if (linenum == 0)
-         return (0);
-      }
-      else
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.",
-                  linenum);
-        return (0);
-      }
+      linenum = read_location(fp, value, linenum);
+      if (linenum == 0)
+       return (0);
     }
-    else if (!strcasecmp(line, "<Policy"))
+    else if (!strcasecmp(line, "<Policy") && value)
     {
      /*
       * <Policy name>
       */
 
-      if (value)
-      {
-       linenum = read_policy(fp, value, linenum);
-       if (linenum == 0)
-         return (0);
-      }
-      else
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum);
-        return (0);
-      }
+      linenum = read_policy(fp, value, linenum);
+      if (linenum == 0)
+       return (0);
     }
-    else if (!strcasecmp(line, "FaxRetryInterval"))
+    else if (!strcasecmp(line, "FaxRetryInterval") && value)
     {
-      if (value)
-      {
-        JobRetryInterval = atoi(value);
-       cupsdLogMessage(CUPSD_LOG_WARN,
-                       "FaxRetryInterval is deprecated; use "
-                       "JobRetryInterval on line %d.", linenum);
-      }
-      else
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum);
-        return (0);
-      }
+      JobRetryInterval = atoi(value);
+      cupsdLogMessage(CUPSD_LOG_WARN,
+                     "FaxRetryInterval is deprecated; use "
+                     "JobRetryInterval on line %d.", linenum);
     }
-    else if (!strcasecmp(line, "FaxRetryLimit"))
+    else if (!strcasecmp(line, "FaxRetryLimit") && value)
     {
-      if (value)
-      {
-        JobRetryLimit = atoi(value);
-       cupsdLogMessage(CUPSD_LOG_WARN,
-                       "FaxRetryLimit is deprecated; use "
-                       "JobRetryLimit on line %d.", linenum);
-      }
-      else
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum);
-        return (0);
-      }
+      JobRetryLimit = atoi(value);
+      cupsdLogMessage(CUPSD_LOG_WARN,
+                     "FaxRetryLimit is deprecated; use "
+                     "JobRetryLimit on line %d.", linenum);
     }
     else if (!strcasecmp(line, "Port") || !strcasecmp(line, "Listen")
 #ifdef HAVE_SSL
@@ -2289,7 +2256,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
 
       httpAddrFreeList(addrlist);
     }
-    else if (!strcasecmp(line, "BrowseAddress"))
+    else if (!strcasecmp(line, "BrowseAddress") && value)
     {
      /*
       * Add a browse address to the list...
@@ -2370,7 +2337,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
         cupsdLogMessage(CUPSD_LOG_ERROR, "Bad BrowseAddress %s at line %d.",
                        value, linenum);
     }
-    else if (!strcasecmp(line, "BrowseOrder"))
+    else if (!strcasecmp(line, "BrowseOrder") && value)
     {
      /*
       * "BrowseOrder Deny,Allow" or "BrowseOrder Allow,Deny"...
@@ -2416,8 +2383,8 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
       if (strcasecmp(line, "BrowseRemoteProtocols"))
         BrowseLocalProtocols = protocols;
     }
-    else if (!strcasecmp(line, "BrowseAllow") ||
-             !strcasecmp(line, "BrowseDeny"))
+    else if ((!strcasecmp(line, "BrowseAllow") ||
+              !strcasecmp(line, "BrowseDeny")) && value)
     {
      /*
       * BrowseAllow [From] host/ip...
@@ -2521,7 +2488,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
        }
       }
     }
-    else if (!strcasecmp(line, "BrowseRelay"))
+    else if (!strcasecmp(line, "BrowseRelay") && value)
     {
      /*
       * BrowseRelay [from] source [to] destination
@@ -2697,7 +2664,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
                        value, linenum);
       }
     }
-    else if (!strcasecmp(line, "BrowsePoll"))
+    else if (!strcasecmp(line, "BrowsePoll") && value)
     {
      /*
       * BrowsePoll address[:port]
@@ -2759,7 +2726,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
       cupsdLogMessage(CUPSD_LOG_INFO, "Polling %s:%d", pollp->hostname,
                      pollp->port);
     }
-    else if (!strcasecmp(line, "DefaultAuthType"))
+    else if (!strcasecmp(line, "DefaultAuthType") && value)
     {
      /*
       * DefaultAuthType {basic,digest,basicdigest,negotiate}
@@ -2808,7 +2775,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
     }
 #endif /* HAVE_SSL */
 #ifdef HAVE_GSSAPI
-    else if (!strcasecmp(line, "Krb5Keytab"))
+    else if (!strcasecmp(line, "Krb5Keytab") && value)
     {
       cupsdSetStringf(&Krb5Keytab, "KRB5_KTNAME=%s", value);
       putenv(Krb5Keytab);
@@ -2820,13 +2787,13 @@ read_configuration(cups_file_t *fp)     /* I - File to read from */
 #  endif /* HAVE_GSSKRB5_REGISTER_ACCEPTOR_IDENTITY */
     }
 #endif /* HAVE_GSSAPI */
-    else if (!strcasecmp(line, "User"))
+    else if (!strcasecmp(line, "User") && value)
     {
      /*
       * User ID to run as...
       */
 
-      if (value && isdigit(value[0] & 255))
+      if (isdigit(value[0] & 255))
       {
         int uid = atoi(value);
 
@@ -2839,7 +2806,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
         else
          User = atoi(value);
       }
-      else if (value)
+      else
       {
         struct passwd *p;      /* Password information */
 
@@ -2862,12 +2829,8 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
                          "Unknown User \"%s\" on line %d, ignoring!",
                          value, linenum);
       }
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "User directive on line %d missing the username!",
-                       linenum);
     }
-    else if (!strcasecmp(line, "Group"))
+    else if (!strcasecmp(line, "Group") && value)
     {
      /*
       * Group ID to run as...
@@ -2888,7 +2851,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
                          value, linenum);
       }
     }
-    else if (!strcasecmp(line, "SystemGroup"))
+    else if (!strcasecmp(line, "SystemGroup") && value)
     {
      /*
       * SystemGroup (admin) group(s)...
@@ -2899,7 +2862,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
                        "Unknown SystemGroup \"%s\" on line %d, ignoring!",
                        value, linenum);
     }
-    else if (!strcasecmp(line, "HostNameLookups"))
+    else if (!strcasecmp(line, "HostNameLookups") && value)
     {
      /*
       * Do hostname lookups?
@@ -2915,7 +2878,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
        cupsdLogMessage(CUPSD_LOG_WARN, "Unknown HostNameLookups %s on line %d.",
                        value, linenum);
     }
-    else if (!strcasecmp(line, "LogLevel"))
+    else if (!strcasecmp(line, "LogLevel") && value)
     {
      /*
       * Amount of logging to do...
@@ -2945,7 +2908,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
         cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogLevel %s on line %d.",
                        value, linenum);
     }
-    else if (!strcasecmp(line, "PrintcapFormat"))
+    else if (!strcasecmp(line, "PrintcapFormat") && value)
     {
      /*
       * Format of printcap file?
@@ -2959,7 +2922,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
        cupsdLogMessage(CUPSD_LOG_WARN, "Unknown PrintcapFormat %s on line %d.",
                        value, linenum);
     }
-    else if (!strcasecmp(line, "ServerTokens"))
+    else if (!strcasecmp(line, "ServerTokens") && value)
     {
      /*
       * Set the string used for the Server header...
@@ -2989,7 +2952,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
        cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d.",
                         value, linenum);
     }
-    else if (!strcasecmp(line, "PassEnv"))
+    else if (!strcasecmp(line, "PassEnv") && value)
     {
      /*
       * PassEnv variable [... variable]
@@ -3014,7 +2977,7 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
            break;
       }
     }
-    else if (!strcasecmp(line, "SetEnv"))
+    else if (!strcasecmp(line, "SetEnv") && value)
     {
      /*
       * SetEnv variable value
@@ -3054,8 +3017,12 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
         * Unknown directive!  Output an error message and continue...
        */
 
-        cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d.",
-                       line, linenum);
+        if (!value)
+         cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d.",
+                         line, linenum);
+       else
+         cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d.",
+                         line, linenum);
         continue;
       }
 
@@ -3119,7 +3086,15 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
            break;
 
        case CUPSD_VARTYPE_PATHNAME :
-            if (value[0] == '/')
+            if (!value)
+           {
+             cupsdLogMessage(CUPSD_LOG_ERROR,
+                             "Missing pathname value for %s on line %d!",
+                             line, linenum);
+              break;
+           }
+
+           if (value[0] == '/')
              strlcpy(temp, value, sizeof(temp));
            else
              snprintf(temp, sizeof(temp), "%s/%s", ServerRoot, value);
index 9c5b6991f5d236916fa61d7356fe75ecfb9d3976..a912358f13ee9503895bc3998291a0209587558c 100644 (file)
@@ -669,8 +669,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,13 +679,6 @@ 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;
 
@@ -693,58 +686,29 @@ start_backend(const char *name,           /* I - Backend to run */
 
   backend = backends + num_backends;
 
-  if ((backend->pid = fork()) < 0)
-  {
-   /*
-    * Error!
-    */
+  argv[0] = (char *)name;
+  argv[1] = NULL;
 
-    fprintf(stderr, "ERROR: [cups-deviced] Unable to fork for \"%s\" - %s\n",
-            program, strerror(errno));
-    close(fds[0]);
-    close(fds[1]);
-    return (-1);
-  }
-  else if (!backend->pid)
+  if ((backend->pipe = cupsdPipeCommand(&(backend->pid), program, argv,
+                                        root ? 0 : normal_user)) == NULL)
   {
-   /*
-    * 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]);
-
-    close(fds[0]);                     /* Close copies of pipes */
-    close(fds[1]);
-
-    execl(program, name, (char *)0);   /* Run it! */
     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 ++;
index 6c256a07e31199fbcd352d685cebd5dbd9d3247d..7325f6073c14f08efde746ac99857089e66850e5 100644 (file)
@@ -294,6 +294,7 @@ cat_ppd(const char *name,           /* I - PPD name */
     */
 
     const char *serverbin;             /* CUPS_SERVERBIN env var */
+    char       *argv[4];               /* Arguments for program */
 
 
     if ((serverbin = getenv("CUPS_SERVERBIN")) == NULL)
@@ -340,7 +341,12 @@ cat_ppd(const char *name,          /* I - PPD name */
       cupsdSendIPPTrailer();
     }
 
-    if (execl(line, scheme, "cat", name, (char *)NULL))
+    argv[0] = scheme;
+    argv[1] = (char *)"cat";
+    argv[2] = (char *)name;
+    argv[3] = NULL;
+
+    if (cupsdExec(line, argv))
     {
      /*
       * Unable to execute driver...
@@ -1535,10 +1541,12 @@ load_drivers(void)
                *ptr;                   /* Pointer into string */
   const char   *server_bin;            /* CUPS_SERVERBIN env variable */
   char         drivers[1024];          /* Location of driver programs */
-  FILE         *fp;                    /* Pipe to driver program */
+  int          pid;                    /* Process ID for driver program */
+  cups_file_t  *fp;                    /* Pipe to driver program */
   cups_dir_t   *dir;                   /* Directory pointer */
   cups_dentry_t *dent;                 /* Directory entry */
-  char         filename[1024],         /* Name of driver */
+  char         *argv[3],               /* Arguments for command */
+               filename[1024],         /* Name of driver */
                line[2048],             /* Line from driver */
                name[512],              /* ppd-name */
                make[128],              /* ppd-make */
@@ -1573,6 +1581,9 @@ load_drivers(void)
   * Loop through all of the device drivers...
   */
 
+  argv[1] = (char *)"list";
+  argv[2] = NULL;
+
   while ((dent = cupsDirRead(dir)) != NULL)
   {
    /*
@@ -1586,10 +1597,12 @@ load_drivers(void)
     * Run the driver with no arguments and collect the output...
     */
 
-    snprintf(filename, sizeof(filename), "%s/%s list", drivers, dent->filename);
-    if ((fp = popen(filename, "r")) != NULL)
+    argv[0] = dent->filename;
+    snprintf(filename, sizeof(filename), "%s/%s", drivers, dent->filename);
+
+    if ((fp = cupsdPipeCommand(&pid, filename, argv, 0)) != NULL)
     {
-      while (fgets(line, sizeof(line), fp) != NULL)
+      while (cupsFileGets(fp, line, sizeof(line)))
       {
        /*
         * Each line is of the form:
@@ -1638,7 +1651,8 @@ load_drivers(void)
 
          if (type >= (int)(sizeof(ppd_types) / sizeof(ppd_types[0])))
          {
-           fprintf(stderr, "ERROR: [cups-driverd] Bad ppd-type \"%s\" ignored!\n",
+           fprintf(stderr,
+                   "ERROR: [cups-driverd] Bad ppd-type \"%s\" ignored!\n",
                    type_str);
            type = PPD_TYPE_UNKNOWN;
          }
@@ -1649,7 +1663,7 @@ load_drivers(void)
           if (!ppd)
          {
             cupsDirClose(dir);
-           pclose(fp);
+           cupsFileClose(fp);
            return (0);
          }
 
@@ -1674,7 +1688,7 @@ load_drivers(void)
        }
       }
 
-      pclose(fp);
+      cupsFileClose(fp);
     }
     else
       fprintf(stderr, "WARNING: [cups-driverd] Unable to execute \"%s\": %s\n",
index 3a63fc2e668b80f792abfb5989521fec35af40d6..40912056421a8b4e0e0c5a61d8f5912a132f3666 100644 (file)
@@ -3757,7 +3757,7 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */
                   1);
 
   if (!cupsGetOption("document-format", p->num_options, p->options))
-    ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
+    ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
                 "document-format-default", NULL, "application/octet-stream");
 
   if (!cupsGetOption("job-hold-until", p->num_options, p->options))
index 3d504dba6737cdedac352eeb598fcaab29865597..115bbf8b3b5ed6bad2f77b5989b20f49762c34c8 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Mini-daemon utility functions for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2005 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -15,6 +15,8 @@
  * Contents:
  *
  *   cupsdCompareNames()   - Compare two names.
+ *   cupsdExec()           - Run a program with the correct environment.
+ *   cupsdPipeCommand()    - Read output from a command.
  *   cupsdSendIPPGroup()   - Send a group tag.
  *   cupsdSendIPPHeader()  - Send the IPP response header.
  *   cupsdSendIPPInteger() - Send an integer attribute.
  */
 
 #include "util.h"
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef __APPLE__
+#  include <libgen.h>
+extern char **environ;
+#endif /* __APPLE__ */ 
 
 
 /*
@@ -143,6 +152,174 @@ cupsdCompareNames(const char *s,  /* I - First string */
 }
 
 
+/*
+ * 'cupsdExec()' - Run a program with the correct environment.
+ *
+ * On Mac OS X, we need to update the CFProcessPath environment variable that
+ * is passed in the environment so the child can access its bundled resources.
+ */
+
+int                                    /* O - exec() status */
+cupsdExec(const char *command,         /* I - Full path to program */
+          char       **argv)           /* I - Command-line arguments */
+{
+#ifdef __APPLE__
+  int  i, j;                           /* Looping vars */
+  char *envp[500],                     /* Array of environment variables */
+       cfprocesspath[1024],            /* CFProcessPath environment variable */
+       linkpath[1024];                 /* Link path for symlinks... */
+  int  linkbytes;                      /* Bytes for link path */
+
+
+ /*
+  * Some Mac OS X programs are bundled and need the CFProcessPath environment
+  * variable defined.  If the command is a symlink, resolve the link and point
+  * to the resolved location, otherwise, use the command path itself.
+  */
+
+  if ((linkbytes = readlink(command, linkpath, sizeof(linkpath) - 1)) > 0)
+  {
+   /*
+    * Yes, this is a symlink to the actual program, nul-terminate and
+    * use it...
+    */
+
+    linkpath[linkbytes] = '\0';
+
+    if (linkpath[0] == '/')
+      snprintf(cfprocesspath, sizeof(cfprocesspath), "CFProcessPath=%s",
+              linkpath);
+    else
+      snprintf(cfprocesspath, sizeof(cfprocesspath), "CFProcessPath=%s/%s",
+              dirname((char *)command), linkpath);
+  }
+  else
+    snprintf(cfprocesspath, sizeof(cfprocesspath), "CFProcessPath=%s", command);
+
+  envp[0] = cfprocesspath;
+
+ /*
+  * Copy the rest of the environment except for any CFProcessPath that may
+  * already be there...
+  */
+
+  for (i = 1, j = 0;
+       environ[j] && i < (int)(sizeof(envp) / sizeof(envp[0]) - 1);
+       j ++)
+    if (strncmp(environ[j], "CFProcessPath=", 14))
+      envp[i ++] = environ[j];
+
+  envp[i] = NULL;
+
+ /*
+  * Use execve() to run the program...
+  */
+
+  return (execve(command, argv, envp));
+
+#else
+ /*
+  * On other operating systems, just call execv() to use the same environment
+  * variables as the parent...
+  */
+
+  return (execv(command, argv));
+#endif /* __APPLE__ */
+}
+
+
+/*
+ * 'cupsdPipeCommand()' - Read output from a command.
+ */
+
+cups_file_t *                          /* O - CUPS file or NULL on error */
+cupsdPipeCommand(int        *pid,      /* O - Process ID or 0 on error */
+                 const char *command,  /* I - Command to run */
+                 char       **argv,    /* I - Arguments to pass to command */
+                int        user)       /* I - User to run as or 0 for current */
+{
+  int  fds[2];                         /* Pipe file descriptors */
+
+
+ /*
+  * First create the pipe...
+  */
+
+  if (pipe(fds))
+  {
+    *pid = 0;
+    return (NULL);
+  }
+
+ /*
+  * Set the "close on exec" flag on each end of the pipe...
+  */
+
+  if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
+  {
+    close(fds[0]);
+    close(fds[1]);
+
+    *pid = 0;
+
+    return (NULL);
+  }
+
+  if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
+  {
+    close(fds[0]);
+    close(fds[1]);
+
+    *pid = 0;
+
+    return (NULL);
+  }
+
+ /*
+  * Then run the command...
+  */
+
+  if ((*pid = fork()) < 0)
+  {
+   /*
+    * Unable to fork!
+    */
+
+    *pid = 0;
+    close(fds[0]);
+    close(fds[1]);
+
+    return (NULL);
+  }
+  else if (!*pid)
+  {
+   /*
+    * Child comes here...
+    */
+
+    if (!getuid() && user)
+      setuid(user);                    /* Run as restricted user */
+
+    close(0);                          /* </dev/null */
+    open("/dev/null", O_RDONLY);
+
+    close(1);                          /* >pipe */
+    dup(fds[1]);
+
+    cupsdExec(command, argv);
+    exit(errno);
+  }
+
+ /*
+  * Parent comes here, open the input side of the pipe...
+  */
+
+  close(fds[1]);
+
+  return (cupsFileOpenFd(fds[0], "r"));
+}
+
+
 /*
  * 'cupsdSendIPPGroup()' - Send a group tag.
  */
index bcc5e574aab423dceb77a73dfacde515dd108d11..420030771318a8fbb67a1780176722b592250328 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Mini-daemon utility definitions for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2005 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
  * Prototypes...
  */
 
-extern int     cupsdCompareNames(const char *s, const char *t);
-extern void    cupsdSendIPPGroup(ipp_tag_t group_tag);
-extern void    cupsdSendIPPHeader(ipp_status_t status_code, int request_id);
-extern void    cupsdSendIPPInteger(ipp_tag_t value_tag, const char *name,
-                                   int value);
-extern void    cupsdSendIPPString(ipp_tag_t value_tag, const char *name,
-                                  const char *value);
-extern void    cupsdSendIPPTrailer(void);
+extern int             cupsdCompareNames(const char *s, const char *t);
+extern int             cupsdExec(const char *command, char **argv);
+extern cups_file_t     *cupsdPipeCommand(int *pid, const char *command,
+                                         char **argv, int user);
+extern void            cupsdSendIPPGroup(ipp_tag_t group_tag);
+extern void            cupsdSendIPPHeader(ipp_status_t status_code,
+                                          int request_id);
+extern void            cupsdSendIPPInteger(ipp_tag_t value_tag,
+                                           const char *name, int value);
+extern void            cupsdSendIPPString(ipp_tag_t value_tag,
+                                          const char *name, const char *value);
+extern void            cupsdSendIPPTrailer(void);
 
 
 #endif /* !_CUPSD_UTIL_H_ */
index 2ef8c917cdec8ed229b19a554beca7d922874656..348b858b41cc27a12baeec2453e13b64d8252ba0 100644 (file)
@@ -223,7 +223,7 @@ PHP_FUNCTION(cups_cancel_job)
 
 
   if (ZEND_NUM_ARGS() != 2 ||
-      zend_parse_parameters(2, "sl", &dest, &dest_len, &id))
+      zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &dest, &dest_len, &id))
   {
     WRONG_PARAM_COUNT;
   }
@@ -320,7 +320,7 @@ PHP_FUNCTION(cups_get_jobs)
 
 
   if (ZEND_NUM_ARGS() != 3 ||
-      zend_parse_parameters(3, "sll", &dest, &dest_len, &myjobs, &completed))
+      zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &dest, &dest_len, &myjobs, &completed))
   {
     WRONG_PARAM_COUNT;
   }
@@ -416,7 +416,7 @@ PHP_FUNCTION(cups_print_file)
 
 
   if (ZEND_NUM_ARGS() != 4 ||
-      zend_parse_parameters(4, "sssa", &dest, &dest_len,
+      zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssa", &dest, &dest_len,
                             &filename, &filename_len,
                            &title, &title_len, &optionsobj))
   {
@@ -455,7 +455,7 @@ PHP_FUNCTION(cups_print_files)
 
 
   if (ZEND_NUM_ARGS() != 4 ||
-      zend_parse_parameters(4, "sasa", &dest, &dest_len, &filesobj,
+      zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sasa", &dest, &dest_len, &filesobj,
                            &title, &title_len, &optionsobj))
   {
     WRONG_PARAM_COUNT;
index 6c5410430ec89b977ad6db7ff6182980c536ce01..98bc733e5b596201f6c8f7f83a97f05fc70acc03 100644 (file)
@@ -1979,22 +1979,30 @@ show_printers(http_t      *http,        /* I - HTTP connection to server */
            * Get the current active job on this queue...
            */
 
+            ipp_jstate_t jobstate = IPP_JOB_PENDING;
            jobid = 0;
 
            for (jobattr = jobs->attrs; jobattr; jobattr = jobattr->next)
            {
              if (!jobattr->name)
-               continue;
+             {
+               if (jobstate == IPP_JOB_PROCESSING)
+                 break;
+               else
+                 continue;
+              }
 
              if (!strcmp(jobattr->name, "job-id") &&
                  jobattr->value_tag == IPP_TAG_INTEGER)
                jobid = jobattr->values[0].integer;
               else if (!strcmp(jobattr->name, "job-state") &&
-                      jobattr->value_tag == IPP_TAG_ENUM &&
-                      jobattr->values[0].integer == IPP_JOB_PROCESSING)
-               break;
+                      jobattr->value_tag == IPP_TAG_ENUM)
+               jobstate = jobattr->values[0].integer;
            }
 
+            if (jobstate != IPP_JOB_PROCESSING)
+             jobid = 0;
+
             ippDelete(jobs);
          }
         }