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