1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * IPP backend for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2021 by OpenPrinting
5*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2021 by Apple Inc.
6*5e7646d2SAndroid Build Coastguard Worker * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
7*5e7646d2SAndroid Build Coastguard Worker *
8*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
9*5e7646d2SAndroid Build Coastguard Worker * information.
10*5e7646d2SAndroid Build Coastguard Worker */
11*5e7646d2SAndroid Build Coastguard Worker
12*5e7646d2SAndroid Build Coastguard Worker /*
13*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers.
14*5e7646d2SAndroid Build Coastguard Worker */
15*5e7646d2SAndroid Build Coastguard Worker
16*5e7646d2SAndroid Build Coastguard Worker #include "backend-private.h"
17*5e7646d2SAndroid Build Coastguard Worker #include <cups/ppd-private.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <cups/array-private.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <sys/types.h>
20*5e7646d2SAndroid Build Coastguard Worker #include <sys/stat.h>
21*5e7646d2SAndroid Build Coastguard Worker #include <sys/wait.h>
22*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
23*5e7646d2SAndroid Build Coastguard Worker # include <xpc/xpc.h>
24*5e7646d2SAndroid Build Coastguard Worker # define kPMPrintUIToolAgent "com.apple.printuitool.agent"
25*5e7646d2SAndroid Build Coastguard Worker # define kPMStartJob 100
26*5e7646d2SAndroid Build Coastguard Worker # define kPMWaitForJob 101
27*5e7646d2SAndroid Build Coastguard Worker extern void xpc_connection_set_target_uid(xpc_connection_t connection,
28*5e7646d2SAndroid Build Coastguard Worker uid_t uid);
29*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
30*5e7646d2SAndroid Build Coastguard Worker
31*5e7646d2SAndroid Build Coastguard Worker
32*5e7646d2SAndroid Build Coastguard Worker /*
33*5e7646d2SAndroid Build Coastguard Worker * Bits for job-state-reasons we care about...
34*5e7646d2SAndroid Build Coastguard Worker */
35*5e7646d2SAndroid Build Coastguard Worker
36*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED 0x01
37*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_ACCOUNT_CLOSED 0x02
38*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_ACCOUNT_INFO_NEEDED 0x04
39*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_ACCOUNT_LIMIT_REACHED 0x08
40*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_JOB_PASSWORD_WAIT 0x10
41*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_JOB_RELEASE_WAIT 0x20
42*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_DOCUMENT_FORMAT_ERROR 0x40
43*5e7646d2SAndroid Build Coastguard Worker #define _CUPS_JSR_DOCUMENT_UNPRINTABLE 0x80
44*5e7646d2SAndroid Build Coastguard Worker
45*5e7646d2SAndroid Build Coastguard Worker
46*5e7646d2SAndroid Build Coastguard Worker /*
47*5e7646d2SAndroid Build Coastguard Worker * Types...
48*5e7646d2SAndroid Build Coastguard Worker */
49*5e7646d2SAndroid Build Coastguard Worker
50*5e7646d2SAndroid Build Coastguard Worker typedef struct _cups_monitor_s /**** Monitoring data ****/
51*5e7646d2SAndroid Build Coastguard Worker {
52*5e7646d2SAndroid Build Coastguard Worker const char *uri, /* Printer URI */
53*5e7646d2SAndroid Build Coastguard Worker *hostname, /* Hostname */
54*5e7646d2SAndroid Build Coastguard Worker *user, /* Username */
55*5e7646d2SAndroid Build Coastguard Worker *resource; /* Resource path */
56*5e7646d2SAndroid Build Coastguard Worker int port, /* Port number */
57*5e7646d2SAndroid Build Coastguard Worker version, /* IPP version */
58*5e7646d2SAndroid Build Coastguard Worker job_id, /* Job ID for submitted job */
59*5e7646d2SAndroid Build Coastguard Worker job_reasons, /* Job state reasons bits */
60*5e7646d2SAndroid Build Coastguard Worker create_job, /* Support Create-Job? */
61*5e7646d2SAndroid Build Coastguard Worker get_job_attrs; /* Support Get-Job-Attributes? */
62*5e7646d2SAndroid Build Coastguard Worker const char *job_name; /* Job name for submitted job */
63*5e7646d2SAndroid Build Coastguard Worker http_encryption_t encryption; /* Use encryption? */
64*5e7646d2SAndroid Build Coastguard Worker ipp_jstate_t job_state; /* Current job state */
65*5e7646d2SAndroid Build Coastguard Worker ipp_pstate_t printer_state; /* Current printer state */
66*5e7646d2SAndroid Build Coastguard Worker int retryable; /* Is this a job that should be retried? */
67*5e7646d2SAndroid Build Coastguard Worker } _cups_monitor_t;
68*5e7646d2SAndroid Build Coastguard Worker
69*5e7646d2SAndroid Build Coastguard Worker
70*5e7646d2SAndroid Build Coastguard Worker /*
71*5e7646d2SAndroid Build Coastguard Worker * Globals...
72*5e7646d2SAndroid Build Coastguard Worker */
73*5e7646d2SAndroid Build Coastguard Worker
74*5e7646d2SAndroid Build Coastguard Worker static const char *auth_info_required;
75*5e7646d2SAndroid Build Coastguard Worker /* New auth-info-required value */
76*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
77*5e7646d2SAndroid Build Coastguard Worker static pid_t child_pid = 0; /* Child process ID */
78*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
79*5e7646d2SAndroid Build Coastguard Worker static const char * const jattrs[] = /* Job attributes we want */
80*5e7646d2SAndroid Build Coastguard Worker {
81*5e7646d2SAndroid Build Coastguard Worker "job-id",
82*5e7646d2SAndroid Build Coastguard Worker "job-impressions-completed",
83*5e7646d2SAndroid Build Coastguard Worker "job-media-sheets-completed",
84*5e7646d2SAndroid Build Coastguard Worker "job-name",
85*5e7646d2SAndroid Build Coastguard Worker "job-originating-user-name",
86*5e7646d2SAndroid Build Coastguard Worker "job-state",
87*5e7646d2SAndroid Build Coastguard Worker "job-state-reasons"
88*5e7646d2SAndroid Build Coastguard Worker };
89*5e7646d2SAndroid Build Coastguard Worker static int job_canceled = 0,
90*5e7646d2SAndroid Build Coastguard Worker /* Job cancelled? */
91*5e7646d2SAndroid Build Coastguard Worker uri_credentials = 0;
92*5e7646d2SAndroid Build Coastguard Worker /* Credentials supplied in URI? */
93*5e7646d2SAndroid Build Coastguard Worker static char username[256] = "",
94*5e7646d2SAndroid Build Coastguard Worker /* Username for device URI */
95*5e7646d2SAndroid Build Coastguard Worker *password = NULL;
96*5e7646d2SAndroid Build Coastguard Worker /* Password for device URI */
97*5e7646d2SAndroid Build Coastguard Worker static const char * const pattrs[] = /* Printer attributes we want */
98*5e7646d2SAndroid Build Coastguard Worker {
99*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
100*5e7646d2SAndroid Build Coastguard Worker "compression-supported",
101*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
102*5e7646d2SAndroid Build Coastguard Worker "copies-supported",
103*5e7646d2SAndroid Build Coastguard Worker "cups-version",
104*5e7646d2SAndroid Build Coastguard Worker "document-format-supported",
105*5e7646d2SAndroid Build Coastguard Worker "job-password-encryption-supported",
106*5e7646d2SAndroid Build Coastguard Worker "marker-colors",
107*5e7646d2SAndroid Build Coastguard Worker "marker-high-levels",
108*5e7646d2SAndroid Build Coastguard Worker "marker-levels",
109*5e7646d2SAndroid Build Coastguard Worker "marker-low-levels",
110*5e7646d2SAndroid Build Coastguard Worker "marker-message",
111*5e7646d2SAndroid Build Coastguard Worker "marker-names",
112*5e7646d2SAndroid Build Coastguard Worker "marker-types",
113*5e7646d2SAndroid Build Coastguard Worker "media-col-supported",
114*5e7646d2SAndroid Build Coastguard Worker "multiple-document-handling-supported",
115*5e7646d2SAndroid Build Coastguard Worker "operations-supported",
116*5e7646d2SAndroid Build Coastguard Worker "print-color-mode-supported",
117*5e7646d2SAndroid Build Coastguard Worker "printer-alert",
118*5e7646d2SAndroid Build Coastguard Worker "printer-alert-description",
119*5e7646d2SAndroid Build Coastguard Worker "printer-is-accepting-jobs",
120*5e7646d2SAndroid Build Coastguard Worker "printer-mandatory-job-attributes",
121*5e7646d2SAndroid Build Coastguard Worker "printer-state",
122*5e7646d2SAndroid Build Coastguard Worker "printer-state-message",
123*5e7646d2SAndroid Build Coastguard Worker "printer-state-reasons"
124*5e7646d2SAndroid Build Coastguard Worker };
125*5e7646d2SAndroid Build Coastguard Worker static const char * const remote_job_states[] =
126*5e7646d2SAndroid Build Coastguard Worker { /* Remote job state keywords */
127*5e7646d2SAndroid Build Coastguard Worker "+cups-remote-pending",
128*5e7646d2SAndroid Build Coastguard Worker "+cups-remote-pending-held",
129*5e7646d2SAndroid Build Coastguard Worker "+cups-remote-processing",
130*5e7646d2SAndroid Build Coastguard Worker "+cups-remote-stopped",
131*5e7646d2SAndroid Build Coastguard Worker "+cups-remote-canceled",
132*5e7646d2SAndroid Build Coastguard Worker "+cups-remote-aborted",
133*5e7646d2SAndroid Build Coastguard Worker "+cups-remote-completed"
134*5e7646d2SAndroid Build Coastguard Worker };
135*5e7646d2SAndroid Build Coastguard Worker static _cups_mutex_t report_mutex = _CUPS_MUTEX_INITIALIZER;
136*5e7646d2SAndroid Build Coastguard Worker /* Mutex to control access */
137*5e7646d2SAndroid Build Coastguard Worker static int num_attr_cache = 0;
138*5e7646d2SAndroid Build Coastguard Worker /* Number of cached attributes */
139*5e7646d2SAndroid Build Coastguard Worker static cups_option_t *attr_cache = NULL;
140*5e7646d2SAndroid Build Coastguard Worker /* Cached attributes */
141*5e7646d2SAndroid Build Coastguard Worker static cups_array_t *state_reasons; /* Array of printe-state-reasons keywords */
142*5e7646d2SAndroid Build Coastguard Worker static char tmpfilename[1024] = "";
143*5e7646d2SAndroid Build Coastguard Worker /* Temporary spool file name */
144*5e7646d2SAndroid Build Coastguard Worker static char mandatory_attrs[1024] = "";
145*5e7646d2SAndroid Build Coastguard Worker /* cupsMandatory value */
146*5e7646d2SAndroid Build Coastguard Worker
147*5e7646d2SAndroid Build Coastguard Worker
148*5e7646d2SAndroid Build Coastguard Worker /*
149*5e7646d2SAndroid Build Coastguard Worker * Local functions...
150*5e7646d2SAndroid Build Coastguard Worker */
151*5e7646d2SAndroid Build Coastguard Worker
152*5e7646d2SAndroid Build Coastguard Worker static void cancel_job(http_t *http, const char *uri, int id,
153*5e7646d2SAndroid Build Coastguard Worker const char *resource, const char *user,
154*5e7646d2SAndroid Build Coastguard Worker int version);
155*5e7646d2SAndroid Build Coastguard Worker static ipp_pstate_t check_printer_state(http_t *http, const char *uri,
156*5e7646d2SAndroid Build Coastguard Worker const char *resource,
157*5e7646d2SAndroid Build Coastguard Worker const char *user, int version);
158*5e7646d2SAndroid Build Coastguard Worker static void debug_attributes(ipp_t *ipp);
159*5e7646d2SAndroid Build Coastguard Worker static void *monitor_printer(_cups_monitor_t *monitor);
160*5e7646d2SAndroid Build Coastguard Worker static ipp_t *new_request(ipp_op_t op, int version, const char *uri,
161*5e7646d2SAndroid Build Coastguard Worker const char *user, const char *title,
162*5e7646d2SAndroid Build Coastguard Worker int num_options, cups_option_t *options,
163*5e7646d2SAndroid Build Coastguard Worker const char *compression, int copies,
164*5e7646d2SAndroid Build Coastguard Worker const char *format, _ppd_cache_t *pc,
165*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd,
166*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *media_col_sup,
167*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *doc_handling_sup,
168*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *print_color_mode_sup);
169*5e7646d2SAndroid Build Coastguard Worker static const char *password_cb(const char *prompt, http_t *http,
170*5e7646d2SAndroid Build Coastguard Worker const char *method, const char *resource,
171*5e7646d2SAndroid Build Coastguard Worker int *user_data);
172*5e7646d2SAndroid Build Coastguard Worker static const char *quote_string(const char *s, char *q, size_t qsize);
173*5e7646d2SAndroid Build Coastguard Worker static void report_attr(ipp_attribute_t *attr);
174*5e7646d2SAndroid Build Coastguard Worker static void report_printer_state(ipp_t *ipp);
175*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
176*5e7646d2SAndroid Build Coastguard Worker static int run_as_user(char *argv[], uid_t uid,
177*5e7646d2SAndroid Build Coastguard Worker const char *device_uri, int fd);
178*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
179*5e7646d2SAndroid Build Coastguard Worker static void sigterm_handler(int sig);
180*5e7646d2SAndroid Build Coastguard Worker static int timeout_cb(http_t *http, void *user_data);
181*5e7646d2SAndroid Build Coastguard Worker static void update_reasons(ipp_attribute_t *attr, const char *s);
182*5e7646d2SAndroid Build Coastguard Worker
183*5e7646d2SAndroid Build Coastguard Worker
184*5e7646d2SAndroid Build Coastguard Worker /*
185*5e7646d2SAndroid Build Coastguard Worker * 'main()' - Send a file to the printer or server.
186*5e7646d2SAndroid Build Coastguard Worker *
187*5e7646d2SAndroid Build Coastguard Worker * Usage:
188*5e7646d2SAndroid Build Coastguard Worker *
189*5e7646d2SAndroid Build Coastguard Worker * printer-uri job-id user title copies options [file]
190*5e7646d2SAndroid Build Coastguard Worker */
191*5e7646d2SAndroid Build Coastguard Worker
192*5e7646d2SAndroid Build Coastguard Worker int /* O - Exit status */
main(int argc,char * argv[])193*5e7646d2SAndroid Build Coastguard Worker main(int argc, /* I - Number of command-line args */
194*5e7646d2SAndroid Build Coastguard Worker char *argv[]) /* I - Command-line arguments */
195*5e7646d2SAndroid Build Coastguard Worker {
196*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
197*5e7646d2SAndroid Build Coastguard Worker int send_options; /* Send job options? */
198*5e7646d2SAndroid Build Coastguard Worker int num_options; /* Number of printer options */
199*5e7646d2SAndroid Build Coastguard Worker cups_option_t *options; /* Printer options */
200*5e7646d2SAndroid Build Coastguard Worker const char *device_uri; /* Device URI */
201*5e7646d2SAndroid Build Coastguard Worker char scheme[255], /* Scheme in URI */
202*5e7646d2SAndroid Build Coastguard Worker hostname[1024], /* Hostname */
203*5e7646d2SAndroid Build Coastguard Worker resource[1024], /* Resource info (printer name) */
204*5e7646d2SAndroid Build Coastguard Worker addrname[256], /* Address name */
205*5e7646d2SAndroid Build Coastguard Worker *optptr, /* Pointer to URI options */
206*5e7646d2SAndroid Build Coastguard Worker *name, /* Name of option */
207*5e7646d2SAndroid Build Coastguard Worker *value, /* Value of option */
208*5e7646d2SAndroid Build Coastguard Worker sep; /* Separator character */
209*5e7646d2SAndroid Build Coastguard Worker int password_tries = 0; /* Password tries */
210*5e7646d2SAndroid Build Coastguard Worker http_addrlist_t *addrlist; /* Address of printer */
211*5e7646d2SAndroid Build Coastguard Worker int snmp_enabled = 1; /* Is SNMP enabled? */
212*5e7646d2SAndroid Build Coastguard Worker int snmp_fd, /* SNMP socket */
213*5e7646d2SAndroid Build Coastguard Worker start_count, /* Page count via SNMP at start */
214*5e7646d2SAndroid Build Coastguard Worker page_count, /* Page count via SNMP */
215*5e7646d2SAndroid Build Coastguard Worker have_supplies; /* Printer supports supply levels? */
216*5e7646d2SAndroid Build Coastguard Worker int num_files; /* Number of files to print */
217*5e7646d2SAndroid Build Coastguard Worker char **files, /* Files to print */
218*5e7646d2SAndroid Build Coastguard Worker *compatfile = NULL; /* Compatibility filename */
219*5e7646d2SAndroid Build Coastguard Worker off_t compatsize = 0; /* Size of compatibility file */
220*5e7646d2SAndroid Build Coastguard Worker int port; /* Port number (not used) */
221*5e7646d2SAndroid Build Coastguard Worker char uri[HTTP_MAX_URI]; /* Updated URI without user/pass */
222*5e7646d2SAndroid Build Coastguard Worker char print_job_name[1024]; /* Update job-name for Print-Job */
223*5e7646d2SAndroid Build Coastguard Worker http_status_t http_status; /* Status of HTTP request */
224*5e7646d2SAndroid Build Coastguard Worker ipp_status_t ipp_status; /* Status of IPP request */
225*5e7646d2SAndroid Build Coastguard Worker http_t *http; /* HTTP connection */
226*5e7646d2SAndroid Build Coastguard Worker ipp_t *request, /* IPP request */
227*5e7646d2SAndroid Build Coastguard Worker *response, /* IPP response */
228*5e7646d2SAndroid Build Coastguard Worker *supported; /* get-printer-attributes response */
229*5e7646d2SAndroid Build Coastguard Worker time_t start_time; /* Time of first connect */
230*5e7646d2SAndroid Build Coastguard Worker int contimeout; /* Connection timeout */
231*5e7646d2SAndroid Build Coastguard Worker int delay, /* Delay for retries */
232*5e7646d2SAndroid Build Coastguard Worker prev_delay; /* Previous delay */
233*5e7646d2SAndroid Build Coastguard Worker const char *compression; /* Compression mode */
234*5e7646d2SAndroid Build Coastguard Worker int waitjob, /* Wait for job complete? */
235*5e7646d2SAndroid Build Coastguard Worker waitjob_tries = 0, /* Number of times we've waited */
236*5e7646d2SAndroid Build Coastguard Worker waitprinter; /* Wait for printer ready? */
237*5e7646d2SAndroid Build Coastguard Worker _cups_monitor_t monitor; /* Monitoring data */
238*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *job_id_attr; /* job-id attribute */
239*5e7646d2SAndroid Build Coastguard Worker int job_id; /* job-id value */
240*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *job_sheets; /* job-media-sheets-completed */
241*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *job_state; /* job-state */
242*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
243*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *compression_sup; /* compression-supported */
244*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
245*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *copies_sup; /* copies-supported */
246*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *cups_version; /* cups-version */
247*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *encryption_sup; /* job-password-encryption-supported */
248*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *format_sup; /* document-format-supported */
249*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *job_auth; /* job-authorization-uri */
250*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *media_col_sup; /* media-col-supported */
251*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *operations_sup; /* operations-supported */
252*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *doc_handling_sup; /* multiple-document-handling-supported */
253*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *printer_state; /* printer-state attribute */
254*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *printer_accepting; /* printer-is-accepting-jobs */
255*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *print_color_mode_sup;/* Does printer support print-color-mode? */
256*5e7646d2SAndroid Build Coastguard Worker int create_job = 0, /* Does printer support Create-Job? */
257*5e7646d2SAndroid Build Coastguard Worker get_job_attrs = 0, /* Does printer support Get-Job-Attributes? */
258*5e7646d2SAndroid Build Coastguard Worker send_document = 0, /* Does printer support Send-Document? */
259*5e7646d2SAndroid Build Coastguard Worker validate_job = 0, /* Does printer support Validate-Job? */
260*5e7646d2SAndroid Build Coastguard Worker validate_retried = 0, /* Was Validate-Job request retried? */
261*5e7646d2SAndroid Build Coastguard Worker copies, /* Number of copies for job */
262*5e7646d2SAndroid Build Coastguard Worker copies_remaining; /* Number of copies remaining */
263*5e7646d2SAndroid Build Coastguard Worker const char *content_type, /* CONTENT_TYPE environment variable */
264*5e7646d2SAndroid Build Coastguard Worker *final_content_type, /* FINAL_CONTENT_TYPE environment var */
265*5e7646d2SAndroid Build Coastguard Worker *document_format; /* document-format value */
266*5e7646d2SAndroid Build Coastguard Worker int fd; /* File descriptor */
267*5e7646d2SAndroid Build Coastguard Worker off_t bytes = 0; /* Bytes copied */
268*5e7646d2SAndroid Build Coastguard Worker char buffer[16384]; /* Copy buffer */
269*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
270*5e7646d2SAndroid Build Coastguard Worker struct sigaction action; /* Actions for POSIX signals */
271*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
272*5e7646d2SAndroid Build Coastguard Worker int version; /* IPP version */
273*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd = NULL; /* PPD file */
274*5e7646d2SAndroid Build Coastguard Worker _ppd_cache_t *pc = NULL; /* PPD cache and mapping data */
275*5e7646d2SAndroid Build Coastguard Worker fd_set input; /* Input set for select() */
276*5e7646d2SAndroid Build Coastguard Worker
277*5e7646d2SAndroid Build Coastguard Worker
278*5e7646d2SAndroid Build Coastguard Worker /*
279*5e7646d2SAndroid Build Coastguard Worker * Make sure status messages are not buffered...
280*5e7646d2SAndroid Build Coastguard Worker */
281*5e7646d2SAndroid Build Coastguard Worker
282*5e7646d2SAndroid Build Coastguard Worker setbuf(stderr, NULL);
283*5e7646d2SAndroid Build Coastguard Worker
284*5e7646d2SAndroid Build Coastguard Worker /*
285*5e7646d2SAndroid Build Coastguard Worker * Ignore SIGPIPE and catch SIGTERM signals...
286*5e7646d2SAndroid Build Coastguard Worker */
287*5e7646d2SAndroid Build Coastguard Worker
288*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SIGSET
289*5e7646d2SAndroid Build Coastguard Worker sigset(SIGPIPE, SIG_IGN);
290*5e7646d2SAndroid Build Coastguard Worker sigset(SIGTERM, sigterm_handler);
291*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_SIGACTION)
292*5e7646d2SAndroid Build Coastguard Worker memset(&action, 0, sizeof(action));
293*5e7646d2SAndroid Build Coastguard Worker action.sa_handler = SIG_IGN;
294*5e7646d2SAndroid Build Coastguard Worker sigaction(SIGPIPE, &action, NULL);
295*5e7646d2SAndroid Build Coastguard Worker
296*5e7646d2SAndroid Build Coastguard Worker sigemptyset(&action.sa_mask);
297*5e7646d2SAndroid Build Coastguard Worker sigaddset(&action.sa_mask, SIGTERM);
298*5e7646d2SAndroid Build Coastguard Worker action.sa_handler = sigterm_handler;
299*5e7646d2SAndroid Build Coastguard Worker sigaction(SIGTERM, &action, NULL);
300*5e7646d2SAndroid Build Coastguard Worker #else
301*5e7646d2SAndroid Build Coastguard Worker signal(SIGPIPE, SIG_IGN);
302*5e7646d2SAndroid Build Coastguard Worker signal(SIGTERM, sigterm_handler);
303*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGSET */
304*5e7646d2SAndroid Build Coastguard Worker
305*5e7646d2SAndroid Build Coastguard Worker /*
306*5e7646d2SAndroid Build Coastguard Worker * Check command-line...
307*5e7646d2SAndroid Build Coastguard Worker */
308*5e7646d2SAndroid Build Coastguard Worker
309*5e7646d2SAndroid Build Coastguard Worker if (argc == 1)
310*5e7646d2SAndroid Build Coastguard Worker {
311*5e7646d2SAndroid Build Coastguard Worker char *s;
312*5e7646d2SAndroid Build Coastguard Worker
313*5e7646d2SAndroid Build Coastguard Worker if ((s = strrchr(argv[0], '/')) != NULL)
314*5e7646d2SAndroid Build Coastguard Worker s ++;
315*5e7646d2SAndroid Build Coastguard Worker else
316*5e7646d2SAndroid Build Coastguard Worker s = argv[0];
317*5e7646d2SAndroid Build Coastguard Worker
318*5e7646d2SAndroid Build Coastguard Worker printf("network %s \"Unknown\" \"%s (%s)\"\n",
319*5e7646d2SAndroid Build Coastguard Worker s, _cupsLangString(cupsLangDefault(),
320*5e7646d2SAndroid Build Coastguard Worker _("Internet Printing Protocol")), s);
321*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
322*5e7646d2SAndroid Build Coastguard Worker }
323*5e7646d2SAndroid Build Coastguard Worker else if (argc < 6)
324*5e7646d2SAndroid Build Coastguard Worker {
325*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintf(stderr,
326*5e7646d2SAndroid Build Coastguard Worker _("Usage: %s job-id user title copies options [file]"),
327*5e7646d2SAndroid Build Coastguard Worker argv[0]);
328*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_STOP);
329*5e7646d2SAndroid Build Coastguard Worker }
330*5e7646d2SAndroid Build Coastguard Worker
331*5e7646d2SAndroid Build Coastguard Worker /*
332*5e7646d2SAndroid Build Coastguard Worker * Get the device URI...
333*5e7646d2SAndroid Build Coastguard Worker */
334*5e7646d2SAndroid Build Coastguard Worker
335*5e7646d2SAndroid Build Coastguard Worker while ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
336*5e7646d2SAndroid Build Coastguard Worker {
337*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
338*5e7646d2SAndroid Build Coastguard Worker sleep(10);
339*5e7646d2SAndroid Build Coastguard Worker
340*5e7646d2SAndroid Build Coastguard Worker if (getenv("CLASS") != NULL)
341*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
342*5e7646d2SAndroid Build Coastguard Worker }
343*5e7646d2SAndroid Build Coastguard Worker
344*5e7646d2SAndroid Build Coastguard Worker if ((auth_info_required = getenv("AUTH_INFO_REQUIRED")) == NULL)
345*5e7646d2SAndroid Build Coastguard Worker auth_info_required = "none";
346*5e7646d2SAndroid Build Coastguard Worker
347*5e7646d2SAndroid Build Coastguard Worker state_reasons = _cupsArrayNewStrings(getenv("PRINTER_STATE_REASONS"), ',');
348*5e7646d2SAndroid Build Coastguard Worker
349*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_GSSAPI
350*5e7646d2SAndroid Build Coastguard Worker /*
351*5e7646d2SAndroid Build Coastguard Worker * For Kerberos, become the printing user (if we can) to get the credentials
352*5e7646d2SAndroid Build Coastguard Worker * that way.
353*5e7646d2SAndroid Build Coastguard Worker */
354*5e7646d2SAndroid Build Coastguard Worker
355*5e7646d2SAndroid Build Coastguard Worker if (!getuid() && (value = getenv("AUTH_UID")) != NULL)
356*5e7646d2SAndroid Build Coastguard Worker {
357*5e7646d2SAndroid Build Coastguard Worker uid_t uid = (uid_t)atoi(value);
358*5e7646d2SAndroid Build Coastguard Worker /* User ID */
359*5e7646d2SAndroid Build Coastguard Worker
360*5e7646d2SAndroid Build Coastguard Worker # ifdef HAVE_XPC
361*5e7646d2SAndroid Build Coastguard Worker if (uid > 0)
362*5e7646d2SAndroid Build Coastguard Worker {
363*5e7646d2SAndroid Build Coastguard Worker if (argc == 6)
364*5e7646d2SAndroid Build Coastguard Worker return (run_as_user(argv, uid, device_uri, 0));
365*5e7646d2SAndroid Build Coastguard Worker else
366*5e7646d2SAndroid Build Coastguard Worker {
367*5e7646d2SAndroid Build Coastguard Worker int status = 0; /* Exit status */
368*5e7646d2SAndroid Build Coastguard Worker
369*5e7646d2SAndroid Build Coastguard Worker for (i = 6; i < argc && !status && !job_canceled; i ++)
370*5e7646d2SAndroid Build Coastguard Worker {
371*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(argv[i], O_RDONLY)) >= 0)
372*5e7646d2SAndroid Build Coastguard Worker {
373*5e7646d2SAndroid Build Coastguard Worker status = run_as_user(argv, uid, device_uri, fd);
374*5e7646d2SAndroid Build Coastguard Worker close(fd);
375*5e7646d2SAndroid Build Coastguard Worker }
376*5e7646d2SAndroid Build Coastguard Worker else
377*5e7646d2SAndroid Build Coastguard Worker {
378*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintError("ERROR", _("Unable to open print file"));
379*5e7646d2SAndroid Build Coastguard Worker status = CUPS_BACKEND_FAILED;
380*5e7646d2SAndroid Build Coastguard Worker }
381*5e7646d2SAndroid Build Coastguard Worker }
382*5e7646d2SAndroid Build Coastguard Worker
383*5e7646d2SAndroid Build Coastguard Worker return (status);
384*5e7646d2SAndroid Build Coastguard Worker }
385*5e7646d2SAndroid Build Coastguard Worker }
386*5e7646d2SAndroid Build Coastguard Worker
387*5e7646d2SAndroid Build Coastguard Worker # else /* No XPC, just try to run as the user ID */
388*5e7646d2SAndroid Build Coastguard Worker if (uid > 0)
389*5e7646d2SAndroid Build Coastguard Worker setuid(uid);
390*5e7646d2SAndroid Build Coastguard Worker # endif /* HAVE_XPC */
391*5e7646d2SAndroid Build Coastguard Worker }
392*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI */
393*5e7646d2SAndroid Build Coastguard Worker
394*5e7646d2SAndroid Build Coastguard Worker /*
395*5e7646d2SAndroid Build Coastguard Worker * Get the (final) content type...
396*5e7646d2SAndroid Build Coastguard Worker */
397*5e7646d2SAndroid Build Coastguard Worker
398*5e7646d2SAndroid Build Coastguard Worker if ((content_type = getenv("CONTENT_TYPE")) == NULL)
399*5e7646d2SAndroid Build Coastguard Worker content_type = "application/octet-stream";
400*5e7646d2SAndroid Build Coastguard Worker
401*5e7646d2SAndroid Build Coastguard Worker if ((final_content_type = getenv("FINAL_CONTENT_TYPE")) == NULL)
402*5e7646d2SAndroid Build Coastguard Worker {
403*5e7646d2SAndroid Build Coastguard Worker final_content_type = content_type;
404*5e7646d2SAndroid Build Coastguard Worker
405*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(final_content_type, "printer/", 8))
406*5e7646d2SAndroid Build Coastguard Worker final_content_type = "application/vnd.cups-raw";
407*5e7646d2SAndroid Build Coastguard Worker }
408*5e7646d2SAndroid Build Coastguard Worker
409*5e7646d2SAndroid Build Coastguard Worker /*
410*5e7646d2SAndroid Build Coastguard Worker * Extract the hostname and printer name from the URI...
411*5e7646d2SAndroid Build Coastguard Worker */
412*5e7646d2SAndroid Build Coastguard Worker
413*5e7646d2SAndroid Build Coastguard Worker httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
414*5e7646d2SAndroid Build Coastguard Worker username, sizeof(username), hostname, sizeof(hostname), &port,
415*5e7646d2SAndroid Build Coastguard Worker resource, sizeof(resource));
416*5e7646d2SAndroid Build Coastguard Worker
417*5e7646d2SAndroid Build Coastguard Worker if (!port)
418*5e7646d2SAndroid Build Coastguard Worker port = IPP_PORT; /* Default to port 631 */
419*5e7646d2SAndroid Build Coastguard Worker
420*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(scheme, "https") || !strcmp(scheme, "ipps"))
421*5e7646d2SAndroid Build Coastguard Worker cupsSetEncryption(HTTP_ENCRYPTION_ALWAYS);
422*5e7646d2SAndroid Build Coastguard Worker else
423*5e7646d2SAndroid Build Coastguard Worker cupsSetEncryption(HTTP_ENCRYPTION_IF_REQUESTED);
424*5e7646d2SAndroid Build Coastguard Worker
425*5e7646d2SAndroid Build Coastguard Worker /*
426*5e7646d2SAndroid Build Coastguard Worker * See if there are any options...
427*5e7646d2SAndroid Build Coastguard Worker */
428*5e7646d2SAndroid Build Coastguard Worker
429*5e7646d2SAndroid Build Coastguard Worker compression = NULL;
430*5e7646d2SAndroid Build Coastguard Worker version = 20;
431*5e7646d2SAndroid Build Coastguard Worker waitjob = 1;
432*5e7646d2SAndroid Build Coastguard Worker waitprinter = 1;
433*5e7646d2SAndroid Build Coastguard Worker contimeout = 7 * 24 * 60 * 60;
434*5e7646d2SAndroid Build Coastguard Worker
435*5e7646d2SAndroid Build Coastguard Worker if ((optptr = strchr(resource, '?')) != NULL)
436*5e7646d2SAndroid Build Coastguard Worker {
437*5e7646d2SAndroid Build Coastguard Worker /*
438*5e7646d2SAndroid Build Coastguard Worker * Yup, terminate the device name string and move to the first
439*5e7646d2SAndroid Build Coastguard Worker * character of the optptr...
440*5e7646d2SAndroid Build Coastguard Worker */
441*5e7646d2SAndroid Build Coastguard Worker
442*5e7646d2SAndroid Build Coastguard Worker *optptr++ = '\0';
443*5e7646d2SAndroid Build Coastguard Worker
444*5e7646d2SAndroid Build Coastguard Worker /*
445*5e7646d2SAndroid Build Coastguard Worker * Then parse the optptr...
446*5e7646d2SAndroid Build Coastguard Worker */
447*5e7646d2SAndroid Build Coastguard Worker
448*5e7646d2SAndroid Build Coastguard Worker while (*optptr)
449*5e7646d2SAndroid Build Coastguard Worker {
450*5e7646d2SAndroid Build Coastguard Worker /*
451*5e7646d2SAndroid Build Coastguard Worker * Get the name...
452*5e7646d2SAndroid Build Coastguard Worker */
453*5e7646d2SAndroid Build Coastguard Worker
454*5e7646d2SAndroid Build Coastguard Worker name = optptr;
455*5e7646d2SAndroid Build Coastguard Worker
456*5e7646d2SAndroid Build Coastguard Worker while (*optptr && *optptr != '=' && *optptr != '+' && *optptr != '&')
457*5e7646d2SAndroid Build Coastguard Worker optptr ++;
458*5e7646d2SAndroid Build Coastguard Worker
459*5e7646d2SAndroid Build Coastguard Worker if ((sep = *optptr) != '\0')
460*5e7646d2SAndroid Build Coastguard Worker *optptr++ = '\0';
461*5e7646d2SAndroid Build Coastguard Worker
462*5e7646d2SAndroid Build Coastguard Worker if (sep == '=')
463*5e7646d2SAndroid Build Coastguard Worker {
464*5e7646d2SAndroid Build Coastguard Worker /*
465*5e7646d2SAndroid Build Coastguard Worker * Get the value...
466*5e7646d2SAndroid Build Coastguard Worker */
467*5e7646d2SAndroid Build Coastguard Worker
468*5e7646d2SAndroid Build Coastguard Worker value = optptr;
469*5e7646d2SAndroid Build Coastguard Worker
470*5e7646d2SAndroid Build Coastguard Worker while (*optptr && *optptr != '+' && *optptr != '&')
471*5e7646d2SAndroid Build Coastguard Worker optptr ++;
472*5e7646d2SAndroid Build Coastguard Worker
473*5e7646d2SAndroid Build Coastguard Worker if (*optptr)
474*5e7646d2SAndroid Build Coastguard Worker *optptr++ = '\0';
475*5e7646d2SAndroid Build Coastguard Worker }
476*5e7646d2SAndroid Build Coastguard Worker else
477*5e7646d2SAndroid Build Coastguard Worker value = (char *)"";
478*5e7646d2SAndroid Build Coastguard Worker
479*5e7646d2SAndroid Build Coastguard Worker /*
480*5e7646d2SAndroid Build Coastguard Worker * Process the option...
481*5e7646d2SAndroid Build Coastguard Worker */
482*5e7646d2SAndroid Build Coastguard Worker
483*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(name, "waitjob"))
484*5e7646d2SAndroid Build Coastguard Worker {
485*5e7646d2SAndroid Build Coastguard Worker /*
486*5e7646d2SAndroid Build Coastguard Worker * Wait for job completion?
487*5e7646d2SAndroid Build Coastguard Worker */
488*5e7646d2SAndroid Build Coastguard Worker
489*5e7646d2SAndroid Build Coastguard Worker waitjob = !_cups_strcasecmp(value, "on") ||
490*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "yes") ||
491*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "true");
492*5e7646d2SAndroid Build Coastguard Worker }
493*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "waitprinter"))
494*5e7646d2SAndroid Build Coastguard Worker {
495*5e7646d2SAndroid Build Coastguard Worker /*
496*5e7646d2SAndroid Build Coastguard Worker * Wait for printer idle?
497*5e7646d2SAndroid Build Coastguard Worker */
498*5e7646d2SAndroid Build Coastguard Worker
499*5e7646d2SAndroid Build Coastguard Worker waitprinter = !_cups_strcasecmp(value, "on") ||
500*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "yes") ||
501*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "true");
502*5e7646d2SAndroid Build Coastguard Worker }
503*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "encryption"))
504*5e7646d2SAndroid Build Coastguard Worker {
505*5e7646d2SAndroid Build Coastguard Worker /*
506*5e7646d2SAndroid Build Coastguard Worker * Enable/disable encryption?
507*5e7646d2SAndroid Build Coastguard Worker */
508*5e7646d2SAndroid Build Coastguard Worker
509*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(value, "always"))
510*5e7646d2SAndroid Build Coastguard Worker cupsSetEncryption(HTTP_ENCRYPTION_ALWAYS);
511*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(value, "required"))
512*5e7646d2SAndroid Build Coastguard Worker cupsSetEncryption(HTTP_ENCRYPTION_REQUIRED);
513*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(value, "never"))
514*5e7646d2SAndroid Build Coastguard Worker cupsSetEncryption(HTTP_ENCRYPTION_NEVER);
515*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(value, "ifrequested"))
516*5e7646d2SAndroid Build Coastguard Worker cupsSetEncryption(HTTP_ENCRYPTION_IF_REQUESTED);
517*5e7646d2SAndroid Build Coastguard Worker else
518*5e7646d2SAndroid Build Coastguard Worker {
519*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
520*5e7646d2SAndroid Build Coastguard Worker _("Unknown encryption option value: \"%s\"."),
521*5e7646d2SAndroid Build Coastguard Worker value);
522*5e7646d2SAndroid Build Coastguard Worker }
523*5e7646d2SAndroid Build Coastguard Worker }
524*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "snmp"))
525*5e7646d2SAndroid Build Coastguard Worker {
526*5e7646d2SAndroid Build Coastguard Worker /*
527*5e7646d2SAndroid Build Coastguard Worker * Enable/disable SNMP stuff...
528*5e7646d2SAndroid Build Coastguard Worker */
529*5e7646d2SAndroid Build Coastguard Worker
530*5e7646d2SAndroid Build Coastguard Worker snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") ||
531*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "yes") ||
532*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "true");
533*5e7646d2SAndroid Build Coastguard Worker }
534*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "version"))
535*5e7646d2SAndroid Build Coastguard Worker {
536*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(value, "1.0"))
537*5e7646d2SAndroid Build Coastguard Worker version = 10;
538*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(value, "1.1"))
539*5e7646d2SAndroid Build Coastguard Worker version = 11;
540*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(value, "2.0"))
541*5e7646d2SAndroid Build Coastguard Worker version = 20;
542*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(value, "2.1"))
543*5e7646d2SAndroid Build Coastguard Worker version = 21;
544*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(value, "2.2"))
545*5e7646d2SAndroid Build Coastguard Worker version = 22;
546*5e7646d2SAndroid Build Coastguard Worker else
547*5e7646d2SAndroid Build Coastguard Worker {
548*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
549*5e7646d2SAndroid Build Coastguard Worker _("Unknown version option value: \"%s\"."),
550*5e7646d2SAndroid Build Coastguard Worker value);
551*5e7646d2SAndroid Build Coastguard Worker }
552*5e7646d2SAndroid Build Coastguard Worker }
553*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
554*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "compression"))
555*5e7646d2SAndroid Build Coastguard Worker {
556*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(value, "true") || !_cups_strcasecmp(value, "yes") ||
557*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "gzip"))
558*5e7646d2SAndroid Build Coastguard Worker compression = "gzip";
559*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(value, "deflate"))
560*5e7646d2SAndroid Build Coastguard Worker compression = "deflate";
561*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(value, "false") ||
562*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "no") ||
563*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "off") ||
564*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(value, "none"))
565*5e7646d2SAndroid Build Coastguard Worker compression = "none";
566*5e7646d2SAndroid Build Coastguard Worker }
567*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
568*5e7646d2SAndroid Build Coastguard Worker else if (!_cups_strcasecmp(name, "contimeout"))
569*5e7646d2SAndroid Build Coastguard Worker {
570*5e7646d2SAndroid Build Coastguard Worker /*
571*5e7646d2SAndroid Build Coastguard Worker * Set the connection timeout...
572*5e7646d2SAndroid Build Coastguard Worker */
573*5e7646d2SAndroid Build Coastguard Worker
574*5e7646d2SAndroid Build Coastguard Worker if (atoi(value) > 0)
575*5e7646d2SAndroid Build Coastguard Worker contimeout = atoi(value);
576*5e7646d2SAndroid Build Coastguard Worker }
577*5e7646d2SAndroid Build Coastguard Worker else
578*5e7646d2SAndroid Build Coastguard Worker {
579*5e7646d2SAndroid Build Coastguard Worker /*
580*5e7646d2SAndroid Build Coastguard Worker * Unknown option...
581*5e7646d2SAndroid Build Coastguard Worker */
582*5e7646d2SAndroid Build Coastguard Worker
583*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
584*5e7646d2SAndroid Build Coastguard Worker _("Unknown option \"%s\" with value \"%s\"."),
585*5e7646d2SAndroid Build Coastguard Worker name, value);
586*5e7646d2SAndroid Build Coastguard Worker }
587*5e7646d2SAndroid Build Coastguard Worker }
588*5e7646d2SAndroid Build Coastguard Worker }
589*5e7646d2SAndroid Build Coastguard Worker
590*5e7646d2SAndroid Build Coastguard Worker /*
591*5e7646d2SAndroid Build Coastguard Worker * If we have 7 arguments, print the file named on the command-line.
592*5e7646d2SAndroid Build Coastguard Worker * Otherwise, copy stdin to a temporary file and print the temporary
593*5e7646d2SAndroid Build Coastguard Worker * file.
594*5e7646d2SAndroid Build Coastguard Worker */
595*5e7646d2SAndroid Build Coastguard Worker
596*5e7646d2SAndroid Build Coastguard Worker if (argc == 6)
597*5e7646d2SAndroid Build Coastguard Worker {
598*5e7646d2SAndroid Build Coastguard Worker num_files = 0;
599*5e7646d2SAndroid Build Coastguard Worker files = NULL;
600*5e7646d2SAndroid Build Coastguard Worker send_options = !_cups_strcasecmp(final_content_type, "application/pdf") ||
601*5e7646d2SAndroid Build Coastguard Worker !_cups_strcasecmp(final_content_type, "application/vnd.cups-pdf") ||
602*5e7646d2SAndroid Build Coastguard Worker !_cups_strncasecmp(final_content_type, "image/", 6);
603*5e7646d2SAndroid Build Coastguard Worker
604*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Sending stdin for job...\n", stderr);
605*5e7646d2SAndroid Build Coastguard Worker }
606*5e7646d2SAndroid Build Coastguard Worker else
607*5e7646d2SAndroid Build Coastguard Worker {
608*5e7646d2SAndroid Build Coastguard Worker /*
609*5e7646d2SAndroid Build Coastguard Worker * Point to the files on the command-line...
610*5e7646d2SAndroid Build Coastguard Worker */
611*5e7646d2SAndroid Build Coastguard Worker
612*5e7646d2SAndroid Build Coastguard Worker num_files = argc - 6;
613*5e7646d2SAndroid Build Coastguard Worker files = argv + 6;
614*5e7646d2SAndroid Build Coastguard Worker send_options = 1;
615*5e7646d2SAndroid Build Coastguard Worker
616*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: %d files to send in job...\n", num_files);
617*5e7646d2SAndroid Build Coastguard Worker }
618*5e7646d2SAndroid Build Coastguard Worker
619*5e7646d2SAndroid Build Coastguard Worker /*
620*5e7646d2SAndroid Build Coastguard Worker * Set the authentication info, if any...
621*5e7646d2SAndroid Build Coastguard Worker */
622*5e7646d2SAndroid Build Coastguard Worker
623*5e7646d2SAndroid Build Coastguard Worker cupsSetPasswordCB2((cups_password_cb2_t)password_cb, &password_tries);
624*5e7646d2SAndroid Build Coastguard Worker
625*5e7646d2SAndroid Build Coastguard Worker if (username[0])
626*5e7646d2SAndroid Build Coastguard Worker {
627*5e7646d2SAndroid Build Coastguard Worker /*
628*5e7646d2SAndroid Build Coastguard Worker * Use authentication information in the device URI...
629*5e7646d2SAndroid Build Coastguard Worker */
630*5e7646d2SAndroid Build Coastguard Worker
631*5e7646d2SAndroid Build Coastguard Worker if ((password = strchr(username, ':')) != NULL)
632*5e7646d2SAndroid Build Coastguard Worker *password++ = '\0';
633*5e7646d2SAndroid Build Coastguard Worker
634*5e7646d2SAndroid Build Coastguard Worker cupsSetUser(username);
635*5e7646d2SAndroid Build Coastguard Worker uri_credentials = 1;
636*5e7646d2SAndroid Build Coastguard Worker }
637*5e7646d2SAndroid Build Coastguard Worker else
638*5e7646d2SAndroid Build Coastguard Worker {
639*5e7646d2SAndroid Build Coastguard Worker /*
640*5e7646d2SAndroid Build Coastguard Worker * Try loading authentication information from the environment.
641*5e7646d2SAndroid Build Coastguard Worker */
642*5e7646d2SAndroid Build Coastguard Worker
643*5e7646d2SAndroid Build Coastguard Worker const char *ptr = getenv("AUTH_USERNAME");
644*5e7646d2SAndroid Build Coastguard Worker
645*5e7646d2SAndroid Build Coastguard Worker if (ptr)
646*5e7646d2SAndroid Build Coastguard Worker {
647*5e7646d2SAndroid Build Coastguard Worker strlcpy(username, ptr, sizeof(username));
648*5e7646d2SAndroid Build Coastguard Worker cupsSetUser(ptr);
649*5e7646d2SAndroid Build Coastguard Worker }
650*5e7646d2SAndroid Build Coastguard Worker
651*5e7646d2SAndroid Build Coastguard Worker password = getenv("AUTH_PASSWORD");
652*5e7646d2SAndroid Build Coastguard Worker }
653*5e7646d2SAndroid Build Coastguard Worker
654*5e7646d2SAndroid Build Coastguard Worker /*
655*5e7646d2SAndroid Build Coastguard Worker * Try finding the remote server...
656*5e7646d2SAndroid Build Coastguard Worker */
657*5e7646d2SAndroid Build Coastguard Worker
658*5e7646d2SAndroid Build Coastguard Worker start_time = time(NULL);
659*5e7646d2SAndroid Build Coastguard Worker
660*5e7646d2SAndroid Build Coastguard Worker addrlist = backendLookup(hostname, port, &job_canceled);
661*5e7646d2SAndroid Build Coastguard Worker
662*5e7646d2SAndroid Build Coastguard Worker http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1,
663*5e7646d2SAndroid Build Coastguard Worker 0, NULL);
664*5e7646d2SAndroid Build Coastguard Worker httpSetTimeout(http, 30.0, timeout_cb, NULL);
665*5e7646d2SAndroid Build Coastguard Worker
666*5e7646d2SAndroid Build Coastguard Worker /*
667*5e7646d2SAndroid Build Coastguard Worker * See if the printer supports SNMP...
668*5e7646d2SAndroid Build Coastguard Worker */
669*5e7646d2SAndroid Build Coastguard Worker
670*5e7646d2SAndroid Build Coastguard Worker if (snmp_enabled)
671*5e7646d2SAndroid Build Coastguard Worker snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family);
672*5e7646d2SAndroid Build Coastguard Worker else
673*5e7646d2SAndroid Build Coastguard Worker snmp_fd = -1;
674*5e7646d2SAndroid Build Coastguard Worker
675*5e7646d2SAndroid Build Coastguard Worker if (snmp_fd >= 0)
676*5e7646d2SAndroid Build Coastguard Worker have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr),
677*5e7646d2SAndroid Build Coastguard Worker &start_count, NULL);
678*5e7646d2SAndroid Build Coastguard Worker else
679*5e7646d2SAndroid Build Coastguard Worker have_supplies = start_count = 0;
680*5e7646d2SAndroid Build Coastguard Worker
681*5e7646d2SAndroid Build Coastguard Worker /*
682*5e7646d2SAndroid Build Coastguard Worker * Wait for data from the filter...
683*5e7646d2SAndroid Build Coastguard Worker */
684*5e7646d2SAndroid Build Coastguard Worker
685*5e7646d2SAndroid Build Coastguard Worker if (num_files == 0)
686*5e7646d2SAndroid Build Coastguard Worker {
687*5e7646d2SAndroid Build Coastguard Worker if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB))
688*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
689*5e7646d2SAndroid Build Coastguard Worker else if ((bytes = read(0, buffer, sizeof(buffer))) <= 0)
690*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
691*5e7646d2SAndroid Build Coastguard Worker }
692*5e7646d2SAndroid Build Coastguard Worker
693*5e7646d2SAndroid Build Coastguard Worker /*
694*5e7646d2SAndroid Build Coastguard Worker * Try connecting to the remote server...
695*5e7646d2SAndroid Build Coastguard Worker */
696*5e7646d2SAndroid Build Coastguard Worker
697*5e7646d2SAndroid Build Coastguard Worker delay = _cupsNextDelay(0, &prev_delay);
698*5e7646d2SAndroid Build Coastguard Worker
699*5e7646d2SAndroid Build Coastguard Worker do
700*5e7646d2SAndroid Build Coastguard Worker {
701*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port);
702*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
703*5e7646d2SAndroid Build Coastguard Worker
704*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
705*5e7646d2SAndroid Build Coastguard Worker {
706*5e7646d2SAndroid Build Coastguard Worker int error = errno; /* Connection error */
707*5e7646d2SAndroid Build Coastguard Worker
708*5e7646d2SAndroid Build Coastguard Worker if (http->status == HTTP_STATUS_CUPS_PKI_ERROR)
709*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-certificate-error");
710*5e7646d2SAndroid Build Coastguard Worker
711*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
712*5e7646d2SAndroid Build Coastguard Worker break;
713*5e7646d2SAndroid Build Coastguard Worker
714*5e7646d2SAndroid Build Coastguard Worker if (getenv("CLASS") != NULL)
715*5e7646d2SAndroid Build Coastguard Worker {
716*5e7646d2SAndroid Build Coastguard Worker /*
717*5e7646d2SAndroid Build Coastguard Worker * If the CLASS environment variable is set, the job was submitted
718*5e7646d2SAndroid Build Coastguard Worker * to a class and not to a specific queue. In this case, we want
719*5e7646d2SAndroid Build Coastguard Worker * to abort immediately so that the job can be requeued on the next
720*5e7646d2SAndroid Build Coastguard Worker * available printer in the class.
721*5e7646d2SAndroid Build Coastguard Worker */
722*5e7646d2SAndroid Build Coastguard Worker
723*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO",
724*5e7646d2SAndroid Build Coastguard Worker _("Unable to contact printer, queuing on next "
725*5e7646d2SAndroid Build Coastguard Worker "printer in class."));
726*5e7646d2SAndroid Build Coastguard Worker
727*5e7646d2SAndroid Build Coastguard Worker /*
728*5e7646d2SAndroid Build Coastguard Worker * Sleep 5 seconds to keep the job from requeuing too rapidly...
729*5e7646d2SAndroid Build Coastguard Worker */
730*5e7646d2SAndroid Build Coastguard Worker
731*5e7646d2SAndroid Build Coastguard Worker sleep(5);
732*5e7646d2SAndroid Build Coastguard Worker
733*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "-connecting-to-device");
734*5e7646d2SAndroid Build Coastguard Worker
735*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
736*5e7646d2SAndroid Build Coastguard Worker }
737*5e7646d2SAndroid Build Coastguard Worker
738*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno));
739*5e7646d2SAndroid Build Coastguard Worker
740*5e7646d2SAndroid Build Coastguard Worker if (errno == ECONNREFUSED || errno == EHOSTDOWN || errno == EHOSTUNREACH || errno == ETIMEDOUT || errno == ENOTCONN)
741*5e7646d2SAndroid Build Coastguard Worker {
742*5e7646d2SAndroid Build Coastguard Worker if (contimeout && (time(NULL) - start_time) > contimeout)
743*5e7646d2SAndroid Build Coastguard Worker {
744*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
745*5e7646d2SAndroid Build Coastguard Worker _("The printer is not responding."));
746*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "-connecting-to-device");
747*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
748*5e7646d2SAndroid Build Coastguard Worker }
749*5e7646d2SAndroid Build Coastguard Worker
750*5e7646d2SAndroid Build Coastguard Worker switch (error)
751*5e7646d2SAndroid Build Coastguard Worker {
752*5e7646d2SAndroid Build Coastguard Worker case EHOSTDOWN :
753*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "WARNING",
754*5e7646d2SAndroid Build Coastguard Worker _("The printer may not exist or "
755*5e7646d2SAndroid Build Coastguard Worker "is unavailable at this time."));
756*5e7646d2SAndroid Build Coastguard Worker break;
757*5e7646d2SAndroid Build Coastguard Worker
758*5e7646d2SAndroid Build Coastguard Worker case EHOSTUNREACH :
759*5e7646d2SAndroid Build Coastguard Worker default :
760*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "WARNING",
761*5e7646d2SAndroid Build Coastguard Worker _("The printer is unreachable at this "
762*5e7646d2SAndroid Build Coastguard Worker "time."));
763*5e7646d2SAndroid Build Coastguard Worker break;
764*5e7646d2SAndroid Build Coastguard Worker
765*5e7646d2SAndroid Build Coastguard Worker case ECONNREFUSED :
766*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "WARNING",
767*5e7646d2SAndroid Build Coastguard Worker _("The printer is in use."));
768*5e7646d2SAndroid Build Coastguard Worker break;
769*5e7646d2SAndroid Build Coastguard Worker }
770*5e7646d2SAndroid Build Coastguard Worker
771*5e7646d2SAndroid Build Coastguard Worker sleep((unsigned)delay);
772*5e7646d2SAndroid Build Coastguard Worker
773*5e7646d2SAndroid Build Coastguard Worker delay = _cupsNextDelay(delay, &prev_delay);
774*5e7646d2SAndroid Build Coastguard Worker }
775*5e7646d2SAndroid Build Coastguard Worker else
776*5e7646d2SAndroid Build Coastguard Worker {
777*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
778*5e7646d2SAndroid Build Coastguard Worker _("The printer is not responding."));
779*5e7646d2SAndroid Build Coastguard Worker sleep(30);
780*5e7646d2SAndroid Build Coastguard Worker }
781*5e7646d2SAndroid Build Coastguard Worker
782*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
783*5e7646d2SAndroid Build Coastguard Worker break;
784*5e7646d2SAndroid Build Coastguard Worker }
785*5e7646d2SAndroid Build Coastguard Worker else
786*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "-cups-certificate-error");
787*5e7646d2SAndroid Build Coastguard Worker }
788*5e7646d2SAndroid Build Coastguard Worker while (http->fd < 0);
789*5e7646d2SAndroid Build Coastguard Worker
790*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
791*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
792*5e7646d2SAndroid Build Coastguard Worker else if (!http)
793*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
794*5e7646d2SAndroid Build Coastguard Worker
795*5e7646d2SAndroid Build Coastguard Worker if (httpIsEncrypted(http))
796*5e7646d2SAndroid Build Coastguard Worker {
797*5e7646d2SAndroid Build Coastguard Worker /*
798*5e7646d2SAndroid Build Coastguard Worker * Validate TLS credentials...
799*5e7646d2SAndroid Build Coastguard Worker */
800*5e7646d2SAndroid Build Coastguard Worker
801*5e7646d2SAndroid Build Coastguard Worker cups_array_t *creds; /* TLS credentials */
802*5e7646d2SAndroid Build Coastguard Worker cups_array_t *lcreds = NULL; /* Loaded credentials */
803*5e7646d2SAndroid Build Coastguard Worker http_trust_t trust; /* Trust level */
804*5e7646d2SAndroid Build Coastguard Worker char credinfo[1024], /* Information on credentials */
805*5e7646d2SAndroid Build Coastguard Worker lcredinfo[1024];/* Information on saved credentials */
806*5e7646d2SAndroid Build Coastguard Worker static const char * const trusts[] = { NULL, "+cups-pki-invalid", "+cups-pki-changed", "+cups-pki-expired", NULL, "+cups-pki-unknown" };
807*5e7646d2SAndroid Build Coastguard Worker /* Trust keywords */
808*5e7646d2SAndroid Build Coastguard Worker static const char * const trust_msgs[] =
809*5e7646d2SAndroid Build Coastguard Worker {
810*5e7646d2SAndroid Build Coastguard Worker "Credentials are OK/trusted",
811*5e7646d2SAndroid Build Coastguard Worker "Credentials are invalid",
812*5e7646d2SAndroid Build Coastguard Worker "Credentials have changed",
813*5e7646d2SAndroid Build Coastguard Worker "Credentials are expired",
814*5e7646d2SAndroid Build Coastguard Worker "Credentials have been renewed",
815*5e7646d2SAndroid Build Coastguard Worker "Credentials are unknown/new"
816*5e7646d2SAndroid Build Coastguard Worker };
817*5e7646d2SAndroid Build Coastguard Worker
818*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Connection is encrypted.\n", stderr);
819*5e7646d2SAndroid Build Coastguard Worker
820*5e7646d2SAndroid Build Coastguard Worker if (!httpCopyCredentials(http, &creds))
821*5e7646d2SAndroid Build Coastguard Worker {
822*5e7646d2SAndroid Build Coastguard Worker trust = httpCredentialsGetTrust(creds, hostname);
823*5e7646d2SAndroid Build Coastguard Worker httpCredentialsString(creds, credinfo, sizeof(credinfo));
824*5e7646d2SAndroid Build Coastguard Worker
825*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: %s (%s)\n", trust_msgs[trust], cupsLastErrorString());
826*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Printer credentials: %s\n", credinfo);
827*5e7646d2SAndroid Build Coastguard Worker
828*5e7646d2SAndroid Build Coastguard Worker if (!httpLoadCredentials(NULL, &lcreds, hostname))
829*5e7646d2SAndroid Build Coastguard Worker {
830*5e7646d2SAndroid Build Coastguard Worker httpCredentialsString(lcreds, lcredinfo, sizeof(lcredinfo));
831*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Stored credentials: %s\n", lcredinfo);
832*5e7646d2SAndroid Build Coastguard Worker }
833*5e7646d2SAndroid Build Coastguard Worker else
834*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: No stored credentials.\n", stderr);
835*5e7646d2SAndroid Build Coastguard Worker
836*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "-cups-pki-invalid,cups-pki-changed,cups-pki-expired,cups-pki-unknown");
837*5e7646d2SAndroid Build Coastguard Worker if (trusts[trust])
838*5e7646d2SAndroid Build Coastguard Worker {
839*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, trusts[trust]);
840*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_STOP);
841*5e7646d2SAndroid Build Coastguard Worker }
842*5e7646d2SAndroid Build Coastguard Worker
843*5e7646d2SAndroid Build Coastguard Worker if (!lcreds)
844*5e7646d2SAndroid Build Coastguard Worker {
845*5e7646d2SAndroid Build Coastguard Worker /*
846*5e7646d2SAndroid Build Coastguard Worker * Could not load the credentials, let's save the ones we have so we
847*5e7646d2SAndroid Build Coastguard Worker * can detect changes...
848*5e7646d2SAndroid Build Coastguard Worker */
849*5e7646d2SAndroid Build Coastguard Worker
850*5e7646d2SAndroid Build Coastguard Worker httpSaveCredentials(NULL, creds, hostname);
851*5e7646d2SAndroid Build Coastguard Worker }
852*5e7646d2SAndroid Build Coastguard Worker
853*5e7646d2SAndroid Build Coastguard Worker httpFreeCredentials(lcreds);
854*5e7646d2SAndroid Build Coastguard Worker httpFreeCredentials(creds);
855*5e7646d2SAndroid Build Coastguard Worker }
856*5e7646d2SAndroid Build Coastguard Worker else
857*5e7646d2SAndroid Build Coastguard Worker {
858*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: No printer credentials.\n", stderr);
859*5e7646d2SAndroid Build Coastguard Worker
860*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "cups-pki-unknown");
861*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_STOP);
862*5e7646d2SAndroid Build Coastguard Worker }
863*5e7646d2SAndroid Build Coastguard Worker }
864*5e7646d2SAndroid Build Coastguard Worker
865*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "-connecting-to-device");
866*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));
867*5e7646d2SAndroid Build Coastguard Worker
868*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Connected to %s:%d...\n",
869*5e7646d2SAndroid Build Coastguard Worker httpAddrString(http->hostaddr, addrname, sizeof(addrname)),
870*5e7646d2SAndroid Build Coastguard Worker httpAddrPort(http->hostaddr));
871*5e7646d2SAndroid Build Coastguard Worker
872*5e7646d2SAndroid Build Coastguard Worker /*
873*5e7646d2SAndroid Build Coastguard Worker * Build a URI for the printer and fill the standard IPP attributes for
874*5e7646d2SAndroid Build Coastguard Worker * an IPP_PRINT_FILE request. We can't use the URI in argv[0] because it
875*5e7646d2SAndroid Build Coastguard Worker * might contain username:password information...
876*5e7646d2SAndroid Build Coastguard Worker */
877*5e7646d2SAndroid Build Coastguard Worker
878*5e7646d2SAndroid Build Coastguard Worker httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), scheme, NULL, hostname,
879*5e7646d2SAndroid Build Coastguard Worker port, resource);
880*5e7646d2SAndroid Build Coastguard Worker
881*5e7646d2SAndroid Build Coastguard Worker /*
882*5e7646d2SAndroid Build Coastguard Worker * First validate the destination and see if the device supports multiple
883*5e7646d2SAndroid Build Coastguard Worker * copies...
884*5e7646d2SAndroid Build Coastguard Worker */
885*5e7646d2SAndroid Build Coastguard Worker
886*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
887*5e7646d2SAndroid Build Coastguard Worker compression_sup = NULL;
888*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
889*5e7646d2SAndroid Build Coastguard Worker copies_sup = NULL;
890*5e7646d2SAndroid Build Coastguard Worker cups_version = NULL;
891*5e7646d2SAndroid Build Coastguard Worker encryption_sup = NULL;
892*5e7646d2SAndroid Build Coastguard Worker format_sup = NULL;
893*5e7646d2SAndroid Build Coastguard Worker media_col_sup = NULL;
894*5e7646d2SAndroid Build Coastguard Worker supported = NULL;
895*5e7646d2SAndroid Build Coastguard Worker operations_sup = NULL;
896*5e7646d2SAndroid Build Coastguard Worker doc_handling_sup = NULL;
897*5e7646d2SAndroid Build Coastguard Worker print_color_mode_sup = NULL;
898*5e7646d2SAndroid Build Coastguard Worker
899*5e7646d2SAndroid Build Coastguard Worker do
900*5e7646d2SAndroid Build Coastguard Worker {
901*5e7646d2SAndroid Build Coastguard Worker /*
902*5e7646d2SAndroid Build Coastguard Worker * Check for side-channel requests...
903*5e7646d2SAndroid Build Coastguard Worker */
904*5e7646d2SAndroid Build Coastguard Worker
905*5e7646d2SAndroid Build Coastguard Worker backendCheckSideChannel(snmp_fd, http->hostaddr);
906*5e7646d2SAndroid Build Coastguard Worker
907*5e7646d2SAndroid Build Coastguard Worker /*
908*5e7646d2SAndroid Build Coastguard Worker * Build the IPP request...
909*5e7646d2SAndroid Build Coastguard Worker */
910*5e7646d2SAndroid Build Coastguard Worker
911*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
912*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, version / 10, version % 10);
913*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
914*5e7646d2SAndroid Build Coastguard Worker NULL, uri);
915*5e7646d2SAndroid Build Coastguard Worker
916*5e7646d2SAndroid Build Coastguard Worker ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
917*5e7646d2SAndroid Build Coastguard Worker "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
918*5e7646d2SAndroid Build Coastguard Worker NULL, pattrs);
919*5e7646d2SAndroid Build Coastguard Worker
920*5e7646d2SAndroid Build Coastguard Worker /*
921*5e7646d2SAndroid Build Coastguard Worker * Do the request...
922*5e7646d2SAndroid Build Coastguard Worker */
923*5e7646d2SAndroid Build Coastguard Worker
924*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Getting supported attributes...\n", stderr);
925*5e7646d2SAndroid Build Coastguard Worker
926*5e7646d2SAndroid Build Coastguard Worker if (http->version < HTTP_VERSION_1_1)
927*5e7646d2SAndroid Build Coastguard Worker {
928*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Printer responded with HTTP version %d.%d.\n",
929*5e7646d2SAndroid Build Coastguard Worker http->version / 100, http->version % 100);
930*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
931*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-wrong-http-version");
932*5e7646d2SAndroid Build Coastguard Worker }
933*5e7646d2SAndroid Build Coastguard Worker
934*5e7646d2SAndroid Build Coastguard Worker supported = cupsDoRequest(http, request, resource);
935*5e7646d2SAndroid Build Coastguard Worker ipp_status = cupsLastError();
936*5e7646d2SAndroid Build Coastguard Worker
937*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
938*5e7646d2SAndroid Build Coastguard Worker ippErrorString(ipp_status), cupsLastErrorString());
939*5e7646d2SAndroid Build Coastguard Worker
940*5e7646d2SAndroid Build Coastguard Worker if (ipp_status <= IPP_STATUS_OK_CONFLICTING)
941*5e7646d2SAndroid Build Coastguard Worker password_tries = 0;
942*5e7646d2SAndroid Build Coastguard Worker else
943*5e7646d2SAndroid Build Coastguard Worker {
944*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Get-Printer-Attributes returned %s.\n",
945*5e7646d2SAndroid Build Coastguard Worker ippErrorString(ipp_status));
946*5e7646d2SAndroid Build Coastguard Worker
947*5e7646d2SAndroid Build Coastguard Worker if (ipp_status == IPP_STATUS_ERROR_BUSY ||
948*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE)
949*5e7646d2SAndroid Build Coastguard Worker {
950*5e7646d2SAndroid Build Coastguard Worker if (contimeout && (time(NULL) - start_time) > contimeout)
951*5e7646d2SAndroid Build Coastguard Worker {
952*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
953*5e7646d2SAndroid Build Coastguard Worker _("The printer is not responding."));
954*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
955*5e7646d2SAndroid Build Coastguard Worker }
956*5e7646d2SAndroid Build Coastguard Worker
957*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
958*5e7646d2SAndroid Build Coastguard Worker
959*5e7646d2SAndroid Build Coastguard Worker report_printer_state(supported);
960*5e7646d2SAndroid Build Coastguard Worker
961*5e7646d2SAndroid Build Coastguard Worker sleep((unsigned)delay);
962*5e7646d2SAndroid Build Coastguard Worker
963*5e7646d2SAndroid Build Coastguard Worker delay = _cupsNextDelay(delay, &prev_delay);
964*5e7646d2SAndroid Build Coastguard Worker }
965*5e7646d2SAndroid Build Coastguard Worker else if ((ipp_status == IPP_STATUS_ERROR_BAD_REQUEST ||
966*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) && version > 10)
967*5e7646d2SAndroid Build Coastguard Worker {
968*5e7646d2SAndroid Build Coastguard Worker /*
969*5e7646d2SAndroid Build Coastguard Worker * Switch to IPP/1.1 or IPP/1.0...
970*5e7646d2SAndroid Build Coastguard Worker */
971*5e7646d2SAndroid Build Coastguard Worker
972*5e7646d2SAndroid Build Coastguard Worker if (version >= 20)
973*5e7646d2SAndroid Build Coastguard Worker {
974*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Preparing to print."));
975*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr,
976*5e7646d2SAndroid Build Coastguard Worker "DEBUG: The printer does not support IPP/%d.%d, trying "
977*5e7646d2SAndroid Build Coastguard Worker "IPP/1.1.\n", version / 10, version % 10);
978*5e7646d2SAndroid Build Coastguard Worker version = 11;
979*5e7646d2SAndroid Build Coastguard Worker }
980*5e7646d2SAndroid Build Coastguard Worker else
981*5e7646d2SAndroid Build Coastguard Worker {
982*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Preparing to print."));
983*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr,
984*5e7646d2SAndroid Build Coastguard Worker "DEBUG: The printer does not support IPP/%d.%d, trying "
985*5e7646d2SAndroid Build Coastguard Worker "IPP/1.0.\n", version / 10, version % 10);
986*5e7646d2SAndroid Build Coastguard Worker version = 10;
987*5e7646d2SAndroid Build Coastguard Worker }
988*5e7646d2SAndroid Build Coastguard Worker
989*5e7646d2SAndroid Build Coastguard Worker httpReconnect2(http, 30000, NULL);
990*5e7646d2SAndroid Build Coastguard Worker }
991*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND)
992*5e7646d2SAndroid Build Coastguard Worker {
993*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
994*5e7646d2SAndroid Build Coastguard Worker _("The printer configuration is incorrect or the "
995*5e7646d2SAndroid Build Coastguard Worker "printer no longer exists."));
996*5e7646d2SAndroid Build Coastguard Worker
997*5e7646d2SAndroid Build Coastguard Worker ippDelete(supported);
998*5e7646d2SAndroid Build Coastguard Worker
999*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_STOP);
1000*5e7646d2SAndroid Build Coastguard Worker }
1001*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
1002*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
1003*5e7646d2SAndroid Build Coastguard Worker {
1004*5e7646d2SAndroid Build Coastguard Worker const char *www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
1005*5e7646d2SAndroid Build Coastguard Worker /* WWW-Authenticate field value */
1006*5e7646d2SAndroid Build Coastguard Worker
1007*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(www_auth, "Negotiate", 9))
1008*5e7646d2SAndroid Build Coastguard Worker auth_info_required = "negotiate";
1009*5e7646d2SAndroid Build Coastguard Worker else if (www_auth[0])
1010*5e7646d2SAndroid Build Coastguard Worker auth_info_required = "username,password";
1011*5e7646d2SAndroid Build Coastguard Worker
1012*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
1013*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_AUTH_REQUIRED);
1014*5e7646d2SAndroid Build Coastguard Worker }
1015*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status != IPP_STATUS_ERROR_NOT_AUTHORIZED)
1016*5e7646d2SAndroid Build Coastguard Worker {
1017*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
1018*5e7646d2SAndroid Build Coastguard Worker _("Unable to get printer status."));
1019*5e7646d2SAndroid Build Coastguard Worker sleep(10);
1020*5e7646d2SAndroid Build Coastguard Worker
1021*5e7646d2SAndroid Build Coastguard Worker httpReconnect2(http, 30000, NULL);
1022*5e7646d2SAndroid Build Coastguard Worker }
1023*5e7646d2SAndroid Build Coastguard Worker
1024*5e7646d2SAndroid Build Coastguard Worker ippDelete(supported);
1025*5e7646d2SAndroid Build Coastguard Worker supported = NULL;
1026*5e7646d2SAndroid Build Coastguard Worker continue;
1027*5e7646d2SAndroid Build Coastguard Worker }
1028*5e7646d2SAndroid Build Coastguard Worker
1029*5e7646d2SAndroid Build Coastguard Worker if (!getenv("CLASS"))
1030*5e7646d2SAndroid Build Coastguard Worker {
1031*5e7646d2SAndroid Build Coastguard Worker /*
1032*5e7646d2SAndroid Build Coastguard Worker * Check printer-is-accepting-jobs = false and printer-state-reasons for the
1033*5e7646d2SAndroid Build Coastguard Worker * "spool-area-full" keyword...
1034*5e7646d2SAndroid Build Coastguard Worker */
1035*5e7646d2SAndroid Build Coastguard Worker
1036*5e7646d2SAndroid Build Coastguard Worker int busy = 0;
1037*5e7646d2SAndroid Build Coastguard Worker
1038*5e7646d2SAndroid Build Coastguard Worker if ((printer_accepting = ippFindAttribute(supported,
1039*5e7646d2SAndroid Build Coastguard Worker "printer-is-accepting-jobs",
1040*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN)) != NULL &&
1041*5e7646d2SAndroid Build Coastguard Worker !printer_accepting->values[0].boolean)
1042*5e7646d2SAndroid Build Coastguard Worker busy = 1;
1043*5e7646d2SAndroid Build Coastguard Worker else if (!printer_accepting)
1044*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1045*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-printer-is-accepting-jobs");
1046*5e7646d2SAndroid Build Coastguard Worker
1047*5e7646d2SAndroid Build Coastguard Worker if ((printer_state = ippFindAttribute(supported,
1048*5e7646d2SAndroid Build Coastguard Worker "printer-state-reasons",
1049*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) == NULL)
1050*5e7646d2SAndroid Build Coastguard Worker {
1051*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1052*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-printer-state-reasons");
1053*5e7646d2SAndroid Build Coastguard Worker }
1054*5e7646d2SAndroid Build Coastguard Worker else if (!busy)
1055*5e7646d2SAndroid Build Coastguard Worker {
1056*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < printer_state->num_values; i ++)
1057*5e7646d2SAndroid Build Coastguard Worker {
1058*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(printer_state->values[0].string.text,
1059*5e7646d2SAndroid Build Coastguard Worker "spool-area-full") ||
1060*5e7646d2SAndroid Build Coastguard Worker !strncmp(printer_state->values[0].string.text, "spool-area-full-",
1061*5e7646d2SAndroid Build Coastguard Worker 16))
1062*5e7646d2SAndroid Build Coastguard Worker {
1063*5e7646d2SAndroid Build Coastguard Worker busy = 1;
1064*5e7646d2SAndroid Build Coastguard Worker break;
1065*5e7646d2SAndroid Build Coastguard Worker }
1066*5e7646d2SAndroid Build Coastguard Worker }
1067*5e7646d2SAndroid Build Coastguard Worker }
1068*5e7646d2SAndroid Build Coastguard Worker
1069*5e7646d2SAndroid Build Coastguard Worker if (busy)
1070*5e7646d2SAndroid Build Coastguard Worker {
1071*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
1072*5e7646d2SAndroid Build Coastguard Worker
1073*5e7646d2SAndroid Build Coastguard Worker report_printer_state(supported);
1074*5e7646d2SAndroid Build Coastguard Worker
1075*5e7646d2SAndroid Build Coastguard Worker sleep((unsigned)delay);
1076*5e7646d2SAndroid Build Coastguard Worker
1077*5e7646d2SAndroid Build Coastguard Worker delay = _cupsNextDelay(delay, &prev_delay);
1078*5e7646d2SAndroid Build Coastguard Worker
1079*5e7646d2SAndroid Build Coastguard Worker ippDelete(supported);
1080*5e7646d2SAndroid Build Coastguard Worker supported = NULL;
1081*5e7646d2SAndroid Build Coastguard Worker ipp_status = IPP_STATUS_ERROR_BUSY;
1082*5e7646d2SAndroid Build Coastguard Worker continue;
1083*5e7646d2SAndroid Build Coastguard Worker }
1084*5e7646d2SAndroid Build Coastguard Worker }
1085*5e7646d2SAndroid Build Coastguard Worker
1086*5e7646d2SAndroid Build Coastguard Worker /*
1087*5e7646d2SAndroid Build Coastguard Worker * Check for supported attributes...
1088*5e7646d2SAndroid Build Coastguard Worker */
1089*5e7646d2SAndroid Build Coastguard Worker
1090*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
1091*5e7646d2SAndroid Build Coastguard Worker if ((compression_sup = ippFindAttribute(supported, "compression-supported",
1092*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
1093*5e7646d2SAndroid Build Coastguard Worker {
1094*5e7646d2SAndroid Build Coastguard Worker /*
1095*5e7646d2SAndroid Build Coastguard Worker * Check whether the requested compression is supported and/or default to
1096*5e7646d2SAndroid Build Coastguard Worker * compression if supported...
1097*5e7646d2SAndroid Build Coastguard Worker */
1098*5e7646d2SAndroid Build Coastguard Worker
1099*5e7646d2SAndroid Build Coastguard Worker if (compression && !ippContainsString(compression_sup, compression))
1100*5e7646d2SAndroid Build Coastguard Worker {
1101*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Printer does not support the requested "
1102*5e7646d2SAndroid Build Coastguard Worker "compression value \"%s\".\n", compression);
1103*5e7646d2SAndroid Build Coastguard Worker compression = NULL;
1104*5e7646d2SAndroid Build Coastguard Worker }
1105*5e7646d2SAndroid Build Coastguard Worker else if (!compression && (!strcmp(final_content_type, "image/pwg-raster") || !strcmp(final_content_type, "image/urf")))
1106*5e7646d2SAndroid Build Coastguard Worker {
1107*5e7646d2SAndroid Build Coastguard Worker if (ippContainsString(compression_sup, "gzip"))
1108*5e7646d2SAndroid Build Coastguard Worker compression = "gzip";
1109*5e7646d2SAndroid Build Coastguard Worker else if (ippContainsString(compression_sup, "deflate"))
1110*5e7646d2SAndroid Build Coastguard Worker compression = "deflate";
1111*5e7646d2SAndroid Build Coastguard Worker
1112*5e7646d2SAndroid Build Coastguard Worker if (compression)
1113*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Automatically using \"%s\" compression.\n",
1114*5e7646d2SAndroid Build Coastguard Worker compression);
1115*5e7646d2SAndroid Build Coastguard Worker }
1116*5e7646d2SAndroid Build Coastguard Worker }
1117*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
1118*5e7646d2SAndroid Build Coastguard Worker
1119*5e7646d2SAndroid Build Coastguard Worker if ((copies_sup = ippFindAttribute(supported, "copies-supported",
1120*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_RANGE)) != NULL)
1121*5e7646d2SAndroid Build Coastguard Worker {
1122*5e7646d2SAndroid Build Coastguard Worker /*
1123*5e7646d2SAndroid Build Coastguard Worker * Has the "copies-supported" attribute - does it have an upper
1124*5e7646d2SAndroid Build Coastguard Worker * bound > 1?
1125*5e7646d2SAndroid Build Coastguard Worker */
1126*5e7646d2SAndroid Build Coastguard Worker
1127*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: copies-supported=%d-%d\n",
1128*5e7646d2SAndroid Build Coastguard Worker copies_sup->values[0].range.lower,
1129*5e7646d2SAndroid Build Coastguard Worker copies_sup->values[0].range.upper);
1130*5e7646d2SAndroid Build Coastguard Worker
1131*5e7646d2SAndroid Build Coastguard Worker if (copies_sup->values[0].range.upper <= 1)
1132*5e7646d2SAndroid Build Coastguard Worker copies_sup = NULL; /* No */
1133*5e7646d2SAndroid Build Coastguard Worker }
1134*5e7646d2SAndroid Build Coastguard Worker
1135*5e7646d2SAndroid Build Coastguard Worker if ((cups_version = ippFindAttribute(supported, "cups-version", IPP_TAG_TEXT)) != NULL)
1136*5e7646d2SAndroid Build Coastguard Worker {
1137*5e7646d2SAndroid Build Coastguard Worker const char *val = ippGetString(cups_version, 0, NULL);
1138*5e7646d2SAndroid Build Coastguard Worker
1139*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: cups-version = \"%s\"\n", val);
1140*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(val, "cups-version"))
1141*5e7646d2SAndroid Build Coastguard Worker cups_version = NULL; /* Bogus cups-version value returned by buggy printers! */
1142*5e7646d2SAndroid Build Coastguard Worker }
1143*5e7646d2SAndroid Build Coastguard Worker
1144*5e7646d2SAndroid Build Coastguard Worker encryption_sup = ippFindAttribute(supported, "job-password-encryption-supported", IPP_TAG_KEYWORD);
1145*5e7646d2SAndroid Build Coastguard Worker
1146*5e7646d2SAndroid Build Coastguard Worker if ((format_sup = ippFindAttribute(supported, "document-format-supported",
1147*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_MIMETYPE)) != NULL)
1148*5e7646d2SAndroid Build Coastguard Worker {
1149*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: document-format-supported (%d values)\n",
1150*5e7646d2SAndroid Build Coastguard Worker format_sup->num_values);
1151*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < format_sup->num_values; i ++)
1152*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
1153*5e7646d2SAndroid Build Coastguard Worker format_sup->values[i].string.text);
1154*5e7646d2SAndroid Build Coastguard Worker }
1155*5e7646d2SAndroid Build Coastguard Worker
1156*5e7646d2SAndroid Build Coastguard Worker if ((media_col_sup = ippFindAttribute(supported, "media-col-supported",
1157*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
1158*5e7646d2SAndroid Build Coastguard Worker {
1159*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: media-col-supported (%d values)\n",
1160*5e7646d2SAndroid Build Coastguard Worker media_col_sup->num_values);
1161*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < media_col_sup->num_values; i ++)
1162*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: [%d] = \"%s\"\n", i,
1163*5e7646d2SAndroid Build Coastguard Worker media_col_sup->values[i].string.text);
1164*5e7646d2SAndroid Build Coastguard Worker }
1165*5e7646d2SAndroid Build Coastguard Worker
1166*5e7646d2SAndroid Build Coastguard Worker print_color_mode_sup = ippFindAttribute(supported, "print-color-mode-supported", IPP_TAG_KEYWORD);
1167*5e7646d2SAndroid Build Coastguard Worker
1168*5e7646d2SAndroid Build Coastguard Worker if ((operations_sup = ippFindAttribute(supported, "operations-supported",
1169*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM)) != NULL)
1170*5e7646d2SAndroid Build Coastguard Worker {
1171*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: operations-supported (%d values)\n",
1172*5e7646d2SAndroid Build Coastguard Worker operations_sup->num_values);
1173*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < operations_sup->num_values; i ++)
1174*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: [%d] = %s\n", i,
1175*5e7646d2SAndroid Build Coastguard Worker ippOpString(operations_sup->values[i].integer));
1176*5e7646d2SAndroid Build Coastguard Worker
1177*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < operations_sup->num_values; i ++)
1178*5e7646d2SAndroid Build Coastguard Worker if (operations_sup->values[i].integer == IPP_OP_PRINT_JOB)
1179*5e7646d2SAndroid Build Coastguard Worker break;
1180*5e7646d2SAndroid Build Coastguard Worker
1181*5e7646d2SAndroid Build Coastguard Worker if (i >= operations_sup->num_values)
1182*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1183*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-print-job");
1184*5e7646d2SAndroid Build Coastguard Worker
1185*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < operations_sup->num_values; i ++)
1186*5e7646d2SAndroid Build Coastguard Worker if (operations_sup->values[i].integer == IPP_OP_CANCEL_JOB)
1187*5e7646d2SAndroid Build Coastguard Worker break;
1188*5e7646d2SAndroid Build Coastguard Worker
1189*5e7646d2SAndroid Build Coastguard Worker if (i >= operations_sup->num_values)
1190*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1191*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-cancel-job");
1192*5e7646d2SAndroid Build Coastguard Worker
1193*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < operations_sup->num_values; i ++)
1194*5e7646d2SAndroid Build Coastguard Worker if (operations_sup->values[i].integer == IPP_OP_GET_JOB_ATTRIBUTES)
1195*5e7646d2SAndroid Build Coastguard Worker break;
1196*5e7646d2SAndroid Build Coastguard Worker
1197*5e7646d2SAndroid Build Coastguard Worker if (i >= operations_sup->num_values)
1198*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1199*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-get-job-attributes");
1200*5e7646d2SAndroid Build Coastguard Worker
1201*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < operations_sup->num_values; i ++)
1202*5e7646d2SAndroid Build Coastguard Worker if (operations_sup->values[i].integer == IPP_OP_GET_PRINTER_ATTRIBUTES)
1203*5e7646d2SAndroid Build Coastguard Worker break;
1204*5e7646d2SAndroid Build Coastguard Worker
1205*5e7646d2SAndroid Build Coastguard Worker if (i >= operations_sup->num_values)
1206*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1207*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-get-printer-attributes");
1208*5e7646d2SAndroid Build Coastguard Worker
1209*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < operations_sup->num_values; i ++)
1210*5e7646d2SAndroid Build Coastguard Worker {
1211*5e7646d2SAndroid Build Coastguard Worker if (operations_sup->values[i].integer == IPP_OP_VALIDATE_JOB)
1212*5e7646d2SAndroid Build Coastguard Worker validate_job = 1;
1213*5e7646d2SAndroid Build Coastguard Worker else if (operations_sup->values[i].integer == IPP_OP_CREATE_JOB)
1214*5e7646d2SAndroid Build Coastguard Worker create_job = 1;
1215*5e7646d2SAndroid Build Coastguard Worker else if (operations_sup->values[i].integer == IPP_OP_SEND_DOCUMENT)
1216*5e7646d2SAndroid Build Coastguard Worker send_document = 1;
1217*5e7646d2SAndroid Build Coastguard Worker else if (operations_sup->values[i].integer == IPP_OP_GET_JOB_ATTRIBUTES)
1218*5e7646d2SAndroid Build Coastguard Worker get_job_attrs = 1;
1219*5e7646d2SAndroid Build Coastguard Worker }
1220*5e7646d2SAndroid Build Coastguard Worker
1221*5e7646d2SAndroid Build Coastguard Worker if (create_job && !send_document)
1222*5e7646d2SAndroid Build Coastguard Worker {
1223*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Printer supports Create-Job but not Send-Document.\n",
1224*5e7646d2SAndroid Build Coastguard Worker stderr);
1225*5e7646d2SAndroid Build Coastguard Worker create_job = 0;
1226*5e7646d2SAndroid Build Coastguard Worker
1227*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1228*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-send-document");
1229*5e7646d2SAndroid Build Coastguard Worker }
1230*5e7646d2SAndroid Build Coastguard Worker
1231*5e7646d2SAndroid Build Coastguard Worker if (!validate_job)
1232*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1233*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-validate-job");
1234*5e7646d2SAndroid Build Coastguard Worker }
1235*5e7646d2SAndroid Build Coastguard Worker else
1236*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1237*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-operations-supported");
1238*5e7646d2SAndroid Build Coastguard Worker
1239*5e7646d2SAndroid Build Coastguard Worker doc_handling_sup = ippFindAttribute(supported,
1240*5e7646d2SAndroid Build Coastguard Worker "multiple-document-handling-supported",
1241*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD);
1242*5e7646d2SAndroid Build Coastguard Worker
1243*5e7646d2SAndroid Build Coastguard Worker report_printer_state(supported);
1244*5e7646d2SAndroid Build Coastguard Worker }
1245*5e7646d2SAndroid Build Coastguard Worker while (!job_canceled && ipp_status > IPP_STATUS_OK_CONFLICTING);
1246*5e7646d2SAndroid Build Coastguard Worker
1247*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
1248*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
1249*5e7646d2SAndroid Build Coastguard Worker
1250*5e7646d2SAndroid Build Coastguard Worker /*
1251*5e7646d2SAndroid Build Coastguard Worker * See if the printer is accepting jobs and is not stopped; if either
1252*5e7646d2SAndroid Build Coastguard Worker * condition is true and we are printing to a class, requeue the job...
1253*5e7646d2SAndroid Build Coastguard Worker */
1254*5e7646d2SAndroid Build Coastguard Worker
1255*5e7646d2SAndroid Build Coastguard Worker if (getenv("CLASS") != NULL)
1256*5e7646d2SAndroid Build Coastguard Worker {
1257*5e7646d2SAndroid Build Coastguard Worker printer_state = ippFindAttribute(supported, "printer-state",
1258*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM);
1259*5e7646d2SAndroid Build Coastguard Worker printer_accepting = ippFindAttribute(supported, "printer-is-accepting-jobs",
1260*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_BOOLEAN);
1261*5e7646d2SAndroid Build Coastguard Worker
1262*5e7646d2SAndroid Build Coastguard Worker if (printer_state == NULL ||
1263*5e7646d2SAndroid Build Coastguard Worker (printer_state->values[0].integer > IPP_PSTATE_PROCESSING &&
1264*5e7646d2SAndroid Build Coastguard Worker waitprinter) ||
1265*5e7646d2SAndroid Build Coastguard Worker printer_accepting == NULL ||
1266*5e7646d2SAndroid Build Coastguard Worker !printer_accepting->values[0].boolean)
1267*5e7646d2SAndroid Build Coastguard Worker {
1268*5e7646d2SAndroid Build Coastguard Worker /*
1269*5e7646d2SAndroid Build Coastguard Worker * If the CLASS environment variable is set, the job was submitted
1270*5e7646d2SAndroid Build Coastguard Worker * to a class and not to a specific queue. In this case, we want
1271*5e7646d2SAndroid Build Coastguard Worker * to abort immediately so that the job can be requeued on the next
1272*5e7646d2SAndroid Build Coastguard Worker * available printer in the class.
1273*5e7646d2SAndroid Build Coastguard Worker */
1274*5e7646d2SAndroid Build Coastguard Worker
1275*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO",
1276*5e7646d2SAndroid Build Coastguard Worker _("Unable to contact printer, queuing on next "
1277*5e7646d2SAndroid Build Coastguard Worker "printer in class."));
1278*5e7646d2SAndroid Build Coastguard Worker
1279*5e7646d2SAndroid Build Coastguard Worker ippDelete(supported);
1280*5e7646d2SAndroid Build Coastguard Worker httpClose(http);
1281*5e7646d2SAndroid Build Coastguard Worker
1282*5e7646d2SAndroid Build Coastguard Worker /*
1283*5e7646d2SAndroid Build Coastguard Worker * Sleep 5 seconds to keep the job from requeuing too rapidly...
1284*5e7646d2SAndroid Build Coastguard Worker */
1285*5e7646d2SAndroid Build Coastguard Worker
1286*5e7646d2SAndroid Build Coastguard Worker sleep(5);
1287*5e7646d2SAndroid Build Coastguard Worker
1288*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
1289*5e7646d2SAndroid Build Coastguard Worker }
1290*5e7646d2SAndroid Build Coastguard Worker }
1291*5e7646d2SAndroid Build Coastguard Worker
1292*5e7646d2SAndroid Build Coastguard Worker /*
1293*5e7646d2SAndroid Build Coastguard Worker * See if the printer supports multiple copies...
1294*5e7646d2SAndroid Build Coastguard Worker */
1295*5e7646d2SAndroid Build Coastguard Worker
1296*5e7646d2SAndroid Build Coastguard Worker copies = atoi(argv[4]);
1297*5e7646d2SAndroid Build Coastguard Worker
1298*5e7646d2SAndroid Build Coastguard Worker if (copies_sup || argc < 7)
1299*5e7646d2SAndroid Build Coastguard Worker copies_remaining = 1;
1300*5e7646d2SAndroid Build Coastguard Worker else
1301*5e7646d2SAndroid Build Coastguard Worker copies_remaining = copies;
1302*5e7646d2SAndroid Build Coastguard Worker
1303*5e7646d2SAndroid Build Coastguard Worker /*
1304*5e7646d2SAndroid Build Coastguard Worker * Prepare remaining printing options...
1305*5e7646d2SAndroid Build Coastguard Worker */
1306*5e7646d2SAndroid Build Coastguard Worker
1307*5e7646d2SAndroid Build Coastguard Worker options = NULL;
1308*5e7646d2SAndroid Build Coastguard Worker
1309*5e7646d2SAndroid Build Coastguard Worker if (send_options)
1310*5e7646d2SAndroid Build Coastguard Worker {
1311*5e7646d2SAndroid Build Coastguard Worker num_options = cupsParseOptions(argv[5], 0, &options);
1312*5e7646d2SAndroid Build Coastguard Worker
1313*5e7646d2SAndroid Build Coastguard Worker if (!cups_version && media_col_sup)
1314*5e7646d2SAndroid Build Coastguard Worker {
1315*5e7646d2SAndroid Build Coastguard Worker /*
1316*5e7646d2SAndroid Build Coastguard Worker * Load the PPD file and generate PWG attribute mapping information...
1317*5e7646d2SAndroid Build Coastguard Worker */
1318*5e7646d2SAndroid Build Coastguard Worker
1319*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *mandatory; /* cupsMandatory value */
1320*5e7646d2SAndroid Build Coastguard Worker
1321*5e7646d2SAndroid Build Coastguard Worker ppd = ppdOpenFile(getenv("PPD"));
1322*5e7646d2SAndroid Build Coastguard Worker pc = _ppdCacheCreateWithPPD(ppd);
1323*5e7646d2SAndroid Build Coastguard Worker
1324*5e7646d2SAndroid Build Coastguard Worker ppdMarkDefaults(ppd);
1325*5e7646d2SAndroid Build Coastguard Worker cupsMarkOptions(ppd, num_options, options);
1326*5e7646d2SAndroid Build Coastguard Worker
1327*5e7646d2SAndroid Build Coastguard Worker if ((mandatory = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL)
1328*5e7646d2SAndroid Build Coastguard Worker strlcpy(mandatory_attrs, mandatory->value, sizeof(mandatory_attrs));
1329*5e7646d2SAndroid Build Coastguard Worker }
1330*5e7646d2SAndroid Build Coastguard Worker
1331*5e7646d2SAndroid Build Coastguard Worker /*
1332*5e7646d2SAndroid Build Coastguard Worker * Validate job-password/-encryption...
1333*5e7646d2SAndroid Build Coastguard Worker */
1334*5e7646d2SAndroid Build Coastguard Worker
1335*5e7646d2SAndroid Build Coastguard Worker if (cupsGetOption("job-password", num_options, options))
1336*5e7646d2SAndroid Build Coastguard Worker {
1337*5e7646d2SAndroid Build Coastguard Worker const char *keyword; /* job-password-encryption value */
1338*5e7646d2SAndroid Build Coastguard Worker static const char * const hashes[] =
1339*5e7646d2SAndroid Build Coastguard Worker { /* List of supported hash algorithms, in order of preference */
1340*5e7646d2SAndroid Build Coastguard Worker "sha-512",
1341*5e7646d2SAndroid Build Coastguard Worker "sha-384",
1342*5e7646d2SAndroid Build Coastguard Worker "sha-512_256",
1343*5e7646d2SAndroid Build Coastguard Worker "sha-512-224",
1344*5e7646d2SAndroid Build Coastguard Worker "sha-256",
1345*5e7646d2SAndroid Build Coastguard Worker "sha-224",
1346*5e7646d2SAndroid Build Coastguard Worker "sha",
1347*5e7646d2SAndroid Build Coastguard Worker "none"
1348*5e7646d2SAndroid Build Coastguard Worker };
1349*5e7646d2SAndroid Build Coastguard Worker
1350*5e7646d2SAndroid Build Coastguard Worker if ((keyword = cupsGetOption("job-password-encryption", num_options, options)) == NULL || !ippContainsString(encryption_sup, keyword))
1351*5e7646d2SAndroid Build Coastguard Worker {
1352*5e7646d2SAndroid Build Coastguard Worker /*
1353*5e7646d2SAndroid Build Coastguard Worker * Either no job-password-encryption or the value isn't supported by
1354*5e7646d2SAndroid Build Coastguard Worker * the printer...
1355*5e7646d2SAndroid Build Coastguard Worker */
1356*5e7646d2SAndroid Build Coastguard Worker
1357*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < (int)(sizeof(hashes) / sizeof(hashes[0])); i ++)
1358*5e7646d2SAndroid Build Coastguard Worker if (ippContainsString(encryption_sup, hashes[i]))
1359*5e7646d2SAndroid Build Coastguard Worker break;
1360*5e7646d2SAndroid Build Coastguard Worker
1361*5e7646d2SAndroid Build Coastguard Worker if (i < (int)(sizeof(hashes) / sizeof(hashes[0])))
1362*5e7646d2SAndroid Build Coastguard Worker num_options = cupsAddOption("job-password-encryption", hashes[i], num_options, &options);
1363*5e7646d2SAndroid Build Coastguard Worker }
1364*5e7646d2SAndroid Build Coastguard Worker }
1365*5e7646d2SAndroid Build Coastguard Worker }
1366*5e7646d2SAndroid Build Coastguard Worker else
1367*5e7646d2SAndroid Build Coastguard Worker num_options = 0;
1368*5e7646d2SAndroid Build Coastguard Worker
1369*5e7646d2SAndroid Build Coastguard Worker document_format = NULL;
1370*5e7646d2SAndroid Build Coastguard Worker
1371*5e7646d2SAndroid Build Coastguard Worker if (format_sup != NULL)
1372*5e7646d2SAndroid Build Coastguard Worker {
1373*5e7646d2SAndroid Build Coastguard Worker if (ippContainsString(format_sup, final_content_type))
1374*5e7646d2SAndroid Build Coastguard Worker document_format = final_content_type;
1375*5e7646d2SAndroid Build Coastguard Worker else if (ippContainsString(format_sup, "application/octet-stream"))
1376*5e7646d2SAndroid Build Coastguard Worker document_format = "application/octet-stream";
1377*5e7646d2SAndroid Build Coastguard Worker }
1378*5e7646d2SAndroid Build Coastguard Worker
1379*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: final_content_type=\"%s\", document_format=\"%s\"\n",
1380*5e7646d2SAndroid Build Coastguard Worker final_content_type, document_format ? document_format : "(null)");
1381*5e7646d2SAndroid Build Coastguard Worker
1382*5e7646d2SAndroid Build Coastguard Worker /*
1383*5e7646d2SAndroid Build Coastguard Worker * If the printer does not support HTTP/1.1 (which IPP requires), copy stdin
1384*5e7646d2SAndroid Build Coastguard Worker * to a temporary file so that we can do a HTTP/1.0 submission...
1385*5e7646d2SAndroid Build Coastguard Worker *
1386*5e7646d2SAndroid Build Coastguard Worker * (I hate compatibility hacks!)
1387*5e7646d2SAndroid Build Coastguard Worker */
1388*5e7646d2SAndroid Build Coastguard Worker
1389*5e7646d2SAndroid Build Coastguard Worker if (http->version < HTTP_VERSION_1_1 && num_files == 0)
1390*5e7646d2SAndroid Build Coastguard Worker {
1391*5e7646d2SAndroid Build Coastguard Worker if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
1392*5e7646d2SAndroid Build Coastguard Worker {
1393*5e7646d2SAndroid Build Coastguard Worker perror("DEBUG: Unable to create temporary file");
1394*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
1395*5e7646d2SAndroid Build Coastguard Worker }
1396*5e7646d2SAndroid Build Coastguard Worker
1397*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Copying print data."));
1398*5e7646d2SAndroid Build Coastguard Worker
1399*5e7646d2SAndroid Build Coastguard Worker if ((compatsize = write(fd, buffer, (size_t)bytes)) < 0)
1400*5e7646d2SAndroid Build Coastguard Worker {
1401*5e7646d2SAndroid Build Coastguard Worker perror("DEBUG: Unable to write temporary file");
1402*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
1403*5e7646d2SAndroid Build Coastguard Worker }
1404*5e7646d2SAndroid Build Coastguard Worker
1405*5e7646d2SAndroid Build Coastguard Worker if ((bytes = backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0,
1406*5e7646d2SAndroid Build Coastguard Worker backendNetworkSideCB)) < 0)
1407*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
1408*5e7646d2SAndroid Build Coastguard Worker
1409*5e7646d2SAndroid Build Coastguard Worker compatsize += bytes;
1410*5e7646d2SAndroid Build Coastguard Worker
1411*5e7646d2SAndroid Build Coastguard Worker close(fd);
1412*5e7646d2SAndroid Build Coastguard Worker
1413*5e7646d2SAndroid Build Coastguard Worker compatfile = tmpfilename;
1414*5e7646d2SAndroid Build Coastguard Worker files = &compatfile;
1415*5e7646d2SAndroid Build Coastguard Worker num_files = 1;
1416*5e7646d2SAndroid Build Coastguard Worker }
1417*5e7646d2SAndroid Build Coastguard Worker else if (http->version < HTTP_VERSION_1_1 && num_files == 1)
1418*5e7646d2SAndroid Build Coastguard Worker {
1419*5e7646d2SAndroid Build Coastguard Worker struct stat fileinfo; /* File information */
1420*5e7646d2SAndroid Build Coastguard Worker
1421*5e7646d2SAndroid Build Coastguard Worker if (!stat(files[0], &fileinfo))
1422*5e7646d2SAndroid Build Coastguard Worker compatsize = fileinfo.st_size;
1423*5e7646d2SAndroid Build Coastguard Worker }
1424*5e7646d2SAndroid Build Coastguard Worker
1425*5e7646d2SAndroid Build Coastguard Worker /*
1426*5e7646d2SAndroid Build Coastguard Worker * If the printer only claims to support IPP/1.0, or if the user specifically
1427*5e7646d2SAndroid Build Coastguard Worker * included version=1.0 in the URI, then do not try to use Create-Job or
1428*5e7646d2SAndroid Build Coastguard Worker * Send-Document. This is another dreaded compatibility hack, but
1429*5e7646d2SAndroid Build Coastguard Worker * unfortunately there are enough broken printers out there that we need
1430*5e7646d2SAndroid Build Coastguard Worker * this for now...
1431*5e7646d2SAndroid Build Coastguard Worker */
1432*5e7646d2SAndroid Build Coastguard Worker
1433*5e7646d2SAndroid Build Coastguard Worker if (version == 10)
1434*5e7646d2SAndroid Build Coastguard Worker create_job = send_document = 0;
1435*5e7646d2SAndroid Build Coastguard Worker
1436*5e7646d2SAndroid Build Coastguard Worker /*
1437*5e7646d2SAndroid Build Coastguard Worker * Start monitoring the printer in the background...
1438*5e7646d2SAndroid Build Coastguard Worker */
1439*5e7646d2SAndroid Build Coastguard Worker
1440*5e7646d2SAndroid Build Coastguard Worker monitor.uri = uri;
1441*5e7646d2SAndroid Build Coastguard Worker monitor.hostname = hostname;
1442*5e7646d2SAndroid Build Coastguard Worker monitor.user = argv[2];
1443*5e7646d2SAndroid Build Coastguard Worker monitor.resource = resource;
1444*5e7646d2SAndroid Build Coastguard Worker monitor.port = port;
1445*5e7646d2SAndroid Build Coastguard Worker monitor.version = version;
1446*5e7646d2SAndroid Build Coastguard Worker monitor.job_id = 0;
1447*5e7646d2SAndroid Build Coastguard Worker monitor.create_job = create_job;
1448*5e7646d2SAndroid Build Coastguard Worker monitor.get_job_attrs = get_job_attrs;
1449*5e7646d2SAndroid Build Coastguard Worker monitor.encryption = cupsEncryption();
1450*5e7646d2SAndroid Build Coastguard Worker monitor.job_state = IPP_JSTATE_PENDING;
1451*5e7646d2SAndroid Build Coastguard Worker monitor.printer_state = IPP_PSTATE_IDLE;
1452*5e7646d2SAndroid Build Coastguard Worker monitor.retryable = argc == 6 && document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf");
1453*5e7646d2SAndroid Build Coastguard Worker
1454*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: retryable=%d\n", monitor.retryable);
1455*5e7646d2SAndroid Build Coastguard Worker
1456*5e7646d2SAndroid Build Coastguard Worker if (create_job)
1457*5e7646d2SAndroid Build Coastguard Worker {
1458*5e7646d2SAndroid Build Coastguard Worker monitor.job_name = argv[3];
1459*5e7646d2SAndroid Build Coastguard Worker }
1460*5e7646d2SAndroid Build Coastguard Worker else
1461*5e7646d2SAndroid Build Coastguard Worker {
1462*5e7646d2SAndroid Build Coastguard Worker snprintf(print_job_name, sizeof(print_job_name), "%s - %s", argv[1],
1463*5e7646d2SAndroid Build Coastguard Worker argv[3]);
1464*5e7646d2SAndroid Build Coastguard Worker monitor.job_name = print_job_name;
1465*5e7646d2SAndroid Build Coastguard Worker }
1466*5e7646d2SAndroid Build Coastguard Worker
1467*5e7646d2SAndroid Build Coastguard Worker _cupsThreadCreate((_cups_thread_func_t)monitor_printer, &monitor);
1468*5e7646d2SAndroid Build Coastguard Worker
1469*5e7646d2SAndroid Build Coastguard Worker /*
1470*5e7646d2SAndroid Build Coastguard Worker * Validate access to the printer...
1471*5e7646d2SAndroid Build Coastguard Worker */
1472*5e7646d2SAndroid Build Coastguard Worker
1473*5e7646d2SAndroid Build Coastguard Worker while (!job_canceled && validate_job)
1474*5e7646d2SAndroid Build Coastguard Worker {
1475*5e7646d2SAndroid Build Coastguard Worker request = new_request(IPP_OP_VALIDATE_JOB, version, uri, argv[2],
1476*5e7646d2SAndroid Build Coastguard Worker monitor.job_name, num_options, options, compression,
1477*5e7646d2SAndroid Build Coastguard Worker copies_sup ? copies : 1, document_format, pc, ppd,
1478*5e7646d2SAndroid Build Coastguard Worker media_col_sup, doc_handling_sup, print_color_mode_sup);
1479*5e7646d2SAndroid Build Coastguard Worker
1480*5e7646d2SAndroid Build Coastguard Worker response = cupsDoRequest(http, request, resource);
1481*5e7646d2SAndroid Build Coastguard Worker
1482*5e7646d2SAndroid Build Coastguard Worker ipp_status = cupsLastError();
1483*5e7646d2SAndroid Build Coastguard Worker
1484*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Validate-Job: %s (%s)\n",
1485*5e7646d2SAndroid Build Coastguard Worker ippErrorString(ipp_status), cupsLastErrorString());
1486*5e7646d2SAndroid Build Coastguard Worker debug_attributes(response);
1487*5e7646d2SAndroid Build Coastguard Worker
1488*5e7646d2SAndroid Build Coastguard Worker if ((job_auth = ippFindAttribute(response, "job-authorization-uri",
1489*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_URI)) != NULL)
1490*5e7646d2SAndroid Build Coastguard Worker num_options = cupsAddOption("job-authorization-uri",
1491*5e7646d2SAndroid Build Coastguard Worker ippGetString(job_auth, 0, NULL), num_options,
1492*5e7646d2SAndroid Build Coastguard Worker &options);
1493*5e7646d2SAndroid Build Coastguard Worker
1494*5e7646d2SAndroid Build Coastguard Worker if (ipp_status == IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED || ipp_status == IPP_STATUS_OK_CONFLICTING)
1495*5e7646d2SAndroid Build Coastguard Worker {
1496*5e7646d2SAndroid Build Coastguard Worker /*
1497*5e7646d2SAndroid Build Coastguard Worker * One or more options are not supported...
1498*5e7646d2SAndroid Build Coastguard Worker */
1499*5e7646d2SAndroid Build Coastguard Worker
1500*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Unsupported attribute */
1501*5e7646d2SAndroid Build Coastguard Worker
1502*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(response, "sides", IPP_TAG_ZERO)) != NULL)
1503*5e7646d2SAndroid Build Coastguard Worker {
1504*5e7646d2SAndroid Build Coastguard Worker /*
1505*5e7646d2SAndroid Build Coastguard Worker * The sides value is not supported, revert to one-sided as needed...
1506*5e7646d2SAndroid Build Coastguard Worker */
1507*5e7646d2SAndroid Build Coastguard Worker
1508*5e7646d2SAndroid Build Coastguard Worker const char *sides = cupsGetOption("sides", num_options, options);
1509*5e7646d2SAndroid Build Coastguard Worker
1510*5e7646d2SAndroid Build Coastguard Worker if (!sides || !strncmp(sides, "two-sided-", 10))
1511*5e7646d2SAndroid Build Coastguard Worker {
1512*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Unable to do two-sided printing, setting sides to 'one-sided'.\n", stderr);
1513*5e7646d2SAndroid Build Coastguard Worker num_options = cupsAddOption("sides", "one-sided", num_options, &options);
1514*5e7646d2SAndroid Build Coastguard Worker }
1515*5e7646d2SAndroid Build Coastguard Worker }
1516*5e7646d2SAndroid Build Coastguard Worker }
1517*5e7646d2SAndroid Build Coastguard Worker
1518*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
1519*5e7646d2SAndroid Build Coastguard Worker
1520*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
1521*5e7646d2SAndroid Build Coastguard Worker break;
1522*5e7646d2SAndroid Build Coastguard Worker
1523*5e7646d2SAndroid Build Coastguard Worker if (ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE ||
1524*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_BUSY)
1525*5e7646d2SAndroid Build Coastguard Worker {
1526*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
1527*5e7646d2SAndroid Build Coastguard Worker sleep(10);
1528*5e7646d2SAndroid Build Coastguard Worker }
1529*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED ||
1530*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
1531*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
1532*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
1533*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
1534*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
1535*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1536*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
1537*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
1538*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
1539*5e7646d2SAndroid Build Coastguard Worker {
1540*5e7646d2SAndroid Build Coastguard Worker const char *www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
1541*5e7646d2SAndroid Build Coastguard Worker /* WWW-Authenticate field value */
1542*5e7646d2SAndroid Build Coastguard Worker
1543*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(www_auth, "Negotiate", 9))
1544*5e7646d2SAndroid Build Coastguard Worker auth_info_required = "negotiate";
1545*5e7646d2SAndroid Build Coastguard Worker else if (www_auth[0])
1546*5e7646d2SAndroid Build Coastguard Worker auth_info_required = "username,password";
1547*5e7646d2SAndroid Build Coastguard Worker
1548*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1549*5e7646d2SAndroid Build Coastguard Worker }
1550*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED)
1551*5e7646d2SAndroid Build Coastguard Worker {
1552*5e7646d2SAndroid Build Coastguard Worker /*
1553*5e7646d2SAndroid Build Coastguard Worker * This is all too common...
1554*5e7646d2SAndroid Build Coastguard Worker */
1555*5e7646d2SAndroid Build Coastguard Worker
1556*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1557*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-validate-job");
1558*5e7646d2SAndroid Build Coastguard Worker break;
1559*5e7646d2SAndroid Build Coastguard Worker }
1560*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status < IPP_STATUS_REDIRECTION_OTHER_SITE ||
1561*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_BAD_REQUEST)
1562*5e7646d2SAndroid Build Coastguard Worker break;
1563*5e7646d2SAndroid Build Coastguard Worker else if (job_auth == NULL && ipp_status > IPP_STATUS_ERROR_BAD_REQUEST)
1564*5e7646d2SAndroid Build Coastguard Worker {
1565*5e7646d2SAndroid Build Coastguard Worker if (!validate_retried)
1566*5e7646d2SAndroid Build Coastguard Worker {
1567*5e7646d2SAndroid Build Coastguard Worker // Retry Validate-Job operation once, to work around known printer bug...
1568*5e7646d2SAndroid Build Coastguard Worker validate_retried = 1;
1569*5e7646d2SAndroid Build Coastguard Worker sleep(10);
1570*5e7646d2SAndroid Build Coastguard Worker continue;
1571*5e7646d2SAndroid Build Coastguard Worker }
1572*5e7646d2SAndroid Build Coastguard Worker
1573*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1574*5e7646d2SAndroid Build Coastguard Worker }
1575*5e7646d2SAndroid Build Coastguard Worker }
1576*5e7646d2SAndroid Build Coastguard Worker
1577*5e7646d2SAndroid Build Coastguard Worker /*
1578*5e7646d2SAndroid Build Coastguard Worker * Then issue the print-job request...
1579*5e7646d2SAndroid Build Coastguard Worker */
1580*5e7646d2SAndroid Build Coastguard Worker
1581*5e7646d2SAndroid Build Coastguard Worker job_id = 0;
1582*5e7646d2SAndroid Build Coastguard Worker
1583*5e7646d2SAndroid Build Coastguard Worker while (!job_canceled && copies_remaining > 0)
1584*5e7646d2SAndroid Build Coastguard Worker {
1585*5e7646d2SAndroid Build Coastguard Worker /*
1586*5e7646d2SAndroid Build Coastguard Worker * Check for side-channel requests...
1587*5e7646d2SAndroid Build Coastguard Worker */
1588*5e7646d2SAndroid Build Coastguard Worker
1589*5e7646d2SAndroid Build Coastguard Worker backendCheckSideChannel(snmp_fd, http->hostaddr);
1590*5e7646d2SAndroid Build Coastguard Worker
1591*5e7646d2SAndroid Build Coastguard Worker /*
1592*5e7646d2SAndroid Build Coastguard Worker * Build the IPP job creation request...
1593*5e7646d2SAndroid Build Coastguard Worker */
1594*5e7646d2SAndroid Build Coastguard Worker
1595*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
1596*5e7646d2SAndroid Build Coastguard Worker break;
1597*5e7646d2SAndroid Build Coastguard Worker
1598*5e7646d2SAndroid Build Coastguard Worker request = new_request((num_files > 1 || create_job) ? IPP_OP_CREATE_JOB :
1599*5e7646d2SAndroid Build Coastguard Worker IPP_OP_PRINT_JOB,
1600*5e7646d2SAndroid Build Coastguard Worker version, uri, argv[2], monitor.job_name, num_options,
1601*5e7646d2SAndroid Build Coastguard Worker options, compression, copies_sup ? copies : 1,
1602*5e7646d2SAndroid Build Coastguard Worker document_format, pc, ppd, media_col_sup,
1603*5e7646d2SAndroid Build Coastguard Worker doc_handling_sup, print_color_mode_sup);
1604*5e7646d2SAndroid Build Coastguard Worker
1605*5e7646d2SAndroid Build Coastguard Worker /*
1606*5e7646d2SAndroid Build Coastguard Worker * Do the request...
1607*5e7646d2SAndroid Build Coastguard Worker */
1608*5e7646d2SAndroid Build Coastguard Worker
1609*5e7646d2SAndroid Build Coastguard Worker if (num_files > 1 || create_job)
1610*5e7646d2SAndroid Build Coastguard Worker response = cupsDoRequest(http, request, resource);
1611*5e7646d2SAndroid Build Coastguard Worker else
1612*5e7646d2SAndroid Build Coastguard Worker {
1613*5e7646d2SAndroid Build Coastguard Worker size_t length = 0; /* Length of request */
1614*5e7646d2SAndroid Build Coastguard Worker
1615*5e7646d2SAndroid Build Coastguard Worker if (compatsize > 0)
1616*5e7646d2SAndroid Build Coastguard Worker {
1617*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Sending file using HTTP/1.0 Content-Length...\n", stderr);
1618*5e7646d2SAndroid Build Coastguard Worker length = ippLength(request) + (size_t)compatsize;
1619*5e7646d2SAndroid Build Coastguard Worker }
1620*5e7646d2SAndroid Build Coastguard Worker else
1621*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Sending file using HTTP/1.1 chunking...\n", stderr);
1622*5e7646d2SAndroid Build Coastguard Worker
1623*5e7646d2SAndroid Build Coastguard Worker http_status = cupsSendRequest(http, request, resource, length);
1624*5e7646d2SAndroid Build Coastguard Worker if (http_status == HTTP_STATUS_CONTINUE && request->state == IPP_STATE_DATA)
1625*5e7646d2SAndroid Build Coastguard Worker {
1626*5e7646d2SAndroid Build Coastguard Worker if (compression && strcmp(compression, "none"))
1627*5e7646d2SAndroid Build Coastguard Worker httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
1628*5e7646d2SAndroid Build Coastguard Worker
1629*5e7646d2SAndroid Build Coastguard Worker if (num_files == 1)
1630*5e7646d2SAndroid Build Coastguard Worker {
1631*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(files[0], O_RDONLY)) < 0)
1632*5e7646d2SAndroid Build Coastguard Worker {
1633*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintError("ERROR", _("Unable to open print file"));
1634*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
1635*5e7646d2SAndroid Build Coastguard Worker }
1636*5e7646d2SAndroid Build Coastguard Worker }
1637*5e7646d2SAndroid Build Coastguard Worker else
1638*5e7646d2SAndroid Build Coastguard Worker {
1639*5e7646d2SAndroid Build Coastguard Worker fd = 0;
1640*5e7646d2SAndroid Build Coastguard Worker http_status = cupsWriteRequestData(http, buffer, (size_t)bytes);
1641*5e7646d2SAndroid Build Coastguard Worker }
1642*5e7646d2SAndroid Build Coastguard Worker
1643*5e7646d2SAndroid Build Coastguard Worker while (http_status == HTTP_STATUS_CONTINUE &&
1644*5e7646d2SAndroid Build Coastguard Worker (!job_canceled || compatsize > 0))
1645*5e7646d2SAndroid Build Coastguard Worker {
1646*5e7646d2SAndroid Build Coastguard Worker /*
1647*5e7646d2SAndroid Build Coastguard Worker * Check for side-channel requests and more print data...
1648*5e7646d2SAndroid Build Coastguard Worker */
1649*5e7646d2SAndroid Build Coastguard Worker
1650*5e7646d2SAndroid Build Coastguard Worker FD_ZERO(&input);
1651*5e7646d2SAndroid Build Coastguard Worker FD_SET(fd, &input);
1652*5e7646d2SAndroid Build Coastguard Worker FD_SET(snmp_fd, &input);
1653*5e7646d2SAndroid Build Coastguard Worker FD_SET(CUPS_SC_FD, &input);
1654*5e7646d2SAndroid Build Coastguard Worker
1655*5e7646d2SAndroid Build Coastguard Worker while (select(fd > snmp_fd ? fd + 1 : snmp_fd + 1, &input, NULL, NULL,
1656*5e7646d2SAndroid Build Coastguard Worker NULL) <= 0 && !job_canceled);
1657*5e7646d2SAndroid Build Coastguard Worker
1658*5e7646d2SAndroid Build Coastguard Worker if (FD_ISSET(snmp_fd, &input))
1659*5e7646d2SAndroid Build Coastguard Worker backendCheckSideChannel(snmp_fd, http->hostaddr);
1660*5e7646d2SAndroid Build Coastguard Worker
1661*5e7646d2SAndroid Build Coastguard Worker if (FD_ISSET(fd, &input))
1662*5e7646d2SAndroid Build Coastguard Worker {
1663*5e7646d2SAndroid Build Coastguard Worker if ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
1664*5e7646d2SAndroid Build Coastguard Worker {
1665*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Read %d bytes...\n", (int)bytes);
1666*5e7646d2SAndroid Build Coastguard Worker
1667*5e7646d2SAndroid Build Coastguard Worker if ((http_status = cupsWriteRequestData(http, buffer, (size_t)bytes))
1668*5e7646d2SAndroid Build Coastguard Worker != HTTP_STATUS_CONTINUE)
1669*5e7646d2SAndroid Build Coastguard Worker break;
1670*5e7646d2SAndroid Build Coastguard Worker }
1671*5e7646d2SAndroid Build Coastguard Worker else if (bytes == 0 || (errno != EINTR && errno != EAGAIN))
1672*5e7646d2SAndroid Build Coastguard Worker break;
1673*5e7646d2SAndroid Build Coastguard Worker }
1674*5e7646d2SAndroid Build Coastguard Worker }
1675*5e7646d2SAndroid Build Coastguard Worker
1676*5e7646d2SAndroid Build Coastguard Worker if (http_status == HTTP_STATUS_ERROR)
1677*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Error writing document data for "
1678*5e7646d2SAndroid Build Coastguard Worker "Print-Job: %s\n", strerror(httpError(http)));
1679*5e7646d2SAndroid Build Coastguard Worker
1680*5e7646d2SAndroid Build Coastguard Worker if (num_files == 1)
1681*5e7646d2SAndroid Build Coastguard Worker close(fd);
1682*5e7646d2SAndroid Build Coastguard Worker }
1683*5e7646d2SAndroid Build Coastguard Worker
1684*5e7646d2SAndroid Build Coastguard Worker response = cupsGetResponse(http, resource);
1685*5e7646d2SAndroid Build Coastguard Worker ippDelete(request);
1686*5e7646d2SAndroid Build Coastguard Worker }
1687*5e7646d2SAndroid Build Coastguard Worker
1688*5e7646d2SAndroid Build Coastguard Worker ipp_status = cupsLastError();
1689*5e7646d2SAndroid Build Coastguard Worker
1690*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: %s: %s (%s)\n",
1691*5e7646d2SAndroid Build Coastguard Worker (num_files > 1 || create_job) ? "Create-Job" : "Print-Job",
1692*5e7646d2SAndroid Build Coastguard Worker ippErrorString(ipp_status), cupsLastErrorString());
1693*5e7646d2SAndroid Build Coastguard Worker debug_attributes(response);
1694*5e7646d2SAndroid Build Coastguard Worker
1695*5e7646d2SAndroid Build Coastguard Worker if (ipp_status > IPP_STATUS_OK_CONFLICTING)
1696*5e7646d2SAndroid Build Coastguard Worker {
1697*5e7646d2SAndroid Build Coastguard Worker job_id = 0;
1698*5e7646d2SAndroid Build Coastguard Worker
1699*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
1700*5e7646d2SAndroid Build Coastguard Worker break;
1701*5e7646d2SAndroid Build Coastguard Worker
1702*5e7646d2SAndroid Build Coastguard Worker if (ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE ||
1703*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_NOT_POSSIBLE ||
1704*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_BUSY)
1705*5e7646d2SAndroid Build Coastguard Worker {
1706*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
1707*5e7646d2SAndroid Build Coastguard Worker sleep(10);
1708*5e7646d2SAndroid Build Coastguard Worker
1709*5e7646d2SAndroid Build Coastguard Worker if (num_files == 0)
1710*5e7646d2SAndroid Build Coastguard Worker {
1711*5e7646d2SAndroid Build Coastguard Worker /*
1712*5e7646d2SAndroid Build Coastguard Worker * We can't re-submit when we have no files to print, so exit
1713*5e7646d2SAndroid Build Coastguard Worker * immediately with the right status code...
1714*5e7646d2SAndroid Build Coastguard Worker */
1715*5e7646d2SAndroid Build Coastguard Worker
1716*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1717*5e7646d2SAndroid Build Coastguard Worker }
1718*5e7646d2SAndroid Build Coastguard Worker }
1719*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_JOB_CANCELED ||
1720*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
1721*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
1722*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
1723*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
1724*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
1725*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
1726*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1727*5e7646d2SAndroid Build Coastguard Worker else
1728*5e7646d2SAndroid Build Coastguard Worker {
1729*5e7646d2SAndroid Build Coastguard Worker /*
1730*5e7646d2SAndroid Build Coastguard Worker * Update auth-info-required as needed...
1731*5e7646d2SAndroid Build Coastguard Worker */
1732*5e7646d2SAndroid Build Coastguard Worker
1733*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
1734*5e7646d2SAndroid Build Coastguard Worker _("Print job was not accepted."));
1735*5e7646d2SAndroid Build Coastguard Worker
1736*5e7646d2SAndroid Build Coastguard Worker if (ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
1737*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
1738*5e7646d2SAndroid Build Coastguard Worker {
1739*5e7646d2SAndroid Build Coastguard Worker const char *www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
1740*5e7646d2SAndroid Build Coastguard Worker /* WWW-Authenticate field value */
1741*5e7646d2SAndroid Build Coastguard Worker
1742*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(www_auth, "Negotiate", 9))
1743*5e7646d2SAndroid Build Coastguard Worker auth_info_required = "negotiate";
1744*5e7646d2SAndroid Build Coastguard Worker else if (www_auth[0])
1745*5e7646d2SAndroid Build Coastguard Worker auth_info_required = "username,password";
1746*5e7646d2SAndroid Build Coastguard Worker }
1747*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
1748*5e7646d2SAndroid Build Coastguard Worker {
1749*5e7646d2SAndroid Build Coastguard Worker /*
1750*5e7646d2SAndroid Build Coastguard Worker * Print file is too large, abort this job...
1751*5e7646d2SAndroid Build Coastguard Worker */
1752*5e7646d2SAndroid Build Coastguard Worker
1753*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1754*5e7646d2SAndroid Build Coastguard Worker }
1755*5e7646d2SAndroid Build Coastguard Worker else
1756*5e7646d2SAndroid Build Coastguard Worker sleep(10);
1757*5e7646d2SAndroid Build Coastguard Worker
1758*5e7646d2SAndroid Build Coastguard Worker if (num_files == 0)
1759*5e7646d2SAndroid Build Coastguard Worker {
1760*5e7646d2SAndroid Build Coastguard Worker /*
1761*5e7646d2SAndroid Build Coastguard Worker * We can't re-submit when we have no files to print, so exit
1762*5e7646d2SAndroid Build Coastguard Worker * immediately with the right status code...
1763*5e7646d2SAndroid Build Coastguard Worker */
1764*5e7646d2SAndroid Build Coastguard Worker
1765*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1766*5e7646d2SAndroid Build Coastguard Worker }
1767*5e7646d2SAndroid Build Coastguard Worker }
1768*5e7646d2SAndroid Build Coastguard Worker }
1769*5e7646d2SAndroid Build Coastguard Worker else if ((job_id_attr = ippFindAttribute(response, "job-id",
1770*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) == NULL)
1771*5e7646d2SAndroid Build Coastguard Worker {
1772*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Print job accepted - job ID unknown.\n", stderr);
1773*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1774*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-job-id");
1775*5e7646d2SAndroid Build Coastguard Worker job_id = 0;
1776*5e7646d2SAndroid Build Coastguard Worker }
1777*5e7646d2SAndroid Build Coastguard Worker else
1778*5e7646d2SAndroid Build Coastguard Worker {
1779*5e7646d2SAndroid Build Coastguard Worker password_tries = 0;
1780*5e7646d2SAndroid Build Coastguard Worker monitor.job_id = job_id = job_id_attr->values[0].integer;
1781*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Print job accepted - job ID %d.\n", job_id);
1782*5e7646d2SAndroid Build Coastguard Worker }
1783*5e7646d2SAndroid Build Coastguard Worker
1784*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
1785*5e7646d2SAndroid Build Coastguard Worker
1786*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
1787*5e7646d2SAndroid Build Coastguard Worker break;
1788*5e7646d2SAndroid Build Coastguard Worker
1789*5e7646d2SAndroid Build Coastguard Worker if (job_id && (num_files > 1 || create_job))
1790*5e7646d2SAndroid Build Coastguard Worker {
1791*5e7646d2SAndroid Build Coastguard Worker for (i = 0; num_files == 0 || i < num_files; i ++)
1792*5e7646d2SAndroid Build Coastguard Worker {
1793*5e7646d2SAndroid Build Coastguard Worker /*
1794*5e7646d2SAndroid Build Coastguard Worker * Check for side-channel requests...
1795*5e7646d2SAndroid Build Coastguard Worker */
1796*5e7646d2SAndroid Build Coastguard Worker
1797*5e7646d2SAndroid Build Coastguard Worker backendCheckSideChannel(snmp_fd, http->hostaddr);
1798*5e7646d2SAndroid Build Coastguard Worker
1799*5e7646d2SAndroid Build Coastguard Worker /*
1800*5e7646d2SAndroid Build Coastguard Worker * Send the next file in the job...
1801*5e7646d2SAndroid Build Coastguard Worker */
1802*5e7646d2SAndroid Build Coastguard Worker
1803*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(IPP_OP_SEND_DOCUMENT);
1804*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, version / 10, version % 10);
1805*5e7646d2SAndroid Build Coastguard Worker
1806*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1807*5e7646d2SAndroid Build Coastguard Worker NULL, uri);
1808*5e7646d2SAndroid Build Coastguard Worker
1809*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
1810*5e7646d2SAndroid Build Coastguard Worker job_id);
1811*5e7646d2SAndroid Build Coastguard Worker
1812*5e7646d2SAndroid Build Coastguard Worker if (argv[2][0])
1813*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1814*5e7646d2SAndroid Build Coastguard Worker "requesting-user-name", NULL, argv[2]);
1815*5e7646d2SAndroid Build Coastguard Worker
1816*5e7646d2SAndroid Build Coastguard Worker ippAddBoolean(request, IPP_TAG_OPERATION, "last-document",
1817*5e7646d2SAndroid Build Coastguard Worker (i + 1) >= num_files);
1818*5e7646d2SAndroid Build Coastguard Worker
1819*5e7646d2SAndroid Build Coastguard Worker if (document_format)
1820*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
1821*5e7646d2SAndroid Build Coastguard Worker "document-format", NULL, document_format);
1822*5e7646d2SAndroid Build Coastguard Worker
1823*5e7646d2SAndroid Build Coastguard Worker if (compression)
1824*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1825*5e7646d2SAndroid Build Coastguard Worker "compression", NULL, compression);
1826*5e7646d2SAndroid Build Coastguard Worker
1827*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Sending file %d using chunking...\n", i + 1);
1828*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: IPP/%d.%d %s #%d\n", version / 10, version % 10, ippOpString(ippGetOperation(request)), ippGetRequestId(request));
1829*5e7646d2SAndroid Build Coastguard Worker debug_attributes(request);
1830*5e7646d2SAndroid Build Coastguard Worker
1831*5e7646d2SAndroid Build Coastguard Worker http_status = cupsSendRequest(http, request, resource, 0);
1832*5e7646d2SAndroid Build Coastguard Worker if (http_status == HTTP_STATUS_CONTINUE && request->state == IPP_STATE_DATA)
1833*5e7646d2SAndroid Build Coastguard Worker {
1834*5e7646d2SAndroid Build Coastguard Worker if (compression && strcmp(compression, "none"))
1835*5e7646d2SAndroid Build Coastguard Worker httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
1836*5e7646d2SAndroid Build Coastguard Worker
1837*5e7646d2SAndroid Build Coastguard Worker if (num_files == 0)
1838*5e7646d2SAndroid Build Coastguard Worker {
1839*5e7646d2SAndroid Build Coastguard Worker fd = 0;
1840*5e7646d2SAndroid Build Coastguard Worker http_status = cupsWriteRequestData(http, buffer, (size_t)bytes);
1841*5e7646d2SAndroid Build Coastguard Worker }
1842*5e7646d2SAndroid Build Coastguard Worker else
1843*5e7646d2SAndroid Build Coastguard Worker {
1844*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(files[i], O_RDONLY)) < 0)
1845*5e7646d2SAndroid Build Coastguard Worker {
1846*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintError("ERROR", _("Unable to open print file"));
1847*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
1848*5e7646d2SAndroid Build Coastguard Worker }
1849*5e7646d2SAndroid Build Coastguard Worker }
1850*5e7646d2SAndroid Build Coastguard Worker }
1851*5e7646d2SAndroid Build Coastguard Worker else
1852*5e7646d2SAndroid Build Coastguard Worker fd = -1;
1853*5e7646d2SAndroid Build Coastguard Worker
1854*5e7646d2SAndroid Build Coastguard Worker if (fd >= 0)
1855*5e7646d2SAndroid Build Coastguard Worker {
1856*5e7646d2SAndroid Build Coastguard Worker while (!job_canceled && http_status == HTTP_STATUS_CONTINUE &&
1857*5e7646d2SAndroid Build Coastguard Worker (bytes = read(fd, buffer, sizeof(buffer))) > 0)
1858*5e7646d2SAndroid Build Coastguard Worker {
1859*5e7646d2SAndroid Build Coastguard Worker if ((http_status = cupsWriteRequestData(http, buffer, (size_t)bytes))
1860*5e7646d2SAndroid Build Coastguard Worker != HTTP_STATUS_CONTINUE)
1861*5e7646d2SAndroid Build Coastguard Worker break;
1862*5e7646d2SAndroid Build Coastguard Worker else
1863*5e7646d2SAndroid Build Coastguard Worker {
1864*5e7646d2SAndroid Build Coastguard Worker /*
1865*5e7646d2SAndroid Build Coastguard Worker * Check for side-channel requests...
1866*5e7646d2SAndroid Build Coastguard Worker */
1867*5e7646d2SAndroid Build Coastguard Worker
1868*5e7646d2SAndroid Build Coastguard Worker backendCheckSideChannel(snmp_fd, http->hostaddr);
1869*5e7646d2SAndroid Build Coastguard Worker }
1870*5e7646d2SAndroid Build Coastguard Worker }
1871*5e7646d2SAndroid Build Coastguard Worker
1872*5e7646d2SAndroid Build Coastguard Worker if (fd > 0)
1873*5e7646d2SAndroid Build Coastguard Worker close(fd);
1874*5e7646d2SAndroid Build Coastguard Worker }
1875*5e7646d2SAndroid Build Coastguard Worker
1876*5e7646d2SAndroid Build Coastguard Worker if (http_status == HTTP_STATUS_ERROR)
1877*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Error writing document data for "
1878*5e7646d2SAndroid Build Coastguard Worker "Send-Document: %s\n", strerror(httpError(http)));
1879*5e7646d2SAndroid Build Coastguard Worker
1880*5e7646d2SAndroid Build Coastguard Worker response = cupsGetResponse(http, resource);
1881*5e7646d2SAndroid Build Coastguard Worker ippDelete(request);
1882*5e7646d2SAndroid Build Coastguard Worker
1883*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Send-Document: %s (%s)\n", ippErrorString(cupsLastError()), cupsLastErrorString());
1884*5e7646d2SAndroid Build Coastguard Worker debug_attributes(response);
1885*5e7646d2SAndroid Build Coastguard Worker
1886*5e7646d2SAndroid Build Coastguard Worker if (cupsLastError() > IPP_STATUS_OK_CONFLICTING && !job_canceled)
1887*5e7646d2SAndroid Build Coastguard Worker {
1888*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *reasons = ippFindAttribute(response, "job-state-reasons", IPP_TAG_KEYWORD);
1889*5e7646d2SAndroid Build Coastguard Worker /* job-state-reasons values */
1890*5e7646d2SAndroid Build Coastguard Worker
1891*5e7646d2SAndroid Build Coastguard Worker ipp_status = cupsLastError();
1892*5e7646d2SAndroid Build Coastguard Worker
1893*5e7646d2SAndroid Build Coastguard Worker if (ippContainsString(reasons, "document-format-error"))
1894*5e7646d2SAndroid Build Coastguard Worker ipp_status = IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR;
1895*5e7646d2SAndroid Build Coastguard Worker else if (ippContainsString(reasons, "document-unprintable"))
1896*5e7646d2SAndroid Build Coastguard Worker ipp_status = IPP_STATUS_ERROR_DOCUMENT_UNPRINTABLE;
1897*5e7646d2SAndroid Build Coastguard Worker
1898*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
1899*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR", _("Unable to add document to print job."));
1900*5e7646d2SAndroid Build Coastguard Worker break;
1901*5e7646d2SAndroid Build Coastguard Worker }
1902*5e7646d2SAndroid Build Coastguard Worker else
1903*5e7646d2SAndroid Build Coastguard Worker {
1904*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
1905*5e7646d2SAndroid Build Coastguard Worker
1906*5e7646d2SAndroid Build Coastguard Worker password_tries = 0;
1907*5e7646d2SAndroid Build Coastguard Worker
1908*5e7646d2SAndroid Build Coastguard Worker if (num_files == 0 || fd < 0)
1909*5e7646d2SAndroid Build Coastguard Worker break;
1910*5e7646d2SAndroid Build Coastguard Worker }
1911*5e7646d2SAndroid Build Coastguard Worker }
1912*5e7646d2SAndroid Build Coastguard Worker }
1913*5e7646d2SAndroid Build Coastguard Worker
1914*5e7646d2SAndroid Build Coastguard Worker if (job_canceled)
1915*5e7646d2SAndroid Build Coastguard Worker break;
1916*5e7646d2SAndroid Build Coastguard Worker
1917*5e7646d2SAndroid Build Coastguard Worker if (ipp_status <= IPP_STATUS_OK_CONFLICTING && argc > 6)
1918*5e7646d2SAndroid Build Coastguard Worker {
1919*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1);
1920*5e7646d2SAndroid Build Coastguard Worker copies_remaining --;
1921*5e7646d2SAndroid Build Coastguard Worker }
1922*5e7646d2SAndroid Build Coastguard Worker else if ((ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED || ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_ERROR || ipp_status == IPP_STATUS_ERROR_DOCUMENT_UNPRINTABLE) &&
1923*5e7646d2SAndroid Build Coastguard Worker argc == 6 &&
1924*5e7646d2SAndroid Build Coastguard Worker document_format && strcmp(document_format, "image/pwg-raster") && strcmp(document_format, "image/urf"))
1925*5e7646d2SAndroid Build Coastguard Worker {
1926*5e7646d2SAndroid Build Coastguard Worker /*
1927*5e7646d2SAndroid Build Coastguard Worker * Need to reprocess the job as raster...
1928*5e7646d2SAndroid Build Coastguard Worker */
1929*5e7646d2SAndroid Build Coastguard Worker
1930*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: cups-retry-as-raster\n", stderr);
1931*5e7646d2SAndroid Build Coastguard Worker if (job_id > 0)
1932*5e7646d2SAndroid Build Coastguard Worker cancel_job(http, uri, job_id, resource, argv[2], version);
1933*5e7646d2SAndroid Build Coastguard Worker
1934*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1935*5e7646d2SAndroid Build Coastguard Worker }
1936*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE ||
1937*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_NOT_POSSIBLE ||
1938*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_BUSY)
1939*5e7646d2SAndroid Build Coastguard Worker {
1940*5e7646d2SAndroid Build Coastguard Worker if (argc == 6)
1941*5e7646d2SAndroid Build Coastguard Worker {
1942*5e7646d2SAndroid Build Coastguard Worker /*
1943*5e7646d2SAndroid Build Coastguard Worker * Need to reprocess the entire job; if we have a job ID, cancel the
1944*5e7646d2SAndroid Build Coastguard Worker * job first...
1945*5e7646d2SAndroid Build Coastguard Worker */
1946*5e7646d2SAndroid Build Coastguard Worker
1947*5e7646d2SAndroid Build Coastguard Worker if (job_id > 0)
1948*5e7646d2SAndroid Build Coastguard Worker cancel_job(http, uri, job_id, resource, argv[2], version);
1949*5e7646d2SAndroid Build Coastguard Worker
1950*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1951*5e7646d2SAndroid Build Coastguard Worker }
1952*5e7646d2SAndroid Build Coastguard Worker continue;
1953*5e7646d2SAndroid Build Coastguard Worker }
1954*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE ||
1955*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_JOB_CANCELED ||
1956*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
1957*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
1958*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
1959*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
1960*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED ||
1961*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_INTERNAL)
1962*5e7646d2SAndroid Build Coastguard Worker {
1963*5e7646d2SAndroid Build Coastguard Worker /*
1964*5e7646d2SAndroid Build Coastguard Worker * Print file is too large, job was canceled, we need new
1965*5e7646d2SAndroid Build Coastguard Worker * authentication data, or we had some sort of error...
1966*5e7646d2SAndroid Build Coastguard Worker */
1967*5e7646d2SAndroid Build Coastguard Worker
1968*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1969*5e7646d2SAndroid Build Coastguard Worker }
1970*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_CUPS_UPGRADE_REQUIRED)
1971*5e7646d2SAndroid Build Coastguard Worker {
1972*5e7646d2SAndroid Build Coastguard Worker /*
1973*5e7646d2SAndroid Build Coastguard Worker * Server is configured incorrectly; the policy for Create-Job and
1974*5e7646d2SAndroid Build Coastguard Worker * Send-Document has to be the same (auth or no auth, encryption or
1975*5e7646d2SAndroid Build Coastguard Worker * no encryption). Force the queue to stop since printing will never
1976*5e7646d2SAndroid Build Coastguard Worker * work.
1977*5e7646d2SAndroid Build Coastguard Worker */
1978*5e7646d2SAndroid Build Coastguard Worker
1979*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: The server or printer is configured incorrectly.\n",
1980*5e7646d2SAndroid Build Coastguard Worker stderr);
1981*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: The policy for Create-Job and Send-Document must have the "
1982*5e7646d2SAndroid Build Coastguard Worker "same authentication and encryption requirements.\n", stderr);
1983*5e7646d2SAndroid Build Coastguard Worker
1984*5e7646d2SAndroid Build Coastguard Worker ipp_status = IPP_STATUS_ERROR_INTERNAL;
1985*5e7646d2SAndroid Build Coastguard Worker
1986*5e7646d2SAndroid Build Coastguard Worker if (job_id > 0)
1987*5e7646d2SAndroid Build Coastguard Worker cancel_job(http, uri, job_id, resource, argv[2], version);
1988*5e7646d2SAndroid Build Coastguard Worker
1989*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
1990*5e7646d2SAndroid Build Coastguard Worker }
1991*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND)
1992*5e7646d2SAndroid Build Coastguard Worker {
1993*5e7646d2SAndroid Build Coastguard Worker /*
1994*5e7646d2SAndroid Build Coastguard Worker * Printer does not actually implement support for Create-Job/
1995*5e7646d2SAndroid Build Coastguard Worker * Send-Document, so log the conformance issue and stop the printer.
1996*5e7646d2SAndroid Build Coastguard Worker */
1997*5e7646d2SAndroid Build Coastguard Worker
1998*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: This printer claims to support Create-Job and "
1999*5e7646d2SAndroid Build Coastguard Worker "Send-Document, but those operations failed.\n", stderr);
2000*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Add '?version=1.0' to the device URI to use legacy "
2001*5e7646d2SAndroid Build Coastguard Worker "compatibility mode.\n", stderr);
2002*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
2003*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-send-document");
2004*5e7646d2SAndroid Build Coastguard Worker
2005*5e7646d2SAndroid Build Coastguard Worker ipp_status = IPP_STATUS_ERROR_INTERNAL; /* Force queue to stop */
2006*5e7646d2SAndroid Build Coastguard Worker
2007*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
2008*5e7646d2SAndroid Build Coastguard Worker }
2009*5e7646d2SAndroid Build Coastguard Worker else
2010*5e7646d2SAndroid Build Coastguard Worker copies_remaining --;
2011*5e7646d2SAndroid Build Coastguard Worker
2012*5e7646d2SAndroid Build Coastguard Worker /*
2013*5e7646d2SAndroid Build Coastguard Worker * Wait for the job to complete...
2014*5e7646d2SAndroid Build Coastguard Worker */
2015*5e7646d2SAndroid Build Coastguard Worker
2016*5e7646d2SAndroid Build Coastguard Worker if (!job_id || !waitjob || !get_job_attrs)
2017*5e7646d2SAndroid Build Coastguard Worker continue;
2018*5e7646d2SAndroid Build Coastguard Worker
2019*5e7646d2SAndroid Build Coastguard Worker fputs("STATE: +cups-waiting-for-job-completed\n", stderr);
2020*5e7646d2SAndroid Build Coastguard Worker
2021*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Waiting for job to complete."));
2022*5e7646d2SAndroid Build Coastguard Worker
2023*5e7646d2SAndroid Build Coastguard Worker for (delay = _cupsNextDelay(0, &prev_delay); !job_canceled;)
2024*5e7646d2SAndroid Build Coastguard Worker {
2025*5e7646d2SAndroid Build Coastguard Worker /*
2026*5e7646d2SAndroid Build Coastguard Worker * Check for side-channel requests...
2027*5e7646d2SAndroid Build Coastguard Worker */
2028*5e7646d2SAndroid Build Coastguard Worker
2029*5e7646d2SAndroid Build Coastguard Worker backendCheckSideChannel(snmp_fd, http->hostaddr);
2030*5e7646d2SAndroid Build Coastguard Worker
2031*5e7646d2SAndroid Build Coastguard Worker /*
2032*5e7646d2SAndroid Build Coastguard Worker * Check printer state...
2033*5e7646d2SAndroid Build Coastguard Worker */
2034*5e7646d2SAndroid Build Coastguard Worker
2035*5e7646d2SAndroid Build Coastguard Worker check_printer_state(http, uri, resource, argv[2], version);
2036*5e7646d2SAndroid Build Coastguard Worker
2037*5e7646d2SAndroid Build Coastguard Worker if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
2038*5e7646d2SAndroid Build Coastguard Worker password_tries = 0;
2039*5e7646d2SAndroid Build Coastguard Worker
2040*5e7646d2SAndroid Build Coastguard Worker /*
2041*5e7646d2SAndroid Build Coastguard Worker * Build an IPP_OP_GET_JOB_ATTRIBUTES request...
2042*5e7646d2SAndroid Build Coastguard Worker */
2043*5e7646d2SAndroid Build Coastguard Worker
2044*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES);
2045*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, version / 10, version % 10);
2046*5e7646d2SAndroid Build Coastguard Worker
2047*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2048*5e7646d2SAndroid Build Coastguard Worker NULL, uri);
2049*5e7646d2SAndroid Build Coastguard Worker
2050*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
2051*5e7646d2SAndroid Build Coastguard Worker job_id);
2052*5e7646d2SAndroid Build Coastguard Worker
2053*5e7646d2SAndroid Build Coastguard Worker if (argv[2][0])
2054*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
2055*5e7646d2SAndroid Build Coastguard Worker "requesting-user-name", NULL, argv[2]);
2056*5e7646d2SAndroid Build Coastguard Worker
2057*5e7646d2SAndroid Build Coastguard Worker ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2058*5e7646d2SAndroid Build Coastguard Worker "requested-attributes", sizeof(jattrs) / sizeof(jattrs[0]),
2059*5e7646d2SAndroid Build Coastguard Worker NULL, jattrs);
2060*5e7646d2SAndroid Build Coastguard Worker
2061*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: IPP/%d.%d %s #%d\n", version / 10, version % 10, ippOpString(ippGetOperation(request)), ippGetRequestId(request));
2062*5e7646d2SAndroid Build Coastguard Worker debug_attributes(request);
2063*5e7646d2SAndroid Build Coastguard Worker
2064*5e7646d2SAndroid Build Coastguard Worker /*
2065*5e7646d2SAndroid Build Coastguard Worker * Do the request...
2066*5e7646d2SAndroid Build Coastguard Worker */
2067*5e7646d2SAndroid Build Coastguard Worker
2068*5e7646d2SAndroid Build Coastguard Worker httpReconnect2(http, 30000, NULL);
2069*5e7646d2SAndroid Build Coastguard Worker response = cupsDoRequest(http, request, resource);
2070*5e7646d2SAndroid Build Coastguard Worker ipp_status = cupsLastError();
2071*5e7646d2SAndroid Build Coastguard Worker
2072*5e7646d2SAndroid Build Coastguard Worker if (ipp_status == IPP_STATUS_ERROR_NOT_FOUND || ipp_status == IPP_STATUS_ERROR_NOT_POSSIBLE)
2073*5e7646d2SAndroid Build Coastguard Worker {
2074*5e7646d2SAndroid Build Coastguard Worker /*
2075*5e7646d2SAndroid Build Coastguard Worker * Job has gone away and/or the server has no job history...
2076*5e7646d2SAndroid Build Coastguard Worker */
2077*5e7646d2SAndroid Build Coastguard Worker
2078*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
2079*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-job-history");
2080*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
2081*5e7646d2SAndroid Build Coastguard Worker
2082*5e7646d2SAndroid Build Coastguard Worker ipp_status = IPP_STATUS_OK;
2083*5e7646d2SAndroid Build Coastguard Worker break;
2084*5e7646d2SAndroid Build Coastguard Worker }
2085*5e7646d2SAndroid Build Coastguard Worker
2086*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Get-Job-Attributes: %s (%s)\n",
2087*5e7646d2SAndroid Build Coastguard Worker ippErrorString(ipp_status), cupsLastErrorString());
2088*5e7646d2SAndroid Build Coastguard Worker debug_attributes(response);
2089*5e7646d2SAndroid Build Coastguard Worker
2090*5e7646d2SAndroid Build Coastguard Worker if (ipp_status <= IPP_STATUS_OK_CONFLICTING)
2091*5e7646d2SAndroid Build Coastguard Worker password_tries = 0;
2092*5e7646d2SAndroid Build Coastguard Worker else
2093*5e7646d2SAndroid Build Coastguard Worker {
2094*5e7646d2SAndroid Build Coastguard Worker if (ipp_status != IPP_STATUS_ERROR_SERVICE_UNAVAILABLE &&
2095*5e7646d2SAndroid Build Coastguard Worker ipp_status != IPP_STATUS_ERROR_BUSY)
2096*5e7646d2SAndroid Build Coastguard Worker {
2097*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
2098*5e7646d2SAndroid Build Coastguard Worker ipp_status = IPP_STATUS_OK;
2099*5e7646d2SAndroid Build Coastguard Worker break;
2100*5e7646d2SAndroid Build Coastguard Worker }
2101*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_INTERNAL)
2102*5e7646d2SAndroid Build Coastguard Worker {
2103*5e7646d2SAndroid Build Coastguard Worker waitjob_tries ++;
2104*5e7646d2SAndroid Build Coastguard Worker
2105*5e7646d2SAndroid Build Coastguard Worker if (waitjob_tries > 4)
2106*5e7646d2SAndroid Build Coastguard Worker {
2107*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
2108*5e7646d2SAndroid Build Coastguard Worker ipp_status = IPP_STATUS_OK;
2109*5e7646d2SAndroid Build Coastguard Worker break;
2110*5e7646d2SAndroid Build Coastguard Worker }
2111*5e7646d2SAndroid Build Coastguard Worker }
2112*5e7646d2SAndroid Build Coastguard Worker }
2113*5e7646d2SAndroid Build Coastguard Worker
2114*5e7646d2SAndroid Build Coastguard Worker if (response)
2115*5e7646d2SAndroid Build Coastguard Worker {
2116*5e7646d2SAndroid Build Coastguard Worker if ((job_state = ippFindAttribute(response, "job-state",
2117*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM)) != NULL)
2118*5e7646d2SAndroid Build Coastguard Worker {
2119*5e7646d2SAndroid Build Coastguard Worker /*
2120*5e7646d2SAndroid Build Coastguard Worker * Reflect the remote job state in the local queue...
2121*5e7646d2SAndroid Build Coastguard Worker */
2122*5e7646d2SAndroid Build Coastguard Worker
2123*5e7646d2SAndroid Build Coastguard Worker if (cups_version &&
2124*5e7646d2SAndroid Build Coastguard Worker job_state->values[0].integer >= IPP_JSTATE_PENDING &&
2125*5e7646d2SAndroid Build Coastguard Worker job_state->values[0].integer <= IPP_JSTATE_COMPLETED)
2126*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL,
2127*5e7646d2SAndroid Build Coastguard Worker remote_job_states[job_state->values[0].integer -
2128*5e7646d2SAndroid Build Coastguard Worker IPP_JSTATE_PENDING]);
2129*5e7646d2SAndroid Build Coastguard Worker
2130*5e7646d2SAndroid Build Coastguard Worker if ((job_sheets = ippFindAttribute(response, "job-impressions-completed", IPP_TAG_INTEGER)) == NULL)
2131*5e7646d2SAndroid Build Coastguard Worker job_sheets = ippFindAttribute(response, "job-media-sheets-completed", IPP_TAG_INTEGER);
2132*5e7646d2SAndroid Build Coastguard Worker
2133*5e7646d2SAndroid Build Coastguard Worker if (job_sheets)
2134*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "PAGE: total %d\n",
2135*5e7646d2SAndroid Build Coastguard Worker job_sheets->values[0].integer);
2136*5e7646d2SAndroid Build Coastguard Worker
2137*5e7646d2SAndroid Build Coastguard Worker /*
2138*5e7646d2SAndroid Build Coastguard Worker * Stop polling if the job is finished or pending-held...
2139*5e7646d2SAndroid Build Coastguard Worker */
2140*5e7646d2SAndroid Build Coastguard Worker
2141*5e7646d2SAndroid Build Coastguard Worker if (job_state->values[0].integer > IPP_JSTATE_STOPPED || job_state->values[0].integer == IPP_JSTATE_HELD)
2142*5e7646d2SAndroid Build Coastguard Worker {
2143*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
2144*5e7646d2SAndroid Build Coastguard Worker break;
2145*5e7646d2SAndroid Build Coastguard Worker }
2146*5e7646d2SAndroid Build Coastguard Worker }
2147*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status != IPP_STATUS_ERROR_SERVICE_UNAVAILABLE &&
2148*5e7646d2SAndroid Build Coastguard Worker ipp_status != IPP_STATUS_ERROR_NOT_POSSIBLE &&
2149*5e7646d2SAndroid Build Coastguard Worker ipp_status != IPP_STATUS_ERROR_BUSY)
2150*5e7646d2SAndroid Build Coastguard Worker {
2151*5e7646d2SAndroid Build Coastguard Worker /*
2152*5e7646d2SAndroid Build Coastguard Worker * If the printer does not return a job-state attribute, it does not
2153*5e7646d2SAndroid Build Coastguard Worker * conform to the IPP specification - break out immediately and fail
2154*5e7646d2SAndroid Build Coastguard Worker * the job...
2155*5e7646d2SAndroid Build Coastguard Worker */
2156*5e7646d2SAndroid Build Coastguard Worker
2157*5e7646d2SAndroid Build Coastguard Worker update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
2158*5e7646d2SAndroid Build Coastguard Worker "cups-ipp-missing-job-state");
2159*5e7646d2SAndroid Build Coastguard Worker ipp_status = IPP_STATUS_ERROR_INTERNAL;
2160*5e7646d2SAndroid Build Coastguard Worker break;
2161*5e7646d2SAndroid Build Coastguard Worker }
2162*5e7646d2SAndroid Build Coastguard Worker }
2163*5e7646d2SAndroid Build Coastguard Worker
2164*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
2165*5e7646d2SAndroid Build Coastguard Worker
2166*5e7646d2SAndroid Build Coastguard Worker /*
2167*5e7646d2SAndroid Build Coastguard Worker * Wait before polling again...
2168*5e7646d2SAndroid Build Coastguard Worker */
2169*5e7646d2SAndroid Build Coastguard Worker
2170*5e7646d2SAndroid Build Coastguard Worker sleep((unsigned)delay);
2171*5e7646d2SAndroid Build Coastguard Worker
2172*5e7646d2SAndroid Build Coastguard Worker delay = _cupsNextDelay(delay, &prev_delay);
2173*5e7646d2SAndroid Build Coastguard Worker }
2174*5e7646d2SAndroid Build Coastguard Worker }
2175*5e7646d2SAndroid Build Coastguard Worker
2176*5e7646d2SAndroid Build Coastguard Worker /*
2177*5e7646d2SAndroid Build Coastguard Worker * Cancel the job as needed...
2178*5e7646d2SAndroid Build Coastguard Worker */
2179*5e7646d2SAndroid Build Coastguard Worker
2180*5e7646d2SAndroid Build Coastguard Worker if (job_canceled > 0 && job_id > 0)
2181*5e7646d2SAndroid Build Coastguard Worker {
2182*5e7646d2SAndroid Build Coastguard Worker cancel_job(http, uri, job_id, resource, argv[2], version);
2183*5e7646d2SAndroid Build Coastguard Worker
2184*5e7646d2SAndroid Build Coastguard Worker if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
2185*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR", _("Unable to cancel print job."));
2186*5e7646d2SAndroid Build Coastguard Worker }
2187*5e7646d2SAndroid Build Coastguard Worker
2188*5e7646d2SAndroid Build Coastguard Worker /*
2189*5e7646d2SAndroid Build Coastguard Worker * Check the printer state and report it if necessary...
2190*5e7646d2SAndroid Build Coastguard Worker */
2191*5e7646d2SAndroid Build Coastguard Worker
2192*5e7646d2SAndroid Build Coastguard Worker check_printer_state(http, uri, resource, argv[2], version);
2193*5e7646d2SAndroid Build Coastguard Worker
2194*5e7646d2SAndroid Build Coastguard Worker if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
2195*5e7646d2SAndroid Build Coastguard Worker password_tries = 0;
2196*5e7646d2SAndroid Build Coastguard Worker
2197*5e7646d2SAndroid Build Coastguard Worker /*
2198*5e7646d2SAndroid Build Coastguard Worker * Collect the final page count as needed...
2199*5e7646d2SAndroid Build Coastguard Worker */
2200*5e7646d2SAndroid Build Coastguard Worker
2201*5e7646d2SAndroid Build Coastguard Worker if (have_supplies &&
2202*5e7646d2SAndroid Build Coastguard Worker !backendSNMPSupplies(snmp_fd, &(http->addrlist->addr), &page_count,
2203*5e7646d2SAndroid Build Coastguard Worker NULL) &&
2204*5e7646d2SAndroid Build Coastguard Worker page_count > start_count)
2205*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "PAGE: total %d\n", page_count - start_count);
2206*5e7646d2SAndroid Build Coastguard Worker
2207*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_GSSAPI
2208*5e7646d2SAndroid Build Coastguard Worker /*
2209*5e7646d2SAndroid Build Coastguard Worker * See if we used Kerberos at all...
2210*5e7646d2SAndroid Build Coastguard Worker */
2211*5e7646d2SAndroid Build Coastguard Worker
2212*5e7646d2SAndroid Build Coastguard Worker if (http->gssctx)
2213*5e7646d2SAndroid Build Coastguard Worker auth_info_required = "negotiate";
2214*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI */
2215*5e7646d2SAndroid Build Coastguard Worker
2216*5e7646d2SAndroid Build Coastguard Worker /*
2217*5e7646d2SAndroid Build Coastguard Worker * Free memory...
2218*5e7646d2SAndroid Build Coastguard Worker */
2219*5e7646d2SAndroid Build Coastguard Worker
2220*5e7646d2SAndroid Build Coastguard Worker cleanup:
2221*5e7646d2SAndroid Build Coastguard Worker
2222*5e7646d2SAndroid Build Coastguard Worker cupsFreeOptions(num_options, options);
2223*5e7646d2SAndroid Build Coastguard Worker _ppdCacheDestroy(pc);
2224*5e7646d2SAndroid Build Coastguard Worker ppdClose(ppd);
2225*5e7646d2SAndroid Build Coastguard Worker
2226*5e7646d2SAndroid Build Coastguard Worker httpClose(http);
2227*5e7646d2SAndroid Build Coastguard Worker
2228*5e7646d2SAndroid Build Coastguard Worker ippDelete(supported);
2229*5e7646d2SAndroid Build Coastguard Worker
2230*5e7646d2SAndroid Build Coastguard Worker /*
2231*5e7646d2SAndroid Build Coastguard Worker * Remove the temporary file(s) if necessary...
2232*5e7646d2SAndroid Build Coastguard Worker */
2233*5e7646d2SAndroid Build Coastguard Worker
2234*5e7646d2SAndroid Build Coastguard Worker if (tmpfilename[0])
2235*5e7646d2SAndroid Build Coastguard Worker unlink(tmpfilename);
2236*5e7646d2SAndroid Build Coastguard Worker
2237*5e7646d2SAndroid Build Coastguard Worker /*
2238*5e7646d2SAndroid Build Coastguard Worker * Return the queue status...
2239*5e7646d2SAndroid Build Coastguard Worker */
2240*5e7646d2SAndroid Build Coastguard Worker
2241*5e7646d2SAndroid Build Coastguard Worker if (ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED || ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
2242*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED ||
2243*5e7646d2SAndroid Build Coastguard Worker ipp_status <= IPP_STATUS_OK_CONFLICTING)
2244*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
2245*5e7646d2SAndroid Build Coastguard Worker
2246*5e7646d2SAndroid Build Coastguard Worker if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED)
2247*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: account-info-needed\n", stderr);
2248*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED)
2249*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: account-closed\n", stderr);
2250*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED)
2251*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: account-limit-reached\n", stderr);
2252*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
2253*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: account-authorization-failed\n", stderr);
2254*5e7646d2SAndroid Build Coastguard Worker
2255*5e7646d2SAndroid Build Coastguard Worker // job_canceled can be -1 which should not be treated as CUPS_BACKEND_OK
2256*5e7646d2SAndroid Build Coastguard Worker if (job_canceled > 0)
2257*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
2258*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED || ipp_status == IPP_STATUS_ERROR_FORBIDDEN || ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
2259*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_AUTH_REQUIRED);
2260*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
2261*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
2262*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
2263*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
2264*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_HOLD);
2265*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_INTERNAL)
2266*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_STOP);
2267*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_CONFLICTING || ipp_status == IPP_STATUS_ERROR_REQUEST_ENTITY || ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
2268*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_FAILED);
2269*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE ||
2270*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
2271*5e7646d2SAndroid Build Coastguard Worker ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED || job_canceled < 0)
2272*5e7646d2SAndroid Build Coastguard Worker {
2273*5e7646d2SAndroid Build Coastguard Worker if (ipp_status == IPP_STATUS_ERROR_REQUEST_VALUE)
2274*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR", _("Print job too large."));
2275*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED)
2276*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
2277*5e7646d2SAndroid Build Coastguard Worker _("Printer cannot print supplied content."));
2278*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES)
2279*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
2280*5e7646d2SAndroid Build Coastguard Worker _("Printer cannot print with supplied options."));
2281*5e7646d2SAndroid Build Coastguard Worker else
2282*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR", _("Print job canceled at printer."));
2283*5e7646d2SAndroid Build Coastguard Worker
2284*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_CANCEL);
2285*5e7646d2SAndroid Build Coastguard Worker }
2286*5e7646d2SAndroid Build Coastguard Worker else if (ipp_status > IPP_STATUS_OK_CONFLICTING && ipp_status != IPP_STATUS_ERROR_JOB_CANCELED)
2287*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_RETRY_CURRENT);
2288*5e7646d2SAndroid Build Coastguard Worker else
2289*5e7646d2SAndroid Build Coastguard Worker return (CUPS_BACKEND_OK);
2290*5e7646d2SAndroid Build Coastguard Worker }
2291*5e7646d2SAndroid Build Coastguard Worker
2292*5e7646d2SAndroid Build Coastguard Worker
2293*5e7646d2SAndroid Build Coastguard Worker /*
2294*5e7646d2SAndroid Build Coastguard Worker * 'cancel_job()' - Cancel a print job.
2295*5e7646d2SAndroid Build Coastguard Worker */
2296*5e7646d2SAndroid Build Coastguard Worker
2297*5e7646d2SAndroid Build Coastguard Worker static void
cancel_job(http_t * http,const char * uri,int id,const char * resource,const char * user,int version)2298*5e7646d2SAndroid Build Coastguard Worker cancel_job(http_t *http, /* I - HTTP connection */
2299*5e7646d2SAndroid Build Coastguard Worker const char *uri, /* I - printer-uri */
2300*5e7646d2SAndroid Build Coastguard Worker int id, /* I - job-id */
2301*5e7646d2SAndroid Build Coastguard Worker const char *resource, /* I - Resource path */
2302*5e7646d2SAndroid Build Coastguard Worker const char *user, /* I - requesting-user-name */
2303*5e7646d2SAndroid Build Coastguard Worker int version) /* I - IPP version */
2304*5e7646d2SAndroid Build Coastguard Worker {
2305*5e7646d2SAndroid Build Coastguard Worker ipp_t *request; /* Cancel-Job request */
2306*5e7646d2SAndroid Build Coastguard Worker
2307*5e7646d2SAndroid Build Coastguard Worker
2308*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "INFO", _("Canceling print job."));
2309*5e7646d2SAndroid Build Coastguard Worker
2310*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(IPP_OP_CANCEL_JOB);
2311*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, version / 10, version % 10);
2312*5e7646d2SAndroid Build Coastguard Worker
2313*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2314*5e7646d2SAndroid Build Coastguard Worker NULL, uri);
2315*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", id);
2316*5e7646d2SAndroid Build Coastguard Worker
2317*5e7646d2SAndroid Build Coastguard Worker if (user && user[0])
2318*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
2319*5e7646d2SAndroid Build Coastguard Worker "requesting-user-name", NULL, user);
2320*5e7646d2SAndroid Build Coastguard Worker
2321*5e7646d2SAndroid Build Coastguard Worker /*
2322*5e7646d2SAndroid Build Coastguard Worker * Do the request...
2323*5e7646d2SAndroid Build Coastguard Worker */
2324*5e7646d2SAndroid Build Coastguard Worker
2325*5e7646d2SAndroid Build Coastguard Worker ippDelete(cupsDoRequest(http, request, resource));
2326*5e7646d2SAndroid Build Coastguard Worker }
2327*5e7646d2SAndroid Build Coastguard Worker
2328*5e7646d2SAndroid Build Coastguard Worker
2329*5e7646d2SAndroid Build Coastguard Worker /*
2330*5e7646d2SAndroid Build Coastguard Worker * 'check_printer_state()' - Check the printer state.
2331*5e7646d2SAndroid Build Coastguard Worker */
2332*5e7646d2SAndroid Build Coastguard Worker
2333*5e7646d2SAndroid Build Coastguard Worker static ipp_pstate_t /* O - Current printer-state */
check_printer_state(http_t * http,const char * uri,const char * resource,const char * user,int version)2334*5e7646d2SAndroid Build Coastguard Worker check_printer_state(
2335*5e7646d2SAndroid Build Coastguard Worker http_t *http, /* I - HTTP connection */
2336*5e7646d2SAndroid Build Coastguard Worker const char *uri, /* I - Printer URI */
2337*5e7646d2SAndroid Build Coastguard Worker const char *resource, /* I - Resource path */
2338*5e7646d2SAndroid Build Coastguard Worker const char *user, /* I - Username, if any */
2339*5e7646d2SAndroid Build Coastguard Worker int version) /* I - IPP version */
2340*5e7646d2SAndroid Build Coastguard Worker {
2341*5e7646d2SAndroid Build Coastguard Worker ipp_t *request, /* IPP request */
2342*5e7646d2SAndroid Build Coastguard Worker *response; /* IPP response */
2343*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Attribute in response */
2344*5e7646d2SAndroid Build Coastguard Worker ipp_pstate_t printer_state = IPP_PSTATE_STOPPED;
2345*5e7646d2SAndroid Build Coastguard Worker /* Current printer-state */
2346*5e7646d2SAndroid Build Coastguard Worker
2347*5e7646d2SAndroid Build Coastguard Worker
2348*5e7646d2SAndroid Build Coastguard Worker /*
2349*5e7646d2SAndroid Build Coastguard Worker * Send a Get-Printer-Attributes request and log the results...
2350*5e7646d2SAndroid Build Coastguard Worker */
2351*5e7646d2SAndroid Build Coastguard Worker
2352*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
2353*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, version / 10, version % 10);
2354*5e7646d2SAndroid Build Coastguard Worker
2355*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2356*5e7646d2SAndroid Build Coastguard Worker NULL, uri);
2357*5e7646d2SAndroid Build Coastguard Worker
2358*5e7646d2SAndroid Build Coastguard Worker if (user && user[0])
2359*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
2360*5e7646d2SAndroid Build Coastguard Worker "requesting-user-name", NULL, user);
2361*5e7646d2SAndroid Build Coastguard Worker
2362*5e7646d2SAndroid Build Coastguard Worker ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2363*5e7646d2SAndroid Build Coastguard Worker "requested-attributes",
2364*5e7646d2SAndroid Build Coastguard Worker (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
2365*5e7646d2SAndroid Build Coastguard Worker
2366*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: IPP/%d.%d %s #%d\n", version / 10, version % 10, ippOpString(ippGetOperation(request)), ippGetRequestId(request));
2367*5e7646d2SAndroid Build Coastguard Worker debug_attributes(request);
2368*5e7646d2SAndroid Build Coastguard Worker
2369*5e7646d2SAndroid Build Coastguard Worker if ((response = cupsDoRequest(http, request, resource)) != NULL)
2370*5e7646d2SAndroid Build Coastguard Worker {
2371*5e7646d2SAndroid Build Coastguard Worker report_printer_state(response);
2372*5e7646d2SAndroid Build Coastguard Worker
2373*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(response, "printer-state",
2374*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM)) != NULL)
2375*5e7646d2SAndroid Build Coastguard Worker printer_state = (ipp_pstate_t)attr->values[0].integer;
2376*5e7646d2SAndroid Build Coastguard Worker }
2377*5e7646d2SAndroid Build Coastguard Worker
2378*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
2379*5e7646d2SAndroid Build Coastguard Worker ippErrorString(cupsLastError()), cupsLastErrorString());
2380*5e7646d2SAndroid Build Coastguard Worker debug_attributes(response);
2381*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
2382*5e7646d2SAndroid Build Coastguard Worker
2383*5e7646d2SAndroid Build Coastguard Worker /*
2384*5e7646d2SAndroid Build Coastguard Worker * Return the printer-state value...
2385*5e7646d2SAndroid Build Coastguard Worker */
2386*5e7646d2SAndroid Build Coastguard Worker
2387*5e7646d2SAndroid Build Coastguard Worker return (printer_state);
2388*5e7646d2SAndroid Build Coastguard Worker }
2389*5e7646d2SAndroid Build Coastguard Worker
2390*5e7646d2SAndroid Build Coastguard Worker
2391*5e7646d2SAndroid Build Coastguard Worker /*
2392*5e7646d2SAndroid Build Coastguard Worker * 'debug_attributes()' - Print out the request or response attributes as DEBUG
2393*5e7646d2SAndroid Build Coastguard Worker * messages...
2394*5e7646d2SAndroid Build Coastguard Worker */
2395*5e7646d2SAndroid Build Coastguard Worker
2396*5e7646d2SAndroid Build Coastguard Worker static void
debug_attributes(ipp_t * ipp)2397*5e7646d2SAndroid Build Coastguard Worker debug_attributes(ipp_t *ipp) /* I - Request or response message */
2398*5e7646d2SAndroid Build Coastguard Worker {
2399*5e7646d2SAndroid Build Coastguard Worker ipp_tag_t group; /* Current group */
2400*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Current attribute */
2401*5e7646d2SAndroid Build Coastguard Worker char buffer[1024]; /* Value buffer */
2402*5e7646d2SAndroid Build Coastguard Worker
2403*5e7646d2SAndroid Build Coastguard Worker
2404*5e7646d2SAndroid Build Coastguard Worker for (group = IPP_TAG_ZERO, attr = ippFirstAttribute(ipp);
2405*5e7646d2SAndroid Build Coastguard Worker attr;
2406*5e7646d2SAndroid Build Coastguard Worker attr = ippNextAttribute(ipp))
2407*5e7646d2SAndroid Build Coastguard Worker {
2408*5e7646d2SAndroid Build Coastguard Worker const char *name = ippGetName(attr);
2409*5e7646d2SAndroid Build Coastguard Worker
2410*5e7646d2SAndroid Build Coastguard Worker if (!name)
2411*5e7646d2SAndroid Build Coastguard Worker {
2412*5e7646d2SAndroid Build Coastguard Worker group = IPP_TAG_ZERO;
2413*5e7646d2SAndroid Build Coastguard Worker continue;
2414*5e7646d2SAndroid Build Coastguard Worker }
2415*5e7646d2SAndroid Build Coastguard Worker
2416*5e7646d2SAndroid Build Coastguard Worker if (group != ippGetGroupTag(attr))
2417*5e7646d2SAndroid Build Coastguard Worker {
2418*5e7646d2SAndroid Build Coastguard Worker group = ippGetGroupTag(attr);
2419*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: ---- %s ----\n", ippTagString(group));
2420*5e7646d2SAndroid Build Coastguard Worker }
2421*5e7646d2SAndroid Build Coastguard Worker
2422*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(name, "job-password"))
2423*5e7646d2SAndroid Build Coastguard Worker strlcpy(buffer, "---", sizeof(buffer));
2424*5e7646d2SAndroid Build Coastguard Worker else
2425*5e7646d2SAndroid Build Coastguard Worker ippAttributeString(attr, buffer, sizeof(buffer));
2426*5e7646d2SAndroid Build Coastguard Worker
2427*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: %s %s%s %s\n", name,
2428*5e7646d2SAndroid Build Coastguard Worker ippGetCount(attr) > 1 ? "1setOf " : "",
2429*5e7646d2SAndroid Build Coastguard Worker ippTagString(ippGetValueTag(attr)), buffer);
2430*5e7646d2SAndroid Build Coastguard Worker }
2431*5e7646d2SAndroid Build Coastguard Worker
2432*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: ---- %s ----\n", ippTagString(IPP_TAG_END));
2433*5e7646d2SAndroid Build Coastguard Worker }
2434*5e7646d2SAndroid Build Coastguard Worker
2435*5e7646d2SAndroid Build Coastguard Worker
2436*5e7646d2SAndroid Build Coastguard Worker /*
2437*5e7646d2SAndroid Build Coastguard Worker * 'monitor_printer()' - Monitor the printer state.
2438*5e7646d2SAndroid Build Coastguard Worker */
2439*5e7646d2SAndroid Build Coastguard Worker
2440*5e7646d2SAndroid Build Coastguard Worker static void * /* O - Thread exit code */
monitor_printer(_cups_monitor_t * monitor)2441*5e7646d2SAndroid Build Coastguard Worker monitor_printer(
2442*5e7646d2SAndroid Build Coastguard Worker _cups_monitor_t *monitor) /* I - Monitoring data */
2443*5e7646d2SAndroid Build Coastguard Worker {
2444*5e7646d2SAndroid Build Coastguard Worker http_t *http; /* Connection to printer */
2445*5e7646d2SAndroid Build Coastguard Worker ipp_t *request, /* IPP request */
2446*5e7646d2SAndroid Build Coastguard Worker *response; /* IPP response */
2447*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *attr; /* Attribute in response */
2448*5e7646d2SAndroid Build Coastguard Worker int delay, /* Current delay */
2449*5e7646d2SAndroid Build Coastguard Worker prev_delay; /* Previous delay */
2450*5e7646d2SAndroid Build Coastguard Worker ipp_op_t job_op; /* Operation to use */
2451*5e7646d2SAndroid Build Coastguard Worker int job_id; /* Job ID */
2452*5e7646d2SAndroid Build Coastguard Worker const char *job_name; /* Job name */
2453*5e7646d2SAndroid Build Coastguard Worker ipp_jstate_t job_state; /* Job state */
2454*5e7646d2SAndroid Build Coastguard Worker const char *job_user; /* Job originating user name */
2455*5e7646d2SAndroid Build Coastguard Worker int password_tries = 0; /* Password tries */
2456*5e7646d2SAndroid Build Coastguard Worker
2457*5e7646d2SAndroid Build Coastguard Worker
2458*5e7646d2SAndroid Build Coastguard Worker /*
2459*5e7646d2SAndroid Build Coastguard Worker * Make a copy of the printer connection...
2460*5e7646d2SAndroid Build Coastguard Worker */
2461*5e7646d2SAndroid Build Coastguard Worker
2462*5e7646d2SAndroid Build Coastguard Worker http = httpConnect2(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
2463*5e7646d2SAndroid Build Coastguard Worker monitor->encryption, 1, 0, NULL);
2464*5e7646d2SAndroid Build Coastguard Worker httpSetTimeout(http, 30.0, timeout_cb, NULL);
2465*5e7646d2SAndroid Build Coastguard Worker if (username[0])
2466*5e7646d2SAndroid Build Coastguard Worker cupsSetUser(username);
2467*5e7646d2SAndroid Build Coastguard Worker
2468*5e7646d2SAndroid Build Coastguard Worker cupsSetPasswordCB2((cups_password_cb2_t)password_cb, &password_tries);
2469*5e7646d2SAndroid Build Coastguard Worker
2470*5e7646d2SAndroid Build Coastguard Worker /*
2471*5e7646d2SAndroid Build Coastguard Worker * Loop until the job is canceled, aborted, or completed.
2472*5e7646d2SAndroid Build Coastguard Worker */
2473*5e7646d2SAndroid Build Coastguard Worker
2474*5e7646d2SAndroid Build Coastguard Worker delay = _cupsNextDelay(0, &prev_delay);
2475*5e7646d2SAndroid Build Coastguard Worker
2476*5e7646d2SAndroid Build Coastguard Worker monitor->job_reasons = 0;
2477*5e7646d2SAndroid Build Coastguard Worker
2478*5e7646d2SAndroid Build Coastguard Worker while (monitor->job_state < IPP_JSTATE_CANCELED && !job_canceled)
2479*5e7646d2SAndroid Build Coastguard Worker {
2480*5e7646d2SAndroid Build Coastguard Worker /*
2481*5e7646d2SAndroid Build Coastguard Worker * Reconnect to the printer as needed...
2482*5e7646d2SAndroid Build Coastguard Worker */
2483*5e7646d2SAndroid Build Coastguard Worker
2484*5e7646d2SAndroid Build Coastguard Worker if (httpGetFd(http) < 0)
2485*5e7646d2SAndroid Build Coastguard Worker httpReconnect2(http, 30000, NULL);
2486*5e7646d2SAndroid Build Coastguard Worker
2487*5e7646d2SAndroid Build Coastguard Worker if (httpGetFd(http) >= 0)
2488*5e7646d2SAndroid Build Coastguard Worker {
2489*5e7646d2SAndroid Build Coastguard Worker /*
2490*5e7646d2SAndroid Build Coastguard Worker * Connected, so check on the printer state...
2491*5e7646d2SAndroid Build Coastguard Worker */
2492*5e7646d2SAndroid Build Coastguard Worker
2493*5e7646d2SAndroid Build Coastguard Worker monitor->printer_state = check_printer_state(http, monitor->uri,
2494*5e7646d2SAndroid Build Coastguard Worker monitor->resource,
2495*5e7646d2SAndroid Build Coastguard Worker monitor->user,
2496*5e7646d2SAndroid Build Coastguard Worker monitor->version);
2497*5e7646d2SAndroid Build Coastguard Worker if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
2498*5e7646d2SAndroid Build Coastguard Worker password_tries = 0;
2499*5e7646d2SAndroid Build Coastguard Worker
2500*5e7646d2SAndroid Build Coastguard Worker if (monitor->job_id == 0 && monitor->create_job)
2501*5e7646d2SAndroid Build Coastguard Worker {
2502*5e7646d2SAndroid Build Coastguard Worker /*
2503*5e7646d2SAndroid Build Coastguard Worker * No job-id yet, so continue...
2504*5e7646d2SAndroid Build Coastguard Worker */
2505*5e7646d2SAndroid Build Coastguard Worker
2506*5e7646d2SAndroid Build Coastguard Worker goto monitor_sleep;
2507*5e7646d2SAndroid Build Coastguard Worker }
2508*5e7646d2SAndroid Build Coastguard Worker
2509*5e7646d2SAndroid Build Coastguard Worker /*
2510*5e7646d2SAndroid Build Coastguard Worker * Check the status of the job itself...
2511*5e7646d2SAndroid Build Coastguard Worker */
2512*5e7646d2SAndroid Build Coastguard Worker
2513*5e7646d2SAndroid Build Coastguard Worker job_op = (monitor->job_id > 0 && monitor->get_job_attrs) ?
2514*5e7646d2SAndroid Build Coastguard Worker IPP_OP_GET_JOB_ATTRIBUTES : IPP_OP_GET_JOBS;
2515*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(job_op);
2516*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, monitor->version / 10, monitor->version % 10);
2517*5e7646d2SAndroid Build Coastguard Worker
2518*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2519*5e7646d2SAndroid Build Coastguard Worker NULL, monitor->uri);
2520*5e7646d2SAndroid Build Coastguard Worker if (job_op == IPP_OP_GET_JOB_ATTRIBUTES)
2521*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
2522*5e7646d2SAndroid Build Coastguard Worker monitor->job_id);
2523*5e7646d2SAndroid Build Coastguard Worker
2524*5e7646d2SAndroid Build Coastguard Worker if (monitor->user && monitor->user[0])
2525*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
2526*5e7646d2SAndroid Build Coastguard Worker "requesting-user-name", NULL, monitor->user);
2527*5e7646d2SAndroid Build Coastguard Worker
2528*5e7646d2SAndroid Build Coastguard Worker ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2529*5e7646d2SAndroid Build Coastguard Worker "requested-attributes",
2530*5e7646d2SAndroid Build Coastguard Worker (int)(sizeof(jattrs) / sizeof(jattrs[0])), NULL, jattrs);
2531*5e7646d2SAndroid Build Coastguard Worker
2532*5e7646d2SAndroid Build Coastguard Worker /*
2533*5e7646d2SAndroid Build Coastguard Worker * Do the request...
2534*5e7646d2SAndroid Build Coastguard Worker */
2535*5e7646d2SAndroid Build Coastguard Worker
2536*5e7646d2SAndroid Build Coastguard Worker response = cupsDoRequest(http, request, monitor->resource);
2537*5e7646d2SAndroid Build Coastguard Worker
2538*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: (monitor) %s: %s (%s)\n", ippOpString(job_op),
2539*5e7646d2SAndroid Build Coastguard Worker ippErrorString(cupsLastError()), cupsLastErrorString());
2540*5e7646d2SAndroid Build Coastguard Worker
2541*5e7646d2SAndroid Build Coastguard Worker if (cupsLastError() <= IPP_STATUS_OK_CONFLICTING)
2542*5e7646d2SAndroid Build Coastguard Worker password_tries = 0;
2543*5e7646d2SAndroid Build Coastguard Worker
2544*5e7646d2SAndroid Build Coastguard Worker if (job_op == IPP_OP_GET_JOB_ATTRIBUTES)
2545*5e7646d2SAndroid Build Coastguard Worker {
2546*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(response, "job-state",
2547*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_ENUM)) != NULL)
2548*5e7646d2SAndroid Build Coastguard Worker monitor->job_state = (ipp_jstate_t)attr->values[0].integer;
2549*5e7646d2SAndroid Build Coastguard Worker else
2550*5e7646d2SAndroid Build Coastguard Worker monitor->job_state = IPP_JSTATE_COMPLETED;
2551*5e7646d2SAndroid Build Coastguard Worker }
2552*5e7646d2SAndroid Build Coastguard Worker else if (response)
2553*5e7646d2SAndroid Build Coastguard Worker {
2554*5e7646d2SAndroid Build Coastguard Worker for (attr = response->attrs; attr; attr = attr->next)
2555*5e7646d2SAndroid Build Coastguard Worker {
2556*5e7646d2SAndroid Build Coastguard Worker job_id = 0;
2557*5e7646d2SAndroid Build Coastguard Worker job_name = NULL;
2558*5e7646d2SAndroid Build Coastguard Worker job_state = IPP_JSTATE_PENDING;
2559*5e7646d2SAndroid Build Coastguard Worker job_user = NULL;
2560*5e7646d2SAndroid Build Coastguard Worker
2561*5e7646d2SAndroid Build Coastguard Worker while (attr && attr->group_tag != IPP_TAG_JOB)
2562*5e7646d2SAndroid Build Coastguard Worker attr = attr->next;
2563*5e7646d2SAndroid Build Coastguard Worker
2564*5e7646d2SAndroid Build Coastguard Worker if (!attr)
2565*5e7646d2SAndroid Build Coastguard Worker break;
2566*5e7646d2SAndroid Build Coastguard Worker
2567*5e7646d2SAndroid Build Coastguard Worker while (attr && attr->group_tag == IPP_TAG_JOB)
2568*5e7646d2SAndroid Build Coastguard Worker {
2569*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->name, "job-id") &&
2570*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_INTEGER)
2571*5e7646d2SAndroid Build Coastguard Worker job_id = attr->values[0].integer;
2572*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "job-name") &&
2573*5e7646d2SAndroid Build Coastguard Worker (attr->value_tag == IPP_TAG_NAME ||
2574*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_NAMELANG))
2575*5e7646d2SAndroid Build Coastguard Worker job_name = attr->values[0].string.text;
2576*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "job-state") &&
2577*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_ENUM)
2578*5e7646d2SAndroid Build Coastguard Worker job_state = (ipp_jstate_t)attr->values[0].integer;
2579*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->name, "job-originating-user-name") &&
2580*5e7646d2SAndroid Build Coastguard Worker (attr->value_tag == IPP_TAG_NAME ||
2581*5e7646d2SAndroid Build Coastguard Worker attr->value_tag == IPP_TAG_NAMELANG))
2582*5e7646d2SAndroid Build Coastguard Worker job_user = attr->values[0].string.text;
2583*5e7646d2SAndroid Build Coastguard Worker
2584*5e7646d2SAndroid Build Coastguard Worker attr = attr->next;
2585*5e7646d2SAndroid Build Coastguard Worker }
2586*5e7646d2SAndroid Build Coastguard Worker
2587*5e7646d2SAndroid Build Coastguard Worker if (job_id > 0 && job_name && !strcmp(job_name, monitor->job_name) &&
2588*5e7646d2SAndroid Build Coastguard Worker job_user && monitor->user && !strcmp(job_user, monitor->user))
2589*5e7646d2SAndroid Build Coastguard Worker {
2590*5e7646d2SAndroid Build Coastguard Worker monitor->job_id = job_id;
2591*5e7646d2SAndroid Build Coastguard Worker monitor->job_state = job_state;
2592*5e7646d2SAndroid Build Coastguard Worker break;
2593*5e7646d2SAndroid Build Coastguard Worker }
2594*5e7646d2SAndroid Build Coastguard Worker
2595*5e7646d2SAndroid Build Coastguard Worker if (!attr)
2596*5e7646d2SAndroid Build Coastguard Worker break;
2597*5e7646d2SAndroid Build Coastguard Worker }
2598*5e7646d2SAndroid Build Coastguard Worker }
2599*5e7646d2SAndroid Build Coastguard Worker
2600*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: (monitor) job-state = %s\n", ippEnumString("job-state", (int)monitor->job_state));
2601*5e7646d2SAndroid Build Coastguard Worker
2602*5e7646d2SAndroid Build Coastguard Worker if (!job_canceled &&
2603*5e7646d2SAndroid Build Coastguard Worker (monitor->job_state == IPP_JSTATE_CANCELED ||
2604*5e7646d2SAndroid Build Coastguard Worker monitor->job_state == IPP_JSTATE_ABORTED))
2605*5e7646d2SAndroid Build Coastguard Worker {
2606*5e7646d2SAndroid Build Coastguard Worker job_canceled = -1;
2607*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: (monitor) job_canceled = -1\n");
2608*5e7646d2SAndroid Build Coastguard Worker }
2609*5e7646d2SAndroid Build Coastguard Worker
2610*5e7646d2SAndroid Build Coastguard Worker if ((attr = ippFindAttribute(response, "job-state-reasons",
2611*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
2612*5e7646d2SAndroid Build Coastguard Worker {
2613*5e7646d2SAndroid Build Coastguard Worker int i, new_reasons = 0; /* Looping var, new reasons */
2614*5e7646d2SAndroid Build Coastguard Worker
2615*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
2616*5e7646d2SAndroid Build Coastguard Worker {
2617*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(attr->values[i].string.text, "account-authorization-failed"))
2618*5e7646d2SAndroid Build Coastguard Worker new_reasons |= _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED;
2619*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[i].string.text, "account-closed"))
2620*5e7646d2SAndroid Build Coastguard Worker new_reasons |= _CUPS_JSR_ACCOUNT_CLOSED;
2621*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[i].string.text, "account-info-needed"))
2622*5e7646d2SAndroid Build Coastguard Worker new_reasons |= _CUPS_JSR_ACCOUNT_INFO_NEEDED;
2623*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[i].string.text, "account-limit-reached"))
2624*5e7646d2SAndroid Build Coastguard Worker new_reasons |= _CUPS_JSR_ACCOUNT_LIMIT_REACHED;
2625*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[i].string.text, "job-password-wait"))
2626*5e7646d2SAndroid Build Coastguard Worker new_reasons |= _CUPS_JSR_JOB_PASSWORD_WAIT;
2627*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[i].string.text, "job-release-wait"))
2628*5e7646d2SAndroid Build Coastguard Worker new_reasons |= _CUPS_JSR_JOB_RELEASE_WAIT;
2629*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[i].string.text, "document-format-error"))
2630*5e7646d2SAndroid Build Coastguard Worker new_reasons |= _CUPS_JSR_DOCUMENT_FORMAT_ERROR;
2631*5e7646d2SAndroid Build Coastguard Worker else if (!strcmp(attr->values[i].string.text, "document-unprintable"))
2632*5e7646d2SAndroid Build Coastguard Worker new_reasons |= _CUPS_JSR_DOCUMENT_UNPRINTABLE;
2633*5e7646d2SAndroid Build Coastguard Worker
2634*5e7646d2SAndroid Build Coastguard Worker if (!job_canceled && (!strncmp(attr->values[i].string.text, "job-canceled-", 13) || !strcmp(attr->values[i].string.text, "aborted-by-system")))
2635*5e7646d2SAndroid Build Coastguard Worker job_canceled = 1;
2636*5e7646d2SAndroid Build Coastguard Worker }
2637*5e7646d2SAndroid Build Coastguard Worker
2638*5e7646d2SAndroid Build Coastguard Worker if (new_reasons != monitor->job_reasons)
2639*5e7646d2SAndroid Build Coastguard Worker {
2640*5e7646d2SAndroid Build Coastguard Worker if (new_reasons & _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED)
2641*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: account-authorization-failed\n", stderr);
2642*5e7646d2SAndroid Build Coastguard Worker else if (new_reasons & _CUPS_JSR_ACCOUNT_CLOSED)
2643*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: account-closed\n", stderr);
2644*5e7646d2SAndroid Build Coastguard Worker else if (new_reasons & _CUPS_JSR_ACCOUNT_INFO_NEEDED)
2645*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: account-info-needed\n", stderr);
2646*5e7646d2SAndroid Build Coastguard Worker else if (new_reasons & _CUPS_JSR_ACCOUNT_LIMIT_REACHED)
2647*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: account-limit-reached\n", stderr);
2648*5e7646d2SAndroid Build Coastguard Worker else if (new_reasons & _CUPS_JSR_JOB_PASSWORD_WAIT)
2649*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: job-password-wait\n", stderr);
2650*5e7646d2SAndroid Build Coastguard Worker else if (new_reasons & _CUPS_JSR_JOB_RELEASE_WAIT)
2651*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: job-release-wait\n", stderr);
2652*5e7646d2SAndroid Build Coastguard Worker else if (new_reasons & (_CUPS_JSR_DOCUMENT_FORMAT_ERROR | _CUPS_JSR_DOCUMENT_UNPRINTABLE))
2653*5e7646d2SAndroid Build Coastguard Worker {
2654*5e7646d2SAndroid Build Coastguard Worker if (monitor->retryable)
2655*5e7646d2SAndroid Build Coastguard Worker {
2656*5e7646d2SAndroid Build Coastguard Worker /*
2657*5e7646d2SAndroid Build Coastguard Worker * Can't print this, so retry as raster...
2658*5e7646d2SAndroid Build Coastguard Worker */
2659*5e7646d2SAndroid Build Coastguard Worker
2660*5e7646d2SAndroid Build Coastguard Worker job_canceled = 1;
2661*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: cups-retry-as-raster\n", stderr);
2662*5e7646d2SAndroid Build Coastguard Worker }
2663*5e7646d2SAndroid Build Coastguard Worker else if (new_reasons & _CUPS_JSR_DOCUMENT_FORMAT_ERROR)
2664*5e7646d2SAndroid Build Coastguard Worker {
2665*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: document-format-error\n", stderr);
2666*5e7646d2SAndroid Build Coastguard Worker }
2667*5e7646d2SAndroid Build Coastguard Worker else
2668*5e7646d2SAndroid Build Coastguard Worker {
2669*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: document-unprintable\n", stderr);
2670*5e7646d2SAndroid Build Coastguard Worker }
2671*5e7646d2SAndroid Build Coastguard Worker }
2672*5e7646d2SAndroid Build Coastguard Worker else
2673*5e7646d2SAndroid Build Coastguard Worker fputs("JOBSTATE: job-printing\n", stderr);
2674*5e7646d2SAndroid Build Coastguard Worker
2675*5e7646d2SAndroid Build Coastguard Worker monitor->job_reasons = new_reasons;
2676*5e7646d2SAndroid Build Coastguard Worker }
2677*5e7646d2SAndroid Build Coastguard Worker }
2678*5e7646d2SAndroid Build Coastguard Worker
2679*5e7646d2SAndroid Build Coastguard Worker ippDelete(response);
2680*5e7646d2SAndroid Build Coastguard Worker
2681*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: (monitor) job-state = %s\n", ippEnumString("job-state", (int)monitor->job_state));
2682*5e7646d2SAndroid Build Coastguard Worker
2683*5e7646d2SAndroid Build Coastguard Worker if (!job_canceled &&
2684*5e7646d2SAndroid Build Coastguard Worker (monitor->job_state == IPP_JSTATE_CANCELED ||
2685*5e7646d2SAndroid Build Coastguard Worker monitor->job_state == IPP_JSTATE_ABORTED))
2686*5e7646d2SAndroid Build Coastguard Worker job_canceled = -1;
2687*5e7646d2SAndroid Build Coastguard Worker }
2688*5e7646d2SAndroid Build Coastguard Worker
2689*5e7646d2SAndroid Build Coastguard Worker /*
2690*5e7646d2SAndroid Build Coastguard Worker * Sleep for N seconds...
2691*5e7646d2SAndroid Build Coastguard Worker */
2692*5e7646d2SAndroid Build Coastguard Worker
2693*5e7646d2SAndroid Build Coastguard Worker monitor_sleep:
2694*5e7646d2SAndroid Build Coastguard Worker
2695*5e7646d2SAndroid Build Coastguard Worker sleep((unsigned)delay);
2696*5e7646d2SAndroid Build Coastguard Worker
2697*5e7646d2SAndroid Build Coastguard Worker delay = _cupsNextDelay(delay, &prev_delay);
2698*5e7646d2SAndroid Build Coastguard Worker }
2699*5e7646d2SAndroid Build Coastguard Worker
2700*5e7646d2SAndroid Build Coastguard Worker /*
2701*5e7646d2SAndroid Build Coastguard Worker * Cancel the job if necessary...
2702*5e7646d2SAndroid Build Coastguard Worker */
2703*5e7646d2SAndroid Build Coastguard Worker
2704*5e7646d2SAndroid Build Coastguard Worker if (job_canceled > 0 && monitor->job_id > 0)
2705*5e7646d2SAndroid Build Coastguard Worker {
2706*5e7646d2SAndroid Build Coastguard Worker if (httpGetFd(http) < 0)
2707*5e7646d2SAndroid Build Coastguard Worker httpReconnect2(http, 30000, NULL);
2708*5e7646d2SAndroid Build Coastguard Worker
2709*5e7646d2SAndroid Build Coastguard Worker if (httpGetFd(http) >= 0)
2710*5e7646d2SAndroid Build Coastguard Worker {
2711*5e7646d2SAndroid Build Coastguard Worker cancel_job(http, monitor->uri, monitor->job_id, monitor->resource,
2712*5e7646d2SAndroid Build Coastguard Worker monitor->user, monitor->version);
2713*5e7646d2SAndroid Build Coastguard Worker
2714*5e7646d2SAndroid Build Coastguard Worker if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
2715*5e7646d2SAndroid Build Coastguard Worker {
2716*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: (monitor) cancel_job() = %s\n", cupsLastErrorString());
2717*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR", _("Unable to cancel print job."));
2718*5e7646d2SAndroid Build Coastguard Worker }
2719*5e7646d2SAndroid Build Coastguard Worker }
2720*5e7646d2SAndroid Build Coastguard Worker }
2721*5e7646d2SAndroid Build Coastguard Worker
2722*5e7646d2SAndroid Build Coastguard Worker /*
2723*5e7646d2SAndroid Build Coastguard Worker * Cleanup and return...
2724*5e7646d2SAndroid Build Coastguard Worker */
2725*5e7646d2SAndroid Build Coastguard Worker
2726*5e7646d2SAndroid Build Coastguard Worker httpClose(http);
2727*5e7646d2SAndroid Build Coastguard Worker
2728*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2729*5e7646d2SAndroid Build Coastguard Worker }
2730*5e7646d2SAndroid Build Coastguard Worker
2731*5e7646d2SAndroid Build Coastguard Worker
2732*5e7646d2SAndroid Build Coastguard Worker /*
2733*5e7646d2SAndroid Build Coastguard Worker * 'new_request()' - Create a new print creation or validation request.
2734*5e7646d2SAndroid Build Coastguard Worker */
2735*5e7646d2SAndroid Build Coastguard Worker
2736*5e7646d2SAndroid Build Coastguard Worker static ipp_t * /* O - Request data */
new_request(ipp_op_t op,int version,const char * uri,const char * user,const char * title,int num_options,cups_option_t * options,const char * compression,int copies,const char * format,_ppd_cache_t * pc,ppd_file_t * ppd,ipp_attribute_t * media_col_sup,ipp_attribute_t * doc_handling_sup,ipp_attribute_t * print_color_mode_sup)2737*5e7646d2SAndroid Build Coastguard Worker new_request(
2738*5e7646d2SAndroid Build Coastguard Worker ipp_op_t op, /* I - IPP operation code */
2739*5e7646d2SAndroid Build Coastguard Worker int version, /* I - IPP version number */
2740*5e7646d2SAndroid Build Coastguard Worker const char *uri, /* I - printer-uri value */
2741*5e7646d2SAndroid Build Coastguard Worker const char *user, /* I - requesting-user-name value */
2742*5e7646d2SAndroid Build Coastguard Worker const char *title, /* I - job-name value */
2743*5e7646d2SAndroid Build Coastguard Worker int num_options, /* I - Number of options to send */
2744*5e7646d2SAndroid Build Coastguard Worker cups_option_t *options, /* I - Options to send */
2745*5e7646d2SAndroid Build Coastguard Worker const char *compression, /* I - compression value or NULL */
2746*5e7646d2SAndroid Build Coastguard Worker int copies, /* I - copies value or 0 */
2747*5e7646d2SAndroid Build Coastguard Worker const char *format, /* I - document-format value or NULL */
2748*5e7646d2SAndroid Build Coastguard Worker _ppd_cache_t *pc, /* I - PPD cache and mapping data */
2749*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd, /* I - PPD file data */
2750*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *media_col_sup, /* I - media-col-supported values */
2751*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *doc_handling_sup, /* I - multiple-document-handling-supported values */
2752*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *print_color_mode_sup)
2753*5e7646d2SAndroid Build Coastguard Worker /* I - Printer supports print-color-mode */
2754*5e7646d2SAndroid Build Coastguard Worker {
2755*5e7646d2SAndroid Build Coastguard Worker ipp_t *request; /* Request data */
2756*5e7646d2SAndroid Build Coastguard Worker const char *keyword; /* PWG keyword */
2757*5e7646d2SAndroid Build Coastguard Worker
2758*5e7646d2SAndroid Build Coastguard Worker
2759*5e7646d2SAndroid Build Coastguard Worker /*
2760*5e7646d2SAndroid Build Coastguard Worker * Create the IPP request...
2761*5e7646d2SAndroid Build Coastguard Worker */
2762*5e7646d2SAndroid Build Coastguard Worker
2763*5e7646d2SAndroid Build Coastguard Worker request = ippNewRequest(op);
2764*5e7646d2SAndroid Build Coastguard Worker ippSetVersion(request, version / 10, version % 10);
2765*5e7646d2SAndroid Build Coastguard Worker
2766*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: %s IPP/%d.%d\n",
2767*5e7646d2SAndroid Build Coastguard Worker ippOpString(request->request.op.operation_id),
2768*5e7646d2SAndroid Build Coastguard Worker request->request.op.version[0],
2769*5e7646d2SAndroid Build Coastguard Worker request->request.op.version[1]);
2770*5e7646d2SAndroid Build Coastguard Worker
2771*5e7646d2SAndroid Build Coastguard Worker /*
2772*5e7646d2SAndroid Build Coastguard Worker * Add standard attributes...
2773*5e7646d2SAndroid Build Coastguard Worker */
2774*5e7646d2SAndroid Build Coastguard Worker
2775*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
2776*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: printer-uri=\"%s\"\n", uri);
2777*5e7646d2SAndroid Build Coastguard Worker
2778*5e7646d2SAndroid Build Coastguard Worker if (user && *user)
2779*5e7646d2SAndroid Build Coastguard Worker {
2780*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user);
2781*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: requesting-user-name=\"%s\"\n", user);
2782*5e7646d2SAndroid Build Coastguard Worker }
2783*5e7646d2SAndroid Build Coastguard Worker
2784*5e7646d2SAndroid Build Coastguard Worker if (title && *title)
2785*5e7646d2SAndroid Build Coastguard Worker {
2786*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title);
2787*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: job-name=\"%s\"\n", title);
2788*5e7646d2SAndroid Build Coastguard Worker }
2789*5e7646d2SAndroid Build Coastguard Worker
2790*5e7646d2SAndroid Build Coastguard Worker if (format && op != IPP_OP_CREATE_JOB)
2791*5e7646d2SAndroid Build Coastguard Worker {
2792*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, format);
2793*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: document-format=\"%s\"\n", format);
2794*5e7646d2SAndroid Build Coastguard Worker }
2795*5e7646d2SAndroid Build Coastguard Worker
2796*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
2797*5e7646d2SAndroid Build Coastguard Worker if (compression && op != IPP_OP_CREATE_JOB && op != IPP_OP_VALIDATE_JOB)
2798*5e7646d2SAndroid Build Coastguard Worker {
2799*5e7646d2SAndroid Build Coastguard Worker ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "compression", NULL, compression);
2800*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: compression=\"%s\"\n", compression);
2801*5e7646d2SAndroid Build Coastguard Worker }
2802*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_LIBZ */
2803*5e7646d2SAndroid Build Coastguard Worker
2804*5e7646d2SAndroid Build Coastguard Worker /*
2805*5e7646d2SAndroid Build Coastguard Worker * Handle options on the command-line...
2806*5e7646d2SAndroid Build Coastguard Worker */
2807*5e7646d2SAndroid Build Coastguard Worker
2808*5e7646d2SAndroid Build Coastguard Worker if (num_options > 0)
2809*5e7646d2SAndroid Build Coastguard Worker {
2810*5e7646d2SAndroid Build Coastguard Worker if (pc)
2811*5e7646d2SAndroid Build Coastguard Worker {
2812*5e7646d2SAndroid Build Coastguard Worker /*
2813*5e7646d2SAndroid Build Coastguard Worker * Send standard IPP attributes...
2814*5e7646d2SAndroid Build Coastguard Worker */
2815*5e7646d2SAndroid Build Coastguard Worker
2816*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Adding standard IPP operation/job attributes.\n", stderr);
2817*5e7646d2SAndroid Build Coastguard Worker
2818*5e7646d2SAndroid Build Coastguard Worker copies = _cupsConvertOptions(request, ppd, pc, media_col_sup, doc_handling_sup, print_color_mode_sup, user, format, copies, num_options, options);
2819*5e7646d2SAndroid Build Coastguard Worker
2820*5e7646d2SAndroid Build Coastguard Worker /*
2821*5e7646d2SAndroid Build Coastguard Worker * Map FaxOut options...
2822*5e7646d2SAndroid Build Coastguard Worker */
2823*5e7646d2SAndroid Build Coastguard Worker
2824*5e7646d2SAndroid Build Coastguard Worker if ((keyword = cupsGetOption("phone", num_options, options)) != NULL)
2825*5e7646d2SAndroid Build Coastguard Worker {
2826*5e7646d2SAndroid Build Coastguard Worker ipp_t *destination; /* destination collection */
2827*5e7646d2SAndroid Build Coastguard Worker char phone[1024], /* Phone number string */
2828*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into string */
2829*5e7646d2SAndroid Build Coastguard Worker tel_uri[1024]; /* tel: URI */
2830*5e7646d2SAndroid Build Coastguard Worker static const char * const allowed = "0123456789#*-+.()pw";
2831*5e7646d2SAndroid Build Coastguard Worker /* Allowed characters */
2832*5e7646d2SAndroid Build Coastguard Worker
2833*5e7646d2SAndroid Build Coastguard Worker destination = ippNew();
2834*5e7646d2SAndroid Build Coastguard Worker
2835*5e7646d2SAndroid Build Coastguard Worker /*
2836*5e7646d2SAndroid Build Coastguard Worker * Unescape and filter out spaces and other characters that are not
2837*5e7646d2SAndroid Build Coastguard Worker * allowed in a tel: URI.
2838*5e7646d2SAndroid Build Coastguard Worker */
2839*5e7646d2SAndroid Build Coastguard Worker
2840*5e7646d2SAndroid Build Coastguard Worker _httpDecodeURI(phone, keyword, sizeof(phone));
2841*5e7646d2SAndroid Build Coastguard Worker ptr = phone;
2842*5e7646d2SAndroid Build Coastguard Worker
2843*5e7646d2SAndroid Build Coastguard Worker /*
2844*5e7646d2SAndroid Build Coastguard Worker * Weed out "Custom." in the beginning, this allows to put the
2845*5e7646d2SAndroid Build Coastguard Worker * "phone" option as custom string option into the PPD so that
2846*5e7646d2SAndroid Build Coastguard Worker * print dialogs not supporting fax display the option and
2847*5e7646d2SAndroid Build Coastguard Worker * allow entering the phone number. Print dialogs also send "None"
2848*5e7646d2SAndroid Build Coastguard Worker * if no phone number got entered, filter this, too.
2849*5e7646d2SAndroid Build Coastguard Worker */
2850*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(phone, "None"))
2851*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
2852*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strncasecmp(phone, "Custom.", 7))
2853*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 7);
2854*5e7646d2SAndroid Build Coastguard Worker
2855*5e7646d2SAndroid Build Coastguard Worker for (; *ptr;)
2856*5e7646d2SAndroid Build Coastguard Worker {
2857*5e7646d2SAndroid Build Coastguard Worker if (*ptr == ',')
2858*5e7646d2SAndroid Build Coastguard Worker *ptr = 'p';
2859*5e7646d2SAndroid Build Coastguard Worker else if (!strchr(allowed, *ptr))
2860*5e7646d2SAndroid Build Coastguard Worker _cups_strcpy(ptr, ptr + 1);
2861*5e7646d2SAndroid Build Coastguard Worker else
2862*5e7646d2SAndroid Build Coastguard Worker ptr ++;
2863*5e7646d2SAndroid Build Coastguard Worker }
2864*5e7646d2SAndroid Build Coastguard Worker
2865*5e7646d2SAndroid Build Coastguard Worker if (strlen(phone) > 0)
2866*5e7646d2SAndroid Build Coastguard Worker {
2867*5e7646d2SAndroid Build Coastguard Worker httpAssembleURI(HTTP_URI_CODING_ALL, tel_uri, sizeof(tel_uri), "tel", NULL, NULL, 0, phone);
2868*5e7646d2SAndroid Build Coastguard Worker ippAddString(destination, IPP_TAG_JOB, IPP_TAG_URI, "destination-uri", NULL, tel_uri);
2869*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Faxing to phone %s; destination-uri: %s\n", phone, tel_uri);
2870*5e7646d2SAndroid Build Coastguard Worker
2871*5e7646d2SAndroid Build Coastguard Worker if ((keyword = cupsGetOption("faxPrefix", num_options, options)) != NULL && *keyword)
2872*5e7646d2SAndroid Build Coastguard Worker {
2873*5e7646d2SAndroid Build Coastguard Worker char predial[1024]; /* Pre-dial string */
2874*5e7646d2SAndroid Build Coastguard Worker
2875*5e7646d2SAndroid Build Coastguard Worker _httpDecodeURI(predial, keyword, sizeof(predial));
2876*5e7646d2SAndroid Build Coastguard Worker ptr = predial;
2877*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(ptr, "None"))
2878*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
2879*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strncasecmp(ptr, "Custom.", 7))
2880*5e7646d2SAndroid Build Coastguard Worker ptr += 7;
2881*5e7646d2SAndroid Build Coastguard Worker if (strlen(ptr) > 0)
2882*5e7646d2SAndroid Build Coastguard Worker {
2883*5e7646d2SAndroid Build Coastguard Worker ippAddString(destination, IPP_TAG_JOB, IPP_TAG_TEXT, "pre-dial-string", NULL, ptr);
2884*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Pre-dialing %s; pre-dial-string: %s\n", ptr, ptr);
2885*5e7646d2SAndroid Build Coastguard Worker }
2886*5e7646d2SAndroid Build Coastguard Worker else
2887*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "WARNING: Pre-dial number for fax not valid! Sending fax without pre-dial number.\n");
2888*5e7646d2SAndroid Build Coastguard Worker }
2889*5e7646d2SAndroid Build Coastguard Worker
2890*5e7646d2SAndroid Build Coastguard Worker ippAddCollection(request, IPP_TAG_JOB, "destination-uris", destination);
2891*5e7646d2SAndroid Build Coastguard Worker ippDelete(destination);
2892*5e7646d2SAndroid Build Coastguard Worker }
2893*5e7646d2SAndroid Build Coastguard Worker else
2894*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: Phone number for fax not valid! Fax cannot be sent.\n");
2895*5e7646d2SAndroid Build Coastguard Worker }
2896*5e7646d2SAndroid Build Coastguard Worker }
2897*5e7646d2SAndroid Build Coastguard Worker else
2898*5e7646d2SAndroid Build Coastguard Worker {
2899*5e7646d2SAndroid Build Coastguard Worker /*
2900*5e7646d2SAndroid Build Coastguard Worker * When talking to another CUPS server, send all options...
2901*5e7646d2SAndroid Build Coastguard Worker */
2902*5e7646d2SAndroid Build Coastguard Worker
2903*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Adding all operation/job attributes.\n", stderr);
2904*5e7646d2SAndroid Build Coastguard Worker cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
2905*5e7646d2SAndroid Build Coastguard Worker cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
2906*5e7646d2SAndroid Build Coastguard Worker }
2907*5e7646d2SAndroid Build Coastguard Worker
2908*5e7646d2SAndroid Build Coastguard Worker if (copies > 1 && (!pc || copies <= pc->max_copies))
2909*5e7646d2SAndroid Build Coastguard Worker ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", copies);
2910*5e7646d2SAndroid Build Coastguard Worker }
2911*5e7646d2SAndroid Build Coastguard Worker
2912*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: IPP/%d.%d %s #%d\n", version / 10, version % 10, ippOpString(ippGetOperation(request)), ippGetRequestId(request));
2913*5e7646d2SAndroid Build Coastguard Worker debug_attributes(request);
2914*5e7646d2SAndroid Build Coastguard Worker
2915*5e7646d2SAndroid Build Coastguard Worker return (request);
2916*5e7646d2SAndroid Build Coastguard Worker }
2917*5e7646d2SAndroid Build Coastguard Worker
2918*5e7646d2SAndroid Build Coastguard Worker
2919*5e7646d2SAndroid Build Coastguard Worker /*
2920*5e7646d2SAndroid Build Coastguard Worker * 'password_cb()' - Disable the password prompt for cupsDoFileRequest().
2921*5e7646d2SAndroid Build Coastguard Worker */
2922*5e7646d2SAndroid Build Coastguard Worker
2923*5e7646d2SAndroid Build Coastguard Worker static const char * /* O - Password */
password_cb(const char * prompt,http_t * http,const char * method,const char * resource,int * password_tries)2924*5e7646d2SAndroid Build Coastguard Worker password_cb(const char *prompt, /* I - Prompt (not used) */
2925*5e7646d2SAndroid Build Coastguard Worker http_t *http, /* I - Connection */
2926*5e7646d2SAndroid Build Coastguard Worker const char *method, /* I - Request method (not used) */
2927*5e7646d2SAndroid Build Coastguard Worker const char *resource, /* I - Resource path (not used) */
2928*5e7646d2SAndroid Build Coastguard Worker int *password_tries) /* I - Password tries */
2929*5e7646d2SAndroid Build Coastguard Worker {
2930*5e7646d2SAndroid Build Coastguard Worker char def_username[HTTP_MAX_VALUE]; /* Default username */
2931*5e7646d2SAndroid Build Coastguard Worker
2932*5e7646d2SAndroid Build Coastguard Worker
2933*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: password_cb(prompt=\"%s\", http=%p, method=\"%s\", "
2934*5e7646d2SAndroid Build Coastguard Worker "resource=\"%s\", password_tries=%p(%d)), password=%p\n",
2935*5e7646d2SAndroid Build Coastguard Worker prompt, http, method, resource, password_tries, *password_tries,
2936*5e7646d2SAndroid Build Coastguard Worker password);
2937*5e7646d2SAndroid Build Coastguard Worker
2938*5e7646d2SAndroid Build Coastguard Worker (void)prompt;
2939*5e7646d2SAndroid Build Coastguard Worker (void)method;
2940*5e7646d2SAndroid Build Coastguard Worker (void)resource;
2941*5e7646d2SAndroid Build Coastguard Worker
2942*5e7646d2SAndroid Build Coastguard Worker if (!uri_credentials)
2943*5e7646d2SAndroid Build Coastguard Worker {
2944*5e7646d2SAndroid Build Coastguard Worker /*
2945*5e7646d2SAndroid Build Coastguard Worker * Remember that we need to authenticate...
2946*5e7646d2SAndroid Build Coastguard Worker */
2947*5e7646d2SAndroid Build Coastguard Worker
2948*5e7646d2SAndroid Build Coastguard Worker auth_info_required = "username,password";
2949*5e7646d2SAndroid Build Coastguard Worker
2950*5e7646d2SAndroid Build Coastguard Worker if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username",
2951*5e7646d2SAndroid Build Coastguard Worker def_username))
2952*5e7646d2SAndroid Build Coastguard Worker {
2953*5e7646d2SAndroid Build Coastguard Worker char quoted[HTTP_MAX_VALUE * 2 + 4];
2954*5e7646d2SAndroid Build Coastguard Worker /* Quoted string */
2955*5e7646d2SAndroid Build Coastguard Worker
2956*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ATTR: auth-info-default=%s,\n",
2957*5e7646d2SAndroid Build Coastguard Worker quote_string(def_username, quoted, sizeof(quoted)));
2958*5e7646d2SAndroid Build Coastguard Worker }
2959*5e7646d2SAndroid Build Coastguard Worker }
2960*5e7646d2SAndroid Build Coastguard Worker
2961*5e7646d2SAndroid Build Coastguard Worker if (password && *password && *password_tries < 3)
2962*5e7646d2SAndroid Build Coastguard Worker {
2963*5e7646d2SAndroid Build Coastguard Worker (*password_tries) ++;
2964*5e7646d2SAndroid Build Coastguard Worker
2965*5e7646d2SAndroid Build Coastguard Worker cupsSetUser(username);
2966*5e7646d2SAndroid Build Coastguard Worker
2967*5e7646d2SAndroid Build Coastguard Worker return (password);
2968*5e7646d2SAndroid Build Coastguard Worker }
2969*5e7646d2SAndroid Build Coastguard Worker else
2970*5e7646d2SAndroid Build Coastguard Worker {
2971*5e7646d2SAndroid Build Coastguard Worker /*
2972*5e7646d2SAndroid Build Coastguard Worker * Give up after 3 tries or if we don't have a password to begin with...
2973*5e7646d2SAndroid Build Coastguard Worker */
2974*5e7646d2SAndroid Build Coastguard Worker
2975*5e7646d2SAndroid Build Coastguard Worker return (NULL);
2976*5e7646d2SAndroid Build Coastguard Worker }
2977*5e7646d2SAndroid Build Coastguard Worker }
2978*5e7646d2SAndroid Build Coastguard Worker
2979*5e7646d2SAndroid Build Coastguard Worker
2980*5e7646d2SAndroid Build Coastguard Worker /*
2981*5e7646d2SAndroid Build Coastguard Worker * 'quote_string()' - Quote a string value.
2982*5e7646d2SAndroid Build Coastguard Worker */
2983*5e7646d2SAndroid Build Coastguard Worker
2984*5e7646d2SAndroid Build Coastguard Worker static const char * /* O - Quoted string */
quote_string(const char * s,char * q,size_t qsize)2985*5e7646d2SAndroid Build Coastguard Worker quote_string(const char *s, /* I - String */
2986*5e7646d2SAndroid Build Coastguard Worker char *q, /* I - Quoted string buffer */
2987*5e7646d2SAndroid Build Coastguard Worker size_t qsize) /* I - Size of quoted string buffer */
2988*5e7646d2SAndroid Build Coastguard Worker {
2989*5e7646d2SAndroid Build Coastguard Worker char *qptr, /* Pointer into string buffer */
2990*5e7646d2SAndroid Build Coastguard Worker *qend; /* End of string buffer */
2991*5e7646d2SAndroid Build Coastguard Worker
2992*5e7646d2SAndroid Build Coastguard Worker
2993*5e7646d2SAndroid Build Coastguard Worker qptr = q;
2994*5e7646d2SAndroid Build Coastguard Worker qend = q + qsize - 5;
2995*5e7646d2SAndroid Build Coastguard Worker
2996*5e7646d2SAndroid Build Coastguard Worker if (qend < q)
2997*5e7646d2SAndroid Build Coastguard Worker {
2998*5e7646d2SAndroid Build Coastguard Worker *q = '\0';
2999*5e7646d2SAndroid Build Coastguard Worker return (q);
3000*5e7646d2SAndroid Build Coastguard Worker }
3001*5e7646d2SAndroid Build Coastguard Worker
3002*5e7646d2SAndroid Build Coastguard Worker *qptr++ = '\'';
3003*5e7646d2SAndroid Build Coastguard Worker *qptr++ = '\"';
3004*5e7646d2SAndroid Build Coastguard Worker
3005*5e7646d2SAndroid Build Coastguard Worker while (*s && qptr < qend)
3006*5e7646d2SAndroid Build Coastguard Worker {
3007*5e7646d2SAndroid Build Coastguard Worker if (*s == '\\' || *s == '\"' || *s == '\'')
3008*5e7646d2SAndroid Build Coastguard Worker {
3009*5e7646d2SAndroid Build Coastguard Worker if (qptr < (qend - 4))
3010*5e7646d2SAndroid Build Coastguard Worker {
3011*5e7646d2SAndroid Build Coastguard Worker *qptr++ = '\\';
3012*5e7646d2SAndroid Build Coastguard Worker *qptr++ = '\\';
3013*5e7646d2SAndroid Build Coastguard Worker *qptr++ = '\\';
3014*5e7646d2SAndroid Build Coastguard Worker }
3015*5e7646d2SAndroid Build Coastguard Worker else
3016*5e7646d2SAndroid Build Coastguard Worker break;
3017*5e7646d2SAndroid Build Coastguard Worker }
3018*5e7646d2SAndroid Build Coastguard Worker
3019*5e7646d2SAndroid Build Coastguard Worker *qptr++ = *s++;
3020*5e7646d2SAndroid Build Coastguard Worker }
3021*5e7646d2SAndroid Build Coastguard Worker
3022*5e7646d2SAndroid Build Coastguard Worker *qptr++ = '\"';
3023*5e7646d2SAndroid Build Coastguard Worker *qptr++ = '\'';
3024*5e7646d2SAndroid Build Coastguard Worker *qptr = '\0';
3025*5e7646d2SAndroid Build Coastguard Worker
3026*5e7646d2SAndroid Build Coastguard Worker return (q);
3027*5e7646d2SAndroid Build Coastguard Worker }
3028*5e7646d2SAndroid Build Coastguard Worker
3029*5e7646d2SAndroid Build Coastguard Worker
3030*5e7646d2SAndroid Build Coastguard Worker /*
3031*5e7646d2SAndroid Build Coastguard Worker * 'report_attr()' - Report an IPP attribute value.
3032*5e7646d2SAndroid Build Coastguard Worker */
3033*5e7646d2SAndroid Build Coastguard Worker
3034*5e7646d2SAndroid Build Coastguard Worker static void
report_attr(ipp_attribute_t * attr)3035*5e7646d2SAndroid Build Coastguard Worker report_attr(ipp_attribute_t *attr) /* I - Attribute */
3036*5e7646d2SAndroid Build Coastguard Worker {
3037*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
3038*5e7646d2SAndroid Build Coastguard Worker char value[1024], /* Value string */
3039*5e7646d2SAndroid Build Coastguard Worker *valptr; /* Pointer into value string */
3040*5e7646d2SAndroid Build Coastguard Worker const char *cached; /* Cached attribute */
3041*5e7646d2SAndroid Build Coastguard Worker
3042*5e7646d2SAndroid Build Coastguard Worker
3043*5e7646d2SAndroid Build Coastguard Worker /*
3044*5e7646d2SAndroid Build Coastguard Worker * Convert the attribute values into quoted strings...
3045*5e7646d2SAndroid Build Coastguard Worker */
3046*5e7646d2SAndroid Build Coastguard Worker
3047*5e7646d2SAndroid Build Coastguard Worker for (i = 0, valptr = value;
3048*5e7646d2SAndroid Build Coastguard Worker i < attr->num_values && valptr < (value + sizeof(value) - 10);
3049*5e7646d2SAndroid Build Coastguard Worker i ++)
3050*5e7646d2SAndroid Build Coastguard Worker {
3051*5e7646d2SAndroid Build Coastguard Worker if (i > 0)
3052*5e7646d2SAndroid Build Coastguard Worker *valptr++ = ',';
3053*5e7646d2SAndroid Build Coastguard Worker
3054*5e7646d2SAndroid Build Coastguard Worker switch (attr->value_tag)
3055*5e7646d2SAndroid Build Coastguard Worker {
3056*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_INTEGER :
3057*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_ENUM :
3058*5e7646d2SAndroid Build Coastguard Worker snprintf(valptr, sizeof(value) - (size_t)(valptr - value), "%d", attr->values[i].integer);
3059*5e7646d2SAndroid Build Coastguard Worker valptr += strlen(valptr);
3060*5e7646d2SAndroid Build Coastguard Worker break;
3061*5e7646d2SAndroid Build Coastguard Worker
3062*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_TEXT :
3063*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_NAME :
3064*5e7646d2SAndroid Build Coastguard Worker case IPP_TAG_KEYWORD :
3065*5e7646d2SAndroid Build Coastguard Worker quote_string(attr->values[i].string.text, valptr, (size_t)(value + sizeof(value) - valptr));
3066*5e7646d2SAndroid Build Coastguard Worker valptr += strlen(valptr);
3067*5e7646d2SAndroid Build Coastguard Worker break;
3068*5e7646d2SAndroid Build Coastguard Worker
3069*5e7646d2SAndroid Build Coastguard Worker default :
3070*5e7646d2SAndroid Build Coastguard Worker /*
3071*5e7646d2SAndroid Build Coastguard Worker * Unsupported value type...
3072*5e7646d2SAndroid Build Coastguard Worker */
3073*5e7646d2SAndroid Build Coastguard Worker
3074*5e7646d2SAndroid Build Coastguard Worker return;
3075*5e7646d2SAndroid Build Coastguard Worker }
3076*5e7646d2SAndroid Build Coastguard Worker }
3077*5e7646d2SAndroid Build Coastguard Worker
3078*5e7646d2SAndroid Build Coastguard Worker *valptr = '\0';
3079*5e7646d2SAndroid Build Coastguard Worker
3080*5e7646d2SAndroid Build Coastguard Worker _cupsMutexLock(&report_mutex);
3081*5e7646d2SAndroid Build Coastguard Worker
3082*5e7646d2SAndroid Build Coastguard Worker if ((cached = cupsGetOption(attr->name, num_attr_cache,
3083*5e7646d2SAndroid Build Coastguard Worker attr_cache)) == NULL || strcmp(cached, value))
3084*5e7646d2SAndroid Build Coastguard Worker {
3085*5e7646d2SAndroid Build Coastguard Worker /*
3086*5e7646d2SAndroid Build Coastguard Worker * Tell the scheduler about the new values...
3087*5e7646d2SAndroid Build Coastguard Worker */
3088*5e7646d2SAndroid Build Coastguard Worker
3089*5e7646d2SAndroid Build Coastguard Worker num_attr_cache = cupsAddOption(attr->name, value, num_attr_cache,
3090*5e7646d2SAndroid Build Coastguard Worker &attr_cache);
3091*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "ATTR: %s=%s\n", attr->name, value);
3092*5e7646d2SAndroid Build Coastguard Worker }
3093*5e7646d2SAndroid Build Coastguard Worker
3094*5e7646d2SAndroid Build Coastguard Worker _cupsMutexUnlock(&report_mutex);
3095*5e7646d2SAndroid Build Coastguard Worker }
3096*5e7646d2SAndroid Build Coastguard Worker
3097*5e7646d2SAndroid Build Coastguard Worker
3098*5e7646d2SAndroid Build Coastguard Worker /*
3099*5e7646d2SAndroid Build Coastguard Worker * 'report_printer_state()' - Report the printer state.
3100*5e7646d2SAndroid Build Coastguard Worker */
3101*5e7646d2SAndroid Build Coastguard Worker
3102*5e7646d2SAndroid Build Coastguard Worker static void
report_printer_state(ipp_t * ipp)3103*5e7646d2SAndroid Build Coastguard Worker report_printer_state(ipp_t *ipp) /* I - IPP response */
3104*5e7646d2SAndroid Build Coastguard Worker {
3105*5e7646d2SAndroid Build Coastguard Worker ipp_attribute_t *pa, /* printer-alert */
3106*5e7646d2SAndroid Build Coastguard Worker *pam, /* printer-alert-message */
3107*5e7646d2SAndroid Build Coastguard Worker *pmja, /* printer-mandatory-job-attributes */
3108*5e7646d2SAndroid Build Coastguard Worker *psm, /* printer-state-message */
3109*5e7646d2SAndroid Build Coastguard Worker *reasons, /* printer-state-reasons */
3110*5e7646d2SAndroid Build Coastguard Worker *marker; /* marker-* attributes */
3111*5e7646d2SAndroid Build Coastguard Worker char value[1024], /* State/message string */
3112*5e7646d2SAndroid Build Coastguard Worker *valptr; /* Pointer into string */
3113*5e7646d2SAndroid Build Coastguard Worker static int ipp_supplies = -1;
3114*5e7646d2SAndroid Build Coastguard Worker /* Report supply levels? */
3115*5e7646d2SAndroid Build Coastguard Worker
3116*5e7646d2SAndroid Build Coastguard Worker
3117*5e7646d2SAndroid Build Coastguard Worker /*
3118*5e7646d2SAndroid Build Coastguard Worker * Report alerts and messages...
3119*5e7646d2SAndroid Build Coastguard Worker */
3120*5e7646d2SAndroid Build Coastguard Worker
3121*5e7646d2SAndroid Build Coastguard Worker if ((pa = ippFindAttribute(ipp, "printer-alert", IPP_TAG_STRING)) != NULL)
3122*5e7646d2SAndroid Build Coastguard Worker report_attr(pa);
3123*5e7646d2SAndroid Build Coastguard Worker
3124*5e7646d2SAndroid Build Coastguard Worker if ((pam = ippFindAttribute(ipp, "printer-alert-message",
3125*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
3126*5e7646d2SAndroid Build Coastguard Worker report_attr(pam);
3127*5e7646d2SAndroid Build Coastguard Worker
3128*5e7646d2SAndroid Build Coastguard Worker if ((pmja = ippFindAttribute(ipp, "printer-mandatory-job-attributes", IPP_TAG_KEYWORD)) != NULL)
3129*5e7646d2SAndroid Build Coastguard Worker {
3130*5e7646d2SAndroid Build Coastguard Worker int i, /* Looping var */
3131*5e7646d2SAndroid Build Coastguard Worker count = ippGetCount(pmja); /* Number of values */
3132*5e7646d2SAndroid Build Coastguard Worker
3133*5e7646d2SAndroid Build Coastguard Worker for (i = 0, valptr = value; i < count; i ++, valptr += strlen(valptr))
3134*5e7646d2SAndroid Build Coastguard Worker {
3135*5e7646d2SAndroid Build Coastguard Worker if (i)
3136*5e7646d2SAndroid Build Coastguard Worker snprintf(valptr, sizeof(value) - (size_t)(valptr - value), " %s", ippGetString(pmja, i, NULL));
3137*5e7646d2SAndroid Build Coastguard Worker else
3138*5e7646d2SAndroid Build Coastguard Worker strlcpy(value, ippGetString(pmja, i, NULL), sizeof(value));
3139*5e7646d2SAndroid Build Coastguard Worker }
3140*5e7646d2SAndroid Build Coastguard Worker
3141*5e7646d2SAndroid Build Coastguard Worker if (strcmp(value, mandatory_attrs))
3142*5e7646d2SAndroid Build Coastguard Worker {
3143*5e7646d2SAndroid Build Coastguard Worker strlcpy(mandatory_attrs, value, sizeof(mandatory_attrs));
3144*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "PPD: cupsMandatory=\"%s\"\n", value);
3145*5e7646d2SAndroid Build Coastguard Worker }
3146*5e7646d2SAndroid Build Coastguard Worker }
3147*5e7646d2SAndroid Build Coastguard Worker
3148*5e7646d2SAndroid Build Coastguard Worker if ((psm = ippFindAttribute(ipp, "printer-state-message",
3149*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
3150*5e7646d2SAndroid Build Coastguard Worker {
3151*5e7646d2SAndroid Build Coastguard Worker char *ptr; /* Pointer into message */
3152*5e7646d2SAndroid Build Coastguard Worker
3153*5e7646d2SAndroid Build Coastguard Worker
3154*5e7646d2SAndroid Build Coastguard Worker strlcpy(value, "INFO: ", sizeof(value));
3155*5e7646d2SAndroid Build Coastguard Worker for (ptr = psm->values[0].string.text, valptr = value + 6;
3156*5e7646d2SAndroid Build Coastguard Worker *ptr && valptr < (value + sizeof(value) - 6);
3157*5e7646d2SAndroid Build Coastguard Worker ptr ++)
3158*5e7646d2SAndroid Build Coastguard Worker {
3159*5e7646d2SAndroid Build Coastguard Worker if (*ptr < ' ' && *ptr > 0 && *ptr != '\t')
3160*5e7646d2SAndroid Build Coastguard Worker {
3161*5e7646d2SAndroid Build Coastguard Worker /*
3162*5e7646d2SAndroid Build Coastguard Worker * Substitute "<XX>" for the control character...
3163*5e7646d2SAndroid Build Coastguard Worker */
3164*5e7646d2SAndroid Build Coastguard Worker
3165*5e7646d2SAndroid Build Coastguard Worker snprintf(valptr, sizeof(value) - (size_t)(valptr - value), "<%02X>", *ptr);
3166*5e7646d2SAndroid Build Coastguard Worker valptr += 4;
3167*5e7646d2SAndroid Build Coastguard Worker }
3168*5e7646d2SAndroid Build Coastguard Worker else
3169*5e7646d2SAndroid Build Coastguard Worker *valptr++ = *ptr;
3170*5e7646d2SAndroid Build Coastguard Worker }
3171*5e7646d2SAndroid Build Coastguard Worker
3172*5e7646d2SAndroid Build Coastguard Worker *valptr++ = '\n';
3173*5e7646d2SAndroid Build Coastguard Worker *valptr = '\0';
3174*5e7646d2SAndroid Build Coastguard Worker
3175*5e7646d2SAndroid Build Coastguard Worker fputs(value, stderr);
3176*5e7646d2SAndroid Build Coastguard Worker }
3177*5e7646d2SAndroid Build Coastguard Worker
3178*5e7646d2SAndroid Build Coastguard Worker /*
3179*5e7646d2SAndroid Build Coastguard Worker * Now report printer-state-reasons, filtering out some of the reasons we never
3180*5e7646d2SAndroid Build Coastguard Worker * want to set...
3181*5e7646d2SAndroid Build Coastguard Worker */
3182*5e7646d2SAndroid Build Coastguard Worker
3183*5e7646d2SAndroid Build Coastguard Worker if ((reasons = ippFindAttribute(ipp, "printer-state-reasons",
3184*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) == NULL)
3185*5e7646d2SAndroid Build Coastguard Worker return;
3186*5e7646d2SAndroid Build Coastguard Worker
3187*5e7646d2SAndroid Build Coastguard Worker update_reasons(reasons, NULL);
3188*5e7646d2SAndroid Build Coastguard Worker
3189*5e7646d2SAndroid Build Coastguard Worker /*
3190*5e7646d2SAndroid Build Coastguard Worker * Relay the current marker-* attribute values...
3191*5e7646d2SAndroid Build Coastguard Worker */
3192*5e7646d2SAndroid Build Coastguard Worker
3193*5e7646d2SAndroid Build Coastguard Worker if (ipp_supplies < 0)
3194*5e7646d2SAndroid Build Coastguard Worker {
3195*5e7646d2SAndroid Build Coastguard Worker ppd_file_t *ppd; /* PPD file */
3196*5e7646d2SAndroid Build Coastguard Worker ppd_attr_t *ppdattr; /* Attribute in PPD file */
3197*5e7646d2SAndroid Build Coastguard Worker
3198*5e7646d2SAndroid Build Coastguard Worker if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL &&
3199*5e7646d2SAndroid Build Coastguard Worker (ppdattr = ppdFindAttr(ppd, "cupsIPPSupplies", NULL)) != NULL &&
3200*5e7646d2SAndroid Build Coastguard Worker ppdattr->value && _cups_strcasecmp(ppdattr->value, "true"))
3201*5e7646d2SAndroid Build Coastguard Worker ipp_supplies = 0;
3202*5e7646d2SAndroid Build Coastguard Worker else
3203*5e7646d2SAndroid Build Coastguard Worker ipp_supplies = 1;
3204*5e7646d2SAndroid Build Coastguard Worker
3205*5e7646d2SAndroid Build Coastguard Worker ppdClose(ppd);
3206*5e7646d2SAndroid Build Coastguard Worker }
3207*5e7646d2SAndroid Build Coastguard Worker
3208*5e7646d2SAndroid Build Coastguard Worker if (ipp_supplies > 0)
3209*5e7646d2SAndroid Build Coastguard Worker {
3210*5e7646d2SAndroid Build Coastguard Worker if ((marker = ippFindAttribute(ipp, "marker-colors", IPP_TAG_NAME)) != NULL)
3211*5e7646d2SAndroid Build Coastguard Worker report_attr(marker);
3212*5e7646d2SAndroid Build Coastguard Worker if ((marker = ippFindAttribute(ipp, "marker-high-levels",
3213*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
3214*5e7646d2SAndroid Build Coastguard Worker report_attr(marker);
3215*5e7646d2SAndroid Build Coastguard Worker if ((marker = ippFindAttribute(ipp, "marker-levels",
3216*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
3217*5e7646d2SAndroid Build Coastguard Worker report_attr(marker);
3218*5e7646d2SAndroid Build Coastguard Worker if ((marker = ippFindAttribute(ipp, "marker-low-levels",
3219*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_INTEGER)) != NULL)
3220*5e7646d2SAndroid Build Coastguard Worker report_attr(marker);
3221*5e7646d2SAndroid Build Coastguard Worker if ((marker = ippFindAttribute(ipp, "marker-message",
3222*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_TEXT)) != NULL)
3223*5e7646d2SAndroid Build Coastguard Worker report_attr(marker);
3224*5e7646d2SAndroid Build Coastguard Worker if ((marker = ippFindAttribute(ipp, "marker-names", IPP_TAG_NAME)) != NULL)
3225*5e7646d2SAndroid Build Coastguard Worker report_attr(marker);
3226*5e7646d2SAndroid Build Coastguard Worker if ((marker = ippFindAttribute(ipp, "marker-types",
3227*5e7646d2SAndroid Build Coastguard Worker IPP_TAG_KEYWORD)) != NULL)
3228*5e7646d2SAndroid Build Coastguard Worker report_attr(marker);
3229*5e7646d2SAndroid Build Coastguard Worker }
3230*5e7646d2SAndroid Build Coastguard Worker }
3231*5e7646d2SAndroid Build Coastguard Worker
3232*5e7646d2SAndroid Build Coastguard Worker
3233*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
3234*5e7646d2SAndroid Build Coastguard Worker /*
3235*5e7646d2SAndroid Build Coastguard Worker * 'run_as_user()' - Run the IPP backend as the printing user.
3236*5e7646d2SAndroid Build Coastguard Worker *
3237*5e7646d2SAndroid Build Coastguard Worker * This function uses an XPC-based user agent to run the backend as the printing
3238*5e7646d2SAndroid Build Coastguard Worker * user. We need to do this in order to have access to the user's Kerberos
3239*5e7646d2SAndroid Build Coastguard Worker * credentials.
3240*5e7646d2SAndroid Build Coastguard Worker */
3241*5e7646d2SAndroid Build Coastguard Worker
3242*5e7646d2SAndroid Build Coastguard Worker static int /* O - Exit status */
run_as_user(char * argv[],uid_t uid,const char * device_uri,int fd)3243*5e7646d2SAndroid Build Coastguard Worker run_as_user(char *argv[], /* I - Command-line arguments */
3244*5e7646d2SAndroid Build Coastguard Worker uid_t uid, /* I - User ID */
3245*5e7646d2SAndroid Build Coastguard Worker const char *device_uri, /* I - Device URI */
3246*5e7646d2SAndroid Build Coastguard Worker int fd) /* I - File to print */
3247*5e7646d2SAndroid Build Coastguard Worker {
3248*5e7646d2SAndroid Build Coastguard Worker const char *auth_negotiate,/* AUTH_NEGOTIATE env var */
3249*5e7646d2SAndroid Build Coastguard Worker *content_type; /* [FINAL_]CONTENT_TYPE env vars */
3250*5e7646d2SAndroid Build Coastguard Worker xpc_connection_t conn; /* Connection to XPC service */
3251*5e7646d2SAndroid Build Coastguard Worker xpc_object_t request; /* Request message dictionary */
3252*5e7646d2SAndroid Build Coastguard Worker __block xpc_object_t response; /* Response message dictionary */
3253*5e7646d2SAndroid Build Coastguard Worker dispatch_semaphore_t sem; /* Semaphore for waiting for response */
3254*5e7646d2SAndroid Build Coastguard Worker int status = CUPS_BACKEND_FAILED;
3255*5e7646d2SAndroid Build Coastguard Worker /* Status of request */
3256*5e7646d2SAndroid Build Coastguard Worker
3257*5e7646d2SAndroid Build Coastguard Worker
3258*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Running IPP backend as UID %d.\n", (int)uid);
3259*5e7646d2SAndroid Build Coastguard Worker
3260*5e7646d2SAndroid Build Coastguard Worker /*
3261*5e7646d2SAndroid Build Coastguard Worker * Connect to the user agent for the specified UID...
3262*5e7646d2SAndroid Build Coastguard Worker */
3263*5e7646d2SAndroid Build Coastguard Worker
3264*5e7646d2SAndroid Build Coastguard Worker conn = xpc_connection_create_mach_service(kPMPrintUIToolAgent,
3265*5e7646d2SAndroid Build Coastguard Worker dispatch_get_global_queue(0, 0), 0);
3266*5e7646d2SAndroid Build Coastguard Worker if (!conn)
3267*5e7646d2SAndroid Build Coastguard Worker {
3268*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
3269*5e7646d2SAndroid Build Coastguard Worker _("Unable to start backend process."));
3270*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: Unable to create connection to agent.\n", stderr);
3271*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
3272*5e7646d2SAndroid Build Coastguard Worker }
3273*5e7646d2SAndroid Build Coastguard Worker
3274*5e7646d2SAndroid Build Coastguard Worker xpc_connection_set_event_handler(conn,
3275*5e7646d2SAndroid Build Coastguard Worker ^(xpc_object_t event)
3276*5e7646d2SAndroid Build Coastguard Worker {
3277*5e7646d2SAndroid Build Coastguard Worker xpc_type_t messageType = xpc_get_type(event);
3278*5e7646d2SAndroid Build Coastguard Worker
3279*5e7646d2SAndroid Build Coastguard Worker if (messageType == XPC_TYPE_ERROR)
3280*5e7646d2SAndroid Build Coastguard Worker {
3281*5e7646d2SAndroid Build Coastguard Worker if (event == XPC_ERROR_CONNECTION_INTERRUPTED)
3282*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Interrupted connection to service %s.\n",
3283*5e7646d2SAndroid Build Coastguard Worker xpc_connection_get_name(conn));
3284*5e7646d2SAndroid Build Coastguard Worker else if (event == XPC_ERROR_CONNECTION_INVALID)
3285*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Connection invalid for service %s.\n",
3286*5e7646d2SAndroid Build Coastguard Worker xpc_connection_get_name(conn));
3287*5e7646d2SAndroid Build Coastguard Worker else
3288*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Unxpected error for service %s: %s\n",
3289*5e7646d2SAndroid Build Coastguard Worker xpc_connection_get_name(conn),
3290*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
3291*5e7646d2SAndroid Build Coastguard Worker }
3292*5e7646d2SAndroid Build Coastguard Worker });
3293*5e7646d2SAndroid Build Coastguard Worker xpc_connection_set_target_uid(conn, uid);
3294*5e7646d2SAndroid Build Coastguard Worker xpc_connection_resume(conn);
3295*5e7646d2SAndroid Build Coastguard Worker
3296*5e7646d2SAndroid Build Coastguard Worker /*
3297*5e7646d2SAndroid Build Coastguard Worker * Try starting the backend...
3298*5e7646d2SAndroid Build Coastguard Worker */
3299*5e7646d2SAndroid Build Coastguard Worker
3300*5e7646d2SAndroid Build Coastguard Worker request = xpc_dictionary_create(NULL, NULL, 0);
3301*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_int64(request, "command", kPMStartJob);
3302*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "device-uri", device_uri);
3303*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "job-id", argv[1]);
3304*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "user", argv[2]);
3305*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "title", argv[3]);
3306*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "copies", argv[4]);
3307*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "options", argv[5]);
3308*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "auth-info-required",
3309*5e7646d2SAndroid Build Coastguard Worker getenv("AUTH_INFO_REQUIRED"));
3310*5e7646d2SAndroid Build Coastguard Worker if ((auth_negotiate = getenv("AUTH_NEGOTIATE")) != NULL)
3311*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "auth-negotiate", auth_negotiate);
3312*5e7646d2SAndroid Build Coastguard Worker if ((content_type = getenv("CONTENT_TYPE")) != NULL)
3313*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "content-type", content_type);
3314*5e7646d2SAndroid Build Coastguard Worker if ((content_type = getenv("FINAL_CONTENT_TYPE")) != NULL)
3315*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_string(request, "final-content-type", content_type);
3316*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_fd(request, "stdin", fd);
3317*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_fd(request, "stderr", 2);
3318*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_fd(request, "side-channel", CUPS_SC_FD);
3319*5e7646d2SAndroid Build Coastguard Worker
3320*5e7646d2SAndroid Build Coastguard Worker sem = dispatch_semaphore_create(0);
3321*5e7646d2SAndroid Build Coastguard Worker response = NULL;
3322*5e7646d2SAndroid Build Coastguard Worker
3323*5e7646d2SAndroid Build Coastguard Worker xpc_connection_send_message_with_reply(conn, request,
3324*5e7646d2SAndroid Build Coastguard Worker dispatch_get_global_queue(0,0),
3325*5e7646d2SAndroid Build Coastguard Worker ^(xpc_object_t reply)
3326*5e7646d2SAndroid Build Coastguard Worker {
3327*5e7646d2SAndroid Build Coastguard Worker /* Save the response and wake up */
3328*5e7646d2SAndroid Build Coastguard Worker if (xpc_get_type(reply)
3329*5e7646d2SAndroid Build Coastguard Worker == XPC_TYPE_DICTIONARY)
3330*5e7646d2SAndroid Build Coastguard Worker response = xpc_retain(reply);
3331*5e7646d2SAndroid Build Coastguard Worker
3332*5e7646d2SAndroid Build Coastguard Worker dispatch_semaphore_signal(sem);
3333*5e7646d2SAndroid Build Coastguard Worker });
3334*5e7646d2SAndroid Build Coastguard Worker
3335*5e7646d2SAndroid Build Coastguard Worker dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
3336*5e7646d2SAndroid Build Coastguard Worker xpc_release(request);
3337*5e7646d2SAndroid Build Coastguard Worker dispatch_release(sem);
3338*5e7646d2SAndroid Build Coastguard Worker
3339*5e7646d2SAndroid Build Coastguard Worker if (response)
3340*5e7646d2SAndroid Build Coastguard Worker {
3341*5e7646d2SAndroid Build Coastguard Worker child_pid = (pid_t)xpc_dictionary_get_int64(response, "child-pid");
3342*5e7646d2SAndroid Build Coastguard Worker
3343*5e7646d2SAndroid Build Coastguard Worker xpc_release(response);
3344*5e7646d2SAndroid Build Coastguard Worker
3345*5e7646d2SAndroid Build Coastguard Worker if (child_pid)
3346*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Child PID=%d.\n", (int)child_pid);
3347*5e7646d2SAndroid Build Coastguard Worker else
3348*5e7646d2SAndroid Build Coastguard Worker {
3349*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
3350*5e7646d2SAndroid Build Coastguard Worker _("Unable to start backend process."));
3351*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: No child PID.\n", stderr);
3352*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
3353*5e7646d2SAndroid Build Coastguard Worker }
3354*5e7646d2SAndroid Build Coastguard Worker }
3355*5e7646d2SAndroid Build Coastguard Worker else
3356*5e7646d2SAndroid Build Coastguard Worker {
3357*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
3358*5e7646d2SAndroid Build Coastguard Worker _("Unable to start backend process."));
3359*5e7646d2SAndroid Build Coastguard Worker fputs("DEBUG: No reply from agent.\n", stderr);
3360*5e7646d2SAndroid Build Coastguard Worker goto cleanup;
3361*5e7646d2SAndroid Build Coastguard Worker }
3362*5e7646d2SAndroid Build Coastguard Worker
3363*5e7646d2SAndroid Build Coastguard Worker /*
3364*5e7646d2SAndroid Build Coastguard Worker * Then wait for the backend to finish...
3365*5e7646d2SAndroid Build Coastguard Worker */
3366*5e7646d2SAndroid Build Coastguard Worker
3367*5e7646d2SAndroid Build Coastguard Worker request = xpc_dictionary_create(NULL, NULL, 0);
3368*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_int64(request, "command", kPMWaitForJob);
3369*5e7646d2SAndroid Build Coastguard Worker xpc_dictionary_set_fd(request, "stderr", 2);
3370*5e7646d2SAndroid Build Coastguard Worker
3371*5e7646d2SAndroid Build Coastguard Worker sem = dispatch_semaphore_create(0);
3372*5e7646d2SAndroid Build Coastguard Worker response = NULL;
3373*5e7646d2SAndroid Build Coastguard Worker
3374*5e7646d2SAndroid Build Coastguard Worker xpc_connection_send_message_with_reply(conn, request,
3375*5e7646d2SAndroid Build Coastguard Worker dispatch_get_global_queue(0,0),
3376*5e7646d2SAndroid Build Coastguard Worker ^(xpc_object_t reply)
3377*5e7646d2SAndroid Build Coastguard Worker {
3378*5e7646d2SAndroid Build Coastguard Worker /* Save the response and wake up */
3379*5e7646d2SAndroid Build Coastguard Worker if (xpc_get_type(reply)
3380*5e7646d2SAndroid Build Coastguard Worker == XPC_TYPE_DICTIONARY)
3381*5e7646d2SAndroid Build Coastguard Worker response = xpc_retain(reply);
3382*5e7646d2SAndroid Build Coastguard Worker
3383*5e7646d2SAndroid Build Coastguard Worker dispatch_semaphore_signal(sem);
3384*5e7646d2SAndroid Build Coastguard Worker });
3385*5e7646d2SAndroid Build Coastguard Worker
3386*5e7646d2SAndroid Build Coastguard Worker dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
3387*5e7646d2SAndroid Build Coastguard Worker xpc_release(request);
3388*5e7646d2SAndroid Build Coastguard Worker dispatch_release(sem);
3389*5e7646d2SAndroid Build Coastguard Worker
3390*5e7646d2SAndroid Build Coastguard Worker if (response)
3391*5e7646d2SAndroid Build Coastguard Worker {
3392*5e7646d2SAndroid Build Coastguard Worker status = (int)xpc_dictionary_get_int64(response, "status");
3393*5e7646d2SAndroid Build Coastguard Worker
3394*5e7646d2SAndroid Build Coastguard Worker if (status == SIGTERM || status == SIGKILL || status == SIGPIPE)
3395*5e7646d2SAndroid Build Coastguard Worker {
3396*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Child terminated on signal %d.\n", status);
3397*5e7646d2SAndroid Build Coastguard Worker status = CUPS_BACKEND_FAILED;
3398*5e7646d2SAndroid Build Coastguard Worker }
3399*5e7646d2SAndroid Build Coastguard Worker else if (WIFSIGNALED(status))
3400*5e7646d2SAndroid Build Coastguard Worker {
3401*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Child crashed on signal %d.\n", status);
3402*5e7646d2SAndroid Build Coastguard Worker status = CUPS_BACKEND_STOP;
3403*5e7646d2SAndroid Build Coastguard Worker }
3404*5e7646d2SAndroid Build Coastguard Worker else if (WIFEXITED(status))
3405*5e7646d2SAndroid Build Coastguard Worker {
3406*5e7646d2SAndroid Build Coastguard Worker status = WEXITSTATUS(status);
3407*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: Child exited with status %d.\n", status);
3408*5e7646d2SAndroid Build Coastguard Worker }
3409*5e7646d2SAndroid Build Coastguard Worker
3410*5e7646d2SAndroid Build Coastguard Worker xpc_release(response);
3411*5e7646d2SAndroid Build Coastguard Worker }
3412*5e7646d2SAndroid Build Coastguard Worker else
3413*5e7646d2SAndroid Build Coastguard Worker _cupsLangPrintFilter(stderr, "ERROR",
3414*5e7646d2SAndroid Build Coastguard Worker _("Unable to get backend exit status."));
3415*5e7646d2SAndroid Build Coastguard Worker
3416*5e7646d2SAndroid Build Coastguard Worker cleanup:
3417*5e7646d2SAndroid Build Coastguard Worker
3418*5e7646d2SAndroid Build Coastguard Worker if (conn)
3419*5e7646d2SAndroid Build Coastguard Worker {
3420*5e7646d2SAndroid Build Coastguard Worker xpc_connection_cancel(conn);
3421*5e7646d2SAndroid Build Coastguard Worker xpc_release(conn);
3422*5e7646d2SAndroid Build Coastguard Worker }
3423*5e7646d2SAndroid Build Coastguard Worker
3424*5e7646d2SAndroid Build Coastguard Worker return (status);
3425*5e7646d2SAndroid Build Coastguard Worker }
3426*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
3427*5e7646d2SAndroid Build Coastguard Worker
3428*5e7646d2SAndroid Build Coastguard Worker
3429*5e7646d2SAndroid Build Coastguard Worker /*
3430*5e7646d2SAndroid Build Coastguard Worker * 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
3431*5e7646d2SAndroid Build Coastguard Worker */
3432*5e7646d2SAndroid Build Coastguard Worker
3433*5e7646d2SAndroid Build Coastguard Worker static void
sigterm_handler(int sig)3434*5e7646d2SAndroid Build Coastguard Worker sigterm_handler(int sig) /* I - Signal */
3435*5e7646d2SAndroid Build Coastguard Worker {
3436*5e7646d2SAndroid Build Coastguard Worker (void)sig; /* remove compiler warnings... */
3437*5e7646d2SAndroid Build Coastguard Worker
3438*5e7646d2SAndroid Build Coastguard Worker backendMessage("DEBUG: Got SIGTERM.\n");
3439*5e7646d2SAndroid Build Coastguard Worker
3440*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
3441*5e7646d2SAndroid Build Coastguard Worker if (child_pid)
3442*5e7646d2SAndroid Build Coastguard Worker {
3443*5e7646d2SAndroid Build Coastguard Worker kill(child_pid, sig);
3444*5e7646d2SAndroid Build Coastguard Worker child_pid = 0;
3445*5e7646d2SAndroid Build Coastguard Worker }
3446*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI && HAVE_XPC */
3447*5e7646d2SAndroid Build Coastguard Worker
3448*5e7646d2SAndroid Build Coastguard Worker if (!job_canceled)
3449*5e7646d2SAndroid Build Coastguard Worker {
3450*5e7646d2SAndroid Build Coastguard Worker /*
3451*5e7646d2SAndroid Build Coastguard Worker * Flag that the job should be canceled...
3452*5e7646d2SAndroid Build Coastguard Worker */
3453*5e7646d2SAndroid Build Coastguard Worker
3454*5e7646d2SAndroid Build Coastguard Worker backendMessage("DEBUG: sigterm_handler: job_canceled = 1.\n");
3455*5e7646d2SAndroid Build Coastguard Worker
3456*5e7646d2SAndroid Build Coastguard Worker job_canceled = 1;
3457*5e7646d2SAndroid Build Coastguard Worker return;
3458*5e7646d2SAndroid Build Coastguard Worker }
3459*5e7646d2SAndroid Build Coastguard Worker
3460*5e7646d2SAndroid Build Coastguard Worker /*
3461*5e7646d2SAndroid Build Coastguard Worker * The scheduler already tried to cancel us once, now just terminate
3462*5e7646d2SAndroid Build Coastguard Worker * after removing our temp file!
3463*5e7646d2SAndroid Build Coastguard Worker */
3464*5e7646d2SAndroid Build Coastguard Worker
3465*5e7646d2SAndroid Build Coastguard Worker if (tmpfilename[0])
3466*5e7646d2SAndroid Build Coastguard Worker unlink(tmpfilename);
3467*5e7646d2SAndroid Build Coastguard Worker
3468*5e7646d2SAndroid Build Coastguard Worker _exit(1);
3469*5e7646d2SAndroid Build Coastguard Worker }
3470*5e7646d2SAndroid Build Coastguard Worker
3471*5e7646d2SAndroid Build Coastguard Worker
3472*5e7646d2SAndroid Build Coastguard Worker /*
3473*5e7646d2SAndroid Build Coastguard Worker * 'timeout_cb()' - Handle HTTP timeouts.
3474*5e7646d2SAndroid Build Coastguard Worker */
3475*5e7646d2SAndroid Build Coastguard Worker
3476*5e7646d2SAndroid Build Coastguard Worker static int /* O - 1 to continue, 0 to cancel */
timeout_cb(http_t * http,void * user_data)3477*5e7646d2SAndroid Build Coastguard Worker timeout_cb(http_t *http, /* I - Connection to server (unused) */
3478*5e7646d2SAndroid Build Coastguard Worker void *user_data) /* I - User data (unused) */
3479*5e7646d2SAndroid Build Coastguard Worker {
3480*5e7646d2SAndroid Build Coastguard Worker (void)http;
3481*5e7646d2SAndroid Build Coastguard Worker (void)user_data;
3482*5e7646d2SAndroid Build Coastguard Worker
3483*5e7646d2SAndroid Build Coastguard Worker return (!job_canceled);
3484*5e7646d2SAndroid Build Coastguard Worker }
3485*5e7646d2SAndroid Build Coastguard Worker
3486*5e7646d2SAndroid Build Coastguard Worker
3487*5e7646d2SAndroid Build Coastguard Worker /*
3488*5e7646d2SAndroid Build Coastguard Worker * 'update_reasons()' - Update the printer-state-reasons values.
3489*5e7646d2SAndroid Build Coastguard Worker */
3490*5e7646d2SAndroid Build Coastguard Worker
3491*5e7646d2SAndroid Build Coastguard Worker static void
update_reasons(ipp_attribute_t * attr,const char * s)3492*5e7646d2SAndroid Build Coastguard Worker update_reasons(ipp_attribute_t *attr, /* I - printer-state-reasons or NULL */
3493*5e7646d2SAndroid Build Coastguard Worker const char *s) /* I - STATE: string or NULL */
3494*5e7646d2SAndroid Build Coastguard Worker {
3495*5e7646d2SAndroid Build Coastguard Worker char op; /* Add (+), remove (-), replace (\0) */
3496*5e7646d2SAndroid Build Coastguard Worker cups_array_t *new_reasons; /* New reasons array */
3497*5e7646d2SAndroid Build Coastguard Worker char *reason, /* Current reason */
3498*5e7646d2SAndroid Build Coastguard Worker add[2048], /* Reasons added string */
3499*5e7646d2SAndroid Build Coastguard Worker *addptr, /* Pointer into add string */
3500*5e7646d2SAndroid Build Coastguard Worker rem[2048], /* Reasons removed string */
3501*5e7646d2SAndroid Build Coastguard Worker *remptr; /* Pointer into remove string */
3502*5e7646d2SAndroid Build Coastguard Worker const char *addprefix, /* Current add string prefix */
3503*5e7646d2SAndroid Build Coastguard Worker *remprefix; /* Current remove string prefix */
3504*5e7646d2SAndroid Build Coastguard Worker
3505*5e7646d2SAndroid Build Coastguard Worker
3506*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG: update_reasons(attr=%d(%s%s), s=\"%s\")\n",
3507*5e7646d2SAndroid Build Coastguard Worker attr ? attr->num_values : 0, attr ? attr->values[0].string.text : "",
3508*5e7646d2SAndroid Build Coastguard Worker attr && attr->num_values > 1 ? ",..." : "", s ? s : "(null)");
3509*5e7646d2SAndroid Build Coastguard Worker
3510*5e7646d2SAndroid Build Coastguard Worker /*
3511*5e7646d2SAndroid Build Coastguard Worker * Create an array of new reason keyword strings...
3512*5e7646d2SAndroid Build Coastguard Worker */
3513*5e7646d2SAndroid Build Coastguard Worker
3514*5e7646d2SAndroid Build Coastguard Worker if (attr)
3515*5e7646d2SAndroid Build Coastguard Worker {
3516*5e7646d2SAndroid Build Coastguard Worker int i; /* Looping var */
3517*5e7646d2SAndroid Build Coastguard Worker
3518*5e7646d2SAndroid Build Coastguard Worker new_reasons = cupsArrayNew((cups_array_func_t)strcmp, NULL);
3519*5e7646d2SAndroid Build Coastguard Worker op = '\0';
3520*5e7646d2SAndroid Build Coastguard Worker
3521*5e7646d2SAndroid Build Coastguard Worker for (i = 0; i < attr->num_values; i ++)
3522*5e7646d2SAndroid Build Coastguard Worker {
3523*5e7646d2SAndroid Build Coastguard Worker reason = attr->values[i].string.text;
3524*5e7646d2SAndroid Build Coastguard Worker
3525*5e7646d2SAndroid Build Coastguard Worker if (strcmp(reason, "none") &&
3526*5e7646d2SAndroid Build Coastguard Worker strcmp(reason, "none-report") &&
3527*5e7646d2SAndroid Build Coastguard Worker strcmp(reason, "paused") &&
3528*5e7646d2SAndroid Build Coastguard Worker strncmp(reason, "spool-area-full", 15) &&
3529*5e7646d2SAndroid Build Coastguard Worker strcmp(reason, "com.apple.print.recoverable-warning") &&
3530*5e7646d2SAndroid Build Coastguard Worker strncmp(reason, "cups-", 5))
3531*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(new_reasons, reason);
3532*5e7646d2SAndroid Build Coastguard Worker }
3533*5e7646d2SAndroid Build Coastguard Worker }
3534*5e7646d2SAndroid Build Coastguard Worker else if (s)
3535*5e7646d2SAndroid Build Coastguard Worker {
3536*5e7646d2SAndroid Build Coastguard Worker if (*s == '+' || *s == '-')
3537*5e7646d2SAndroid Build Coastguard Worker op = *s++;
3538*5e7646d2SAndroid Build Coastguard Worker else
3539*5e7646d2SAndroid Build Coastguard Worker op = '\0';
3540*5e7646d2SAndroid Build Coastguard Worker
3541*5e7646d2SAndroid Build Coastguard Worker new_reasons = _cupsArrayNewStrings(s, ',');
3542*5e7646d2SAndroid Build Coastguard Worker }
3543*5e7646d2SAndroid Build Coastguard Worker else
3544*5e7646d2SAndroid Build Coastguard Worker return;
3545*5e7646d2SAndroid Build Coastguard Worker
3546*5e7646d2SAndroid Build Coastguard Worker /*
3547*5e7646d2SAndroid Build Coastguard Worker * Compute the changes...
3548*5e7646d2SAndroid Build Coastguard Worker */
3549*5e7646d2SAndroid Build Coastguard Worker
3550*5e7646d2SAndroid Build Coastguard Worker add[0] = '\0';
3551*5e7646d2SAndroid Build Coastguard Worker addprefix = "STATE: +";
3552*5e7646d2SAndroid Build Coastguard Worker addptr = add;
3553*5e7646d2SAndroid Build Coastguard Worker rem[0] = '\0';
3554*5e7646d2SAndroid Build Coastguard Worker remprefix = "STATE: -";
3555*5e7646d2SAndroid Build Coastguard Worker remptr = rem;
3556*5e7646d2SAndroid Build Coastguard Worker
3557*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "DEBUG2: op='%c', new_reasons=%d, state_reasons=%d\n",
3558*5e7646d2SAndroid Build Coastguard Worker op ? op : ' ', cupsArrayCount(new_reasons),
3559*5e7646d2SAndroid Build Coastguard Worker cupsArrayCount(state_reasons));
3560*5e7646d2SAndroid Build Coastguard Worker
3561*5e7646d2SAndroid Build Coastguard Worker _cupsMutexLock(&report_mutex);
3562*5e7646d2SAndroid Build Coastguard Worker
3563*5e7646d2SAndroid Build Coastguard Worker if (op == '+')
3564*5e7646d2SAndroid Build Coastguard Worker {
3565*5e7646d2SAndroid Build Coastguard Worker /*
3566*5e7646d2SAndroid Build Coastguard Worker * Add reasons...
3567*5e7646d2SAndroid Build Coastguard Worker */
3568*5e7646d2SAndroid Build Coastguard Worker
3569*5e7646d2SAndroid Build Coastguard Worker for (reason = (char *)cupsArrayFirst(new_reasons);
3570*5e7646d2SAndroid Build Coastguard Worker reason;
3571*5e7646d2SAndroid Build Coastguard Worker reason = (char *)cupsArrayNext(new_reasons))
3572*5e7646d2SAndroid Build Coastguard Worker {
3573*5e7646d2SAndroid Build Coastguard Worker if (!cupsArrayFind(state_reasons, reason))
3574*5e7646d2SAndroid Build Coastguard Worker {
3575*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(reason, "cups-remote-", 12))
3576*5e7646d2SAndroid Build Coastguard Worker {
3577*5e7646d2SAndroid Build Coastguard Worker /*
3578*5e7646d2SAndroid Build Coastguard Worker * If we are setting cups-remote-xxx, remove all other cups-remote-xxx
3579*5e7646d2SAndroid Build Coastguard Worker * keywords...
3580*5e7646d2SAndroid Build Coastguard Worker */
3581*5e7646d2SAndroid Build Coastguard Worker
3582*5e7646d2SAndroid Build Coastguard Worker char *temp; /* Current reason in state_reasons */
3583*5e7646d2SAndroid Build Coastguard Worker
3584*5e7646d2SAndroid Build Coastguard Worker cupsArraySave(state_reasons);
3585*5e7646d2SAndroid Build Coastguard Worker
3586*5e7646d2SAndroid Build Coastguard Worker for (temp = (char *)cupsArrayFirst(state_reasons);
3587*5e7646d2SAndroid Build Coastguard Worker temp;
3588*5e7646d2SAndroid Build Coastguard Worker temp = (char *)cupsArrayNext(state_reasons))
3589*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(temp, "cups-remote-", 12))
3590*5e7646d2SAndroid Build Coastguard Worker {
3591*5e7646d2SAndroid Build Coastguard Worker snprintf(remptr, sizeof(rem) - (size_t)(remptr - rem), "%s%s", remprefix, temp);
3592*5e7646d2SAndroid Build Coastguard Worker remptr += strlen(remptr);
3593*5e7646d2SAndroid Build Coastguard Worker remprefix = ",";
3594*5e7646d2SAndroid Build Coastguard Worker
3595*5e7646d2SAndroid Build Coastguard Worker cupsArrayRemove(state_reasons, temp);
3596*5e7646d2SAndroid Build Coastguard Worker break;
3597*5e7646d2SAndroid Build Coastguard Worker }
3598*5e7646d2SAndroid Build Coastguard Worker
3599*5e7646d2SAndroid Build Coastguard Worker cupsArrayRestore(state_reasons);
3600*5e7646d2SAndroid Build Coastguard Worker }
3601*5e7646d2SAndroid Build Coastguard Worker
3602*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(state_reasons, reason);
3603*5e7646d2SAndroid Build Coastguard Worker
3604*5e7646d2SAndroid Build Coastguard Worker snprintf(addptr, sizeof(add) - (size_t)(addptr - add), "%s%s", addprefix, reason);
3605*5e7646d2SAndroid Build Coastguard Worker addptr += strlen(addptr);
3606*5e7646d2SAndroid Build Coastguard Worker addprefix = ",";
3607*5e7646d2SAndroid Build Coastguard Worker }
3608*5e7646d2SAndroid Build Coastguard Worker }
3609*5e7646d2SAndroid Build Coastguard Worker }
3610*5e7646d2SAndroid Build Coastguard Worker else if (op == '-')
3611*5e7646d2SAndroid Build Coastguard Worker {
3612*5e7646d2SAndroid Build Coastguard Worker /*
3613*5e7646d2SAndroid Build Coastguard Worker * Remove reasons...
3614*5e7646d2SAndroid Build Coastguard Worker */
3615*5e7646d2SAndroid Build Coastguard Worker
3616*5e7646d2SAndroid Build Coastguard Worker for (reason = (char *)cupsArrayFirst(new_reasons);
3617*5e7646d2SAndroid Build Coastguard Worker reason;
3618*5e7646d2SAndroid Build Coastguard Worker reason = (char *)cupsArrayNext(new_reasons))
3619*5e7646d2SAndroid Build Coastguard Worker {
3620*5e7646d2SAndroid Build Coastguard Worker if (cupsArrayFind(state_reasons, reason))
3621*5e7646d2SAndroid Build Coastguard Worker {
3622*5e7646d2SAndroid Build Coastguard Worker snprintf(remptr, sizeof(rem) - (size_t)(remptr - rem), "%s%s", remprefix, reason);
3623*5e7646d2SAndroid Build Coastguard Worker remptr += strlen(remptr);
3624*5e7646d2SAndroid Build Coastguard Worker remprefix = ",";
3625*5e7646d2SAndroid Build Coastguard Worker
3626*5e7646d2SAndroid Build Coastguard Worker cupsArrayRemove(state_reasons, reason);
3627*5e7646d2SAndroid Build Coastguard Worker }
3628*5e7646d2SAndroid Build Coastguard Worker }
3629*5e7646d2SAndroid Build Coastguard Worker }
3630*5e7646d2SAndroid Build Coastguard Worker else
3631*5e7646d2SAndroid Build Coastguard Worker {
3632*5e7646d2SAndroid Build Coastguard Worker /*
3633*5e7646d2SAndroid Build Coastguard Worker * Replace reasons...
3634*5e7646d2SAndroid Build Coastguard Worker */
3635*5e7646d2SAndroid Build Coastguard Worker
3636*5e7646d2SAndroid Build Coastguard Worker for (reason = (char *)cupsArrayFirst(state_reasons);
3637*5e7646d2SAndroid Build Coastguard Worker reason;
3638*5e7646d2SAndroid Build Coastguard Worker reason = (char *)cupsArrayNext(state_reasons))
3639*5e7646d2SAndroid Build Coastguard Worker {
3640*5e7646d2SAndroid Build Coastguard Worker if (strncmp(reason, "cups-", 5) && !cupsArrayFind(new_reasons, reason))
3641*5e7646d2SAndroid Build Coastguard Worker {
3642*5e7646d2SAndroid Build Coastguard Worker snprintf(remptr, sizeof(rem) - (size_t)(remptr - rem), "%s%s", remprefix, reason);
3643*5e7646d2SAndroid Build Coastguard Worker remptr += strlen(remptr);
3644*5e7646d2SAndroid Build Coastguard Worker remprefix = ",";
3645*5e7646d2SAndroid Build Coastguard Worker
3646*5e7646d2SAndroid Build Coastguard Worker cupsArrayRemove(state_reasons, reason);
3647*5e7646d2SAndroid Build Coastguard Worker }
3648*5e7646d2SAndroid Build Coastguard Worker }
3649*5e7646d2SAndroid Build Coastguard Worker
3650*5e7646d2SAndroid Build Coastguard Worker for (reason = (char *)cupsArrayFirst(new_reasons);
3651*5e7646d2SAndroid Build Coastguard Worker reason;
3652*5e7646d2SAndroid Build Coastguard Worker reason = (char *)cupsArrayNext(new_reasons))
3653*5e7646d2SAndroid Build Coastguard Worker {
3654*5e7646d2SAndroid Build Coastguard Worker if (!cupsArrayFind(state_reasons, reason))
3655*5e7646d2SAndroid Build Coastguard Worker {
3656*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(state_reasons, reason);
3657*5e7646d2SAndroid Build Coastguard Worker
3658*5e7646d2SAndroid Build Coastguard Worker snprintf(addptr, sizeof(add) - (size_t)(addptr - add), "%s%s", addprefix, reason);
3659*5e7646d2SAndroid Build Coastguard Worker addptr += strlen(addptr);
3660*5e7646d2SAndroid Build Coastguard Worker addprefix = ",";
3661*5e7646d2SAndroid Build Coastguard Worker }
3662*5e7646d2SAndroid Build Coastguard Worker }
3663*5e7646d2SAndroid Build Coastguard Worker }
3664*5e7646d2SAndroid Build Coastguard Worker
3665*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(new_reasons);
3666*5e7646d2SAndroid Build Coastguard Worker
3667*5e7646d2SAndroid Build Coastguard Worker _cupsMutexUnlock(&report_mutex);
3668*5e7646d2SAndroid Build Coastguard Worker
3669*5e7646d2SAndroid Build Coastguard Worker /*
3670*5e7646d2SAndroid Build Coastguard Worker * Report changes and return...
3671*5e7646d2SAndroid Build Coastguard Worker */
3672*5e7646d2SAndroid Build Coastguard Worker
3673*5e7646d2SAndroid Build Coastguard Worker if (add[0] && rem[0])
3674*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s\n%s\n", add, rem);
3675*5e7646d2SAndroid Build Coastguard Worker else if (add[0])
3676*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s\n", add);
3677*5e7646d2SAndroid Build Coastguard Worker else if (rem[0])
3678*5e7646d2SAndroid Build Coastguard Worker fprintf(stderr, "%s\n", rem);
3679*5e7646d2SAndroid Build Coastguard Worker }
3680