]>
Commit | Line | Data |
---|---|---|
c8f9565c | 1 | /* |
5a2c7855 | 2 | * "$Id: ipp.c,v 1.28 2000/07/10 13:52:54 mike Exp $" |
c8f9565c | 3 | * |
4 | * IPP backend for the Common UNIX Printing System (CUPS). | |
5 | * | |
71fe22b7 | 6 | * Copyright 1997-2000 by Easy Software Products, all rights reserved. |
c8f9565c | 7 | * |
8 | * These coded instructions, statements, and computer programs are the | |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
16 | * Easy Software Products | |
8784b6a6 | 17 | * 44141 Airport View Drive, Suite 204 |
c8f9565c | 18 | * Hollywood, Maryland 20636-3111 USA |
19 | * | |
20 | * Voice: (301) 373-9603 | |
21 | * EMail: cups-info@cups.org | |
22 | * WWW: http://www.cups.org | |
23 | * | |
24 | * Contents: | |
25 | * | |
6d0582d2 | 26 | * main() - Send a file to the printer or server. |
c8f9565c | 27 | */ |
28 | ||
29 | /* | |
30 | * Include necessary headers. | |
31 | */ | |
32 | ||
33 | #include <stdio.h> | |
34 | #include <stdlib.h> | |
35 | #include <errno.h> | |
36 | #include <sys/types.h> | |
37 | #include <sys/stat.h> | |
38 | #include <cups/cups.h> | |
39 | #include <cups/language.h> | |
40 | #include <cups/string.h> | |
4ff40357 | 41 | #include <signal.h> |
c8f9565c | 42 | |
43 | ||
44 | /* | |
45 | * 'main()' - Send a file to the printer or server. | |
46 | * | |
47 | * Usage: | |
48 | * | |
49 | * printer-uri job-id user title copies options [file] | |
50 | */ | |
51 | ||
52 | int /* O - Exit status */ | |
53 | main(int argc, /* I - Number of command-line arguments (6 or 7) */ | |
54 | char *argv[]) /* I - Command-line arguments */ | |
55 | { | |
56 | int i; /* Looping var */ | |
57 | int n, n2; /* Attribute values */ | |
58 | char *option, /* Name of option */ | |
c8f9565c | 59 | *s; /* Pointer into option value */ |
3079988e | 60 | const char *val; /* Pointer to option value */ |
c8f9565c | 61 | int num_options; /* Number of printer options */ |
3079988e | 62 | cups_option_t *options; /* Printer options */ |
c8f9565c | 63 | char method[255], /* Method in URI */ |
64 | hostname[1024], /* Hostname */ | |
65 | username[255], /* Username info */ | |
66 | resource[1024], /* Resource info (printer name) */ | |
67 | filename[1024]; /* File to print */ | |
68 | int port; /* Port number (not used) */ | |
69 | char password[255], /* Password info */ | |
70 | uri[HTTP_MAX_URI];/* Updated URI without user/pass */ | |
71 | http_status_t status; /* Status of HTTP job */ | |
97fcaf92 | 72 | ipp_status_t ipp_status; /* Status of IPP request */ |
c8f9565c | 73 | FILE *fp; /* File to print */ |
74 | http_t *http; /* HTTP connection */ | |
75 | ipp_t *request, /* IPP request */ | |
76 | *response; /* IPP response */ | |
77 | ipp_attribute_t *job_id; /* job-id attribute */ | |
97fcaf92 | 78 | ipp_attribute_t *copies_sup; /* copies-supported attribute */ |
c8f9565c | 79 | cups_lang_t *language; /* Default language */ |
80 | struct stat fileinfo; /* File statistics */ | |
81 | size_t nbytes, /* Number of bytes written */ | |
82 | tbytes; /* Total bytes written */ | |
83 | char buffer[8192]; /* Output buffer */ | |
97fcaf92 | 84 | int copies; /* Number of copies remaining */ |
0a3944d6 | 85 | const char *content_type; /* CONTENT_TYPE environment variable */ |
4ff40357 | 86 | #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) |
87 | struct sigaction action; /* Actions for POSIX signals */ | |
88 | #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ | |
5a2c7855 | 89 | int version; /* IPP version */ |
c8f9565c | 90 | |
91 | ||
68edc300 | 92 | if (argc == 1) |
93 | { | |
d4c438d4 | 94 | if ((s = strrchr(argv[0], '/')) != NULL) |
95 | s ++; | |
96 | else | |
97 | s = argv[0]; | |
98 | ||
99 | printf("network %s \"Unknown\" \"Internet Printing Protocol\"\n", s); | |
68edc300 | 100 | return (0); |
101 | } | |
102 | else if (argc < 6 || argc > 7) | |
c8f9565c | 103 | { |
104 | fprintf(stderr, "Usage: %s job-id user title copies options [file]\n", | |
105 | argv[0]); | |
106 | return (1); | |
107 | } | |
108 | ||
109 | /* | |
110 | * If we have 7 arguments, print the file named on the command-line. | |
97fcaf92 | 111 | * Otherwise, copy stdin to a temporary file and print the temporary |
112 | * file. | |
c8f9565c | 113 | */ |
114 | ||
115 | if (argc == 6) | |
97fcaf92 | 116 | { |
117 | /* | |
118 | * Copy stdin to a temporary file... | |
119 | */ | |
120 | ||
121 | FILE *fp; /* Temporary file */ | |
122 | char buffer[8192]; /* Buffer for copying */ | |
123 | int bytes; /* Number of bytes read */ | |
124 | ||
125 | ||
126 | if ((fp = fopen(cupsTempFile(filename, sizeof(filename)), "w")) == NULL) | |
127 | { | |
128 | perror("ERROR: unable to create temporary file"); | |
129 | return (1); | |
130 | } | |
131 | ||
132 | while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) | |
133 | if (fwrite(buffer, 1, bytes, fp) < bytes) | |
134 | { | |
135 | perror("ERROR: unable to write to temporary file"); | |
136 | fclose(fp); | |
137 | unlink(filename); | |
138 | return (1); | |
139 | } | |
140 | ||
141 | fclose(fp); | |
142 | } | |
143 | else | |
144 | { | |
145 | strncpy(filename, argv[6], sizeof(filename) - 1); | |
146 | filename[sizeof(filename) - 1] = '\0'; | |
147 | } | |
148 | ||
149 | /* | |
150 | * Open the print file... | |
151 | */ | |
152 | ||
153 | if ((fp = fopen(filename, "rb")) == NULL) | |
c8f9565c | 154 | { |
155 | perror("ERROR: Unable to open print file"); | |
156 | return (1); | |
157 | } | |
158 | else | |
97fcaf92 | 159 | stat(filename, &fileinfo); |
c8f9565c | 160 | |
161 | /* | |
162 | * Extract the hostname and printer name from the URI... | |
163 | */ | |
164 | ||
165 | httpSeparate(argv[0], method, username, hostname, &port, resource); | |
166 | ||
167 | /* | |
168 | * Try connecting to the remote server... | |
169 | */ | |
170 | ||
97fcaf92 | 171 | do |
c8f9565c | 172 | { |
97fcaf92 | 173 | fprintf(stderr, "INFO: Connecting to %s...\n", hostname); |
c8f9565c | 174 | |
97fcaf92 | 175 | if ((http = httpConnect(hostname, port)) == NULL) |
d21a7597 | 176 | { |
97fcaf92 | 177 | if (errno == ECONNREFUSED) |
178 | { | |
179 | fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in 30 seconds...", | |
180 | hostname); | |
181 | sleep(30); | |
182 | } | |
183 | else | |
184 | { | |
185 | perror("ERROR: Unable to connect to IPP host"); | |
2cc18dd2 | 186 | sleep(30); |
97fcaf92 | 187 | } |
d21a7597 | 188 | } |
c8f9565c | 189 | } |
97fcaf92 | 190 | while (http == NULL); |
c8f9565c | 191 | |
192 | /* | |
193 | * Build a URI for the printer and fill the standard IPP attributes for | |
8ce7c000 | 194 | * an IPP_PRINT_FILE request. We can't use the URI in argv[0] because it |
195 | * might contain username:password information... | |
c8f9565c | 196 | */ |
197 | ||
3f9cb6c6 | 198 | snprintf(uri, sizeof(uri), "%s://%s:%d%s", method, hostname, port, resource); |
c8f9565c | 199 | |
200 | /* | |
97fcaf92 | 201 | * First validate the destination and see if the device supports multiple |
202 | * copies. We have to do this because some IPP servers (e.g. HP JetDirect) | |
203 | * don't support the copies attribute... | |
c8f9565c | 204 | */ |
205 | ||
97fcaf92 | 206 | language = cupsLangDefault(); |
207 | copies_sup = NULL; | |
5a2c7855 | 208 | version = 1; |
c8f9565c | 209 | |
97fcaf92 | 210 | do |
c8f9565c | 211 | { |
212 | /* | |
97fcaf92 | 213 | * Build the IPP request... |
c8f9565c | 214 | */ |
215 | ||
97fcaf92 | 216 | request = ippNew(); |
5a2c7855 | 217 | request->request.op.version[1] = version; |
97fcaf92 | 218 | request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; |
219 | request->request.op.request_id = 1; | |
c8f9565c | 220 | |
97fcaf92 | 221 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, |
67436e05 | 222 | "attributes-charset", NULL, "utf-8"); |
97fcaf92 | 223 | |
224 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, | |
225 | "attributes-natural-language", NULL, | |
67436e05 | 226 | language != NULL ? language->language : "en"); |
c8f9565c | 227 | |
97fcaf92 | 228 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", |
229 | NULL, uri); | |
c8f9565c | 230 | |
97fcaf92 | 231 | /* |
232 | * Now fill in the HTTP request stuff... | |
233 | */ | |
c8f9565c | 234 | |
97fcaf92 | 235 | httpClearFields(http); |
236 | httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp"); | |
237 | if (username[0]) | |
c8f9565c | 238 | { |
97fcaf92 | 239 | httpEncode64(password, username); |
240 | httpSetField(http, HTTP_FIELD_AUTHORIZATION, password); | |
241 | } | |
c8f9565c | 242 | |
97fcaf92 | 243 | sprintf(buffer, "%u", ippLength(request)); |
244 | httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, buffer); | |
c8f9565c | 245 | |
97fcaf92 | 246 | /* |
247 | * Do the request... | |
248 | */ | |
c8f9565c | 249 | |
97fcaf92 | 250 | for (;;) |
c8f9565c | 251 | { |
97fcaf92 | 252 | /* |
253 | * POST the request, retrying as needed... | |
254 | */ | |
255 | ||
256 | if (httpPost(http, resource)) | |
c8f9565c | 257 | { |
97fcaf92 | 258 | fputs("INFO: Unable to POST get-printer-attributes request; retrying...\n", stderr); |
259 | sleep(10); | |
260 | httpReconnect(http); | |
261 | continue; | |
c8f9565c | 262 | } |
c8f9565c | 263 | |
97fcaf92 | 264 | fputs("INFO: POST successful, sending IPP request...\n", stderr); |
c8f9565c | 265 | |
c8f9565c | 266 | /* |
97fcaf92 | 267 | * Send the IPP request... |
c8f9565c | 268 | */ |
97fcaf92 | 269 | |
270 | request->state = IPP_IDLE; | |
271 | ||
272 | if (ippWrite(http, request) == IPP_ERROR) | |
273 | { | |
274 | fputs("ERROR: Unable to send IPP request!\n", stderr); | |
275 | status = HTTP_ERROR; | |
276 | break; | |
277 | } | |
278 | ||
279 | fputs("INFO: IPP request sent, getting status...\n", stderr); | |
280 | ||
c8f9565c | 281 | /* |
97fcaf92 | 282 | * Finally, check the status from the HTTP server... |
c8f9565c | 283 | */ |
284 | ||
97fcaf92 | 285 | while ((status = httpUpdate(http)) == HTTP_CONTINUE); |
286 | ||
287 | if (status == HTTP_OK) | |
c8f9565c | 288 | { |
97fcaf92 | 289 | response = ippNew(); |
290 | ippRead(http, response); | |
291 | ||
292 | ipp_status = response->request.status.status_code; | |
d21a7597 | 293 | |
97fcaf92 | 294 | if (ipp_status > IPP_OK_CONFLICT) |
295 | { | |
296 | if (ipp_status == IPP_PRINTER_BUSY || | |
297 | ipp_status == IPP_SERVICE_UNAVAILABLE) | |
298 | { | |
299 | fputs("INFO: Printer busy; will retry in 10 seconds...\n", stderr); | |
300 | sleep(10); | |
301 | } | |
5a2c7855 | 302 | else if (ipp_status == IPP_BAD_REQUEST && version == 1) |
303 | { | |
304 | /* | |
305 | * Switch to IPP/1.0... | |
306 | */ | |
307 | ||
308 | fputs("INFO: Printer does not support IPP/1.1, trying IPP/1.0...\n", stderr); | |
309 | version = 0; | |
310 | } | |
97fcaf92 | 311 | else |
312 | { | |
313 | fprintf(stderr, "ERROR: Printer will not accept print file (%x)!\n", | |
314 | ipp_status); | |
5a2c7855 | 315 | fprintf(stderr, "ERROR: %s\n", ippErrorString(ipp_status)); |
97fcaf92 | 316 | status = HTTP_ERROR; |
317 | } | |
318 | } | |
319 | else if ((copies_sup = ippFindAttribute(response, "copies-supported", | |
320 | IPP_TAG_RANGE)) != NULL) | |
321 | { | |
322 | /* | |
323 | * Has the "copies-supported" attribute - does it have an upper | |
324 | * bound > 1? | |
325 | */ | |
326 | ||
327 | if (copies_sup->values[0].range.upper <= 1) | |
328 | copies_sup = NULL; /* No */ | |
329 | } | |
330 | ||
331 | ippDelete(response); | |
c8f9565c | 332 | } |
97fcaf92 | 333 | else |
c8f9565c | 334 | { |
d21a7597 | 335 | response = NULL; |
336 | ||
97fcaf92 | 337 | if (status == HTTP_ERROR) |
338 | { | |
339 | fprintf(stderr, "WARNING: Did not receive the IPP response (%d)\n", | |
340 | errno); | |
341 | status = HTTP_OK; | |
342 | ipp_status = IPP_PRINTER_BUSY; | |
343 | } | |
344 | else | |
d21a7597 | 345 | { |
5a2c7855 | 346 | fprintf(stderr, "ERROR: Validate request was not accepted (%d)!\n", |
347 | status); | |
d21a7597 | 348 | ipp_status = IPP_FORBIDDEN; |
349 | } | |
c8f9565c | 350 | } |
97fcaf92 | 351 | |
352 | httpFlush(http); | |
353 | ||
354 | break; | |
355 | } | |
356 | ||
357 | if (status != HTTP_OK) | |
358 | { | |
359 | if (fp != stdin) | |
360 | fclose(fp); | |
361 | ||
362 | httpClose(http); | |
363 | ||
364 | return (1); | |
c8f9565c | 365 | } |
5a2c7855 | 366 | else if (ipp_status > IPP_OK_CONFLICT) |
367 | httpReconnect(http); | |
c8f9565c | 368 | } |
97fcaf92 | 369 | while (ipp_status > IPP_OK_CONFLICT); |
c8f9565c | 370 | |
4ff40357 | 371 | /* |
372 | * Now that we are "connected" to the port, ignore SIGTERM so that we | |
373 | * can finish out any page data the driver sends (e.g. to eject the | |
374 | * current page... | |
375 | */ | |
376 | ||
377 | #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ | |
378 | sigset(SIGTERM, SIG_IGN); | |
379 | #elif defined(HAVE_SIGACTION) | |
380 | memset(&action, 0, sizeof(action)); | |
381 | ||
382 | sigemptyset(&action.sa_mask); | |
383 | action.sa_handler = SIG_IGN; | |
384 | sigaction(SIGTERM, &action, NULL); | |
385 | #else | |
386 | signal(SIGTERM, SIG_IGN); | |
387 | #endif /* HAVE_SIGSET */ | |
388 | ||
c8f9565c | 389 | /* |
97fcaf92 | 390 | * See if the printer supports multiple copies... |
c8f9565c | 391 | */ |
392 | ||
97fcaf92 | 393 | if (copies_sup) |
394 | copies = 1; | |
0c5b0932 | 395 | else |
97fcaf92 | 396 | copies = atoi(argv[4]); |
0c5b0932 | 397 | |
c8f9565c | 398 | /* |
97fcaf92 | 399 | * Then issue the print-job request... |
c8f9565c | 400 | */ |
401 | ||
97fcaf92 | 402 | while (copies > 0) |
c8f9565c | 403 | { |
404 | /* | |
97fcaf92 | 405 | * Build the IPP request... |
c8f9565c | 406 | */ |
407 | ||
97fcaf92 | 408 | request = ippNew(); |
5a2c7855 | 409 | request->request.op.version[1] = version; |
97fcaf92 | 410 | request->request.op.operation_id = IPP_PRINT_JOB; |
411 | request->request.op.request_id = 1; | |
c8f9565c | 412 | |
97fcaf92 | 413 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, |
67436e05 | 414 | "attributes-charset", NULL, "utf-8"); |
8ce7c000 | 415 | |
97fcaf92 | 416 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, |
417 | "attributes-natural-language", NULL, | |
67436e05 | 418 | language != NULL ? language->language : "en"); |
c8f9565c | 419 | |
97fcaf92 | 420 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", |
421 | NULL, uri); | |
c8f9565c | 422 | |
97fcaf92 | 423 | fprintf(stderr, "DEBUG: printer-uri = \"%s\"\n", uri); |
424 | ||
425 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", | |
426 | NULL, argv[2]); | |
427 | ||
428 | fprintf(stderr, "DEBUG: requesting-user-name = \"%s\"\n", argv[2]); | |
429 | ||
430 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, | |
431 | argv[3]); | |
c8f9565c | 432 | |
97fcaf92 | 433 | fprintf(stderr, "DEBUG: job-name = \"%s\"\n", argv[3]); |
8ce7c000 | 434 | |
c8f9565c | 435 | /* |
97fcaf92 | 436 | * Handle options on the command-line... |
c8f9565c | 437 | */ |
438 | ||
97fcaf92 | 439 | options = NULL; |
440 | num_options = cupsParseOptions(argv[5], 0, &options); | |
441 | ||
0a3944d6 | 442 | if (cupsGetOption("raw", num_options, options) || |
443 | ((content_type = getenv("CONTENT_TYPE")) != NULL && | |
444 | strcasecmp(content_type, "application/vnd.cups-raw") == 0)) | |
97fcaf92 | 445 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", |
446 | NULL, "application/vnd.cups-raw"); | |
3079988e | 447 | else if ((val = cupsGetOption("document-format", num_options, options)) != NULL) |
866ee248 | 448 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", |
3079988e | 449 | NULL, val); |
97fcaf92 | 450 | else |
451 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", | |
452 | NULL, "application/octet-stream"); | |
453 | ||
454 | if (copies_sup) | |
455 | ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", atoi(argv[4])); | |
456 | ||
457 | for (i = 0; i < num_options; i ++) | |
c8f9565c | 458 | { |
97fcaf92 | 459 | /* |
460 | * Skip the "raw" option - handled above... | |
461 | */ | |
462 | ||
866ee248 | 463 | if (strcasecmp(options[i].name, "raw") == 0 || |
464 | strcasecmp(options[i].name, "document-format") == 0) | |
97fcaf92 | 465 | continue; |
466 | ||
467 | /* | |
468 | * See what the option value is; for compatibility with older interface | |
469 | * scripts, we have to support single-argument options as well as | |
470 | * option=value, option=low-high, and option=MxN. | |
471 | */ | |
472 | ||
473 | option = options[i].name; | |
474 | val = options[i].value; | |
c8f9565c | 475 | |
97fcaf92 | 476 | if (*val == '\0') |
477 | val = NULL; | |
478 | ||
479 | if (val != NULL) | |
c8f9565c | 480 | { |
97fcaf92 | 481 | if (strcasecmp(val, "true") == 0 || |
482 | strcasecmp(val, "on") == 0 || | |
483 | strcasecmp(val, "yes") == 0) | |
484 | { | |
485 | /* | |
486 | * Boolean value - true... | |
487 | */ | |
488 | ||
489 | n = 1; | |
490 | val = ""; | |
491 | } | |
492 | else if (strcasecmp(val, "false") == 0 || | |
493 | strcasecmp(val, "off") == 0 || | |
494 | strcasecmp(val, "no") == 0) | |
495 | { | |
496 | /* | |
497 | * Boolean value - false... | |
498 | */ | |
499 | ||
500 | n = 0; | |
501 | val = ""; | |
502 | } | |
503 | ||
504 | n = strtol(val, &s, 0); | |
505 | } | |
506 | else | |
507 | { | |
508 | if (strncasecmp(option, "no", 2) == 0) | |
509 | { | |
510 | option += 2; | |
511 | n = 0; | |
512 | } | |
513 | else | |
514 | n = 1; | |
515 | ||
516 | s = ""; | |
c8f9565c | 517 | } |
97fcaf92 | 518 | |
519 | if (*s != '\0' && *s != '-' && (*s != 'x' || s == val)) | |
520 | /* | |
521 | * String value(s)... | |
522 | */ | |
523 | ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, option, NULL, val); | |
524 | else if (val != NULL) | |
525 | { | |
526 | /* | |
527 | * Numeric value, range, or resolution... | |
528 | */ | |
529 | ||
530 | if (*s == '-') | |
531 | { | |
532 | n2 = strtol(s + 1, NULL, 0); | |
533 | ippAddRange(request, IPP_TAG_JOB, option, n, n2); | |
534 | } | |
535 | else if (*s == 'x') | |
536 | { | |
537 | n2 = strtol(s + 1, &s, 0); | |
538 | ||
539 | if (strcasecmp(s, "dpc") == 0) | |
540 | ippAddResolution(request, IPP_TAG_JOB, option, IPP_RES_PER_CM, n, n2); | |
541 | else if (strcasecmp(s, "dpi") == 0) | |
542 | ippAddResolution(request, IPP_TAG_JOB, option, IPP_RES_PER_INCH, n, n2); | |
543 | else | |
544 | ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, option, NULL, val); | |
545 | } | |
546 | else | |
547 | ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, option, n); | |
548 | } | |
549 | else | |
550 | /* | |
551 | * Boolean value... | |
552 | */ | |
553 | ippAddBoolean(request, IPP_TAG_JOB, option, (char)n); | |
c8f9565c | 554 | } |
555 | ||
cb555bcf | 556 | /* |
97fcaf92 | 557 | * Now fill in the HTTP request stuff... |
cb555bcf | 558 | */ |
559 | ||
97fcaf92 | 560 | httpClearFields(http); |
561 | httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp"); | |
562 | if (username[0]) | |
563 | { | |
564 | httpEncode64(password, username); | |
565 | httpSetField(http, HTTP_FIELD_AUTHORIZATION, password); | |
566 | } | |
cb555bcf | 567 | |
97fcaf92 | 568 | sprintf(buffer, "%u", ippLength(request) + (size_t)fileinfo.st_size); |
569 | httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, buffer); | |
8ce7c000 | 570 | |
c8f9565c | 571 | /* |
97fcaf92 | 572 | * Do the request... |
c8f9565c | 573 | */ |
574 | ||
97fcaf92 | 575 | for (;;) |
c8f9565c | 576 | { |
97fcaf92 | 577 | /* |
578 | * POST the request, retrying as needed... | |
579 | */ | |
580 | ||
581 | httpReconnect(http); | |
c8f9565c | 582 | |
97fcaf92 | 583 | if (httpPost(http, resource)) |
3f9cb6c6 | 584 | { |
97fcaf92 | 585 | fputs("INFO: Unable to POST print request; retrying...\n", stderr); |
586 | sleep(10); | |
587 | continue; | |
588 | } | |
589 | ||
590 | fputs("INFO: POST successful, sending IPP request...\n", stderr); | |
3f9cb6c6 | 591 | |
97fcaf92 | 592 | /* |
593 | * Send the IPP request... | |
594 | */ | |
595 | ||
596 | request->state = IPP_IDLE; | |
3f9cb6c6 | 597 | |
97fcaf92 | 598 | if (ippWrite(http, request) == IPP_ERROR) |
599 | { | |
600 | fputs("ERROR: Unable to send IPP request!\n", stderr); | |
601 | status = HTTP_ERROR; | |
602 | break; | |
3f9cb6c6 | 603 | } |
c8f9565c | 604 | |
97fcaf92 | 605 | fputs("INFO: IPP request sent, sending print file...\n", stderr); |
606 | ||
607 | /* | |
608 | * Then send the file... | |
609 | */ | |
610 | ||
611 | rewind(fp); | |
612 | ||
613 | tbytes = 0; | |
614 | while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) | |
615 | { | |
616 | tbytes += nbytes; | |
617 | fprintf(stderr, "INFO: Sending print file, %uk...\n", tbytes / 1024); | |
618 | ||
619 | if (httpWrite(http, buffer, nbytes) < nbytes) | |
620 | { | |
621 | perror("ERROR: Unable to send print file to printer"); | |
622 | status = HTTP_ERROR; | |
623 | break; | |
624 | } | |
625 | } | |
626 | ||
627 | fputs("INFO: Print file sent; checking status...\n", stderr); | |
628 | ||
629 | /* | |
630 | * Finally, check the status from the HTTP server... | |
631 | */ | |
632 | ||
633 | while ((status = httpUpdate(http)) == HTTP_CONTINUE); | |
634 | ||
635 | if (status == HTTP_OK) | |
6a536282 | 636 | { |
97fcaf92 | 637 | response = ippNew(); |
638 | ippRead(http, response); | |
639 | ||
640 | if ((ipp_status = response->request.status.status_code) > IPP_OK_CONFLICT) | |
641 | { | |
642 | if (ipp_status == IPP_SERVICE_UNAVAILABLE || | |
643 | ipp_status == IPP_PRINTER_BUSY) | |
644 | { | |
645 | fputs("INFO: Printer is busy; retrying print job...\n", stderr); | |
646 | sleep(10); | |
647 | } | |
648 | else | |
5a2c7855 | 649 | { |
97fcaf92 | 650 | fprintf(stderr, "ERROR: Print file was not accepted (%04x)!\n", |
651 | response->request.status.status_code); | |
5a2c7855 | 652 | fprintf(stderr, "ERROR: %s\n", ippErrorString(ipp_status)); |
653 | } | |
97fcaf92 | 654 | } |
655 | else if ((job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL) | |
656 | fputs("INFO: Print file accepted - job ID unknown.\n", stderr); | |
657 | else | |
658 | fprintf(stderr, "INFO: Print file accepted - job ID %d.\n", | |
659 | job_id->values[0].integer); | |
6a536282 | 660 | } |
661 | else | |
97fcaf92 | 662 | { |
663 | response = NULL; | |
664 | ipp_status = IPP_PRINTER_BUSY; | |
665 | ||
666 | if (status == HTTP_ERROR) | |
667 | { | |
668 | fprintf(stderr, "WARNING: Did not receive the IPP response (%d)\n", | |
669 | errno); | |
670 | status = HTTP_OK; | |
671 | } | |
672 | else | |
673 | fprintf(stderr, "ERROR: Print request was not accepted (%d)!\n", status); | |
674 | } | |
675 | ||
676 | httpFlush(http); | |
677 | ||
678 | break; | |
c8f9565c | 679 | } |
680 | ||
97fcaf92 | 681 | if (request != NULL) |
682 | ippDelete(request); | |
683 | if (response != NULL) | |
684 | ippDelete(response); | |
685 | ||
686 | if (ipp_status <= IPP_OK_CONFLICT) | |
687 | { | |
688 | fprintf(stderr, "PAGE: 1 %d\n", copies_sup ? atoi(argv[4]) : 1); | |
689 | copies --; | |
690 | } | |
48419d23 | 691 | else if (ipp_status != IPP_SERVICE_UNAVAILABLE && |
692 | ipp_status != IPP_PRINTER_BUSY) | |
693 | break; | |
c8f9565c | 694 | } |
695 | ||
696 | /* | |
697 | * Free memory... | |
698 | */ | |
699 | ||
700 | httpClose(http); | |
c8f9565c | 701 | |
702 | /* | |
97fcaf92 | 703 | * Close and remove the temporary file if necessary... |
c8f9565c | 704 | */ |
705 | ||
97fcaf92 | 706 | fclose(fp); |
3f9cb6c6 | 707 | |
97fcaf92 | 708 | if (argc < 7) |
709 | unlink(filename); | |
c8f9565c | 710 | |
711 | /* | |
712 | * Return the queue status... | |
713 | */ | |
714 | ||
715 | return (status != HTTP_OK); | |
716 | } | |
717 | ||
718 | ||
719 | /* | |
5a2c7855 | 720 | * End of "$Id: ipp.c,v 1.28 2000/07/10 13:52:54 mike Exp $". |
c8f9565c | 721 | */ |