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