/*
- * "$Id: cups-lpd.c 4807 2005-10-21 19:17:52Z mike $"
+ * "$Id$"
*
- * Line Printer Daemon interface for the Common UNIX Printing System (CUPS).
+ * Line Printer Daemon interface for CUPS.
*
- * Copyright 1997-2005 by Easy Software Products, all rights reserved.
+ * Copyright 2007-2015 by Apple Inc.
+ * Copyright 1997-2006 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
- * copyright law. Distribution and use rights are outlined in the file
- * "LICENSE.txt" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
- *
- * Contents:
- *
- * main() - Process an incoming LPD request...
- * print_file() - Print a file to a printer or class.
- * recv_print_job() - Receive a print job from the client.
- * remove_jobs() - Cancel one or more jobs.
- * send_state() - Send the queue state.
- * smart_gets() - Get a line of text, removing the trailing CR
- * and/or LF.
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*/
/*
* Include necessary headers...
*/
-#include <cups/cups.h>
-#include <cups/string.h>
-#include <cups/language.h>
-#include <stdlib.h>
-#include <errno.h>
+#include <cups/cups-private.h>
#include <syslog.h>
-#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
-
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif /* HAVE_INTTYPES_H */
+#ifdef __APPLE__
+# include <vproc.h>
+#endif /* __APPLE__ */
+
/*
* LPD "mini-daemon" for CUPS. This program must be used in conjunction
* Prototypes...
*/
-int print_file(const char *name, const char *file,
- const char *title, const char *docname,
- const char *user, int num_options,
- cups_option_t *options);
-int recv_print_job(const char *dest, int num_defaults, cups_option_t *defaults);
-int remove_jobs(const char *dest, const char *agent, const char *list);
-int send_state(const char *dest, const char *list, int longstatus);
-char *smart_gets(char *s, int len, FILE *fp);
+static int create_job(http_t *http, const char *dest, const char *title,
+ const char *docname, const char *user,
+ int num_options, cups_option_t *options);
+static int get_printer(http_t *http, const char *name, char *dest,
+ size_t destsize, cups_option_t **options,
+ int *accepting, int *shared, ipp_pstate_t *state);
+static int print_file(http_t *http, int id, const char *filename,
+ const char *docname, const char *user,
+ const char *format, int last);
+static int recv_print_job(const char *name, int num_defaults,
+ cups_option_t *defaults);
+static int remove_jobs(const char *name, const char *agent,
+ const char *list);
+static int send_state(const char *name, const char *list,
+ int longstatus);
+static char *smart_gets(char *s, int len, FILE *fp);
/*
char hostname[256], /* Name of client */
hostip[256], /* IP address */
*hostfamily; /* Address family */
+ int hostlookups; /* Do hostname lookups? */
+#ifdef __APPLE__
+ vproc_transaction_t vtran = vproc_transaction_begin(NULL);
+#endif /* __APPLE__ */
/*
openlog("cups-lpd", LOG_PID, LOG_LPR);
- /*
- * Get the address of the client...
- */
-
- hostlen = sizeof(hostaddr);
-
- if (getpeername(0, (struct sockaddr *)&hostaddr, &hostlen))
- {
- syslog(LOG_WARNING, "Unable to get client address - %s", strerror(errno));
- strcpy(hostname, "unknown");
- }
- else
- {
- httpAddrLookup(&hostaddr, hostname, sizeof(hostname));
- httpAddrString(&hostaddr, hostip, sizeof(hostip));
-
-#ifdef AF_INET6
- if (hostaddr.addr.sa_family == AF_INET6)
- hostfamily = "IPv6";
- else
-#endif /* AF_INET6 */
- hostfamily = "IPv4";
-
- syslog(LOG_INFO, "Connection from %s (%s %s)", hostname, hostfamily, hostip);
- }
-
/*
* Scan the command-line for options...
*/
num_defaults = 0;
defaults = NULL;
-
- num_defaults = cupsAddOption("job-originating-host-name", hostname,
- num_defaults, &defaults);
+ hostlookups = 1;
for (i = 1; i < argc; i ++)
if (argv[i][0] == '-')
{
switch (argv[i][1])
{
+ case 'h' : /* -h hostname[:port] */
+ if (argv[i][2])
+ cupsSetServer(argv[i] + 2);
+ else
+ {
+ i ++;
+ if (i < argc)
+ cupsSetServer(argv[i]);
+ else
+ syslog(LOG_WARNING, "Expected hostname string after -h option!");
+ }
+ break;
+
case 'o' : /* Option */
if (argv[i][2])
num_defaults = cupsParseOptions(argv[i] + 2, num_defaults,
{
i ++;
if (i < argc)
- num_defaults = cupsParseOptions(argv[i], num_defaults, &defaults);
+ num_defaults = cupsParseOptions(argv[i], num_defaults,
+ &defaults);
else
syslog(LOG_WARNING, "Expected option string after -o option!");
}
break;
+
+ case 'n' : /* Don't do hostname lookups */
+ hostlookups = 0;
+ break;
+
default :
syslog(LOG_WARNING, "Unknown option \"%c\" ignored!", argv[i][1]);
break;
}
}
else
- syslog(LOG_WARNING, "Unknown command-line option \"%s\" ignored!", argv[i]);
+ syslog(LOG_WARNING, "Unknown command-line option \"%s\" ignored!",
+ argv[i]);
+
+ /*
+ * Get the address of the client...
+ */
+
+ hostlen = sizeof(hostaddr);
+
+ if (getpeername(0, (struct sockaddr *)&hostaddr, &hostlen))
+ {
+ syslog(LOG_WARNING, "Unable to get client address - %s", strerror(errno));
+ strlcpy(hostname, "unknown", sizeof(hostname));
+ }
+ else
+ {
+ httpAddrString(&hostaddr, hostip, sizeof(hostip));
+
+ if (hostlookups)
+ httpAddrLookup(&hostaddr, hostname, sizeof(hostname));
+ else
+ strlcpy(hostname, hostip, sizeof(hostname));
+
+#ifdef AF_INET6
+ if (hostaddr.addr.sa_family == AF_INET6)
+ hostfamily = "IPv6";
+ else
+#endif /* AF_INET6 */
+ hostfamily = "IPv4";
+
+ syslog(LOG_INFO, "Connection from %s (%s %s)", hostname, hostfamily,
+ hostip);
+ }
+
+ num_defaults = cupsAddOption("job-originating-host-name", hostname,
+ num_defaults, &defaults);
/*
* RFC1179 specifies that only 1 daemon command can be received for
syslog(LOG_ERR, "Unable to get command line from client!");
putchar(1);
+
+#ifdef __APPLE__
+ vproc_transaction_end(NULL, vtran);
+#endif /* __APPLE__ */
+
return (1);
}
* resource list, and/or user name.
*/
- command = line[0];
- dest = line + 1;
+ if ((command = line[0]) == '\0')
+ dest = line;
+ else
+ dest = line + 1;
- for (list = dest + 1; *list && !isspace(*list & 255); list ++);
+ if (command == 0x02)
+ list = NULL;
+ else
+ {
+ for (list = dest; *list && !isspace(*list & 255); list ++);
- while (isspace(*list & 255))
- *list++ = '\0';
+ while (isspace(*list & 255))
+ *list++ = '\0';
+ }
/*
* Do the command...
syslog(LOG_INFO, "Receive print job for %s", dest);
/* recv_print_job() sends initial status byte */
- status = recv_print_job(dest, num_defaults, defaults);
+ status = (char)recv_print_job(dest, num_defaults, defaults);
break;
case 0x03 : /* Send queue state (short) */
syslog(LOG_INFO, "Send queue state (short) for %s %s", dest, list);
/* no status byte for this command */
- status = send_state(dest, list, 0);
+ status = (char)send_state(dest, list, 0);
break;
case 0x04 : /* Send queue state (long) */
syslog(LOG_INFO, "Send queue state (long) for %s %s", dest, list);
/* no status byte for this command */
- status = send_state(dest, list, 1);
+ status = (char)send_state(dest, list, 1);
break;
case 0x05 : /* Remove jobs */
- /*
- * Grab the agent and skip to the list of users and/or jobs.
- */
+ if (list)
+ {
+ /*
+ * Grab the agent and skip to the list of users and/or jobs.
+ */
- agent = list;
+ agent = list;
- for (; *list && !isspace(*list & 255); list ++);
- while (isspace(*list & 255))
- *list++ = '\0';
+ for (; *list && !isspace(*list & 255); list ++);
+ while (isspace(*list & 255))
+ *list++ = '\0';
- syslog(LOG_INFO, "Remove jobs %s on %s by %s", list, dest, agent);
+ syslog(LOG_INFO, "Remove jobs %s on %s by %s", list, dest, agent);
- status = remove_jobs(dest, agent, list);
+ status = (char)remove_jobs(dest, agent, list);
+ }
+ else
+ status = 1;
putchar(status);
break;
syslog(LOG_INFO, "Closing connection");
closelog();
+#ifdef __APPLE__
+ vproc_transaction_end(NULL, vtran);
+#endif /* __APPLE__ */
+
return (status);
}
/*
- * 'check_printer()' - Check that a printer exists and is accepting jobs.
+ * 'create_job()' - Create a new print job.
*/
-int /* O - Job ID */
-check_printer(const char *name) /* I - Printer or class name */
+static int /* O - Job ID or -1 on error */
+create_job(http_t *http, /* I - HTTP connection */
+ const char *dest, /* I - Destination name */
+ const char *title, /* I - job-name */
+ const char *docname, /* I - Name of job file */
+ const char *user, /* I - requesting-user-name */
+ int num_options, /* I - Number of options for job */
+ cups_option_t *options) /* I - Options for job */
{
- http_t *http; /* Connection to server */
ipp_t *request; /* IPP request */
ipp_t *response; /* IPP response */
- ipp_attribute_t *attr; /* IPP job-id attribute */
+ ipp_attribute_t *attr; /* IPP attribute */
char uri[HTTP_MAX_URI]; /* Printer URI */
- cups_lang_t *language; /* Language to use */
- int accepting; /* printer-is-accepting-jobs value */
-
-
- /*
- * Setup a connection and request data...
- */
+ int id; /* Job ID */
- if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
- cupsEncryption())) == NULL)
- {
- syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
- strerror(errno));
- return (0);
- }
/*
- * Build a standard CUPS URI for the printer and fill the standard IPP
- * attributes...
+ * Setup the Create-Job request...
*/
- if ((request = ippNew()) == NULL)
- {
- syslog(LOG_ERR, "Unable to create request: %s", strerror(errno));
- httpClose(http);
- return (0);
- }
-
- request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
- request->request.op.request_id = 1;
+ request = ippNewRequest(IPP_CREATE_JOB);
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", name);
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/printers/%s", dest);
- language = cupsLangDefault();
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
- "attributes-charset", NULL, cupsLangEncoding(language));
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, user);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
- "attributes-natural-language", NULL,
- language != NULL ? language->language : "C");
+ if (title[0])
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+ NULL, title);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
+ if (docname[0])
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
+ NULL, docname);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requested-attributes",
- NULL, "printer-is-accepting-jobs");
+ cupsEncodeOptions(request, num_options, options);
/*
* Do the request...
*/
- response = cupsDoRequest(http, request, "/");
+ snprintf(uri, sizeof(uri), "/printers/%s", dest);
+
+ response = cupsDoRequest(http, request, uri);
- if (response == NULL)
+ if (!response || cupsLastError() > IPP_OK_CONFLICT)
{
- syslog(LOG_ERR, "Unable to check printer status - %s",
- ippErrorString(cupsLastError()));
- accepting = 0;
+ syslog(LOG_ERR, "Unable to create job - %s", cupsLastErrorString());
+
+ ippDelete(response);
+
+ return (-1);
}
- else if (response->request.status.status_code > IPP_OK_CONFLICT)
+
+ /*
+ * Get the job-id value from the response and return it...
+ */
+
+ if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
{
- syslog(LOG_ERR, "Unable to check printer status - %s",
- ippErrorString(response->request.status.status_code));
- accepting = 0;
+ id = -1;
+
+ syslog(LOG_ERR, "No job-id attribute found in response from server!");
}
- else if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs",
- IPP_TAG_BOOLEAN)) == NULL)
+ else
{
- syslog(LOG_ERR, "No printer-is-accepting-jobs attribute found in response from server!");
- accepting = 0;
+ id = attr->values[0].integer;
+
+ syslog(LOG_INFO, "Print file - job ID = %d", id);
}
- else
- accepting = attr->values[0].boolean;
- if (response != NULL)
- ippDelete(response);
+ ippDelete(response);
- httpClose(http);
- cupsLangFree(language);
-
- return (accepting);
+ return (id);
}
/*
- * 'print_file()' - Print a file to a printer or class.
+ * 'get_printer()' - Get the named printer and its options.
*/
-int /* O - Job ID */
-print_file(const char *name, /* I - Printer or class name */
- const char *file, /* I - File to print */
- const char *title, /* I - Title of job */
- const char *docname, /* I - Name of job file */
- const char *user, /* I - Owner of job */
- int num_options, /* I - Number of options */
- cups_option_t *options) /* I - Options */
+static int /* O - Number of options or -1 on error */
+get_printer(http_t *http, /* I - HTTP connection */
+ const char *name, /* I - Printer name from request */
+ char *dest, /* I - Destination buffer */
+ size_t destsize, /* I - Size of destination buffer */
+ cups_option_t **options, /* O - Printer options */
+ int *accepting, /* O - printer-is-accepting-jobs value */
+ int *shared, /* O - printer-is-shared value */
+ ipp_pstate_t *state) /* O - printer-state value */
{
- http_t *http; /* Connection to server */
+ int num_options; /* Number of options */
+ cups_file_t *fp; /* lpoptions file */
+ char line[1024], /* Line from lpoptions file */
+ *value, /* Pointer to value on line */
+ *optptr; /* Pointer to options on line */
+ int linenum; /* Line number in file */
+ const char *cups_serverroot; /* CUPS_SERVERROOT env var */
ipp_t *request; /* IPP request */
ipp_t *response; /* IPP response */
- ipp_attribute_t *attr; /* IPP job-id attribute */
+ ipp_attribute_t *attr; /* IPP attribute */
char uri[HTTP_MAX_URI]; /* Printer URI */
- cups_lang_t *language; /* Language to use */
- int jobid; /* New job ID */
+ static const char * const requested[] =
+ { /* Requested attributes */
+ "printer-info",
+ "printer-is-accepting-jobs",
+ "printer-is-shared",
+ "printer-name",
+ "printer-state"
+ };
/*
- * Setup a connection and request data...
+ * Initialize everything...
*/
- if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
- cupsEncryption())) == NULL)
+ if (accepting)
+ *accepting = 0;
+ if (shared)
+ *shared = 0;
+ if (state)
+ *state = IPP_PRINTER_STOPPED;
+ if (options)
+ *options = NULL;
+
+ /*
+ * See if the name is a queue name optionally with an instance name.
+ */
+
+ strlcpy(dest, name, destsize);
+ if ((value = strchr(dest, '/')) != NULL)
+ *value = '\0';
+
+ /*
+ * Setup the Get-Printer-Attributes request...
+ */
+
+ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/printers/%s", dest);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes",
+ (int)(sizeof(requested) / sizeof(requested[0])),
+ NULL, requested);
+
+ /*
+ * Do the request...
+ */
+
+ response = cupsDoRequest(http, request, "/");
+
+ if (!response || cupsLastError() > IPP_OK_CONFLICT)
{
- syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
- strerror(errno));
- return (0);
+ /*
+ * If we can't find the printer by name, look up the printer-name
+ * using the printer-info values...
+ */
+
+ ipp_attribute_t *accepting_attr,/* printer-is-accepting-jobs */
+ *info_attr, /* printer-info */
+ *name_attr, /* printer-name */
+ *shared_attr, /* printer-is-shared */
+ *state_attr; /* printer-state */
+
+
+ ippDelete(response);
+
+ /*
+ * Setup the CUPS-Get-Printers request...
+ */
+
+ request = ippNewRequest(CUPS_GET_PRINTERS);
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes",
+ (int)(sizeof(requested) / sizeof(requested[0])),
+ NULL, requested);
+
+ /*
+ * Do the request...
+ */
+
+ response = cupsDoRequest(http, request, "/");
+
+ if (!response || cupsLastError() > IPP_OK_CONFLICT)
+ {
+ syslog(LOG_ERR, "Unable to get list of printers - %s",
+ cupsLastErrorString());
+
+ ippDelete(response);
+
+ return (-1);
+ }
+
+ /*
+ * Scan the response for printers...
+ */
+
+ *dest = '\0';
+ attr = response->attrs;
+
+ while (attr)
+ {
+ /*
+ * Skip to the next printer...
+ */
+
+ while (attr && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
+
+ if (!attr)
+ break;
+
+ /*
+ * Get all of the attributes for the current printer...
+ */
+
+ accepting_attr = NULL;
+ info_attr = NULL;
+ name_attr = NULL;
+ shared_attr = NULL;
+ state_attr = NULL;
+
+ while (attr && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (!strcmp(attr->name, "printer-is-accepting-jobs") &&
+ attr->value_tag == IPP_TAG_BOOLEAN)
+ accepting_attr = attr;
+ else if (!strcmp(attr->name, "printer-info") &&
+ attr->value_tag == IPP_TAG_TEXT)
+ info_attr = attr;
+ else if (!strcmp(attr->name, "printer-name") &&
+ attr->value_tag == IPP_TAG_NAME)
+ name_attr = attr;
+ else if (!strcmp(attr->name, "printer-is-shared") &&
+ attr->value_tag == IPP_TAG_BOOLEAN)
+ shared_attr = attr;
+ else if (!strcmp(attr->name, "printer-state") &&
+ attr->value_tag == IPP_TAG_ENUM)
+ state_attr = attr;
+
+ attr = attr->next;
+ }
+
+ if (info_attr && name_attr &&
+ !_cups_strcasecmp(name, info_attr->values[0].string.text))
+ {
+ /*
+ * Found a match, use this one!
+ */
+
+ strlcpy(dest, name_attr->values[0].string.text, destsize);
+
+ if (accepting && accepting_attr)
+ *accepting = accepting_attr->values[0].boolean;
+
+ if (shared && shared_attr)
+ *shared = shared_attr->values[0].boolean;
+
+ if (state && state_attr)
+ *state = (ipp_pstate_t)state_attr->values[0].integer;
+
+ break;
+ }
+ }
+
+ ippDelete(response);
+
+ if (!*dest)
+ {
+ syslog(LOG_ERR, "Unable to find \"%s\" in list of printers!", name);
+
+ return (-1);
+ }
+
+ name = dest;
+ }
+ else
+ {
+ /*
+ * Get values from the response...
+ */
+
+ if (accepting)
+ {
+ if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs",
+ IPP_TAG_BOOLEAN)) == NULL)
+ syslog(LOG_ERR, "No printer-is-accepting-jobs attribute found in "
+ "response from server!");
+ else
+ *accepting = attr->values[0].boolean;
+ }
+
+ if (shared)
+ {
+ if ((attr = ippFindAttribute(response, "printer-is-shared",
+ IPP_TAG_BOOLEAN)) == NULL)
+ {
+ syslog(LOG_ERR, "No printer-is-shared attribute found in "
+ "response from server!");
+ *shared = 1;
+ }
+ else
+ *shared = attr->values[0].boolean;
+ }
+
+ if (state)
+ {
+ if ((attr = ippFindAttribute(response, "printer-state",
+ IPP_TAG_ENUM)) == NULL)
+ syslog(LOG_ERR, "No printer-state attribute found in "
+ "response from server!");
+ else
+ *state = (ipp_pstate_t)attr->values[0].integer;
+ }
+
+ ippDelete(response);
}
/*
- * Build a standard CUPS URI for the printer and fill the standard IPP
- * attributes...
+ * Next look for the printer in the lpoptions file...
*/
- if ((request = ippNew()) == NULL)
+ num_options = 0;
+
+ if (options && shared && accepting)
{
- syslog(LOG_ERR, "Unable to create request: %s", strerror(errno));
- httpClose(http);
- return (0);
+ if ((cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL)
+ cups_serverroot = CUPS_SERVERROOT;
+
+ snprintf(line, sizeof(line), "%s/lpoptions", cups_serverroot);
+ if ((fp = cupsFileOpen(line, "r")) != NULL)
+ {
+ linenum = 0;
+ while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
+ {
+ /*
+ * Make sure we have "Dest name options" or "Default name options"...
+ */
+
+ if ((_cups_strcasecmp(line, "Dest") && _cups_strcasecmp(line, "Default")) || !value)
+ continue;
+
+ /*
+ * Separate destination name from options...
+ */
+
+ for (optptr = value; *optptr && !isspace(*optptr & 255); optptr ++);
+
+ while (*optptr == ' ')
+ *optptr++ = '\0';
+
+ /*
+ * If this is our destination, parse the options and break out of
+ * the loop - we're done!
+ */
+
+ if (!_cups_strcasecmp(value, name))
+ {
+ num_options = cupsParseOptions(optptr, num_options, options);
+ break;
+ }
+ }
+
+ cupsFileClose(fp);
+ }
}
+ else if (options)
+ *options = NULL;
+
+ /*
+ * Return the number of options for this destination...
+ */
+
+ return (num_options);
+}
- request->request.op.operation_id = IPP_PRINT_JOB;
- request->request.op.request_id = 1;
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", name);
+/*
+ * 'print_file()' - Add a file to the current job.
+ */
- language = cupsLangDefault();
+static int /* O - 0 on success, -1 on failure */
+print_file(http_t *http, /* I - HTTP connection */
+ int id, /* I - Job ID */
+ const char *filename, /* I - File to print */
+ const char *docname, /* I - document-name */
+ const char *user, /* I - requesting-user-name */
+ const char *format, /* I - document-format */
+ int last) /* I - 1 = last file in job */
+{
+ ipp_t *request; /* IPP request */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
- "attributes-charset", NULL, cupsLangEncoding(language));
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
- "attributes-natural-language", NULL,
- language != NULL ? language->language : "C");
+ /*
+ * Setup the Send-Document request...
+ */
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
+ request = ippNewRequest(IPP_SEND_DOCUMENT);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
- NULL, user);
+ snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", id);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, user);
- if (title)
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title);
if (docname)
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name", NULL, docname);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "document-name", NULL, docname);
- /*
- * Then add all options on the command-line...
- */
+ if (format)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+ "document-format", NULL, format);
- cupsEncodeOptions(request, num_options, options);
+ ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last);
/*
* Do the request...
*/
- snprintf(uri, sizeof(uri), "/printers/%s", name);
+ snprintf(uri, sizeof(uri), "/jobs/%d", id);
- response = cupsDoFileRequest(http, request, uri, file);
+ ippDelete(cupsDoFileRequest(http, request, uri, filename));
- if (response == NULL)
- {
- syslog(LOG_ERR, "Unable to print file - %s",
- ippErrorString(cupsLastError()));
- jobid = 0;
- }
- else if (response->request.status.status_code > IPP_OK_CONFLICT)
- {
- syslog(LOG_ERR, "Unable to print file - %s",
- ippErrorString(response->request.status.status_code));
- jobid = 0;
- }
- else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
- {
- syslog(LOG_ERR, "No job-id attribute found in response from server!");
- jobid = 0;
- }
- else
+ if (cupsLastError() > IPP_OK_CONFLICT)
{
- jobid = attr->values[0].integer;
+ syslog(LOG_ERR, "Unable to send document - %s", cupsLastErrorString());
- syslog(LOG_INFO, "Print file - job ID = %d", jobid);
+ return (-1);
}
- if (response != NULL)
- ippDelete(response);
-
- httpClose(http);
- cupsLangFree(language);
-
- return (jobid);
+ return (0);
}
* 'recv_print_job()' - Receive a print job from the client.
*/
-int /* O - Command status */
-recv_print_job(const char *dest, /* I - Destination */
- int num_defaults,
- /* I - Number of default options */
- cups_option_t *defaults) /* I - Default options */
+static int /* O - Command status */
+recv_print_job(
+ const char *queue, /* I - Printer name */
+ int num_defaults, /* I - Number of default options */
+ cups_option_t *defaults) /* I - Default options */
{
+ http_t *http; /* HTTP connection */
int i; /* Looping var */
int status; /* Command status */
int fd; /* Temporary file */
FILE *fp; /* File pointer */
char filename[1024]; /* Temporary filename */
- int bytes; /* Bytes received */
+ ssize_t bytes; /* Bytes received */
+ size_t total; /* Total bytes */
char line[256], /* Line from file/stdin */
command, /* Command from line */
*count, /* Number of bytes */
*name; /* Name of file */
- const char *cupsd_job_sheets; /* Job sheets */
+ const char *job_sheets; /* Job sheets */
int num_data; /* Number of data files */
char control[1024], /* Control filename */
- data[32][256], /* Data files */
- temp[32][1024]; /* Temporary files */
+ data[100][256], /* Data files */
+ temp[100][1024]; /* Temporary files */
char user[1024], /* User name */
title[1024], /* Job title */
docname[1024], /* Document name */
- queue[256], /* Printer/class queue */
- *instance; /* Printer/class instance */
- int num_dests; /* Number of destinations */
- cups_dest_t *dests, /* Destinations */
- *destptr; /* Current destination */
- int num_options; /* Number of options */
+ dest[256]; /* Printer/class queue */
+ int accepting, /* printer-is-accepting */
+ shared, /* printer-is-shared */
+ num_options; /* Number of options */
cups_option_t *options; /* Options */
- int banner; /* Print banner? */
-
-
- status = 0;
- num_data = 0;
- fd = -1;
-
- control[0] = '\0';
+ int id; /* Job ID */
+ int docnumber, /* Current document number */
+ doccount; /* Count of documents */
- strlcpy(queue, dest, sizeof(queue));
- if ((instance = strrchr(queue, '/')) != NULL)
- *instance++ = '\0';
+ /*
+ * Connect to the server...
+ */
- num_dests = cupsGetDests(&dests);
- if ((destptr = cupsGetDest(queue, instance, num_dests, dests)) == NULL)
+ http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+ if (!http)
{
- /*
- * If the queue name is blank or "lp" then use the default queue.
- */
-
- if (!queue[0] || !strcmp(queue, "lp"))
- if ((destptr = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL)
- strlcpy(queue, destptr->name, sizeof(queue));
+ syslog(LOG_ERR, "Unable to connect to server: %s", strerror(errno));
- if (destptr == NULL)
- {
- if (instance)
- syslog(LOG_ERR, "Unknown destination %s/%s!", queue, instance);
- else
- syslog(LOG_ERR, "Unknown destination %s!", queue);
+ putchar(1);
- cupsFreeDests(num_dests, dests);
+ return (1);
+ }
- putchar(1);
+ /*
+ * See if the printer is available...
+ */
- return (1);
- }
- }
+ num_options = get_printer(http, queue, dest, sizeof(dest), &options,
+ &accepting, &shared, NULL);
- if (!check_printer(queue))
+ if (num_options < 0 || !accepting || !shared)
{
- cupsFreeDests(num_dests, dests);
+ if (dest[0])
+ syslog(LOG_INFO, "Rejecting job because \"%s\" is not %s", dest,
+ !accepting ? "accepting jobs" : "shared");
+ else
+ syslog(LOG_ERR, "Unable to get printer information for \"%s\"", queue);
+
+ httpClose(http);
putchar(1);
return (1);
}
- putchar(0);
+ putchar(0); /* OK so far... */
+
+ /*
+ * Read the request...
+ */
+
+ status = 0;
+ num_data = 0;
+ fd = -1;
+
+ control[0] = '\0';
while (smart_gets(line, sizeof(line), stdin) != NULL)
{
break;
}
- strcpy(filename, control);
+ strlcpy(filename, control, sizeof(filename));
}
break;
break;
}
- if (num_data >= (sizeof(data) / sizeof(data[0])))
+ if (num_data >= (int)(sizeof(data) / sizeof(data[0])))
{
/*
* Too many data files...
break;
}
- strcpy(filename, temp[num_data]);
+ strlcpy(filename, temp[num_data], sizeof(filename));
num_data ++;
break;
* Copy the data or control file from the client...
*/
- for (i = atoi(count); i > 0; i -= bytes)
+ for (total = (size_t)strtoll(count, NULL, 10); total > 0; total -= (size_t)bytes)
{
- if (i > sizeof(line))
- bytes = sizeof(line);
+ if (total > sizeof(line))
+ bytes = (ssize_t)sizeof(line);
else
- bytes = i;
+ bytes = (ssize_t)total;
- if ((bytes = fread(line, 1, bytes, stdin)) > 0)
- bytes = write(fd, line, bytes);
+ if ((bytes = (ssize_t)fread(line, 1, (size_t)bytes, stdin)) > 0)
+ bytes = write(fd, line, (size_t)bytes);
if (bytes < 1)
{
else
{
/*
- * Grab the job information first...
+ * Copy the default options...
+ */
+
+ for (i = 0; i < num_defaults; i ++)
+ num_options = cupsAddOption(defaults[i].name,
+ defaults[i].value,
+ num_options, &options);
+
+ /*
+ * Grab the job information...
*/
title[0] = '\0';
user[0] = '\0';
docname[0] = '\0';
- banner = 0;
+ doccount = 0;
while (smart_gets(line, sizeof(line), fp) != NULL)
{
strlcpy(title, line + 1, sizeof(title));
break;
- case 'N' : /* Document name */
- strlcpy(docname, line + 1, sizeof(docname));
- break;
+ case 'N' : /* Document name */
+ strlcpy(docname, line + 1, sizeof(docname));
+ break;
case 'P' : /* User identification */
strlcpy(user, line + 1, sizeof(user));
break;
case 'L' : /* Print banner page */
- banner = 1;
- break;
- }
-
- if (status)
- break;
- }
-
- /*
- * Then print the jobs...
- */
-
- rewind(fp);
+ /*
+ * If a banner was requested and it's not overridden by a
+ * command line option and the destination's default is none
+ * then add the standard banner...
+ */
- while (smart_gets(line, sizeof(line), fp) != NULL)
- {
- /*
- * Process control lines...
- */
+ if (cupsGetOption("job-sheets", num_defaults, defaults) == NULL &&
+ ((job_sheets = cupsGetOption("job-sheets", num_options,
+ options)) == NULL ||
+ !strcmp(job_sheets, "none,none")))
+ {
+ num_options = cupsAddOption("job-sheets", "standard",
+ num_options, &options);
+ }
+ break;
- switch (line[0])
- {
case 'c' : /* Plot CIF file */
case 'd' : /* Print DVI file */
case 'f' : /* Print formatted file */
case 'r' : /* File to print with FORTRAN carriage control */
case 't' : /* Print troff output file */
case 'v' : /* Print raster file */
- /*
- * Check that we have a username...
- */
+ doccount ++;
- if (!user[0])
- {
- syslog(LOG_WARNING, "No username specified by client! "
- "Using \"anonymous\"...");
- strcpy(user, "anonymous");
- }
+ if (line[0] == 'l' &&
+ !cupsGetOption("document-format", num_options, options))
+ num_options = cupsAddOption("raw", "", num_options, &options);
- /*
- * Copy the default options...
- */
+ if (line[0] == 'p')
+ num_options = cupsAddOption("prettyprint", "", num_options,
+ &options);
+ break;
+ }
+
+ if (status)
+ break;
+ }
- num_options = 0;
- options = NULL;
+ /*
+ * Check that we have a username...
+ */
- for (i = 0; i < destptr->num_options; i ++)
- num_options = cupsAddOption(destptr->options[i].name,
- destptr->options[i].value,
- num_options, &options);
- for (i = 0; i < num_defaults; i ++)
- num_options = cupsAddOption(defaults[i].name,
- defaults[i].value,
- num_options, &options);
+ if (!user[0])
+ {
+ syslog(LOG_WARNING, "No username specified by client! "
+ "Using \"anonymous\"...");
+ strlcpy(user, "anonymous", sizeof(user));
+ }
- /*
- * If a banner was requested and it's not overridden by a
- * command line option and the destination's default is none
- * then add the standard banner...
- */
+ /*
+ * Create the job...
+ */
- if (banner &&
- cupsGetOption("job-sheets", num_defaults, defaults) == NULL &&
- ((cupsd_job_sheets = cupsGetOption("job-sheets",
- destptr->num_options,
- destptr->options)) == NULL ||
- !strcmp(cupsd_job_sheets, "none,none")))
- {
- num_options = cupsAddOption("job-sheets", "standard",
- num_options, &options);
- }
+ if ((id = create_job(http, dest, title, docname, user, num_options,
+ options)) < 0)
+ status = 1;
+ else
+ {
+ /*
+ * Then print the job files...
+ */
- /*
- * Add additional options as needed...
- */
+ rewind(fp);
- if (line[0] == 'l')
- num_options = cupsAddOption("raw", "", num_options, &options);
+ docname[0] = '\0';
+ docnumber = 0;
- if (line[0] == 'p')
- num_options = cupsAddOption("prettyprint", "", num_options,
- &options);
+ while (smart_gets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * Process control lines...
+ */
- /*
- * Figure out which file we are printing...
- */
+ switch (line[0])
+ {
+ case 'N' : /* Document name */
+ strlcpy(docname, line + 1, sizeof(docname));
+ break;
- for (i = 0; i < num_data; i ++)
- if (strcmp(data[i], line + 1) == 0)
+ case 'c' : /* Plot CIF file */
+ case 'd' : /* Print DVI file */
+ case 'f' : /* Print formatted file */
+ case 'g' : /* Plot file */
+ case 'l' : /* Print file leaving control characters (raw) */
+ case 'n' : /* Print ditroff output file */
+ case 'o' : /* Print PostScript output file */
+ case 'p' : /* Print file with 'pr' format (prettyprint) */
+ case 'r' : /* File to print with FORTRAN carriage control */
+ case 't' : /* Print troff output file */
+ case 'v' : /* Print raster file */
+ /*
+ * Figure out which file we are printing...
+ */
+
+ for (i = 0; i < num_data; i ++)
+ if (!strcmp(data[i], line + 1))
+ break;
+
+ if (i >= num_data)
+ {
+ status = 1;
break;
+ }
- if (i >= num_data)
- {
- status = 1;
- break;
- }
+ /*
+ * Send the print file...
+ */
- /*
- * Send the print request...
- */
+ docnumber ++;
- if (print_file(queue, temp[i], title, docname, user, num_options,
- options) == 0)
- status = 1;
- else
- status = 0;
+ if (print_file(http, id, temp[i], docname, user,
+ cupsGetOption("document-format", num_options,
+ options),
+ docnumber == doccount))
+ status = 1;
+ else
+ status = 0;
- cupsFreeOptions(num_options, options);
- break;
- }
+ break;
+ }
- if (status)
- break;
+ if (status)
+ break;
+ }
}
fclose(fp);
}
}
+ cupsFreeOptions(num_options, options);
+
+ httpClose(http);
+
/*
* Clean up all temporary files and return...
*/
for (i = 0; i < num_data; i ++)
unlink(temp[i]);
- cupsFreeDests(num_dests, dests);
-
return (status);
}
* 'remove_jobs()' - Cancel one or more jobs.
*/
-int /* O - Command status */
+static int /* O - Command status */
remove_jobs(const char *dest, /* I - Destination */
const char *agent, /* I - User agent */
const char *list) /* I - List of jobs or users */
{
int id; /* Job ID */
http_t *http; /* HTTP server connection */
- ipp_t *request, /* IPP Request */
- *response; /* IPP Response */
- cups_lang_t *language; /* Default language */
+ ipp_t *request; /* IPP Request */
char uri[HTTP_MAX_URI]; /* Job URI */
return (1);
}
- language = cupsLangDefault();
-
/*
* Loop for each job...
*/
* requesting-user-name
*/
- request = ippNew();
-
- request->request.op.operation_id = IPP_CANCEL_JOB;
- request->request.op.request_id = 1;
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
- "attributes-charset", NULL, cupsLangEncoding(language));
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
- "attributes-natural-language", NULL, language->language);
+ request = ippNewRequest(IPP_CANCEL_JOB);
sprintf(uri, "ipp://localhost/jobs/%d", id);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
* Do the request and get back a response...
*/
- if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
- {
- if (response->request.status.status_code > IPP_OK_CONFLICT)
- {
- syslog(LOG_WARNING, "Cancel of job ID %d failed: %s\n", id,
- ippErrorString(response->request.status.status_code));
- ippDelete(response);
- cupsLangFree(language);
- httpClose(http);
- return (1);
- }
- else
- syslog(LOG_INFO, "Job ID %d cancelled", id);
+ ippDelete(cupsDoRequest(http, request, "/jobs"));
- ippDelete(response);
- }
- else
+ if (cupsLastError() > IPP_OK_CONFLICT)
{
syslog(LOG_WARNING, "Cancel of job ID %d failed: %s\n", id,
- ippErrorString(cupsLastError()));
- cupsLangFree(language);
+ cupsLastErrorString());
httpClose(http);
return (1);
}
+ else
+ syslog(LOG_INFO, "Job ID %d canceled", id);
}
- cupsLangFree(language);
httpClose(http);
return (0);
* 'send_state()' - Send the queue state.
*/
-int /* O - Command status */
-send_state(const char *dest, /* I - Destination */
+static int /* O - Command status */
+send_state(const char *queue, /* I - Destination */
const char *list, /* I - Job or user */
int longstatus) /* I - List of jobs or users */
{
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
ipp_attribute_t *attr; /* Current attribute */
- cups_lang_t *language; /* Default language */
ipp_pstate_t state; /* Printer state */
const char *jobdest, /* Pointer into job-printer-uri */
*jobuser, /* Pointer to job-originating-user-name */
char rankstr[255]; /* Rank string */
char namestr[1024]; /* Job name string */
char uri[HTTP_MAX_URI]; /* Printer URI */
- char queue[256], /* Printer/class queue */
- *instance; /* Printer/class instance */
+ char dest[256]; /* Printer/class queue */
static const char * const ranks[10] = /* Ranking strings */
{
"th",
};
- /*
- * Remove instance from destination, if any...
- */
-
- strlcpy(queue, dest, sizeof(queue));
-
- if ((instance = strrchr(queue, '/')) != NULL)
- *instance++ = '\0';
-
/*
* Try connecting to the local server...
*/
}
/*
- * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * printer-uri
+ * Get the actual destination name and printer state...
*/
- request = ippNew();
-
- request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
- request->request.op.request_id = 1;
-
- language = cupsLangDefault();
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
- "attributes-charset", NULL, cupsLangEncoding(language));
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
- "attributes-natural-language", NULL, language->language);
-
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", queue);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
- "printer-uri", NULL, uri);
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes", NULL, "printer-state");
+ if (get_printer(http, queue, dest, sizeof(dest), NULL, NULL, NULL, &state))
+ {
+ syslog(LOG_ERR, "Unable to get printer %s: %s", queue,
+ cupsLastErrorString());
+ printf("Unable to get printer %s: %s", queue, cupsLastErrorString());
+ return (1);
+ }
/*
- * Do the request and get back a response...
+ * Show the queue state...
*/
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
- {
- if (response->request.status.status_code > IPP_OK_CONFLICT)
- {
- syslog(LOG_WARNING, "Unable to get printer list: %s\n",
- ippErrorString(response->request.status.status_code));
- printf("Unable to get printer list: %s\n",
- ippErrorString(response->request.status.status_code));
- ippDelete(response);
- return (1);
- }
-
- if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
- state = (ipp_pstate_t)attr->values[0].integer;
- else
- state = IPP_PRINTER_STOPPED;
-
- switch (state)
- {
- case IPP_PRINTER_IDLE :
- printf("%s is ready\n", dest);
- break;
- case IPP_PRINTER_PROCESSING :
- printf("%s is ready and printing\n", dest);
- break;
- case IPP_PRINTER_STOPPED :
- printf("%s is not ready\n", dest);
- break;
- }
-
- ippDelete(response);
- }
- else
+ switch (state)
{
- syslog(LOG_WARNING, "Unable to get printer list: %s\n",
- ippErrorString(cupsLastError()));
- printf("Unable to get printer list: %s\n",
- ippErrorString(cupsLastError()));
- return (1);
+ case IPP_PRINTER_IDLE :
+ printf("%s is ready\n", dest);
+ break;
+ case IPP_PRINTER_PROCESSING :
+ printf("%s is ready and printing\n", dest);
+ break;
+ case IPP_PRINTER_STOPPED :
+ printf("%s is not ready\n", dest);
+ break;
}
/*
id = atoi(list);
- request = ippNew();
-
- request->request.op.operation_id = id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS;
- request->request.op.request_id = 1;
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
- "attributes-charset", NULL, cupsLangEncoding(language));
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
- "attributes-natural-language", NULL, language->language);
+ request = ippNewRequest(id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS);
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", queue);
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/printers/%s", dest);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, uri);
}
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes", sizeof(requested) / sizeof(requested[0]),
+ "requested-attributes",
+ sizeof(requested) / sizeof(requested[0]),
NULL, requested);
/*
*/
jobcount = 0;
+ response = cupsDoRequest(http, request, "/");
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ if (cupsLastError() > IPP_OK_CONFLICT)
{
- if (response->request.status.status_code > IPP_OK_CONFLICT)
- {
- printf("get-jobs failed: %s\n",
- ippErrorString(response->request.status.status_code));
- ippDelete(response);
- return (1);
- }
+ printf("get-jobs failed: %s\n", cupsLastErrorString());
+ ippDelete(response);
+ return (1);
+ }
- rank = 1;
+ /*
+ * Loop through the job list and display them...
+ */
+ for (attr = response->attrs, rank = 1; attr; attr = attr->next)
+ {
/*
- * Loop through the job list and display them...
+ * Skip leading attributes until we hit a job...
*/
- for (attr = response->attrs; attr != NULL; attr = attr->next)
- {
- /*
- * Skip leading attributes until we hit a job...
- */
-
- while (attr != NULL &&
- (attr->group_tag != IPP_TAG_JOB || attr->name == NULL))
- attr = attr->next;
-
- if (attr == NULL)
- break;
+ while (attr && (attr->group_tag != IPP_TAG_JOB || !attr->name))
+ attr = attr->next;
- /*
- * Pull the needed attributes from this job...
- */
+ if (!attr)
+ break;
- jobid = 0;
- jobsize = 0;
- jobstate = IPP_JOB_PENDING;
- jobname = "untitled";
- jobuser = NULL;
- jobdest = NULL;
- jobcopies = 1;
+ /*
+ * Pull the needed attributes from this job...
+ */
- while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
- {
- if (strcmp(attr->name, "job-id") == 0 &&
- attr->value_tag == IPP_TAG_INTEGER)
- jobid = attr->values[0].integer;
+ jobid = 0;
+ jobsize = 0;
+ jobstate = IPP_JOB_PENDING;
+ jobname = "untitled";
+ jobuser = NULL;
+ jobdest = NULL;
+ jobcopies = 1;
- if (strcmp(attr->name, "job-k-octets") == 0 &&
- attr->value_tag == IPP_TAG_INTEGER)
- jobsize = attr->values[0].integer;
+ while (attr && attr->group_tag == IPP_TAG_JOB)
+ {
+ if (!strcmp(attr->name, "job-id") &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobid = attr->values[0].integer;
- if (strcmp(attr->name, "job-state") == 0 &&
- attr->value_tag == IPP_TAG_ENUM)
- jobstate = (ipp_jstate_t)attr->values[0].integer;
+ if (!strcmp(attr->name, "job-k-octets") &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobsize = attr->values[0].integer;
- if (strcmp(attr->name, "job-printer-uri") == 0 &&
- attr->value_tag == IPP_TAG_URI)
- if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL)
- jobdest ++;
+ if (!strcmp(attr->name, "job-state") &&
+ attr->value_tag == IPP_TAG_ENUM)
+ jobstate = (ipp_jstate_t)attr->values[0].integer;
- if (strcmp(attr->name, "job-originating-user-name") == 0 &&
- attr->value_tag == IPP_TAG_NAME)
- jobuser = attr->values[0].string.text;
+ if (!strcmp(attr->name, "job-printer-uri") &&
+ attr->value_tag == IPP_TAG_URI)
+ if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL)
+ jobdest ++;
- if (strcmp(attr->name, "job-name") == 0 &&
- attr->value_tag == IPP_TAG_NAME)
- jobname = attr->values[0].string.text;
+ if (!strcmp(attr->name, "job-originating-user-name") &&
+ attr->value_tag == IPP_TAG_NAME)
+ jobuser = attr->values[0].string.text;
- if (strcmp(attr->name, "copies") == 0 &&
- attr->value_tag == IPP_TAG_INTEGER)
- jobcopies = attr->values[0].integer;
+ if (!strcmp(attr->name, "job-name") &&
+ attr->value_tag == IPP_TAG_NAME)
+ jobname = attr->values[0].string.text;
- attr = attr->next;
- }
+ if (!strcmp(attr->name, "copies") &&
+ attr->value_tag == IPP_TAG_INTEGER)
+ jobcopies = attr->values[0].integer;
- /*
- * See if we have everything needed...
- */
+ attr = attr->next;
+ }
- if (jobdest == NULL || jobid == 0)
- {
- if (attr == NULL)
- break;
- else
- continue;
- }
+ /*
+ * See if we have everything needed...
+ */
- if (!longstatus && jobcount == 0)
- puts("Rank Owner Job File(s) Total Size");
+ if (!jobdest || !jobid)
+ {
+ if (!attr)
+ break;
+ else
+ continue;
+ }
- jobcount ++;
+ if (!longstatus && jobcount == 0)
+ puts("Rank Owner Job File(s) Total Size");
- /*
- * Display the job...
- */
+ jobcount ++;
- if (jobstate == IPP_JOB_PROCESSING)
- strcpy(rankstr, "active");
- else
- {
- snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);
- rank ++;
- }
+ /*
+ * Display the job...
+ */
- if (longstatus)
- {
- puts("");
+ if (jobstate == IPP_JOB_PROCESSING)
+ strlcpy(rankstr, "active", sizeof(rankstr));
+ else
+ {
+ snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);
+ rank ++;
+ }
- if (jobcopies > 1)
- snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies,
- jobname);
- else
- strlcpy(namestr, jobname, sizeof(namestr));
+ if (longstatus)
+ {
+ puts("");
- printf("%s: %-33.33s [job %d localhost]\n", jobuser, rankstr, jobid);
- printf(" %-39.39s %.0f bytes\n", namestr, 1024.0 * jobsize);
- }
+ if (jobcopies > 1)
+ snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies,
+ jobname);
else
- printf("%-7s %-7.7s %-7d %-31.31s %.0f bytes\n", rankstr, jobuser,
- jobid, jobname, 1024.0 * jobsize);
+ strlcpy(namestr, jobname, sizeof(namestr));
- if (attr == NULL)
- break;
+ printf("%s: %-33.33s [job %d localhost]\n", jobuser, rankstr, jobid);
+ printf(" %-39.39s %.0f bytes\n", namestr, 1024.0 * jobsize);
}
+ else
+ printf("%-7s %-7.7s %-7d %-31.31s %.0f bytes\n", rankstr, jobuser,
+ jobid, jobname, 1024.0 * jobsize);
- ippDelete(response);
- }
- else
- {
- printf("get-jobs failed: %s\n", ippErrorString(cupsLastError()));
- return (1);
+ if (!attr)
+ break;
}
+ ippDelete(response);
+
if (jobcount == 0)
puts("no entries");
- cupsLangFree(language);
httpClose(http);
return (0);
* 'smart_gets()' - Get a line of text, removing the trailing CR and/or LF.
*/
-char * /* O - Line read or NULL */
+static char * /* O - Line read or NULL */
smart_gets(char *s, /* I - Pointer to line buffer */
int len, /* I - Size of line buffer */
FILE *fp) /* I - File to read from */
break;
}
else if (ptr < end)
- *ptr++ = ch;
+ *ptr++ = (char)ch;
}
*ptr = '\0';
/*
- * End of "$Id: cups-lpd.c 4807 2005-10-21 19:17:52Z mike $".
+ * End of "$Id$".
*/