]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/testcups.c
Greatly simplify the man page handling.
[thirdparty/cups.git] / cups / testcups.c
1 /*
2 * CUPS API test program for CUPS.
3 *
4 * Copyright © 2007-2018 by Apple Inc.
5 * Copyright © 2007 by Easy Software Products.
6 *
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8 */
9
10 /*
11 * Include necessary headers...
12 */
13
14 #undef _CUPS_NO_DEPRECATED
15 #include "cups-private.h"
16 #include "ppd.h"
17 #include <stdlib.h>
18
19
20 /*
21 * Local functions...
22 */
23
24 static int dests_equal(cups_dest_t *a, cups_dest_t *b);
25 static int enum_cb(void *user_data, unsigned flags, cups_dest_t *dest);
26 static void show_diffs(cups_dest_t *a, cups_dest_t *b);
27
28
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 {
37 http_t *http, /* First HTTP connection */
38 *http2; /* Second HTTP connection */
39 int status = 0, /* Exit status */
40 i, /* Looping var */
41 num_dests; /* Number of destinations */
42 cups_dest_t *dests, /* Destinations */
43 *dest, /* Current destination */
44 *named_dest; /* Current named destination */
45 const char *dest_name, /* Destination name */
46 *dval, /* Destination value */
47 *ppdfile; /* PPD file */
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
52
53 if (argc > 1)
54 {
55 if (!strcmp(argv[1], "enum"))
56 {
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);
153 }
154 else if (!strcmp(argv[1], "password"))
155 {
156 const char *pass = cupsGetPassword("Password:");
157 /* Password string */
158
159 if (pass)
160 printf("Password entered: %s\n", pass);
161 else
162 puts("No password entered.");
163 }
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 }
181 else if (!strcmp(argv[1], "print") && argc == 5)
182 {
183 /*
184 * ./testcups print printer file interval
185 */
186
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 */
192
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 }
198
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]);
208
209 if (cupsStartDocument(CUPS_HTTP_DEFAULT, argv[1], job_id, argv[2],
210 CUPS_FORMAT_AUTO, 1) != HTTP_STATUS_CONTINUE)
211 {
212 puts("Unable to start document!");
213 return (1);
214 }
215
216 while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
217 {
218 printf("Writing %d bytes...\n", (int)bytes);
219
220 if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE)
221 {
222 puts("Unable to write bytes!");
223 return (1);
224 }
225
226 if (interval > 0)
227 sleep((unsigned)interval);
228 }
229
230 cupsFileClose(fp);
231
232 if (cupsFinishDocument(CUPS_HTTP_DEFAULT,
233 argv[1]) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
234 {
235 puts("Unable to finish document!");
236 return (1);
237 }
238 }
239 else
240 {
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("");
255 puts("Get the PPD file:");
256 puts("");
257 puts(" ./testcups ppd printer");
258 puts("");
259 puts("Print a file (interval controls delay between buffers in seconds):");
260 puts("");
261 puts(" ./testcups print printer file interval");
262 return (1);
263 }
264
265 return (0);
266 }
267
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
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
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);
373
374 /*
375 * cupsGetDest(printer)
376 */
377
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)");
388 fflush(stdout);
389
390 if ((dest = cupsGetDest(dest_name, NULL, num_dests, dests)) == NULL)
391 {
392 puts("FAIL");
393 return (1);
394 }
395 else
396 puts("PASS");
397
398 /*
399 * cupsGetNamedDest(NULL, printer, instance)
400 */
401
402 printf("cupsGetNamedDest(NULL, \"%s\", \"%s\"): ", dest->name,
403 dest->instance ? dest->instance : "(null)");
404 fflush(stdout);
405
406 if ((named_dest = cupsGetNamedDest(NULL, dest->name, dest->instance)) == NULL ||
407 !dests_equal(dest, named_dest))
408 {
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
418 status = 1;
419 }
420 else
421 puts("PASS");
422
423 if (named_dest)
424 cupsFreeDests(1, named_dest);
425
426 /*
427 * cupsPrintFile()
428 */
429
430 fputs("cupsPrintFile: ", stdout);
431 fflush(stdout);
432
433 if (cupsPrintFile(dest->name, "../test/testfile.pdf", "Test Page",
434 dest->num_options, dest->options) <= 0)
435 {
436 printf("FAIL (%s)\n", cupsLastErrorString());
437 return (1);
438 }
439 else
440 puts("PASS");
441
442 /*
443 * cupsGetPPD(printer)
444 */
445
446 fputs("cupsGetPPD: ", stdout);
447 fflush(stdout);
448
449 if ((ppdfile = cupsGetPPD(dest->name)) == NULL)
450 {
451 puts("FAIL");
452 }
453 else
454 {
455 puts("PASS");
456
457 /*
458 * ppdOpenFile()
459 */
460
461 fputs("ppdOpenFile: ", stdout);
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
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
516 if (!a || !b)
517 return (0);
518
519 if (_cups_strcasecmp(a->name, b->name) ||
520 (a->instance && !b->instance) ||
521 (!a->instance && b->instance) ||
522 (a->instance && _cups_strcasecmp(a->instance, b->instance)) ||
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
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 {
545 int i; /* Looping var */
546 cups_option_t *option; /* Current option */
547
548
549 (void)user_data;
550
551 if (flags & CUPS_DEST_FLAGS_REMOVED)
552 printf("Removed '%s':\n", dest->name);
553 else
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');
560
561 return (1);
562 }
563
564
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 */
575 cups_option_t *boption; /* Current option */
576 const char *bval; /* Option value */
577
578
579 if (!a || !b)
580 return;
581
582 puts(" Item cupsGetDest cupsGetNamedDest");
583 puts(" -------------------- ------------------------ ------------------------");
584
585 if (_cups_strcasecmp(a->name, b->name))
586 printf(" name %-24.24s %-24.24s\n", a->name, b->name);
587
588 if ((a->instance && !b->instance) ||
589 (!a->instance && b->instance) ||
590 (a->instance && _cups_strcasecmp(a->instance, b->instance)))
591 printf(" instance %-24.24s %-24.24s\n",
592 a->instance ? a->instance : "(null)",
593 b->instance ? b->instance : "(null)");
594
595 if (a->num_options != b->num_options)
596 printf(" num_options %-24d %-24d\n", a->num_options,
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))
603 printf(" %-20.20s %-24.24s %-24.24s\n", aoption->name,
604 aoption->value, bval ? bval : "(null)");
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)");
610 }