From: msweet Date: Mon, 9 Jun 2008 15:59:44 +0000 (+0000) Subject: Merge changes from CUPS 1.4svn-r7626. X-Git-Tag: release-1.6.3~162 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fcups.git;a=commitdiff_plain;h=c934a06cde0e8f2657b7e614df31fd300658d53e Merge changes from CUPS 1.4svn-r7626. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@798 a1ca3aef-8c08-0410-bb20-df032aa958be --- diff --git a/CHANGES-1.3.txt b/CHANGES-1.3.txt index a3f418410..90b02ac20 100644 --- a/CHANGES-1.3.txt +++ b/CHANGES-1.3.txt @@ -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) diff --git a/scheduler/client.c b/scheduler/client.c index bd45262cf..f56ed64a2 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -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; diff --git a/scheduler/conf.c b/scheduler/conf.c index 29e43f785..20a5edd66 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -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, " */ - 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, " */ - 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); diff --git a/scheduler/cups-deviced.c b/scheduler/cups-deviced.c index 9c5b6991f..a912358f1 100644 --- a/scheduler/cups-deviced.c +++ b/scheduler/cups-deviced.c @@ -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); /* 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 ++; diff --git a/scheduler/cups-driverd.c b/scheduler/cups-driverd.c index 6c256a07e..7325f6073 100644 --- a/scheduler/cups-driverd.c +++ b/scheduler/cups-driverd.c @@ -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", diff --git a/scheduler/printers.c b/scheduler/printers.c index 3a63fc2e6..409120564 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -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)) diff --git a/scheduler/util.c b/scheduler/util.c index 3d504dba6..115bbf8b3 100644 --- a/scheduler/util.c +++ b/scheduler/util.c @@ -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. @@ -27,6 +29,13 @@ */ #include "util.h" +#include +#include +#include +#ifdef __APPLE__ +# include +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); /* 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. */ diff --git a/scheduler/util.h b/scheduler/util.h index bcc5e574a..420030771 100644 --- a/scheduler/util.h +++ b/scheduler/util.h @@ -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 @@ -33,14 +33,18 @@ * 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_ */ diff --git a/scripting/php/phpcups.c b/scripting/php/phpcups.c index 2ef8c917c..348b858b4 100644 --- a/scripting/php/phpcups.c +++ b/scripting/php/phpcups.c @@ -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; diff --git a/systemv/lpstat.c b/systemv/lpstat.c index 6c5410430..98bc733e5 100644 --- a/systemv/lpstat.c +++ b/systemv/lpstat.c @@ -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); } }