]>
Commit | Line | Data |
---|---|---|
09a101d6 | 1 | /* |
7e86f2f6 | 2 | * CUPS API test program for CUPS. |
09a101d6 | 3 | * |
728fd810 MS |
4 | * Copyright © 2007-2018 by Apple Inc. |
5 | * Copyright © 2007 by Easy Software Products. | |
09a101d6 | 6 | * |
e3101897 | 7 | * Licensed under Apache License v2.0. See the file "LICENSE" for more information. |
09a101d6 | 8 | */ |
9 | ||
10 | /* | |
11 | * Include necessary headers... | |
12 | */ | |
13 | ||
5489ad43 | 14 | #undef _CUPS_NO_DEPRECATED |
728fd810 | 15 | #include "cups-private.h" |
aaf19ab0 | 16 | #include "ppd.h" |
71e16022 | 17 | #include <stdlib.h> |
09a101d6 | 18 | |
19 | ||
a4924f6c MS |
20 | /* |
21 | * Local functions... | |
22 | */ | |
23 | ||
24 | static int dests_equal(cups_dest_t *a, cups_dest_t *b); | |
dcb445bc | 25 | static int enum_cb(void *user_data, unsigned flags, cups_dest_t *dest); |
a4924f6c MS |
26 | static void show_diffs(cups_dest_t *a, cups_dest_t *b); |
27 | ||
28 | ||
09a101d6 | 29 | /* |
30 | * 'main()' - Main entry. | |
31 | */ | |
32 | ||
33 | int /* O - Exit status */ | |
34 | main(int argc, /* I - Number of command-line arguments */ | |
35 | char *argv[]) /* I - Command-line arguments */ | |
36 | { | |
728fd810 MS |
37 | http_t *http, /* First HTTP connection */ |
38 | *http2; /* Second HTTP connection */ | |
09a101d6 | 39 | int status = 0, /* Exit status */ |
a4924f6c | 40 | i, /* Looping var */ |
09a101d6 | 41 | num_dests; /* Number of destinations */ |
42 | cups_dest_t *dests, /* Destinations */ | |
a4924f6c MS |
43 | *dest, /* Current destination */ |
44 | *named_dest; /* Current named destination */ | |
ced9dda8 MS |
45 | const char *dest_name, /* Destination name */ |
46 | *dval, /* Destination value */ | |
47 | *ppdfile; /* PPD file */ | |
09a101d6 | 48 | ppd_file_t *ppd; /* PPD file data */ |
49 | int num_jobs; /* Number of jobs for queue */ | |
50 | cups_job_t *jobs; /* Jobs for queue */ | |
51 | ||
a29fd7dd | 52 | |
dfd5680b MS |
53 | if (argc > 1) |
54 | { | |
dcb445bc MS |
55 | if (!strcmp(argv[1], "enum")) |
56 | { | |
a29fd7dd MS |
57 | cups_ptype_t mask = CUPS_PRINTER_LOCAL, |
58 | /* Printer type mask */ | |
59 | type = CUPS_PRINTER_LOCAL; | |
60 | /* Printer type */ | |
61 | int msec = 0; /* Timeout in milliseconds */ | |
62 | ||
63 | ||
64 | for (i = 2; i < argc; i ++) | |
65 | if (isdigit(argv[i][0] & 255) || argv[i][0] == '.') | |
66 | msec = (int)(atof(argv[i]) * 1000); | |
67 | else if (!_cups_strcasecmp(argv[i], "bw")) | |
68 | { | |
69 | mask |= CUPS_PRINTER_BW; | |
70 | type |= CUPS_PRINTER_BW; | |
71 | } | |
72 | else if (!_cups_strcasecmp(argv[i], "color")) | |
73 | { | |
74 | mask |= CUPS_PRINTER_COLOR; | |
75 | type |= CUPS_PRINTER_COLOR; | |
76 | } | |
77 | else if (!_cups_strcasecmp(argv[i], "mono")) | |
78 | { | |
79 | mask |= CUPS_PRINTER_COLOR; | |
80 | } | |
81 | else if (!_cups_strcasecmp(argv[i], "duplex")) | |
82 | { | |
83 | mask |= CUPS_PRINTER_DUPLEX; | |
84 | type |= CUPS_PRINTER_DUPLEX; | |
85 | } | |
86 | else if (!_cups_strcasecmp(argv[i], "simplex")) | |
87 | { | |
88 | mask |= CUPS_PRINTER_DUPLEX; | |
89 | } | |
90 | else if (!_cups_strcasecmp(argv[i], "staple")) | |
91 | { | |
92 | mask |= CUPS_PRINTER_STAPLE; | |
93 | type |= CUPS_PRINTER_STAPLE; | |
94 | } | |
95 | else if (!_cups_strcasecmp(argv[i], "copies")) | |
96 | { | |
97 | mask |= CUPS_PRINTER_COPIES; | |
98 | type |= CUPS_PRINTER_COPIES; | |
99 | } | |
100 | else if (!_cups_strcasecmp(argv[i], "collate")) | |
101 | { | |
102 | mask |= CUPS_PRINTER_COLLATE; | |
103 | type |= CUPS_PRINTER_COLLATE; | |
104 | } | |
105 | else if (!_cups_strcasecmp(argv[i], "punch")) | |
106 | { | |
107 | mask |= CUPS_PRINTER_PUNCH; | |
108 | type |= CUPS_PRINTER_PUNCH; | |
109 | } | |
110 | else if (!_cups_strcasecmp(argv[i], "cover")) | |
111 | { | |
112 | mask |= CUPS_PRINTER_COVER; | |
113 | type |= CUPS_PRINTER_COVER; | |
114 | } | |
115 | else if (!_cups_strcasecmp(argv[i], "bind")) | |
116 | { | |
117 | mask |= CUPS_PRINTER_BIND; | |
118 | type |= CUPS_PRINTER_BIND; | |
119 | } | |
120 | else if (!_cups_strcasecmp(argv[i], "sort")) | |
121 | { | |
122 | mask |= CUPS_PRINTER_SORT; | |
123 | type |= CUPS_PRINTER_SORT; | |
124 | } | |
125 | else if (!_cups_strcasecmp(argv[i], "mfp")) | |
126 | { | |
127 | mask |= CUPS_PRINTER_MFP; | |
128 | type |= CUPS_PRINTER_MFP; | |
129 | } | |
130 | else if (!_cups_strcasecmp(argv[i], "printer")) | |
131 | { | |
132 | mask |= CUPS_PRINTER_MFP; | |
133 | } | |
134 | else if (!_cups_strcasecmp(argv[i], "large")) | |
135 | { | |
136 | mask |= CUPS_PRINTER_LARGE; | |
137 | type |= CUPS_PRINTER_LARGE; | |
138 | } | |
139 | else if (!_cups_strcasecmp(argv[i], "medium")) | |
140 | { | |
141 | mask |= CUPS_PRINTER_MEDIUM; | |
142 | type |= CUPS_PRINTER_MEDIUM; | |
143 | } | |
144 | else if (!_cups_strcasecmp(argv[i], "small")) | |
145 | { | |
146 | mask |= CUPS_PRINTER_SMALL; | |
147 | type |= CUPS_PRINTER_SMALL; | |
148 | } | |
149 | else | |
150 | fprintf(stderr, "Unknown argument \"%s\" ignored...\n", argv[i]); | |
151 | ||
152 | cupsEnumDests(CUPS_DEST_FLAGS_NONE, msec, NULL, type, mask, enum_cb, NULL); | |
dfd5680b | 153 | } |
dcb445bc | 154 | else if (!strcmp(argv[1], "password")) |
dfd5680b | 155 | { |
dcb445bc MS |
156 | const char *pass = cupsGetPassword("Password:"); |
157 | /* Password string */ | |
dfd5680b | 158 | |
dcb445bc MS |
159 | if (pass) |
160 | printf("Password entered: %s\n", pass); | |
161 | else | |
162 | puts("No password entered."); | |
dfd5680b | 163 | } |
4972f4fe MS |
164 | else if (!strcmp(argv[1], "ppd") && argc == 3) |
165 | { | |
166 | /* | |
167 | * ./testcups ppd printer | |
168 | */ | |
169 | ||
170 | http_status_t http_status; /* Status */ | |
171 | char buffer[1024]; /* PPD filename */ | |
172 | time_t modtime = 0; /* Last modified */ | |
173 | ||
174 | if ((http_status = cupsGetPPD3(CUPS_HTTP_DEFAULT, argv[2], &modtime, | |
175 | buffer, sizeof(buffer))) != HTTP_STATUS_OK) | |
176 | printf("Unable to get PPD: %d (%s)\n", (int)http_status, | |
177 | cupsLastErrorString()); | |
178 | else | |
179 | puts(buffer); | |
180 | } | |
dcb445bc MS |
181 | else if (!strcmp(argv[1], "print") && argc == 5) |
182 | { | |
183 | /* | |
4972f4fe | 184 | * ./testcups print printer file interval |
dcb445bc | 185 | */ |
aaf19ab0 | 186 | |
dcb445bc MS |
187 | int interval, /* Interval between writes */ |
188 | job_id; /* Job ID */ | |
189 | cups_file_t *fp; /* Print file */ | |
190 | char buffer[16384]; /* Read/write buffer */ | |
191 | ssize_t bytes; /* Bytes read/written */ | |
dfd5680b | 192 | |
dcb445bc MS |
193 | if ((fp = cupsFileOpen(argv[3], "r")) == NULL) |
194 | { | |
195 | printf("Unable to open \"%s\": %s\n", argv[2], strerror(errno)); | |
196 | return (1); | |
197 | } | |
dfd5680b | 198 | |
dcb445bc MS |
199 | if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, argv[2], "testcups", 0, |
200 | NULL)) <= 0) | |
201 | { | |
202 | printf("Unable to create print job on %s: %s\n", argv[1], | |
203 | cupsLastErrorString()); | |
204 | return (1); | |
205 | } | |
206 | ||
207 | interval = atoi(argv[4]); | |
dfd5680b | 208 | |
dcb445bc | 209 | if (cupsStartDocument(CUPS_HTTP_DEFAULT, argv[1], job_id, argv[2], |
cb7f98ee | 210 | CUPS_FORMAT_AUTO, 1) != HTTP_STATUS_CONTINUE) |
dfd5680b | 211 | { |
dcb445bc | 212 | puts("Unable to start document!"); |
dfd5680b MS |
213 | return (1); |
214 | } | |
215 | ||
dcb445bc MS |
216 | while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0) |
217 | { | |
218 | printf("Writing %d bytes...\n", (int)bytes); | |
219 | ||
7e86f2f6 | 220 | if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE) |
dcb445bc MS |
221 | { |
222 | puts("Unable to write bytes!"); | |
223 | return (1); | |
224 | } | |
dfd5680b | 225 | |
dcb445bc | 226 | if (interval > 0) |
7e86f2f6 | 227 | sleep((unsigned)interval); |
dcb445bc MS |
228 | } |
229 | ||
230 | cupsFileClose(fp); | |
dfd5680b | 231 | |
cb7f98ee MS |
232 | if (cupsFinishDocument(CUPS_HTTP_DEFAULT, |
233 | argv[1]) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED) | |
dcb445bc MS |
234 | { |
235 | puts("Unable to finish document!"); | |
236 | return (1); | |
237 | } | |
238 | } | |
239 | else | |
dfd5680b | 240 | { |
dcb445bc MS |
241 | puts("Usage:"); |
242 | puts(""); | |
243 | puts("Run basic unit tests:"); | |
244 | puts(""); | |
245 | puts(" ./testcups"); | |
246 | puts(""); | |
247 | puts("Enumerate printers (for N seconds, -1 for indefinitely):"); | |
248 | puts(""); | |
249 | puts(" ./testcups enum [seconds]"); | |
250 | puts(""); | |
251 | puts("Ask for a password:"); | |
252 | puts(""); | |
253 | puts(" ./testcups password"); | |
254 | puts(""); | |
4972f4fe MS |
255 | puts("Get the PPD file:"); |
256 | puts(""); | |
257 | puts(" ./testcups ppd printer"); | |
258 | puts(""); | |
dcb445bc MS |
259 | puts("Print a file (interval controls delay between buffers in seconds):"); |
260 | puts(""); | |
261 | puts(" ./testcups print printer file interval"); | |
dfd5680b MS |
262 | return (1); |
263 | } | |
264 | ||
265 | return (0); | |
266 | } | |
267 | ||
728fd810 MS |
268 | /* |
269 | * _cupsConnect() connection reuse... | |
270 | */ | |
271 | ||
272 | fputs("_cupsConnect: ", stdout); | |
273 | http = _cupsConnect(); | |
274 | http2 = _cupsConnect(); | |
275 | ||
276 | if (http == http2) | |
277 | { | |
278 | puts("PASS"); | |
279 | } | |
280 | else | |
281 | { | |
282 | puts("FAIL (different connections)"); | |
283 | return (1); | |
284 | } | |
285 | ||
09a101d6 | 286 | /* |
287 | * cupsGetDests() | |
288 | */ | |
289 | ||
290 | fputs("cupsGetDests: ", stdout); | |
291 | fflush(stdout); | |
292 | ||
293 | num_dests = cupsGetDests(&dests); | |
294 | ||
295 | if (num_dests == 0) | |
296 | { | |
297 | puts("FAIL"); | |
298 | return (1); | |
299 | } | |
300 | else | |
a4924f6c MS |
301 | { |
302 | printf("PASS (%d dests)\n", num_dests); | |
303 | ||
304 | for (i = num_dests, dest = dests; i > 0; i --, dest ++) | |
305 | { | |
306 | printf(" %s", dest->name); | |
307 | ||
308 | if (dest->instance) | |
309 | printf(" /%s", dest->instance); | |
310 | ||
311 | if (dest->is_default) | |
312 | puts(" ***DEFAULT***"); | |
313 | else | |
314 | putchar('\n'); | |
315 | } | |
316 | } | |
317 | ||
318 | /* | |
319 | * cupsGetDest(NULL) | |
320 | */ | |
321 | ||
322 | fputs("cupsGetDest(NULL): ", stdout); | |
323 | fflush(stdout); | |
324 | ||
325 | if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL) | |
326 | { | |
327 | for (i = num_dests, dest = dests; i > 0; i --, dest ++) | |
328 | if (dest->is_default) | |
329 | break; | |
330 | ||
331 | if (i) | |
332 | { | |
333 | status = 1; | |
334 | puts("FAIL"); | |
335 | } | |
336 | else | |
337 | puts("PASS (no default)"); | |
338 | ||
339 | dest = NULL; | |
340 | } | |
341 | else | |
342 | printf("PASS (%s)\n", dest->name); | |
343 | ||
344 | /* | |
345 | * cupsGetNamedDest(NULL, NULL, NULL) | |
346 | */ | |
347 | ||
348 | fputs("cupsGetNamedDest(NULL, NULL, NULL): ", stdout); | |
349 | fflush(stdout); | |
350 | ||
351 | if ((named_dest = cupsGetNamedDest(NULL, NULL, NULL)) == NULL || | |
352 | !dests_equal(dest, named_dest)) | |
353 | { | |
354 | if (!dest) | |
355 | puts("PASS (no default)"); | |
356 | else if (named_dest) | |
357 | { | |
358 | puts("FAIL (different values)"); | |
359 | show_diffs(dest, named_dest); | |
360 | status = 1; | |
361 | } | |
362 | else | |
363 | { | |
364 | puts("FAIL (no default)"); | |
365 | status = 1; | |
366 | } | |
367 | } | |
368 | else | |
369 | printf("PASS (%s)\n", named_dest->name); | |
370 | ||
371 | if (named_dest) | |
372 | cupsFreeDests(1, named_dest); | |
09a101d6 | 373 | |
374 | /* | |
375 | * cupsGetDest(printer) | |
376 | */ | |
377 | ||
ced9dda8 MS |
378 | for (i = 0, dest_name = NULL; i < num_dests; i ++) |
379 | { | |
380 | if ((dval = cupsGetOption("printer-is-temporary", dests[i].num_options, dest[i].options)) != NULL && !strcmp(dval, "false")) | |
381 | { | |
382 | dest_name = dests[i].name; | |
383 | break; | |
384 | } | |
385 | } | |
386 | ||
387 | printf("cupsGetDest(\"%s\"): ", dest_name ? dest_name : "(null)"); | |
09a101d6 | 388 | fflush(stdout); |
389 | ||
ced9dda8 | 390 | if ((dest = cupsGetDest(dest_name, NULL, num_dests, dests)) == NULL) |
09a101d6 | 391 | { |
09a101d6 | 392 | puts("FAIL"); |
91c84a35 | 393 | return (1); |
09a101d6 | 394 | } |
395 | else | |
396 | puts("PASS"); | |
397 | ||
398 | /* | |
a4924f6c | 399 | * cupsGetNamedDest(NULL, printer, instance) |
09a101d6 | 400 | */ |
401 | ||
a4924f6c MS |
402 | printf("cupsGetNamedDest(NULL, \"%s\", \"%s\"): ", dest->name, |
403 | dest->instance ? dest->instance : "(null)"); | |
09a101d6 | 404 | fflush(stdout); |
405 | ||
ced9dda8 | 406 | if ((named_dest = cupsGetNamedDest(NULL, dest->name, dest->instance)) == NULL || |
a4924f6c | 407 | !dests_equal(dest, named_dest)) |
09a101d6 | 408 | { |
a4924f6c MS |
409 | if (named_dest) |
410 | { | |
411 | puts("FAIL (different values)"); | |
412 | show_diffs(dest, named_dest); | |
413 | } | |
414 | else | |
415 | puts("FAIL (no destination)"); | |
416 | ||
417 | ||
09a101d6 | 418 | status = 1; |
09a101d6 | 419 | } |
420 | else | |
421 | puts("PASS"); | |
422 | ||
a4924f6c MS |
423 | if (named_dest) |
424 | cupsFreeDests(1, named_dest); | |
425 | ||
09a101d6 | 426 | /* |
427 | * cupsPrintFile() | |
428 | */ | |
429 | ||
430 | fputs("cupsPrintFile: ", stdout); | |
431 | fflush(stdout); | |
432 | ||
ced9dda8 | 433 | if (cupsPrintFile(dest->name, "../test/testfile.pdf", "Test Page", |
09a101d6 | 434 | dest->num_options, dest->options) <= 0) |
435 | { | |
426c6a59 | 436 | printf("FAIL (%s)\n", cupsLastErrorString()); |
1f0275e3 | 437 | return (1); |
09a101d6 | 438 | } |
439 | else | |
440 | puts("PASS"); | |
441 | ||
442 | /* | |
443 | * cupsGetPPD(printer) | |
444 | */ | |
445 | ||
ced9dda8 | 446 | fputs("cupsGetPPD: ", stdout); |
09a101d6 | 447 | fflush(stdout); |
448 | ||
449 | if ((ppdfile = cupsGetPPD(dest->name)) == NULL) | |
450 | { | |
09a101d6 | 451 | puts("FAIL"); |
452 | } | |
453 | else | |
454 | { | |
455 | puts("PASS"); | |
456 | ||
457 | /* | |
458 | * ppdOpenFile() | |
459 | */ | |
460 | ||
ced9dda8 | 461 | fputs("ppdOpenFile: ", stdout); |
09a101d6 | 462 | fflush(stdout); |
463 | ||
464 | if ((ppd = ppdOpenFile(ppdfile)) == NULL) | |
465 | { | |
466 | puts("FAIL"); | |
467 | return (1); | |
468 | } | |
469 | else | |
470 | puts("PASS"); | |
471 | ||
472 | ppdClose(ppd); | |
473 | unlink(ppdfile); | |
474 | } | |
475 | ||
476 | /* | |
477 | * cupsGetJobs() | |
478 | */ | |
479 | ||
480 | fputs("cupsGetJobs: ", stdout); | |
481 | fflush(stdout); | |
482 | ||
483 | num_jobs = cupsGetJobs(&jobs, NULL, 0, -1); | |
484 | ||
485 | if (num_jobs == 0) | |
486 | { | |
487 | puts("FAIL"); | |
488 | return (1); | |
489 | } | |
490 | else | |
491 | puts("PASS"); | |
492 | ||
493 | cupsFreeJobs(num_jobs, jobs); | |
494 | cupsFreeDests(num_dests, dests); | |
495 | ||
496 | return (status); | |
497 | } | |
498 | ||
499 | ||
a4924f6c MS |
500 | /* |
501 | * 'dests_equal()' - Determine whether two destinations are equal. | |
502 | */ | |
503 | ||
504 | static int /* O - 1 if equal, 0 if not equal */ | |
505 | dests_equal(cups_dest_t *a, /* I - First destination */ | |
506 | cups_dest_t *b) /* I - Second destination */ | |
507 | { | |
508 | int i; /* Looping var */ | |
509 | cups_option_t *aoption; /* Current option */ | |
510 | const char *bval; /* Option value */ | |
511 | ||
512 | ||
513 | if (a == b) | |
514 | return (1); | |
515 | ||
1f0275e3 | 516 | if (!a || !b) |
a4924f6c MS |
517 | return (0); |
518 | ||
88f9aafc | 519 | if (_cups_strcasecmp(a->name, b->name) || |
a4924f6c MS |
520 | (a->instance && !b->instance) || |
521 | (!a->instance && b->instance) || | |
88f9aafc | 522 | (a->instance && _cups_strcasecmp(a->instance, b->instance)) || |
a4924f6c MS |
523 | a->num_options != b->num_options) |
524 | return (0); | |
525 | ||
526 | for (i = a->num_options, aoption = a->options; i > 0; i --, aoption ++) | |
527 | if ((bval = cupsGetOption(aoption->name, b->num_options, | |
528 | b->options)) == NULL || | |
529 | strcmp(aoption->value, bval)) | |
530 | return (0); | |
531 | ||
532 | return (1); | |
533 | } | |
534 | ||
535 | ||
dcb445bc MS |
536 | /* |
537 | * 'enum_cb()' - Report additions and removals. | |
538 | */ | |
539 | ||
540 | static int /* O - 1 to continue, 0 to stop */ | |
541 | enum_cb(void *user_data, /* I - User data (unused) */ | |
542 | unsigned flags, /* I - Destination flags */ | |
543 | cups_dest_t *dest) /* I - Destination */ | |
544 | { | |
a29fd7dd MS |
545 | int i; /* Looping var */ |
546 | cups_option_t *option; /* Current option */ | |
547 | ||
548 | ||
7e86f2f6 MS |
549 | (void)user_data; |
550 | ||
dcb445bc | 551 | if (flags & CUPS_DEST_FLAGS_REMOVED) |
a29fd7dd | 552 | printf("Removed '%s':\n", dest->name); |
dcb445bc | 553 | else |
a29fd7dd MS |
554 | printf("Added '%s':\n", dest->name); |
555 | ||
556 | for (i = dest->num_options, option = dest->options; i > 0; i --, option ++) | |
557 | printf(" %s=\"%s\"\n", option->name, option->value); | |
558 | ||
559 | putchar('\n'); | |
dcb445bc MS |
560 | |
561 | return (1); | |
562 | } | |
563 | ||
564 | ||
a4924f6c MS |
565 | /* |
566 | * 'show_diffs()' - Show differences between two destinations. | |
567 | */ | |
568 | ||
569 | static void | |
570 | show_diffs(cups_dest_t *a, /* I - First destination */ | |
571 | cups_dest_t *b) /* I - Second destination */ | |
572 | { | |
573 | int i; /* Looping var */ | |
574 | cups_option_t *aoption; /* Current option */ | |
ced9dda8 | 575 | cups_option_t *boption; /* Current option */ |
a4924f6c MS |
576 | const char *bval; /* Option value */ |
577 | ||
578 | ||
579 | if (!a || !b) | |
580 | return; | |
581 | ||
ced9dda8 MS |
582 | puts(" Item cupsGetDest cupsGetNamedDest"); |
583 | puts(" -------------------- ------------------------ ------------------------"); | |
a4924f6c | 584 | |
88f9aafc | 585 | if (_cups_strcasecmp(a->name, b->name)) |
ced9dda8 | 586 | printf(" name %-24.24s %-24.24s\n", a->name, b->name); |
a4924f6c MS |
587 | |
588 | if ((a->instance && !b->instance) || | |
589 | (!a->instance && b->instance) || | |
88f9aafc | 590 | (a->instance && _cups_strcasecmp(a->instance, b->instance))) |
ced9dda8 | 591 | printf(" instance %-24.24s %-24.24s\n", |
a4924f6c MS |
592 | a->instance ? a->instance : "(null)", |
593 | b->instance ? b->instance : "(null)"); | |
594 | ||
595 | if (a->num_options != b->num_options) | |
ced9dda8 | 596 | printf(" num_options %-24d %-24d\n", a->num_options, |
a4924f6c MS |
597 | b->num_options); |
598 | ||
599 | for (i = a->num_options, aoption = a->options; i > 0; i --, aoption ++) | |
600 | if ((bval = cupsGetOption(aoption->name, b->num_options, | |
601 | b->options)) == NULL || | |
602 | strcmp(aoption->value, bval)) | |
ced9dda8 | 603 | printf(" %-20.20s %-24.24s %-24.24s\n", aoption->name, |
a4924f6c | 604 | aoption->value, bval ? bval : "(null)"); |
ced9dda8 MS |
605 | |
606 | for (i = b->num_options, boption = b->options; i > 0; i --, boption ++) | |
607 | if (!cupsGetOption(boption->name, a->num_options, a->options)) | |
608 | printf(" %-20.20s %-24.24s %-24.24s\n", boption->name, | |
609 | boption->value, "(null)"); | |
a4924f6c | 610 | } |