diff options
author | jlovell <jlovell@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2007-05-04 21:17:48 +0000 |
---|---|---|
committer | jlovell <jlovell@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2007-05-04 21:17:48 +0000 |
commit | b94498cfba64422f0f21181b0c51cc0bed7c7d92 (patch) | |
tree | e3bdd0e05380bc8996f35ddb5439ab9044298712 /scheduler | |
parent | 323c5de1e804061e344172cc9a9551bb0ee71005 (diff) | |
download | cups-b94498cfba64422f0f21181b0c51cc0bed7c7d92.tar.gz |
Load cups into easysw/current.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@321 a1ca3aef-8c08-0410-bb20-df032aa958be
Diffstat (limited to 'scheduler')
-rw-r--r-- | scheduler/client.c | 59 | ||||
-rw-r--r-- | scheduler/client.h | 6 | ||||
-rw-r--r-- | scheduler/conf.c | 301 | ||||
-rw-r--r-- | scheduler/conf.h | 10 | ||||
-rw-r--r-- | scheduler/cups-driverd.c | 718 | ||||
-rw-r--r-- | scheduler/dirsvc.c | 6 | ||||
-rw-r--r-- | scheduler/ipp.c | 313 | ||||
-rw-r--r-- | scheduler/job.c | 7 | ||||
-rw-r--r-- | scheduler/log.c | 25 | ||||
-rw-r--r-- | scheduler/main.c | 421 | ||||
-rw-r--r-- | scheduler/printers.c | 21 |
11 files changed, 1119 insertions, 768 deletions
diff --git a/scheduler/client.c b/scheduler/client.c index 71ca92880..68439f30e 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -1,5 +1,5 @@ /* - * "$Id: client.c 6383 2007-03-21 20:01:20Z mike $" + * "$Id: client.c 6504 2007-05-02 00:14:56Z mike $" * * Client routines for the Common UNIX Printing System (CUPS) scheduler. * @@ -2531,10 +2531,10 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ #ifdef DEBUG cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdWriteClient(con=%p) %d response=%p, file=%d " + "cupsdWriteClient(con=%p) %d response=%p(%d), file=%d " "pipe_pid=%d state=%d", - con, con->http.fd, con->response, con->file, con->pipe_pid, - con->http.state); + con, con->http.fd, con->response, con->response->state, + con->file, con->pipe_pid, con->http.state); #endif /* DEBUG */ if (con->http.state != HTTP_GET_SEND && @@ -2562,10 +2562,11 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ con->file_ready = 0; } - if (con->response) + if (con->response && con->response->state != IPP_DATA) { ipp_state = ippWrite(HTTP(con), con->response); - bytes = ipp_state != IPP_ERROR && ipp_state != IPP_DATA; + bytes = ipp_state != IPP_ERROR && + (con->file >= 0 || ipp_state != IPP_DATA); } else if ((bytes = read(con->file, buf, sizeof(buf) - 1)) > 0) { @@ -3581,9 +3582,9 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ cupsdSetString(&con->command, CUPS_JAVA); if (options) - cupsdSetStringf(&con->options, "%s %s", filename, options); + cupsdSetStringf(&con->options, " %s %s", filename, options); else - cupsdSetString(&con->options, filename); + cupsdSetStringf(&con->options, " %s", filename); cupsdLogMessage(CUPSD_LOG_DEBUG2, "is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"", @@ -3602,9 +3603,9 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ cupsdSetString(&con->command, CUPS_PERL); if (options) - cupsdSetStringf(&con->options, "%s %s", filename, options); + cupsdSetStringf(&con->options, " %s %s", filename, options); else - cupsdSetString(&con->options, filename); + cupsdSetStringf(&con->options, " %s", filename); cupsdLogMessage(CUPSD_LOG_DEBUG2, "is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"", @@ -3623,9 +3624,9 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ cupsdSetString(&con->command, CUPS_PHP); if (options) - cupsdSetStringf(&con->options, "%s %s", filename, options); + cupsdSetStringf(&con->options, " %s %s", filename, options); else - cupsdSetString(&con->options, filename); + cupsdSetStringf(&con->options, " %s", filename); cupsdLogMessage(CUPSD_LOG_DEBUG2, "is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"", @@ -3644,9 +3645,9 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ cupsdSetString(&con->command, CUPS_PYTHON); if (options) - cupsdSetStringf(&con->options, "%s %s", filename, options); + cupsdSetStringf(&con->options, " %s %s", filename, options); else - cupsdSetString(&con->options, filename); + cupsdSetStringf(&con->options, " %s", filename); cupsdLogMessage(CUPSD_LOG_DEBUG2, "is_cgi: Returning 1 with command=\"%s\" and options=\"%s\"", @@ -4165,8 +4166,9 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ int envc; /* Number of environment variables */ char argbuf[10240], /* Argument buffer */ *argv[100], /* Argument strings */ - *envp[MAX_ENV + 18]; /* Environment variables */ - char content_length[1024], /* CONTENT_LENGTH environment variable */ + *envp[MAX_ENV + 20]; /* Environment variables */ + char auth_type[256], /* AUTH_TYPE environment variable */ + content_length[1024], /* CONTENT_LENGTH environment variable */ content_type[1024], /* CONTENT_TYPE environment variable */ http_cookie[32768], /* HTTP_COOKIE environment variable */ http_referer[1024], /* HTTP_REFERER environment variable */ @@ -4176,6 +4178,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ remote_addr[1024], /* REMOTE_ADDR environment variable */ remote_host[1024], /* REMOTE_HOST environment variable */ remote_user[1024], /* REMOTE_USER environment variable */ + script_filename[1024], /* SCRIPT_FILENAME environment variable */ script_name[1024], /* SCRIPT_NAME environment variable */ server_name[1024], /* SERVER_NAME environment variable */ server_port[1024]; /* SERVER_PORT environment variable */ @@ -4228,6 +4231,9 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ { commptr = argbuf; path_info[0] = '\0'; + + if (*commptr == ' ') + commptr ++; } cupsdLogMessage(CUPSD_LOG_INFO, "commptr=\"%s\"", commptr); @@ -4302,6 +4308,17 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ * Setup the environment variables as needed... */ + if (con->username[0]) + { + snprintf(auth_type, sizeof(auth_type), "AUTH_TYPE=%s", + httpGetField(HTTP(con), HTTP_FIELD_AUTHORIZATION)); + + if ((uriptr = strchr(auth_type + 10, ' ')) != NULL) + *uriptr = '\0'; + } + else + auth_type[0] = '\0'; + if (con->language) snprintf(lang, sizeof(lang), "LANG=%s.UTF-8", con->language->language); else @@ -4318,6 +4335,9 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ if ((uriptr = strchr(script_name, '?')) != NULL) *uriptr = '\0'; + snprintf(script_filename, sizeof(script_filename), "SCRIPT_FILENAME=%s%s", + DocumentRoot, script_name + 12); + sprintf(server_port, "SERVER_PORT=%d", con->serverport); snprintf(server_name, sizeof(server_name), "SERVER_NAME=%s", @@ -4325,13 +4345,18 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ envc = cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0]))); + if (auth_type[0]) + envp[envc ++] = auth_type; + envp[envc ++] = lang; envp[envc ++] = "REDIRECT_STATUS=1"; + envp[envc ++] = "GATEWAY_INTERFACE=CGI/1.1"; envp[envc ++] = server_name; envp[envc ++] = server_port; envp[envc ++] = remote_addr; envp[envc ++] = remote_host; envp[envc ++] = script_name; + envp[envc ++] = script_filename; if (path_info[0]) envp[envc ++] = path_info; @@ -4537,5 +4562,5 @@ write_pipe(cupsd_client_t *con) /* I - Client connection */ /* - * End of "$Id: client.c 6383 2007-03-21 20:01:20Z mike $". + * End of "$Id: client.c 6504 2007-05-02 00:14:56Z mike $". */ diff --git a/scheduler/client.h b/scheduler/client.h index de1fb6704..82061b7bb 100644 --- a/scheduler/client.h +++ b/scheduler/client.h @@ -1,9 +1,9 @@ /* - * "$Id: client.h 6383 2007-03-21 20:01:20Z mike $" + * "$Id: client.h 6503 2007-05-01 23:06:44Z mike $" * * Client definitions for the Common UNIX Printing System (CUPS) scheduler. * - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal @@ -138,5 +138,5 @@ extern void cupsdWriteClient(cupsd_client_t *con); /* - * End of "$Id: client.h 6383 2007-03-21 20:01:20Z mike $". + * End of "$Id: client.h 6503 2007-05-01 23:06:44Z mike $". */ diff --git a/scheduler/conf.c b/scheduler/conf.c index ad463acb6..5fd8f10cf 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -1,5 +1,5 @@ /* - * "$Id: conf.c 6436 2007-04-02 23:24:02Z mike $" + * "$Id: conf.c 6505 2007-05-03 17:44:22Z mike $" * * Configuration routines for the Common UNIX Printing System (CUPS). * @@ -23,9 +23,9 @@ * * Contents: * - * cupsdReadConfiguration() - Read the cupsd.conf file. - * check_permissions() - Fix the mode and ownership of a file or + * cupsdCheckPermissions() - Fix the mode and ownership of a file or * directory. + * cupsdReadConfiguration() - Read the cupsd.conf file. * get_address() - Get an address + port number from a line. * get_addr_and_mask() - Get an IP address and netmask. * parse_aaa() - Parse authentication, authorization, and @@ -45,12 +45,9 @@ #include <stdarg.h> #include <grp.h> #include <sys/utsname.h> +#include <syslog.h> #include <cups/dir.h> -#ifdef HAVE_VSYSLOG -# include <syslog.h> -#endif /* HAVE_VSYSLOG */ - /* * Possibly missing network definitions... @@ -197,10 +194,6 @@ static unsigned zeros[4] = /* * Local functions... */ -static int check_permissions(const char *filename, - const char *suffix, int mode, - int user, int group, int is_dir, - int create_dir); static http_addrlist_t *get_address(const char *value, int defport); static int get_addr_and_mask(const char *value, unsigned *ip, unsigned *mask); @@ -214,6 +207,138 @@ static int read_policy(cups_file_t *fp, char *name, int linenum); /* + * 'cupsdCheckPermissions()' - Fix the mode and ownership of a file or directory. + */ + +int /* O - 0 on success, -1 on error, 1 on warning */ +cupsdCheckPermissions( + const char *filename, /* I - File/directory name */ + const char *suffix, /* I - Additional file/directory name */ + int mode, /* I - Permissions */ + int user, /* I - Owner */ + int group, /* I - Group */ + int is_dir, /* I - 1 = directory, 0 = file */ + int create_dir) /* I - 1 = create directory, -1 = create w/o logging, 0 = not */ +{ + int dir_created = 0; /* Did we create a directory? */ + char pathname[1024]; /* File name with prefix */ + struct stat fileinfo; /* Stat buffer */ + + + /* + * Prepend the given root to the filename before testing it... + */ + + if (suffix) + { + snprintf(pathname, sizeof(pathname), "%s/%s", filename, suffix); + filename = pathname; + } + + /* + * See if we can stat the file/directory... + */ + + if (stat(filename, &fileinfo)) + { + if (errno == ENOENT && create_dir) + { + if (create_dir > 0) + cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating missing directory \"%s\"", + filename); + + if (mkdir(filename, mode)) + { + if (create_dir > 0) + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to create directory \"%s\" - %s", filename, + strerror(errno)); + else + syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename, + strerror(errno)); + + return (-1); + } + + dir_created = 1; + } + else + return (create_dir ? -1 : 1); + } + + /* + * Make sure it's a regular file... + */ + + if (!dir_created && !is_dir && !S_ISREG(fileinfo.st_mode)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a regular file!", filename); + return (-1); + } + + if (!dir_created && is_dir && !S_ISDIR(fileinfo.st_mode)) + { + if (create_dir >= 0) + cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory!", filename); + else + syslog(LOG_ERR, "\"%s\" is not a directory!", filename); + + return (-1); + } + + /* + * Fix owner, group, and mode as needed... + */ + + if (dir_created || fileinfo.st_uid != user || fileinfo.st_gid != group) + { + if (create_dir >= 0) + cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing ownership of \"%s\"", + filename); + + if (chown(filename, user, group) && !getuid()) + { + if (create_dir >= 0) + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to change ownership of \"%s\" - %s", filename, + strerror(errno)); + else + syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename, + strerror(errno)); + + return (1); + } + } + + if (dir_created || (fileinfo.st_mode & 07777) != mode) + { + if (create_dir >= 0) + cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing access permissions of \"%s\"", + filename); + + if (chmod(filename, mode)) + { + if (create_dir >= 0) + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to change permissions of \"%s\" - %s", filename, + strerror(errno)); + else + syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename, + strerror(errno)); + + return (1); + } + } + + /* + * Everything is OK... + */ + + return (0); +} + + +/* * 'cupsdReadConfiguration()' - Read the cupsd.conf file. */ @@ -658,20 +783,28 @@ cupsdReadConfiguration(void) * writable by the user and group in the cupsd.conf file... */ - if (check_permissions(CacheDir, NULL, 0775, RunUser, Group, 1, 1) < 0 || - check_permissions(StateDir, NULL, 0755, RunUser, Group, 1, 1) < 0 || - check_permissions(StateDir, "certs", RunUser ? 0711 : 0511, User, - SystemGroupIDs[0], 1, 1) < 0 || - check_permissions(ServerRoot, NULL, 0755, RunUser, Group, 1, 0) < 0 || - check_permissions(ServerRoot, "ppd", 0755, RunUser, Group, 1, 1) < 0 || - check_permissions(ServerRoot, "ssl", 0700, RunUser, Group, 1, 0) < 0 || - check_permissions(ServerRoot, "cupsd.conf", ConfigFilePerm, RunUser, - Group, 0, 0) < 0 || - check_permissions(ServerRoot, "classes.conf", 0600, RunUser, Group, - 0, 0) < 0 || - check_permissions(ServerRoot, "printers.conf", 0600, RunUser, Group, - 0, 0) < 0 || - check_permissions(ServerRoot, "passwd.md5", 0600, User, Group, 0, 0) < 0) + if (cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser, + Group, 1, 1) < 0 || + cupsdCheckPermissions(CacheDir, NULL, 0775, RunUser, + Group, 1, 1) < 0 || + cupsdCheckPermissions(StateDir, NULL, 0755, RunUser, + Group, 1, 1) < 0 || + cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User, + SystemGroupIDs[0], 1, 1) < 0 || + cupsdCheckPermissions(ServerRoot, NULL, 0755, RunUser, + Group, 1, 0) < 0 || + cupsdCheckPermissions(ServerRoot, "ppd", 0755, RunUser, + Group, 1, 1) < 0 || + cupsdCheckPermissions(ServerRoot, "ssl", 0700, RunUser, + Group, 1, 0) < 0 || + cupsdCheckPermissions(ServerRoot, "cupsd.conf", ConfigFilePerm, RunUser, + Group, 0, 0) < 0 || + cupsdCheckPermissions(ServerRoot, "classes.conf", 0600, RunUser, + Group, 0, 0) < 0 || + cupsdCheckPermissions(ServerRoot, "printers.conf", 0600, RunUser, + Group, 0, 0) < 0 || + cupsdCheckPermissions(ServerRoot, "passwd.md5", 0600, User, + Group, 0, 0) < 0) return (0); /* @@ -710,13 +843,9 @@ cupsdReadConfiguration(void) } /* - * Make sure the request and temporary directories have the right - * permissions... + * Make sure the temporary directory has the right permissions... */ - if (check_permissions(RequestRoot, NULL, 0710, RunUser, Group, 1, 1) < 0) - return (0); - if (!strncmp(TempDir, RequestRoot, strlen(RequestRoot)) || access(TempDir, 0)) { @@ -725,7 +854,7 @@ cupsdReadConfiguration(void) * is under the spool directory or does not exist... */ - if (check_permissions(TempDir, NULL, 01770, RunUser, Group, 1, 1) < 0) + if (cupsdCheckPermissions(TempDir, NULL, 01770, RunUser, Group, 1, 1) < 0) return (0); } @@ -1133,114 +1262,6 @@ cupsdReadConfiguration(void) /* - * 'check_permissions()' - Fix the mode and ownership of a file or directory. - */ - -static int /* O - 0 on success, -1 on error, 1 on warning */ -check_permissions(const char *filename, /* I - File/directory name */ - const char *suffix, /* I - Additional file/directory name */ - int mode, /* I - Permissions */ - int user, /* I - Owner */ - int group, /* I - Group */ - int is_dir, /* I - 1 = directory, 0 = file */ - int create_dir)/* I - 1 = create directory, 0 = not */ -{ - int dir_created = 0; /* Did we create a directory? */ - char pathname[1024]; /* File name with prefix */ - struct stat fileinfo; /* Stat buffer */ - - - /* - * Prepend the given root to the filename before testing it... - */ - - if (suffix) - { - snprintf(pathname, sizeof(pathname), "%s/%s", filename, suffix); - filename = pathname; - } - - /* - * See if we can stat the file/directory... - */ - - if (stat(filename, &fileinfo)) - { - if (errno == ENOENT && create_dir) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating missing directory \"%s\"", - filename); - - if (mkdir(filename, mode)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create directory \"%s\" - %s", filename, - strerror(errno)); - return (-1); - } - - dir_created = 1; - } - else - return (create_dir ? -1 : 1); - } - - /* - * Make sure it's a regular file... - */ - - if (!dir_created && !is_dir && !S_ISREG(fileinfo.st_mode)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a regular file!", filename); - return (-1); - } - - if (!dir_created && is_dir && !S_ISDIR(fileinfo.st_mode)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory!", filename); - return (-1); - } - - /* - * Fix owner, group, and mode as needed... - */ - - if (dir_created || fileinfo.st_uid != user || fileinfo.st_gid != group) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing ownership of \"%s\"", filename); - - if (chown(filename, user, group) && !getuid()) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to change ownership of \"%s\" - %s", filename, - strerror(errno)); - return (1); - } - } - - if (dir_created || (fileinfo.st_mode & 07777) != mode) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Repairing access permissions of \"%s\"", - filename); - - if (chmod(filename, mode)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to change permissions of \"%s\" - %s", filename, - strerror(errno)); - return (1); - } - } - - /* - * Everything is OK... - */ - - return (0); -} - - -/* * 'get_address()' - Get an address + port number from a line. */ @@ -3352,5 +3373,5 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ /* - * End of "$Id: conf.c 6436 2007-04-02 23:24:02Z mike $". + * End of "$Id: conf.c 6505 2007-05-03 17:44:22Z mike $". */ diff --git a/scheduler/conf.h b/scheduler/conf.h index 6bb223ecb..87eb94eba 100644 --- a/scheduler/conf.h +++ b/scheduler/conf.h @@ -1,5 +1,5 @@ /* - * "$Id: conf.h 6436 2007-04-02 23:24:02Z mike $" + * "$Id: conf.h 6490 2007-04-30 18:09:30Z mike $" * * Configuration file definitions for the Common UNIX Printing System (CUPS) * scheduler. @@ -218,8 +218,11 @@ VAR char *SystemGroupAuthKey VALUE(NULL); * Prototypes... */ +extern int cupsdCheckPermissions(const char *filename, + const char *suffix, int mode, + int user, int group, int is_dir, + int create_dir); extern char *cupsdGetDateTime(time_t t); -extern int cupsdReadConfiguration(void); #ifdef HAVE_GSSAPI extern int cupsdLogGSSMessage(int level, int major_status, int minor_status, @@ -232,8 +235,9 @@ __attribute__ ((__format__ (__printf__, 2, 3))) ; extern int cupsdLogPage(cupsd_job_t *job, const char *page); extern int cupsdLogRequest(cupsd_client_t *con, http_status_t code); +extern int cupsdReadConfiguration(void); /* - * End of "$Id: conf.h 6436 2007-04-02 23:24:02Z mike $". + * End of "$Id: conf.h 6490 2007-04-30 18:09:30Z mike $". */ diff --git a/scheduler/cups-driverd.c b/scheduler/cups-driverd.c index e2898ad29..1a7a3931d 100644 --- a/scheduler/cups-driverd.c +++ b/scheduler/cups-driverd.c @@ -1,5 +1,5 @@ /* - * "$Id: cups-driverd.c 6377 2007-03-21 07:17:11Z mike $" + * "$Id: cups-driverd.c 6508 2007-05-03 20:07:14Z mike $" * * PPD/driver support for the Common UNIX Printing System (CUPS). * @@ -32,6 +32,7 @@ * cat_ppd() - Copy a PPD file to stdout. * compare_names() - Compare PPD filenames for sorting. * compare_ppds() - Compare PPD file make and model names for sorting. + * free_array() - Free an array of strings. * list_ppds() - List PPD files. * load_ppds() - Load PPD files recursively. * load_drivers() - Load driver-generated PPD files. @@ -54,6 +55,16 @@ extern cups_encoding_t _ppdGetEncoding(const char *name); /* + * Constants... + */ + +#define PPD_SYNC 0x50504433 /* Sync word for ppds.dat (PPD3) */ +#define PPD_MAX_LANG 32 /* Maximum languages */ +#define PPD_MAX_PROD 8 /* Maximum products */ +#define PPD_MAX_VERS 8 /* Maximum versions */ + + +/* * PPD information structures... */ @@ -61,14 +72,17 @@ typedef struct /**** PPD record ****/ { time_t mtime; /* Modification time */ size_t size; /* Size in bytes */ - char name[512 - sizeof(time_t) - sizeof(size_t)], - /* PPD name */ - natural_language[6], /* LanguageVersion */ - product[122], /* Product */ + char name[512], /* PPD name */ + languages[PPD_MAX_LANG][6], + /* LanguageVersion/cupsLanguages */ + products[PPD_MAX_PROD][128], + /* Product strings */ + psversions[PPD_MAX_VERS][32], + /* PSVersion strings */ make[128], /* Manufacturer */ make_and_model[128], /* NickName/ModelName */ device_id[128]; /* IEEE 1284 Device ID */ -} ppd_rec_t; +} ppd_rec_t; typedef struct /**** In-memory record ****/ { @@ -92,18 +106,20 @@ int ChangedPPD; /* Did we change the PPD database? */ * Local functions... */ -static ppd_info_t *add_ppd(const char *name, const char *natural_language, +static ppd_info_t *add_ppd(const char *name, const char *language, const char *make, const char *make_and_model, const char *device_id, const char *product, - time_t mtime, size_t size); -static int cat_ppd(const char *name); + const char *psversion, time_t mtime, + size_t size); +static int cat_ppd(const char *name, int request_id); static int compare_names(const ppd_info_t *p0, const ppd_info_t *p1); static int compare_ppds(const ppd_info_t *p0, const ppd_info_t *p1); +static void free_array(cups_array_t *a); static int list_ppds(int request_id, int limit, const char *opt); static int load_drivers(void); -static int load_ppds(const char *d, const char *p); +static int load_ppds(const char *d, const char *p, int descend); /* @@ -123,12 +139,15 @@ main(int argc, /* I - Number of command-line args */ */ if (argc == 3 && !strcmp(argv[1], "cat")) - return (cat_ppd(argv[2])); + return (cat_ppd(argv[2], 0)); + else if (argc == 4 && !strcmp(argv[1], "get")) + return (cat_ppd(argv[3], atoi(argv[2]))); else if (argc == 5 && !strcmp(argv[1], "list")) return (list_ppds(atoi(argv[2]), atoi(argv[3]), argv[4])); else { fputs("Usage: cups-driverd cat ppd-name\n", stderr); + fputs("Usage: cups-driverd get request_id ppd-name\n", stderr); fputs("Usage: cups-driverd list request_id limit options\n", stderr); return (1); } @@ -141,11 +160,12 @@ main(int argc, /* I - Number of command-line args */ static ppd_info_t * /* O - PPD */ add_ppd(const char *name, /* I - PPD name */ - const char *natural_language, /* I - Language(s) */ + const char *language, /* I - LanguageVersion */ const char *make, /* I - Manufacturer */ const char *make_and_model, /* I - NickName/ModelName */ const char *device_id, /* I - 1284DeviceID */ const char *product, /* I - Product */ + const char *psversion, /* I - PSVersion */ time_t mtime, /* I - Modification time */ size_t size) /* I - File size */ { @@ -172,7 +192,8 @@ add_ppd(const char *name, /* I - PPD name */ if (ppd == NULL) { - fprintf(stderr, "ERROR: [cups-driverd] Ran out of memory for %d PPD files!\n", + fprintf(stderr, + "ERROR: [cups-driverd] Ran out of memory for %d PPD files!\n", AllocPPDs); return (NULL); } @@ -194,9 +215,11 @@ add_ppd(const char *name, /* I - PPD name */ ppd->record.size = size; strlcpy(ppd->record.name, name, sizeof(ppd->record.name)); - strlcpy(ppd->record.natural_language, natural_language, - sizeof(ppd->record.natural_language)); - strlcpy(ppd->record.product, product, sizeof(ppd->record.product)); + strlcpy(ppd->record.languages[0], language, + sizeof(ppd->record.languages[0])); + strlcpy(ppd->record.products[0], product, sizeof(ppd->record.products[0])); + strlcpy(ppd->record.psversions[0], psversion, + sizeof(ppd->record.psversions[0])); strlcpy(ppd->record.make, make, sizeof(ppd->record.make)); strlcpy(ppd->record.make_and_model, make_and_model, sizeof(ppd->record.make_and_model)); @@ -207,7 +230,8 @@ add_ppd(const char *name, /* I - PPD name */ * Foomatic drivers... */ - if ((recommended = strstr(ppd->record.make_and_model, " (recommended)")) != NULL) + if ((recommended = strstr(ppd->record.make_and_model, + " (recommended)")) != NULL) *recommended = '\0'; /* @@ -223,11 +247,13 @@ add_ppd(const char *name, /* I - PPD name */ */ static int /* O - Exit code */ -cat_ppd(const char *name) /* I - PPD name */ +cat_ppd(const char *name, /* I - PPD name */ + int request_id) /* I - Request ID for response? */ { char scheme[256], /* Scheme from PPD name */ *sptr; /* Pointer into scheme */ char line[1024]; /* Line/filename */ + char message[2048]; /* status-message */ /* @@ -252,6 +278,8 @@ cat_ppd(const char *name) /* I - PPD name */ else scheme[0] = '\0'; + puts("Content-Type: application/ipp\n"); + if (scheme[0]) { /* @@ -273,6 +301,21 @@ cat_ppd(const char *name) /* I - PPD name */ fprintf(stderr, "ERROR: [cups-driverd] Unable to access \"%s\" - %s\n", line, strerror(errno)); + + if (request_id > 0) + { + snprintf(message, sizeof(message), "Unable to access \"%s\" - %s", + line, strerror(errno)); + + cupsdSendIPPHeader(IPP_NOT_FOUND, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); + cupsdSendIPPString(IPP_TAG_TEXT, "status-message", message); + cupsdSendIPPTrailer(); + } + return (1); } @@ -280,6 +323,16 @@ cat_ppd(const char *name) /* I - PPD name */ * Yes, let it cat the PPD file... */ + if (request_id) + { + cupsdSendIPPHeader(IPP_OK, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); + cupsdSendIPPTrailer(); + } + if (execl(line, scheme, "cat", name, (char *)NULL)) { /* @@ -308,6 +361,20 @@ cat_ppd(const char *name) /* I - PPD name */ */ fprintf(stderr, "ERROR: [cups-driverd] Bad PPD name \"%s\"!\n", name); + + if (request_id) + { + snprintf(message, sizeof(message), "Bad PPD name \"%s\"!", name); + + cupsdSendIPPHeader(IPP_OK, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); + cupsdSendIPPString(IPP_TAG_TEXT, "status-message", message); + cupsdSendIPPTrailer(); + } + return (1); } @@ -315,17 +382,85 @@ cat_ppd(const char *name) /* I - PPD name */ * Try opening the file... */ - if ((datadir = getenv("CUPS_DATADIR")) == NULL) - datadir = CUPS_DATADIR; +#ifdef __APPLE__ + if (!strncmp(name, "System/Library/Printers/PPDs/Contents/Resources/", 48) || + !strncmp(name, "Library/Printers/PPDs/Contents/Resources/", 41)) + { + /* + * Map ppd-name to Mac OS X standard locations... + */ + + snprintf(line, sizeof(line), "/%s", name); + } + else + +#elif defined(__linux) + if (!strncmp(name, "lsb/usr/", 8)) + { + /* + * Map ppd-name to LSB standard /usr/share/ppd location... + */ + + snprintf(line, sizeof(line), "/usr/share/ppd/%s", name + 8); + } + else if (!strncmp(name, "lsb/opt/", 8)) + { + /* + * Map ppd-name to LSB standard /opt/share/ppd location... + */ + + snprintf(line, sizeof(line), "/opt/share/ppd/%s", name + 8); + } + else if (!strncmp(name, "lsb/local/", 10)) + { + /* + * Map ppd-name to LSB standard /usr/local/share/ppd location... + */ + + snprintf(line, sizeof(line), "/usr/local/share/ppd/%s", name + 10); + } + else + +#endif /* __APPLE__ */ + { + if ((datadir = getenv("CUPS_DATADIR")) == NULL) + datadir = CUPS_DATADIR; + + snprintf(line, sizeof(line), "%s/model/%s", datadir, name); + } - snprintf(line, sizeof(line), "%s/model/%s", datadir, name); if ((fp = cupsFileOpen(line, "r")) == NULL) { fprintf(stderr, "ERROR: [cups-driverd] Unable to open \"%s\" - %s\n", line, strerror(errno)); + + if (request_id) + { + snprintf(message, sizeof(message), "Unable to open \"%s\" - %s", + line, strerror(errno)); + + cupsdSendIPPHeader(IPP_NOT_FOUND, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); + cupsdSendIPPString(IPP_TAG_TEXT, "status-message", message); + cupsdSendIPPTrailer(); + } + return (1); } + if (request_id) + { + cupsdSendIPPHeader(IPP_OK, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", + "en-US"); + cupsdSendIPPTrailer(); + } + /* * Now copy the file to stdout... */ @@ -377,8 +512,27 @@ compare_ppds(const ppd_info_t *p0, /* I - First PPD file */ p1->record.make_and_model)) != 0) return (diff); else - return (strcasecmp(p0->record.natural_language, - p1->record.natural_language)); + return (strcasecmp(p0->record.languages[0], + p1->record.languages[0])); +} + + +/* + * 'free_array()' - Free an array of strings. + */ + +static void +free_array(cups_array_t *a) /* I - Array to free */ +{ + char *ptr; /* Pointer to string */ + + + for (ptr = (char *)cupsArrayFirst(a); + ptr; + ptr = (char *)cupsArrayNext(a)) + free(ptr); + + cupsArrayDelete(a); } @@ -391,7 +545,7 @@ list_ppds(int request_id, /* I - Request ID */ int limit, /* I - Limit */ const char *opt) /* I - Option argument */ { - int i; /* Looping var */ + int i, j; /* Looping vars */ int count; /* Number of PPDs to send */ ppd_info_t *ppd; /* Current PPD file */ cups_file_t *fp; /* ppds.dat file */ @@ -403,17 +557,27 @@ list_ppds(int request_id, /* I - Request ID */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ const char *requested, /* requested-attributes option */ - *make; /* ppd-make option */ - int send_natural_language, /* Send ppd-natural-language attribute? */ - send_make, /* Send ppd-make attribute? */ - send_make_and_model, /* Send ppd-make-and-model attribute? */ - send_name, /* Send ppd-name attribute? */ - send_device_id, /* Send ppd-device-id attribute? */ - send_product; /* Send ppd-product attribute? */ - - - fprintf(stderr, "DEBUG2: [cups-driverd] list_ppds(request_id=%d, limit=%d, opt=\"%s\"\n", - request_id, limit, opt); + *device_id, /* ppd-device-id option */ + *language, /* ppd-natural-language option */ + *make, /* ppd-make option */ + *make_and_model, /* ppd-make-and-model option */ + *product, /* ppd-product option */ + *psversion; /* ppd-psversion option */ + int mam_len, /* Length of ppd-make-and-model */ + device_id_len, /* Length of ppd-device-id */ + send_natural_language, /* Send ppd-natural-language? */ + send_make, /* Send ppd-make? */ + send_make_and_model, /* Send ppd-make-and-model? */ + send_name, /* Send ppd-name? */ + send_device_id, /* Send ppd-device-id? */ + send_product, /* Send ppd-product? */ + send_psversion, /* Send ppd-psversion? */ + sent_header; /* Sent the IPP header? */ + + + fprintf(stderr, + "DEBUG2: [cups-driverd] list_ppds(request_id=%d, limit=%d, " + "opt=\"%s\"\n", request_id, limit, opt); /* * See if we a PPD database file... @@ -428,45 +592,48 @@ list_ppds(int request_id, /* I - Request ID */ cups_cachedir = CUPS_CACHEDIR; snprintf(filename, sizeof(filename), "%s/ppds.dat", cups_cachedir); - if (!stat(filename, &fileinfo) && - (fileinfo.st_size % sizeof(ppd_rec_t)) == 0 && - (NumPPDs = fileinfo.st_size / sizeof(ppd_rec_t)) > 0) + if ((fp = cupsFileOpen(filename, "r")) != NULL) { /* - * We have a ppds.dat file, so read it! + * See if we have the right sync word... */ - AllocPPDs = NumPPDs; + unsigned ppdsync; /* Sync word */ - if ((PPDs = malloc(sizeof(ppd_info_t) * NumPPDs)) == NULL) + if (cupsFileRead(fp, (char *)&ppdsync, sizeof(ppdsync)) + == sizeof(ppdsync) && + ppdsync == PPD_SYNC && + !stat(filename, &fileinfo) && + ((fileinfo.st_size - sizeof(ppdsync)) % sizeof(ppd_rec_t)) == 0 && + (NumPPDs = (fileinfo.st_size - sizeof(ppdsync)) / + sizeof(ppd_rec_t)) > 0) { - fprintf(stderr, - "ERROR: [cups-driverd] Unable to allocate memory for %d " - "PPD files!\n", NumPPDs); - NumPPDs = 0; - AllocPPDs = 0; - } - else if ((fp = cupsFileOpen(filename, "r")) != NULL) - { - for (i = NumPPDs, ppd = PPDs; i > 0; i --, ppd ++) + /* + * We have a ppds.dat file, so read it! + */ + + if ((PPDs = malloc(sizeof(ppd_info_t) * NumPPDs)) == NULL) + fprintf(stderr, + "ERROR: [cups-driverd] Unable to allocate memory for %d " + "PPD files!\n", NumPPDs); + else { - cupsFileRead(fp, (char *)&(ppd->record), sizeof(ppd_rec_t)); - ppd->found = 0; - } + AllocPPDs = NumPPDs; - cupsFileClose(fp); + for (i = NumPPDs, ppd = PPDs; i > 0; i --, ppd ++) + { + cupsFileRead(fp, (char *)&(ppd->record), sizeof(ppd_rec_t)); + ppd->found = 0; + } - fprintf(stderr, "INFO: [cups-driverd] Read \"%s\", %d PPDs...\n", - filename, NumPPDs); - } - else - { - fprintf(stderr, "ERROR: [cups-driverd] Unable to read \"%s\" - %s\n", filename, - strerror(errno)); - NumPPDs = 0; + fprintf(stderr, "INFO: [cups-driverd] Read \"%s\", %d PPDs...\n", + filename, NumPPDs); + } } - } + cupsFileClose(fp); + } + /* * Load all PPDs in the specified directory and below... */ @@ -477,7 +644,31 @@ list_ppds(int request_id, /* I - Request ID */ cups_datadir = CUPS_DATADIR; snprintf(model, sizeof(model), "%s/model", cups_datadir); - load_ppds(model, ""); + load_ppds(model, "", 1); + +#ifdef __APPLE__ + /* + * Load PPDs from standard Mac OS X locations... + */ + + load_ppds("/Library/Printers/PPDs/Contents/Resources", + "Library/Printers/PPDs/Contents/Resources", 0); + load_ppds("/Library/Printers/PPDs/Contents/Resources/en.lproj", + "Library/Printers/PPDs/Contents/Resources/en.lproj", 0); + load_ppds("/System/Library/Printers/PPDs/Contents/Resources", + "System/Library/Printers/PPDs/Contents/Resources", 0); + load_ppds("/System/Library/Printers/PPDs/Contents/Resources/en.lproj", + "System/Library/Printers/PPDs/Contents/Resources/en.lproj", 0); + +#elif defined(__linux) + /* + * Load PPDs from LSB-defined locations... + */ + + load_ppds("/usr/local/share/ppds", "lsb/local", 1); + load_ppds("/usr/share/ppds", "lsb/usr", 1); + load_ppds("/opt/share/ppds", "lsb/opt", 1); +#endif /* __APPLE__ */ /* * Cull PPD files that are no longer present... @@ -513,6 +704,11 @@ list_ppds(int request_id, /* I - Request ID */ { if ((fp = cupsFileOpen(filename, "w")) != NULL) { + unsigned ppdsync = PPD_SYNC; /* Sync word */ + + + cupsFileWrite(fp, (char *)&ppdsync, sizeof(ppdsync)); + for (i = NumPPDs, ppd = PPDs; i > 0; i --, ppd ++) cupsFileWrite(fp, (char *)&(ppd->record), sizeof(ppd_rec_t)); @@ -538,7 +734,7 @@ list_ppds(int request_id, /* I - Request ID */ * Add the raw driver... */ - add_ppd("raw", "en", "Raw", "Raw Queue", "", "", 0, 0); + add_ppd("raw", "en", "Raw", "Raw Queue", "", "", "", 0, 0); /* * Sort the PPDs by make and model... @@ -552,12 +748,46 @@ list_ppds(int request_id, /* I - Request ID */ * Send IPP attributes... */ - num_options = cupsParseOptions(opt, 0, &options); - requested = cupsGetOption("requested-attributes", num_options, options); - make = cupsGetOption("ppd-make", num_options, options); + num_options = cupsParseOptions(opt, 0, &options); + requested = cupsGetOption("requested-attributes", num_options, options); + device_id = cupsGetOption("ppd-device-id", num_options, options); + language = cupsGetOption("ppd-natural-language", num_options, options); + make = cupsGetOption("ppd-make", num_options, options); + make_and_model = cupsGetOption("ppd-make-and-model", num_options, options); + product = cupsGetOption("ppd-product", num_options, options); + psversion = cupsGetOption("ppd-psversion", num_options, options); + + if (make_and_model) + mam_len = strlen(make_and_model); + else + mam_len = 0; - fprintf(stderr, "DEBUG: [cups-driverd] requested=\"%s\"\n", - requested ? requested : "(nil)"); + if (device_id) + device_id_len = strlen(device_id); + else + device_id_len = 0; + + if (requested) + fprintf(stderr, "DEBUG: [cups-driverd] requested-attributes=\"%s\"\n", + requested); + if (device_id) + fprintf(stderr, "DEBUG: [cups-driverd] ppd-device-id=\"%s\"\n", + device_id); + if (language) + fprintf(stderr, "DEBUG: [cups-driverd] ppd-natural-language=\"%s\"\n", + language); + if (make) + fprintf(stderr, "DEBUG: [cups-driverd] ppd-make=\"%s\"\n", + make); + if (make_and_model) + fprintf(stderr, "DEBUG: [cups-driverd] ppd-make-and-model=\"%s\"\n", + make_and_model); + if (product) + fprintf(stderr, "DEBUG: [cups-driverd] ppd-product=\"%s\"\n", + product); + if (psversion) + fprintf(stderr, "DEBUG: [cups-driverd] ppd-psversion=\"%s\"\n", + psversion); if (!requested || strstr(requested, "all")) { @@ -567,6 +797,7 @@ list_ppds(int request_id, /* I - Request ID */ send_natural_language = 1; send_device_id = 1; send_product = 1; + send_psversion = 1; } else { @@ -578,14 +809,12 @@ list_ppds(int request_id, /* I - Request ID */ send_natural_language = strstr(requested, "ppd-natural-language") != NULL; send_device_id = strstr(requested, "ppd-device-id") != NULL; send_product = strstr(requested, "ppd-product") != NULL; + send_psversion = strstr(requested, "ppd-psversion") != NULL; } puts("Content-Type: application/ipp\n"); - cupsdSendIPPHeader(IPP_OK, request_id); - cupsdSendIPPGroup(IPP_TAG_OPERATION); - cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); - cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US"); + sent_header = 0; if (limit <= 0 || limit > NumPPDs) count = NumPPDs; @@ -593,59 +822,143 @@ list_ppds(int request_id, /* I - Request ID */ count = limit; for (i = NumPPDs, ppd = PPDs; count > 0 && i > 0; i --, ppd ++) - if (!make || !strcasecmp(ppd->record.make, make)) + { + /* + * Filter PPDs based on make, model, or device ID... + */ + + if (device_id && strncasecmp(ppd->record.device_id, device_id, + device_id_len)) + continue; /* TODO: implement smart compare */ + + if (language) { - /* - * Send this PPD... - */ + for (j = 0; j < PPD_MAX_LANG; j ++) + if (!ppd->record.languages[j][0] || + !strcasecmp(ppd->record.languages[j], language)) + break; + + if (j >= PPD_MAX_LANG || !ppd->record.languages[j][0]) + continue; + } + + if (make && strcasecmp(ppd->record.make, make)) + continue; + + if (make_and_model && strncasecmp(ppd->record.make_and_model, + make_and_model, mam_len)) + continue; + + if (product) + { + for (j = 0; j < PPD_MAX_PROD; j ++) + if (!ppd->record.products[j][0] || + !strcasecmp(ppd->record.products[j], product)) + break; - fprintf(stderr, "DEBUG: [cups-driverd] Sending %s (%s)...\n", - ppd->record.name, ppd->record.make_and_model); + if (j >= PPD_MAX_PROD || !ppd->record.products[j][0]) + continue; + } - count --; + if (psversion) + { + for (j = 0; j < PPD_MAX_VERS; j ++) + if (!ppd->record.psversions[j][0] || + !strcasecmp(ppd->record.psversions[j], psversion)) + break; - cupsdSendIPPGroup(IPP_TAG_PRINTER); + if (j >= PPD_MAX_VERS || !ppd->record.psversions[j][0]) + continue; + } - if (send_name) - cupsdSendIPPString(IPP_TAG_NAME, "ppd-name", ppd->record.name); + /* + * Send this PPD... + */ - if (send_natural_language) - cupsdSendIPPString(IPP_TAG_LANGUAGE, "ppd-natural-language", - ppd->record.natural_language); + if (!sent_header) + { + sent_header = 1; - if (send_make) - cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make", ppd->record.make); + cupsdSendIPPHeader(IPP_OK, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US"); + } - if (send_make_and_model) - cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make-and-model", - ppd->record.make_and_model); + fprintf(stderr, "DEBUG: [cups-driverd] Sending %s (%s)...\n", + ppd->record.name, ppd->record.make_and_model); - if (send_device_id) - cupsdSendIPPString(IPP_TAG_TEXT, "ppd-device-id", - ppd->record.device_id); + count --; - if (send_product) - cupsdSendIPPString(IPP_TAG_TEXT, "ppd-product", - ppd->record.product); + cupsdSendIPPGroup(IPP_TAG_PRINTER); - /* - * If we have only requested the ppd-make attribute, then skip - * the remaining PPDs with this make... - */ + if (send_name) + cupsdSendIPPString(IPP_TAG_NAME, "ppd-name", ppd->record.name); - if (requested && !strcmp(requested, "ppd-make")) - { - const char *this_make; /* This ppd-make */ + if (send_natural_language) + { + cupsdSendIPPString(IPP_TAG_LANGUAGE, "ppd-natural-language", + ppd->record.languages[0]); + for (j = 1; j < PPD_MAX_LANG && ppd->record.languages[j][0]; j ++) + cupsdSendIPPString(IPP_TAG_LANGUAGE, "", ppd->record.languages[j]); + } - for (this_make = ppd->record.make, i --, ppd ++; i > 0; i --, ppd ++) - if (strcasecmp(this_make, ppd->record.make)) - break; + if (send_make) + cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make", ppd->record.make); - i ++; - ppd --; - } + if (send_make_and_model) + cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make-and-model", + ppd->record.make_and_model); + + if (send_device_id) + cupsdSendIPPString(IPP_TAG_TEXT, "ppd-device-id", + ppd->record.device_id); + + if (send_product) + { + cupsdSendIPPString(IPP_TAG_TEXT, "ppd-product", + ppd->record.products[0]); + + for (j = 1; j < PPD_MAX_PROD && ppd->record.products[j][0]; j ++) + cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.products[j]); + } + + if (send_psversion) + { + cupsdSendIPPString(IPP_TAG_TEXT, "ppd-psversion", + ppd->record.psversions[0]); + + for (j = 1; j < PPD_MAX_VERS && ppd->record.psversions[j][0]; j ++) + cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.psversions[j]); + } + + /* + * If we have only requested the ppd-make attribute, then skip + * the remaining PPDs with this make... + */ + + if (requested && !strcmp(requested, "ppd-make")) + { + const char *this_make; /* This ppd-make */ + + + for (this_make = ppd->record.make, i --, ppd ++; i > 0; i --, ppd ++) + if (strcasecmp(this_make, ppd->record.make)) + break; + + i ++; + ppd --; } + } + + if (!sent_header) + { + cupsdSendIPPHeader(IPP_NOT_FOUND, request_id); + cupsdSendIPPGroup(IPP_TAG_OPERATION); + cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); + cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US"); + } cupsdSendIPPTrailer(); @@ -659,7 +972,8 @@ list_ppds(int request_id, /* I - Request ID */ static int /* O - 1 on success, 0 on failure */ load_ppds(const char *d, /* I - Actual directory */ - const char *p) /* I - Virtual path in name */ + const char *p, /* I - Virtual path in name */ + int descend) /* I - Descend into directories? */ { int i; /* Looping var */ cups_file_t *fp; /* Pointer to file */ @@ -677,8 +991,11 @@ load_ppds(const char *d, /* I - Actual directory */ model_name[256], /* ModelName */ nick_name[256], /* NickName */ device_id[256], /* 1284DeviceID */ - product[256]; /* Product */ - cups_array_t *products; /* Array of product strings */ + product[256], /* Product */ + psversion[256]; /* PSVersion */ + cups_array_t *products, /* Product array */ + *psversions, /* PSVersion array */ + *cups_languages; /* cupsLanguages array */ ppd_info_t *ppd, /* New PPD file */ key; /* Search key */ int new_ppd; /* Is this a new PPD? */ @@ -688,7 +1005,7 @@ load_ppds(const char *d, /* I - Actual directory */ *language; /* Language code */ } languages[] = { - { "chinese", "cn" }, + { "chinese", "zh" }, { "danish", "da" }, { "dutch", "nl" }, { "english", "en" }, @@ -711,7 +1028,8 @@ load_ppds(const char *d, /* I - Actual directory */ if ((dir = cupsDirOpen(d)) == NULL) { - fprintf(stderr, "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n", + fprintf(stderr, + "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n", d, strerror(errno)); return (0); } @@ -742,11 +1060,12 @@ load_ppds(const char *d, /* I - Actual directory */ * Do subdirectory... */ - if (!load_ppds(filename, name)) - { - cupsDirClose(dir); - return (1); - } + if (descend) + if (!load_ppds(filename, name, 1)) + { + cupsDirClose(dir); + return (1); + } continue; } @@ -802,7 +1121,9 @@ load_ppds(const char *d, /* I - Actual directory */ * Now read until we get the NickName field... */ - products = cupsArrayNew(NULL, NULL); + cups_languages = cupsArrayNew(NULL, NULL); + products = cupsArrayNew(NULL, NULL); + psversions = cupsArrayNew(NULL, NULL); model_name[0] = '\0'; nick_name[0] = '\0'; @@ -830,6 +1151,39 @@ load_ppds(const char *d, /* I - Actual directory */ sscanf(line, "%*[^\"]\"(%255[^)]", product); cupsArrayAdd(products, strdup(product)); } + else if (!strncasecmp(line, "*PSVersion:", 11)) + { + sscanf(line, "%*[^\"]\"%255[^\"]", psversion); + cupsArrayAdd(psversions, strdup(psversion)); + } + else if (!strncasecmp(line, "*cupsLanguages:", 15)) + { + char *start; /* Start of language */ + + + for (start = line + 15; *start && isspace(*start & 255); start ++); + + if (*start++ == '\"') + { + while (*start) + { + for (ptr = start + 1; + *ptr && *ptr != '\"' && !isspace(*ptr & 255); + ptr ++); + + if (*ptr) + { + *ptr++ = '\0'; + + while (isspace(*ptr & 255)) + *ptr++ = '\0'; + } + + cupsArrayAdd(cups_languages, strdup(start)); + start = ptr; + } + } + } else if (!strncmp(line, "*OpenUI", 7)) { /* @@ -837,7 +1191,8 @@ load_ppds(const char *d, /* I - Actual directory */ * before the first OpenUI... */ - if ((model_name[0] || nick_name[0]) && cupsArrayCount(products) > 0) + if ((model_name[0] || nick_name[0]) && cupsArrayCount(products) > 0 && + cupsArrayCount(psversions) > 0) break; } } @@ -861,7 +1216,8 @@ load_ppds(const char *d, /* I - Actual directory */ while (isspace(make_model[0] & 255)) _cups_strcpy(make_model, make_model + 1); - if (!make_model[0] || cupsArrayCount(products) == 0) + if (!make_model[0] || cupsArrayCount(products) == 0 || + cupsArrayCount(psversions) == 0) { /* * We don't have all the info needed, so skip this file... @@ -874,12 +1230,12 @@ load_ppds(const char *d, /* I - Actual directory */ if (cupsArrayCount(products) == 0) fprintf(stderr, "WARNING: Missing Product in %s!\n", filename); - for (ptr = (char *)cupsArrayFirst(products); - ptr; - ptr = (char *)cupsArrayNext(products)) - free(ptr); + if (cupsArrayCount(psversions) == 0) + fprintf(stderr, "WARNING: Missing PSVersion in %s!\n", filename); - cupsArrayDelete(products); + free_array(products); + free_array(psversions); + free_array(cups_languages); continue; } @@ -1007,10 +1363,12 @@ load_ppds(const char *d, /* I - Actual directory */ fprintf(stderr, "DEBUG: [cups-driverd] Adding ppd \"%s\"...\n", name); - /* TODO: Support multiple Products... */ - if (!add_ppd(name, lang_version, manufacturer, make_model, device_id, - (char *)cupsArrayFirst(products), - dent->fileinfo.st_mtime, dent->fileinfo.st_size)) + ppd = add_ppd(name, lang_version, manufacturer, make_model, device_id, + (char *)cupsArrayFirst(products), + (char *)cupsArrayFirst(psversions), + dent->fileinfo.st_mtime, dent->fileinfo.st_size); + + if (!ppd) { cupsDirClose(dir); return (0); @@ -1034,23 +1392,44 @@ load_ppds(const char *d, /* I - Actual directory */ strlcpy(ppd->record.make, manufacturer, sizeof(ppd->record.make)); strlcpy(ppd->record.make_and_model, make_model, sizeof(ppd->record.make_and_model)); - strlcpy(ppd->record.natural_language, lang_version, - sizeof(ppd->record.natural_language)); - strlcpy(ppd->record.product, (char *)cupsArrayFirst(products), - sizeof(ppd->record.product)); + strlcpy(ppd->record.languages[0], lang_version, + sizeof(ppd->record.languages[0])); + strlcpy(ppd->record.products[0], (char *)cupsArrayFirst(products), + sizeof(ppd->record.products[0])); + strlcpy(ppd->record.psversions[0], (char *)cupsArrayFirst(psversions), + sizeof(ppd->record.psversions[0])); strlcpy(ppd->record.device_id, device_id, sizeof(ppd->record.device_id)); } /* - * Free products... + * Add remaining products, versions, and languages... */ - for (ptr = (char *)cupsArrayFirst(products); - ptr; - ptr = (char *)cupsArrayNext(products)) - free(ptr); + for (i = 1; + i < PPD_MAX_PROD && (ptr = (char *)cupsArrayNext(products)) != NULL; + i ++) + strlcpy(ppd->record.products[i], ptr, + sizeof(ppd->record.products[0])); + + for (i = 1; + i < PPD_MAX_VERS && (ptr = (char *)cupsArrayNext(psversions)) != NULL; + i ++) + strlcpy(ppd->record.psversions[i], ptr, + sizeof(ppd->record.psversions[0])); - cupsArrayDelete(products); + for (i = 1, ptr = (char *)cupsArrayFirst(cups_languages); + i < PPD_MAX_LANG && ptr; + i ++, ptr = (char *)cupsArrayNext(cups_languages)) + strlcpy(ppd->record.languages[i], ptr, + sizeof(ppd->record.languages[0])); + + /* + * Free products, versions, and languages... + */ + + free_array(cups_languages); + free_array(products); + free_array(psversions); ChangedPPD = 1; } @@ -1068,7 +1447,10 @@ load_ppds(const char *d, /* I - Actual directory */ static int /* O - 1 on success, 0 on failure */ load_drivers(void) { - const char *server_bin; /* CUPS_SERVERBIN environment variable */ + int i; /* Looping var */ + char *start, /* Start of value */ + *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 */ cups_dir_t *dir; /* Directory pointer */ @@ -1076,11 +1458,13 @@ load_drivers(void) char filename[1024], /* Name of driver */ line[2048], /* Line from driver */ name[512], /* ppd-name */ - natural_language[128], /* ppd-natural-language */ make[128], /* ppd-make */ - make_and_model[256], /* ppd-make-and-model */ - device_id[256], /* ppd-device-id */ - product[256]; /* ppd-product */ + make_and_model[128], /* ppd-make-and-model */ + device_id[128], /* ppd-device-id */ + languages[128], /* ppd-natural-language */ + product[128], /* ppd-product */ + psversion[128]; /* ppd-psversion */ + ppd_info_t *ppd; /* Newly added PPD */ /* @@ -1126,17 +1510,18 @@ load_drivers(void) * Each line is of the form: * * "ppd-name" ppd-natural-language "ppd-make" "ppd-make-and-model" \ - * "ppd-device-id" "ppd-product" + * "ppd-device-id" "ppd-product" "ppd-psversion" */ device_id[0] = '\0'; product[0] = '\0'; + psversion[0] = '\0'; if (sscanf(line, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\"" - "%*[ \t]\"%256[^\"]\"%*[ \t]\"%256[^\"]\"" - "%*[ \t]\"%256[^\"]\"", - name, natural_language, make, make_and_model, - device_id, product) < 4) + "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"" + "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"", + name, languages, make, make_and_model, + device_id, product, psversion) < 4) { /* * Bad format; strip trailing newline and write an error message. @@ -1155,13 +1540,34 @@ load_drivers(void) * Add the device to the array of available devices... */ - if (!add_ppd(name, natural_language, make, make_and_model, device_id, - product, 0, 0)) + if ((start = strchr(languages, ',')) != NULL) + *start++ = '\0'; + + ppd = add_ppd(name, languages, make, make_and_model, device_id, + product, psversion, 0, 0); + + if (!ppd) { cupsDirClose(dir); return (0); } + if (start && *start) + { + for (i = 1; i < PPD_MAX_LANG && *start; i ++) + { + if ((ptr = strchr(start, ',')) != NULL) + *ptr++ = '\0'; + else + ptr = start + strlen(start); + + strlcpy(ppd->record.languages[i], start, + sizeof(ppd->record.languages[0])); + + start = ptr; + } + } + fprintf(stderr, "DEBUG: [cups-driverd] Added dynamic PPD \"%s\"...\n", name); } @@ -1181,5 +1587,5 @@ load_drivers(void) /* - * End of "$Id: cups-driverd.c 6377 2007-03-21 07:17:11Z mike $". + * End of "$Id: cups-driverd.c 6508 2007-05-03 20:07:14Z mike $". */ diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index 2ae4b6805..373b7c535 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -1,5 +1,5 @@ /* - * "$Id: dirsvc.c 6376 2007-03-21 06:39:10Z mike $" + * "$Id: dirsvc.c 6483 2007-04-30 17:16:16Z mike $" * * Directory services routines for the Common UNIX Printing System (CUPS). * @@ -2931,7 +2931,7 @@ send_cups_browse(cupsd_printer_t *p) /* I - Printer to send */ { httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, iface->hostname, iface->port, - (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s%s" : + (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s" : "/printers/%s", p->name); snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\" %s\n", @@ -3802,5 +3802,5 @@ update_polling(void) /* - * End of "$Id: dirsvc.c 6376 2007-03-21 06:39:10Z mike $". + * End of "$Id: dirsvc.c 6483 2007-04-30 17:16:16Z mike $". */ diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 5a8555ac4..bbba01621 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -1,5 +1,5 @@ /* - * "$Id: ipp.c 6433 2007-04-02 21:50:50Z mike $" + * "$Id: ipp.c 6508 2007-05-03 20:07:14Z mike $" * * IPP routines for the Common UNIX Printing System (CUPS) scheduler. * @@ -65,6 +65,7 @@ * get_job_attrs() - Get job attributes. * get_jobs() - Get a list of jobs for the specified printer. * get_notifications() - Get events for a subscription. + * get_ppd() - Get a named PPD from the local system. * get_ppds() - Get the list of PPD files on the local * system. * get_printer_attrs() - Get printer attributes. @@ -92,6 +93,7 @@ * start_printer() - Start a printer. * stop_printer() - Stop a printer. * url_encode_attr() - URL-encode a string attribute. + * url_encode_string() - URL-encode a string. * user_allowed() - See if a user is allowed to print to a queue. * validate_job() - Validate printer options and destination. * validate_name() - Make sure the printer name only contains @@ -178,6 +180,7 @@ static void get_devices(cupsd_client_t *con); static void get_jobs(cupsd_client_t *con, ipp_attribute_t *uri); static void get_job_attrs(cupsd_client_t *con, ipp_attribute_t *uri); static void get_notifications(cupsd_client_t *con); +static void get_ppd(cupsd_client_t *con, ipp_attribute_t *uri); static void get_ppds(cupsd_client_t *con); static void get_printers(cupsd_client_t *con, int type); static void get_printer_attrs(cupsd_client_t *con, ipp_attribute_t *uri); @@ -216,6 +219,7 @@ static void start_printer(cupsd_client_t *con, ipp_attribute_t *uri); static void stop_printer(cupsd_client_t *con, ipp_attribute_t *uri); static void url_encode_attr(ipp_attribute_t *attr, char *buffer, int bufsize); +static char *url_encode_string(const char *s, char *buffer, int bufsize); static int user_allowed(cupsd_printer_t *p, const char *username); static void validate_job(cupsd_client_t *con, ipp_attribute_t *uri); static int validate_name(const char *name); @@ -344,6 +348,8 @@ cupsdProcessIPPRequest( else if ((attr = ippFindAttribute(con->request, "job-uri", IPP_TAG_URI)) != NULL) uri = attr; + else if (con->request->request.op.operation_id == CUPS_GET_PPD) + uri = ippFindAttribute(con->request, "ppd-name", IPP_TAG_NAME); else uri = NULL; @@ -399,11 +405,12 @@ cupsdProcessIPPRequest( if (!uri) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing printer-uri or job-uri attribute!"); + "Missing printer-uri, job-uri, or ppd-name " + "attribute!"); cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, - "%04X %s Missing printer-uri or job-uri attribute", - IPP_BAD_REQUEST, con->http.hostname); + "%04X %s Missing printer-uri, job-uri, or ppd-name " + "attribute", IPP_BAD_REQUEST, con->http.hostname); } cupsdLogMessage(CUPSD_LOG_DEBUG, "Request attributes follow..."); @@ -572,6 +579,10 @@ cupsdProcessIPPRequest( get_devices(con); break; + case CUPS_GET_PPD : + get_ppd(con, uri); + break; + case CUPS_GET_PPDS : get_ppds(con); break; @@ -665,6 +676,15 @@ cupsdProcessIPPRequest( length = ippLength(con->response); + if (con->file >= 0 && !con->pipe_pid) + { + struct stat fileinfo; /* File information */ + + + if (!fstat(con->file, &fileinfo)) + length += fileinfo.st_size; + } + if (httpPrintf(HTTP(con), "Content-Length: " CUPS_LLFMT "\r\n\r\n", CUPS_LLCAST length) < 0) return (0); @@ -674,6 +694,11 @@ cupsdProcessIPPRequest( con->http.data_encoding = HTTP_ENCODE_LENGTH; con->http.data_remaining = length; + + if (con->http.data_remaining <= INT_MAX) + con->http._data_remaining = con->http.data_remaining; + else + con->http._data_remaining = INT_MAX; } cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient, @@ -5888,6 +5913,147 @@ get_notifications(cupsd_client_t *con) /* I - Client connection */ /* + * 'get_ppd()' - Get a named PPD from the local system. + */ + +static void +get_ppd(cupsd_client_t *con, /* I - Client connection */ + ipp_attribute_t *uri) /* I - Printer URI or PPD name */ +{ + http_status_t status; /* Policy status */ + cupsd_printer_t *dest; /* Destination */ + cups_ptype_t dtype; /* Destination type */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppd(%p[%d], %p[%s=%s])", con, + con->http.fd, uri, uri->name, uri->values[0].string.text); + + if (!strcmp(uri->name, "ppd-name")) + { + /* + * Return a PPD file from cups-driverd... + */ + + char command[1024], /* cups-driverd command */ + options[1024], /* Options to pass to command */ + ppd_name[1024]; /* ppd-name */ + + + /* + * Check policy... + */ + + if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK) + { + send_http_error(con, status, NULL); + return; + } + + /* + * Run cups-driverd command with the given options... + */ + + snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin); + url_encode_string(uri->values[0].string.text, ppd_name, sizeof(ppd_name)); + snprintf(options, sizeof(options), "get+%d+%s", + con->request->request.op.request_id, ppd_name); + + if (cupsdSendCommand(con, command, options, 0)) + { + /* + * Command started successfully, don't send an IPP response here... + */ + + ippDelete(con->response); + con->response = NULL; + } + else + { + /* + * Command failed, return "internal error" so the user knows something + * went wrong... + */ + + send_ipp_status(con, IPP_INTERNAL_ERROR, + _("cups-driverd failed to execute.")); + } + } + else if (!strcmp(uri->name, "printer-uri") && + cupsdValidateDest(uri->values[0].string.text, &dtype, &dest)) + { + int i; /* Looping var */ + char filename[1024]; /* PPD filename */ + + + /* + * Check policy... + */ + + if ((status = cupsdCheckPolicy(dest->op_policy_ptr, con, NULL)) != HTTP_OK) + { + send_http_error(con, status, NULL); + return; + } + + /* + * See if we need the PPD for a class or remote printer... + */ + + if (dtype & CUPS_PRINTER_REMOTE) + { + send_ipp_status(con, CUPS_SEE_OTHER, NULL); + ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, dest->uri); + return; + } + else if (dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) + { + for (i = 0; i < dest->num_printers; i ++) + if (!(dest->printers[i]->type & + (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | + CUPS_PRINTER_REMOTE))) + break; + + if (i < dest->num_printers) + dest = dest->printers[i]; + else + { + send_ipp_status(con, CUPS_SEE_OTHER, NULL); + ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, dest->printers[0]->uri); + return; + } + } + + /* + * Found the printer with the PPD file, now see if there is one... + */ + + snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, + dest->name); + + if ((con->file = open(filename, O_RDONLY)) < 0) + { + send_ipp_status(con, IPP_NOT_FOUND, + _("The PPD file \"%s\" could not be opened: %s"), + uri->values[i].string.text, strerror(errno)); + return; + } + + fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC); + + con->pipe_pid = 0; + + send_ipp_status(con, IPP_OK, NULL); + } + else + send_ipp_status(con, IPP_NOT_FOUND, + _("The PPD file \"%s\" could not be found."), + uri->values[0].string.text); +} + + +/* * 'get_ppds()' - Get the list of PPD files on the local system. */ @@ -5896,13 +6062,26 @@ get_ppds(cupsd_client_t *con) /* I - Client connection */ { http_status_t status; /* Policy status */ ipp_attribute_t *limit, /* Limit attribute */ + *device, /* ppd-device-id attribute */ + *language, /* ppd-natural-language attribute */ *make, /* ppd-make attribute */ + *model, /* ppd-make-and-model attribute */ + *product, /* ppd-product attribute */ + *psversion, /* ppd-psverion attribute */ *requested; /* requested-attributes attribute */ - char command[1024], /* cups-deviced command */ + char command[1024], /* cups-driverd command */ options[1024], /* Options to pass to command */ - requested_str[256], + device_str[256],/* Escaped ppd-device-id string */ + language_str[256], + /* Escaped ppd-natural-language string */ + make_str[256], /* Escaped ppd-make string */ + model_str[256], /* Escaped ppd-make-and-model string */ + product_str[256], + /* Escaped ppd-product string */ + psversion_str[256], + /* Escaped ppd-psversion string */ + requested_str[256]; /* String for requested attributes */ - make_str[256]; /* Escaped ppd-make string */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->http.fd); @@ -5922,7 +6101,14 @@ get_ppds(cupsd_client_t *con) /* I - Client connection */ */ limit = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER); + device = ippFindAttribute(con->request, "ppd-device-id", IPP_TAG_TEXT); + language = ippFindAttribute(con->request, "ppd-natural-language", + IPP_TAG_LANGUAGE); make = ippFindAttribute(con->request, "ppd-make", IPP_TAG_TEXT); + model = ippFindAttribute(con->request, "ppd-make-and-model", + IPP_TAG_TEXT); + product = ippFindAttribute(con->request, "ppd-product", IPP_TAG_TEXT); + psversion = ippFindAttribute(con->request, "ppd-psversion", IPP_TAG_TEXT); requested = ippFindAttribute(con->request, "requested-attributes", IPP_TAG_KEYWORD); @@ -5931,16 +6117,47 @@ get_ppds(cupsd_client_t *con) /* I - Client connection */ else strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str)); + if (device) + url_encode_attr(device, device_str, sizeof(device_str)); + else + device_str[0] = '\0'; + + if (language) + url_encode_attr(language, language_str, sizeof(language_str)); + else + language_str[0] = '\0'; + if (make) url_encode_attr(make, make_str, sizeof(make_str)); else make_str[0] = '\0'; + if (model) + url_encode_attr(model, model_str, sizeof(model_str)); + else + model_str[0] = '\0'; + + if (product) + url_encode_attr(product, product_str, sizeof(product_str)); + else + product_str[0] = '\0'; + + if (psversion) + url_encode_attr(psversion, psversion_str, sizeof(psversion_str)); + else + psversion_str[0] = '\0'; + snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin); - snprintf(options, sizeof(options), "list+%d+%d+%s%s%s", + snprintf(options, sizeof(options), "list+%d+%d+%s%s%s%s%s%s%s%s%s%s%s%s%s", con->request->request.op.request_id, limit ? limit->values[0].integer : 0, - requested_str, make ? "%20" : "", make_str); + requested_str, + device ? "%20" : "", device_str, + language ? "%20" : "", language_str, + make ? "%20" : "", make_str, + model ? "%20" : "", model_str, + product ? "%20" : "", product_str, + psversion ? "%20" : "", psversion_str); if (cupsdSendCommand(con, command, options, 0)) { @@ -7621,6 +7838,9 @@ renew_subscription( cupsdSaveAllSubscriptions(); con->response->request.status.status_code = IPP_OK; + + ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, + "notify-lease-duration", sub->lease); } @@ -9221,8 +9441,7 @@ url_encode_attr(ipp_attribute_t *attr, /* I - Attribute */ { int i; /* Looping var */ char *bufptr, /* Pointer into buffer */ - *bufend, /* End of buffer */ - *valptr; /* Pointer into value */ + *bufend; /* End of buffer */ strlcpy(buffer, attr->name, bufsize); @@ -9244,25 +9463,8 @@ url_encode_attr(ipp_attribute_t *attr, /* I - Attribute */ *bufptr++ = '\''; - for (valptr = attr->values[i].string.text; - *valptr && bufptr < bufend; - valptr ++) - if (*valptr == ' ') - { - if (bufptr >= (bufend - 2)) - break; - - *bufptr++ = '%'; - *bufptr++ = '2'; - *bufptr++ = '0'; - } - else if (*valptr == '\'' || *valptr == '\\') - { - *bufptr++ = '\\'; - *bufptr++ = *valptr; - } - else - *bufptr++ = *valptr; + bufptr = url_encode_string(attr->values[i].string.text, + bufptr, bufend - bufptr + 1); if (bufptr >= bufend) break; @@ -9275,6 +9477,55 @@ url_encode_attr(ipp_attribute_t *attr, /* I - Attribute */ /* + * 'url_encode_string()' - URL-encode a string. + */ + +static char * /* O - End of string */ +url_encode_string(const char *s, /* I - String */ + char *buffer, /* I - String buffer */ + int bufsize) /* I - Size of buffer */ +{ + char *bufptr, /* Pointer into buffer */ + *bufend; /* End of buffer */ + static const char *hex = "0123456789ABCDEF"; + /* Hex digits */ + + + bufptr = buffer; + bufend = buffer + bufsize - 1; + + while (*s && bufptr < bufend) + { + if (*s == ' ' || *s == '%') + { + if (bufptr >= (bufend - 2)) + break; + + *bufptr++ = '%'; + *bufptr++ = hex[(*s >> 4) & 15]; + *bufptr++ = hex[*s & 15]; + + s ++; + } + else if (*s == '\'' || *s == '\\') + { + if (bufptr >= (bufend - 1)) + break; + + *bufptr++ = '\\'; + *bufptr++ = *s++; + } + else + *bufptr++ = *s++; + } + + *bufptr = '\0'; + + return (bufptr); +} + + +/* * 'user_allowed()' - See if a user is allowed to print to a queue. */ @@ -9485,5 +9736,5 @@ validate_user(cupsd_job_t *job, /* I - Job */ /* - * End of "$Id: ipp.c 6433 2007-04-02 21:50:50Z mike $". + * End of "$Id: ipp.c 6508 2007-05-03 20:07:14Z mike $". */ diff --git a/scheduler/job.c b/scheduler/job.c index 96513a2f5..90434af16 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -1,5 +1,5 @@ /* - * "$Id: job.c 6433 2007-04-02 21:50:50Z mike $" + * "$Id: job.c 6462 2007-04-23 19:25:13Z mike $" * * Job management routines for the Common UNIX Printing System (CUPS). * @@ -2721,6 +2721,7 @@ start_job(cupsd_job_t *job, /* I - Job ID */ if ((!strcmp(attr->name, "page-label") || !strcmp(attr->name, "page-border") || !strncmp(attr->name, "number-up", 9) || + !strcmp(attr->name, "page-ranges") || !strcmp(attr->name, "page-set") || !strcasecmp(attr->name, "AP_FIRSTPAGE_InputSlot") || !strcasecmp(attr->name, "AP_FIRSTPAGE_ManualFeed")) && @@ -3323,6 +3324,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */ cupsdClosePipe(job->status_pipes); cupsdStatBufDelete(job->status_buffer); + job->status_buffer = NULL; + cupsArrayDelete(filters); if (printer->remote && job->num_files > 1) @@ -3549,5 +3552,5 @@ update_job(cupsd_job_t *job) /* I - Job to check */ /* - * End of "$Id: job.c 6433 2007-04-02 21:50:50Z mike $". + * End of "$Id: job.c 6462 2007-04-23 19:25:13Z mike $". */ diff --git a/scheduler/log.c b/scheduler/log.c index 11c3cbcfe..2c7c573e2 100644 --- a/scheduler/log.c +++ b/scheduler/log.c @@ -1,9 +1,9 @@ /* - * "$Id: log.c 6328 2007-03-12 14:45:42Z mike $" + * "$Id: log.c 6492 2007-04-30 19:31:36Z mike $" * * Log file routines for the Common UNIX Printing System (CUPS). * - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Easy Software Products and are protected by Federal @@ -546,10 +546,23 @@ check_log_file(cups_file_t **lf, /* IO - Log file */ if ((*lf = cupsFileOpen(filename, "a")) == NULL) { - syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, - strerror(errno)); + /* + * If the file is in CUPS_LOGDIR then try to create a missing directory... + */ - return (0); + if (!strncmp(filename, CUPS_LOGDIR, strlen(CUPS_LOGDIR))) + { + cupsdCheckPermissions(CUPS_LOGDIR, NULL, 0755, RunUser, Group, 1, -1); + + *lf = cupsFileOpen(filename, "a"); + } + + if (*lf == NULL) + { + syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, + strerror(errno)); + return (0); + } } if (strncmp(filename, "/dev/", 5)) @@ -603,5 +616,5 @@ check_log_file(cups_file_t **lf, /* IO - Log file */ /* - * End of "$Id: log.c 6328 2007-03-12 14:45:42Z mike $". + * End of "$Id: log.c 6492 2007-04-30 19:31:36Z mike $". */ diff --git a/scheduler/main.c b/scheduler/main.c index f17969eea..79d70912e 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -1,5 +1,5 @@ /* - * "$Id: main.c 6365 2007-03-19 20:56:57Z mike $" + * "$Id: main.c 6493 2007-04-30 19:33:31Z mike $" * * Scheduler main loop for the Common UNIX Printing System (CUPS). * @@ -33,10 +33,6 @@ * launchd_checkin() - Check-in with launchd and collect the * listening fds. * launchd_checkout() - Check-out with launchd. - * launchd_create_dict() - Create a dictionary representing the launchd - * config file org.cups.cupsd.plist. - * launchd_sync_conf() - Re-write the launchd config file - * org.cups.cupsd.plist based on cupsd.conf. * parent_handler() - Catch USR1/CHLD signals... * process_children() - Process all dead children... * sigchld_handler() - Handle 'child' signals from old processes. @@ -93,8 +89,6 @@ #ifdef HAVE_LAUNCHD static void launchd_checkin(void); static void launchd_checkout(void); -static CFDictionaryRef launchd_create_dict(void); -static int launchd_sync_conf(void); #endif /* HAVE_LAUNCHD */ static void parent_handler(int sig); static void process_children(void); @@ -120,13 +114,6 @@ static int dead_children = 0; static int stop_scheduler = 0; /* Should the scheduler stop? */ -#ifdef HAVE_LAUNCHD -static CFURLRef launchd_conf_url = NULL; - /* org.cups.cupsd.plist url */ -static CFDictionaryRef launchd_conf_dict = NULL; - /* org.cups.cupsd.plist dict */ -#endif /* HAVE_LAUNCHD */ - #if defined(__APPLE__) && defined(HAVE_DLFCN_H) static const char *PSQLibPath = "/usr/lib/libPrintServiceQuota.dylib"; static const char *PSQLibFuncName = "PSQUpdateQuota"; @@ -366,7 +353,7 @@ main(int argc, /* I - Number of command-line args */ getrlimit(RLIMIT_NOFILE, &limit); - for (i = 0; i < limit.rlim_cur; i ++) + for (i = 0; i < limit.rlim_cur && i < 1024; i ++) close(i); #endif /* DEBUG */ } @@ -420,14 +407,7 @@ main(int argc, /* I - Number of command-line args */ if (Launchd) { /* - * If we were started by launchd, make sure the cupsd plist file contains - * the same listeners as cupsd.conf. - */ - - launchd_sync_conf(); - - /* - * Then get the file descriptors from launchd... + * If we were started by launchd get the listen sockets file descriptors... */ launchd_checkin(); @@ -638,7 +618,10 @@ main(int argc, /* I - Number of command-line args */ #if HAVE_LAUNCHD if (Launchd) { - launchd_sync_conf(); + /* + * If we were started by launchd get the listen sockets file descriptors... + */ + launchd_checkin(); } #endif /* HAVE_LAUNCHD */ @@ -952,21 +935,27 @@ main(int argc, /* I - Number of command-line args */ #ifdef HAVE_LAUNCHD /* - * Update the launchd config file as needed... + * Update the launchd KeepAlive file as needed... */ if (Launchd) - { launchd_checkout(); - launchd_sync_conf(); +#endif /* HAVE_LAUNCHD */ - if (launchd_conf_url) - CFRelease(launchd_conf_url); +#ifdef __APPLE__ +#ifdef HAVE_DLFCN_H + /* + * Unload Print Service quota enforcement library (X Server only) + */ - if (launchd_conf_dict) - CFRelease(launchd_conf_dict); + PSQUpdateQuotaProc = NULL; + if (PSQLibRef) + { + dlclose(PSQLibRef); + PSQLibRef = NULL; } -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_DLFCN_H */ +#endif /* __APPLE__ */ #ifdef __sgi /* @@ -1335,38 +1324,6 @@ launchd_checkin(void) } } - /* - * Collect the browse socket (if there is one)... - */ - - if ((ld_array = launch_data_dict_lookup(ld_sockets, "BrowseSockets"))) - { - if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY) - { - if ((tmp = launch_data_array_get_index(ld_array, 0))) - { - if (launch_data_get_type(tmp) == LAUNCH_DATA_FD) - { - if (BrowseSocket != -1) - close(BrowseSocket); - - BrowseSocket = launch_data_get_fd(tmp); - } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "launchd_checkin: BrowseSocket not a fd!"); - } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "launchd_checkin: BrowseSockets is an empty array!"); - } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "launchd_checkin: BrowseSockets is not an array!"); - } - else - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: No BrowseSockets"); - launch_data_free(ld_msg); launch_data_free(ld_resp); } @@ -1408,340 +1365,6 @@ launchd_checkout(void) } } - -/* - * 'launchd_create_dict()' - Create a dictionary representing the launchd - * config file org.cups.cupsd.plist. - */ - -static CFDictionaryRef /* O - CFDictionary */ -launchd_create_dict(void) -{ - int portnum; /* Port number */ - bool runatload; /* Run at load? */ - CFMutableDictionaryRef cupsd_dict, /* org.cups.cupsd.plist dictionary */ - keepalive, /* KeepAlive dictionary */ - pathstate, /* PathState dictionary */ - sockets, /* Sockets dictionary */ - listener; /* Listener dictionary */ - CFMutableArrayRef array; /* Array */ - CFNumberRef socket_mode; /* Domain socket mode bits */ - CFStringRef socket_path; /* Domain socket path */ - CFTypeRef value; /* CF values */ - cupsd_listener_t *lis; /* Current listening socket */ - struct servent *service; /* Services data base entry */ - char temp[1024]; /* Temporary buffer for value */ - - - if ((cupsd_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)) == NULL) - return (NULL); - - CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_LABEL), - CFSTR("org.cups.cupsd")); - CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_ONDEMAND), - kCFBooleanTrue); - - /* - * Use run-at-load and/or KeepAlive if there are active jobs, polling or - * shared printers to advertise... - */ - - if ((keepalive = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)) != NULL) - { - if ((pathstate = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)) != NULL) - { - CFDictionaryAddValue(pathstate, CFSTR(CUPS_KEEPALIVE), kCFBooleanTrue); - CFDictionaryAddValue(keepalive, CFSTR(LAUNCH_JOBKEY_PATHSTATE), - pathstate); - } - - CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_KEEPALIVE), - keepalive); - } - - runatload = (cupsArrayCount(ActiveJobs) || NumPolled || - (Browsing && BrowseLocalProtocols && - NumBrowsers && cupsArrayCount(Printers))) ? true : false; - - CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_RUNATLOAD), - runatload ? kCFBooleanTrue : kCFBooleanFalse); - CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_SERVICEIPC), - kCFBooleanTrue); - - if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 2, - &kCFTypeArrayCallBacks)) != NULL) - { - CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_PROGRAMARGUMENTS), - array); - CFArrayAppendValue(array, CFSTR("/usr/sbin/cupsd")); - CFArrayAppendValue(array, CFSTR("-l")); - CFRelease(array); - } - - /* - * Add a sockets dictionary... - */ - - if ((sockets = (CFMutableDictionaryRef)CFDictionaryCreateMutable( - kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)) != NULL) - { - CFDictionaryAddValue(cupsd_dict, CFSTR(LAUNCH_JOBKEY_SOCKETS), sockets); - - /* - * Add a Listeners array to the sockets dictionary... - */ - - if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks)) != NULL) - { - CFDictionaryAddValue(sockets, CFSTR("Listeners"), array); - - /* - * For each listener add a dictionary to the listeners array... - */ - - for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); - lis; - lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) - { - if ((listener = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)) != NULL) - { - CFArrayAppendValue(array, listener); - -# ifdef AF_LOCAL - if (lis->address.addr.sa_family == AF_LOCAL) - { - if ((socket_path = CFStringCreateWithCString(kCFAllocatorDefault, - lis->address.un.sun_path, - kCFStringEncodingUTF8))) - { - CFDictionaryAddValue(listener, - CFSTR(LAUNCH_JOBSOCKETKEY_PATHNAME), - socket_path); - CFRelease(socket_path); - } - portnum = 0140777; /* (S_IFSOCK|S_IRWXU|S_IRWXG|S_IRWXO) or * - * 49663d decimal */ - if ((socket_mode = CFNumberCreate(kCFAllocatorDefault, - kCFNumberIntType, &portnum))) - { - CFDictionaryAddValue(listener, CFSTR("SockPathMode"), - socket_mode); - CFRelease(socket_mode); - } - } - else -# endif /* AF_LOCAL */ - { -# ifdef AF_INET6 - if (lis->address.addr.sa_family == AF_INET6) - { - CFDictionaryAddValue(listener, - CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY), - CFSTR("IPv6")); - portnum = lis->address.ipv6.sin6_port; - } - else -# endif /* AF_INET6 */ - { - CFDictionaryAddValue(listener, - CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY), - CFSTR("IPv4")); - portnum = lis->address.ipv4.sin_port; - } - - if ((service = getservbyport(portnum, NULL))) - value = CFStringCreateWithCString(kCFAllocatorDefault, - service->s_name, - kCFStringEncodingUTF8); - else - value = CFNumberCreate(kCFAllocatorDefault, - kCFNumberIntType, &portnum); - - if (value) - { - CFDictionaryAddValue(listener, - CFSTR(LAUNCH_JOBSOCKETKEY_SERVICENAME), - value); - CFRelease(value); - } - - httpAddrString(&lis->address, temp, sizeof(temp)); - if ((value = CFStringCreateWithCString(kCFAllocatorDefault, temp, - kCFStringEncodingUTF8))) - { - CFDictionaryAddValue(listener, - CFSTR(LAUNCH_JOBSOCKETKEY_NODENAME), - value); - CFRelease(value); - } - } - - CFRelease(listener); - } - } - - CFRelease(array); - } - - /* - * Add the BrowseSocket to the sockets dictionary... - */ - - if (Browsing && (BrowseRemoteProtocols & BROWSE_CUPS)) - { - if ((array = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks)) != NULL) - { - CFDictionaryAddValue(sockets, CFSTR("BrowseSockets"), array); - - if ((listener = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)) != NULL) - { - CFArrayAppendValue(array, listener); - - CFDictionaryAddValue(listener, CFSTR(LAUNCH_JOBSOCKETKEY_FAMILY), - CFSTR("IPv4")); - CFDictionaryAddValue(listener, CFSTR(LAUNCH_JOBSOCKETKEY_TYPE), - CFSTR("dgram")); - - if ((service = getservbyport(BrowsePort, NULL))) - value = CFStringCreateWithCString(kCFAllocatorDefault, - service->s_name, - kCFStringEncodingUTF8); - else - value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, - &BrowsePort); - - CFDictionaryAddValue(listener, - CFSTR(LAUNCH_JOBSOCKETKEY_SERVICENAME), value); - CFRelease(value); - - CFRelease(listener); - } - - CFRelease(array); - } - } - - CFRelease(sockets); - } - - return (cupsd_dict); -} - - -/* - * 'launchd_sync_conf()' - Rewrite the launchd config file - * org.cups.cupsd.plist based on cupsd.conf. - */ - -static int /* O - 1 if the file was updated */ -launchd_sync_conf(void) -{ - SInt32 errorCode; /* Error code */ - CFDataRef resourceData; /* XML property list */ - CFDictionaryRef cupsd_dict; /* New org.cups.cupsd.plist dict */ - - - /* - * If needed reconstitute the existing org.cups.cupsd.plist... - */ - - if (!launchd_conf_url && - !(launchd_conf_url = CFURLCreateFromFileSystemRepresentation( - kCFAllocatorDefault, - (const unsigned char *)LaunchdConf, - strlen(LaunchdConf), false))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_sync_conf: " - "Unable to create file URL for \"%s\"\n", LaunchdConf); - return (0); - } - - if (!launchd_conf_dict) - { - if (CFURLCreateDataAndPropertiesFromResource(NULL, launchd_conf_url, - &resourceData, NULL, NULL, &errorCode)) - { - launchd_conf_dict = CFPropertyListCreateFromXMLData(NULL, resourceData, - kCFPropertyListImmutable, NULL); - CFRelease(resourceData); - } - - if (!launchd_conf_dict) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_sync_conf: " - "Unable to create dictionary for \"%s\"\n", LaunchdConf); - } - } - - /* - * Create a new org.cups.cupsd.plist dictionary... - */ - - if ((cupsd_dict = launchd_create_dict()) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_sync_conf: " - "Unable to create file URL for \"%s\"\n", LaunchdConf); - return (0); - } - - /* - * If the dictionaries are different write a new org.cups.cupsd.plist... - */ - - if (!CFEqual(cupsd_dict, launchd_conf_dict)) - { - if ((resourceData = CFPropertyListCreateXMLData(kCFAllocatorDefault, - cupsd_dict))) - { - if (CFURLWriteDataAndPropertiesToResource(launchd_conf_url, resourceData, - NULL, &errorCode)) - { - /* - * The new cupsd dictionary becomes the on-disk launchd dictionary... - */ - - if (launchd_conf_dict) - CFRelease(launchd_conf_dict); - - launchd_conf_dict = cupsd_dict; - } - else - { - cupsdLogMessage(CUPSD_LOG_WARN, - "launchd_sync_conf: " - "CFURLWriteDataAndPropertiesToResource(\"%s\") " - "failed: %d\n", - LaunchdConf, (int)errorCode); - - CFRelease(cupsd_dict); - } - - CFRelease(resourceData); - } - - /* - * Let the caller know we updated the file... - */ - - return (1); - } - - return (0); -} #endif /* HAVE_LAUNCHD */ @@ -2155,5 +1778,5 @@ usage(int status) /* O - Exit status */ /* - * End of "$Id: main.c 6365 2007-03-19 20:56:57Z mike $". + * End of "$Id: main.c 6493 2007-04-30 19:33:31Z mike $". */ diff --git a/scheduler/printers.c b/scheduler/printers.c index 1934383ec..411efa495 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -1,5 +1,5 @@ /* - * "$Id: printers.c 6436 2007-04-02 23:24:02Z mike $" + * "$Id: printers.c 6501 2007-04-30 21:53:15Z mike $" * * Printer routines for the Common UNIX Printing System (CUPS). * @@ -26,6 +26,7 @@ * cupsdAddPrinter() - Add a printer to the system. * cupsdAddPrinterHistory() - Add the current printer state to the history. * cupsdAddPrinterUser() - Add a user to the ACL. + * cupsdCreateCommonData() - Create the common printer data. * cupsdDeleteAllPrinters() - Delete all printers from the system. * cupsdDeletePrinter() - Delete a printer from the system. * cupsdFindPrinter() - Find a printer in the list. @@ -266,7 +267,7 @@ cupsdCreateCommonData(void) *notifier; /* Current notifier */ static const int nups[] = /* number-up-supported values */ { 1, 2, 4, 6, 9, 16 }; - static const ipp_orient_t orients[4] =/* orientation-requested-supported values */ + static const int orients[4] =/* orientation-requested-supported values */ { IPP_PORTRAIT, IPP_LANDSCAPE, @@ -289,7 +290,7 @@ cupsdCreateCommonData(void) "1.0", "1.1" }; - static const ipp_op_t ops[] = /* operations-supported values */ + static const int ops[] = /* operations-supported values */ { IPP_PRINT_JOB, IPP_VALIDATE_JOB, @@ -413,6 +414,10 @@ cupsdCreateCommonData(void) /* copies-supported */ ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", 1, MaxCopies); + /* cups-version */ + ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_TEXT, "cups-version", + NULL, CUPS_SVERSION + 6); + /* generated-natural-language-supported */ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, "generated-natural-language-supported", NULL, DefaultLanguage); @@ -545,11 +550,11 @@ cupsdCreateCommonData(void) /* operations-supported */ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, "operations-supported", - sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, (int *)ops); + sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, ops); /* orientation-requested-supported */ ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, - "orientation-requested-supported", 4, (int *)orients); + "orientation-requested-supported", 4, orients); /* page-ranges-supported */ ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1); @@ -1651,7 +1656,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ ipp_attribute_t *attr; /* Attribute data */ ipp_value_t *val; /* Attribute value */ int num_finishings; /* Number of finishings */ - ipp_finish_t finishings[5]; /* finishings-supported values */ + int finishings[5]; /* finishings-supported values */ cups_option_t *option; /* Current printer option */ static const char * const sides[3] = /* sides-supported values */ { @@ -2288,7 +2293,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ } ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, - "finishings-supported", num_finishings, (int *)finishings); + "finishings-supported", num_finishings, finishings); ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "finishings-default", IPP_FINISHINGS_NONE); } @@ -3708,5 +3713,5 @@ write_irix_state(cupsd_printer_t *p) /* I - Printer to update */ /* - * End of "$Id: printers.c 6436 2007-04-02 23:24:02Z mike $". + * End of "$Id: printers.c 6501 2007-04-30 21:53:15Z mike $". */ |