]> git.ipfire.org Git - thirdparty/cups.git/blob - test/ipptest.c
Load cups into easysw/current.
[thirdparty/cups.git] / test / ipptest.c
1 /*
2 * "$Id: ipptest.c 6649 2007-07-11 21:46:42Z mike $"
3 *
4 * IPP test command for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
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/".
14 *
15 * Contents:
16 *
17 * main() - Parse options and do tests.
18 * do_tests() - Do tests as specified in the test file.
19 * get_tag() - Get an IPP value or group tag from a name...
20 * get_token() - Get a token from a file.
21 * print_attr() - Print an attribute on the screen.
22 * usage() - Show program usage.
23 */
24
25 /*
26 * Include necessary headers...
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <cups/string.h>
32 #include <errno.h>
33 #include <ctype.h>
34
35 #include <cups/cups.h>
36 #include <cups/language.h>
37
38
39 /*
40 * Globals...
41 */
42
43 int Verbosity = 0; /* Show all attributes? */
44 const char * const TagNames[] =
45 { /* Value/group tag names */
46 "zero", /* 0x00 */
47 "operation", /* 0x01 */
48 "job", /* 0x02 */
49 "end", /* 0x03 */
50 "printer", /* 0x04 */
51 "unsupported-group", /* 0x05 */
52 "subscription", /* 0x06 */
53 "event-notification", /* 0x07 */
54 "", "", "", "", "", "", "", "",
55 "unsupported-value", /* 0x10 */
56 "default", /* 0x11 */
57 "unknown", /* 0x12 */
58 "novalue", /* 0x13 */
59 "",
60 "notsettable", /* 0x15 */
61 "deleteattr", /* 0x16 */
62 "anyvalue", /* 0x17 */
63 "", "", "", "", "", "", "", "", "",
64 "integer", /* 0x21 */
65 "boolean", /* 0x22 */
66 "enum", /* 0x23 */
67 "", "", "", "", "", "", "", "", "", "", "", "",
68 "string", /* 0x30 */
69 "date", /* 0x31 */
70 "resolution", /* 0x32 */
71 "range", /* 0x33 */
72 "collection", /* 0x34 */
73 "textlang", /* 0x35 */
74 "namelang", /* 0x36 */
75 "", "", "", "", "", "", "", "", "", "",
76 "text", /* 0x41 */
77 "name", /* 0x42 */
78 "",
79 "keyword", /* 0x44 */
80 "uri", /* 0x45 */
81 "urischeme", /* 0x46 */
82 "charset", /* 0x47 */
83 "language", /* 0x48 */
84 "mimetype" /* 0x49 */
85 };
86
87
88
89
90 /*
91 * Local functions...
92 */
93
94 int do_tests(const char *, const char *);
95 ipp_op_t ippOpValue(const char *);
96 ipp_status_t ippErrorValue(const char *);
97 ipp_tag_t get_tag(const char *);
98 const char *get_tag_string(ipp_tag_t tag);
99 char *get_token(FILE *, char *, int, int *linenum);
100 void print_attr(ipp_attribute_t *);
101 void usage(const char *option);
102
103
104 /*
105 * 'main()' - Parse options and do tests.
106 */
107
108 int /* O - Exit status */
109 main(int argc, /* I - Number of command-line arguments */
110 char *argv[]) /* I - Command-line arguments */
111 {
112 int i; /* Looping var */
113 int status; /* Status of tests... */
114 const char *uri; /* URI to use */
115 const char *testfile; /* Test file to use */
116 int interval; /* Test interval */
117
118
119 /*
120 * We need at least:
121 *
122 * testipp URL testfile
123 */
124
125 uri = NULL;
126 testfile = NULL;
127 status = 0;
128 interval = 0;
129
130 for (i = 1; i < argc; i ++)
131 {
132 if (argv[i][0] == '-')
133 {
134 if (!strcmp(argv[i], "-v"))
135 Verbosity ++;
136 else if (!strcmp(argv[i], "-d"))
137 {
138 i ++;
139
140 if (i >= argc)
141 usage(NULL);
142 else
143 putenv(argv[i]);
144 }
145 else if (!strcmp(argv[i], "-i"))
146 {
147 i++;
148
149 if (i >= argc)
150 usage(NULL);
151 else
152 interval = atoi(argv[i]);
153 }
154 else
155 usage(argv[i]);
156 }
157 else if (!strncmp(argv[i], "ipp://", 6) ||
158 !strncmp(argv[i], "http://", 7) ||
159 !strncmp(argv[i], "https://", 8))
160 {
161 /*
162 * Set URI...
163 */
164
165 if (!testfile && uri)
166 usage(NULL);
167
168 uri = argv[i];
169 testfile = NULL;
170 }
171 else
172 {
173 /*
174 * Run test...
175 */
176
177 testfile = argv[i];
178
179 if (!do_tests(uri, testfile))
180 status ++;
181 }
182 }
183
184 if (!uri || !testfile)
185 usage(NULL);
186
187 /*
188 * Loop if the interval is set...
189 */
190
191 if (interval)
192 {
193 for (;;)
194 {
195 sleep(interval);
196 do_tests(uri, testfile);
197 }
198 }
199
200 /*
201 * Exit...
202 */
203
204 return (status);
205 }
206
207
208 /*
209 * 'do_tests()' - Do tests as specified in the test file.
210 */
211
212 int /* 1 = success, 0 = failure */
213 do_tests(const char *uri, /* I - URI to connect on */
214 const char *testfile) /* I - Test file to use */
215 {
216 int i; /* Looping var */
217 int linenum; /* Current line number */
218 int version; /* IPP version number to use */
219 http_t *http; /* HTTP connection to server */
220 char method[HTTP_MAX_URI], /* URI method */
221 userpass[HTTP_MAX_URI], /* username:password */
222 server[HTTP_MAX_URI], /* Server */
223 resource[HTTP_MAX_URI]; /* Resource path */
224 int port; /* Port number */
225 FILE *fp; /* Test file */
226 char token[1024], /* Token from file */
227 *tokenptr, /* Pointer into token */
228 temp[1024], /* Temporary string */
229 *tempptr; /* Pointer into temp string */
230 ipp_t *request; /* IPP request */
231 ipp_t *response; /* IPP response */
232 ipp_op_t op; /* Operation */
233 ipp_tag_t group; /* Current group */
234 ipp_tag_t value; /* Current value type */
235 ipp_attribute_t *attrptr; /* Attribute pointer */
236 char attr[128]; /* Attribute name */
237 int num_statuses; /* Number of valid status codes */
238 ipp_status_t statuses[100]; /* Valid status codes */
239 int num_expects; /* Number of expected attributes */
240 char *expects[100]; /* Expected attributes */
241 int num_displayed; /* Number of displayed attributes */
242 char *displayed[100]; /* Displayed attributes */
243 char name[1024]; /* Name of test */
244 char filename[1024]; /* Filename */
245 int pass; /* Did we pass the test? */
246 int job_id; /* Job ID from last operation */
247 int subscription_id; /* Subscription ID from last operation */
248
249
250 /*
251 * Open the test file...
252 */
253
254 if ((fp = fopen(testfile, "r")) == NULL)
255 {
256 printf("Unable to open test file %s - %s\n", testfile, strerror(errno));
257 return (0);
258 }
259
260 /*
261 * Connect to the server...
262 */
263
264 httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), userpass,
265 sizeof(userpass), server, sizeof(server), &port, resource,
266 sizeof(resource));
267 if ((http = httpConnect(server, port)) == NULL)
268 {
269 printf("Unable to connect to %s on port %d - %s\n", server, port,
270 strerror(errno));
271 return (0);
272 }
273
274 /*
275 * Loop on tests...
276 */
277
278 printf("\"%s\":\n", testfile);
279 pass = 1;
280 job_id = 0;
281 subscription_id = 0;
282 version = 1;
283 linenum = 1;
284
285 while (get_token(fp, token, sizeof(token), &linenum) != NULL)
286 {
287 /*
288 * Expect an open brace...
289 */
290
291 if (strcmp(token, "{"))
292 {
293 printf("Unexpected token %s seen on line %d - aborting test!\n", token,
294 linenum);
295 httpClose(http);
296 return (0);
297 }
298
299 /*
300 * Initialize things...
301 */
302
303 httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), userpass,
304 sizeof(userpass), server, sizeof(server), &port, resource,
305 sizeof(resource));
306
307 request = ippNew();
308 op = (ipp_op_t)0;
309 group = IPP_TAG_ZERO;
310 value = IPP_TAG_ZERO;
311 num_statuses = 0;
312 num_expects = 0;
313 num_displayed = 0;
314 filename[0] = '\0';
315
316 strcpy(name, testfile);
317 if (strrchr(name, '.') != NULL)
318 *strrchr(name, '.') = '\0';
319
320 /*
321 * Parse until we see a close brace...
322 */
323
324 while (get_token(fp, token, sizeof(token), &linenum) != NULL)
325 {
326 if (!strcmp(token, "}"))
327 break;
328 else if (!strcasecmp(token, "NAME"))
329 {
330 /*
331 * Name of test...
332 */
333
334 get_token(fp, name, sizeof(name), &linenum);
335 }
336 else if (!strcasecmp(token, "VERSION"))
337 {
338 /*
339 * IPP version number for test...
340 */
341
342 get_token(fp, temp, sizeof(temp), &linenum);
343 sscanf(temp, "%*d.%d", &version);
344 }
345 else if (!strcasecmp(token, "RESOURCE"))
346 {
347 /*
348 * Resource name...
349 */
350
351 get_token(fp, resource, sizeof(resource), &linenum);
352 }
353 else if (!strcasecmp(token, "OPERATION"))
354 {
355 /*
356 * Operation...
357 */
358
359 get_token(fp, token, sizeof(token), &linenum);
360 op = ippOpValue(token);
361 }
362 else if (!strcasecmp(token, "GROUP"))
363 {
364 /*
365 * Attribute group...
366 */
367
368 get_token(fp, token, sizeof(token), &linenum);
369 value = get_tag(token);
370
371 if (value == group)
372 ippAddSeparator(request);
373
374 group = value;
375 }
376 else if (!strcasecmp(token, "DELAY"))
377 {
378 /*
379 * Delay before operation...
380 */
381
382 int delay;
383
384 get_token(fp, token, sizeof(token), &linenum);
385 if ((delay = atoi(token)) > 0)
386 sleep(delay);
387 }
388 else if (!strcasecmp(token, "ATTR"))
389 {
390 /*
391 * Attribute...
392 */
393
394 get_token(fp, token, sizeof(token), &linenum);
395 value = get_tag(token);
396 get_token(fp, attr, sizeof(attr), &linenum);
397 get_token(fp, temp, sizeof(temp), &linenum);
398
399 token[sizeof(token) - 1] = '\0';
400
401 for (tempptr = temp, tokenptr = token;
402 *tempptr && tokenptr < (token + sizeof(token) - 1);)
403 if (*tempptr == '$')
404 {
405 /*
406 * Substitute a string/number...
407 */
408
409 if (!strncasecmp(tempptr + 1, "uri", 3))
410 {
411 strlcpy(tokenptr, uri, sizeof(token) - (tokenptr - token));
412 tempptr += 4;
413 }
414 else if (!strncasecmp(tempptr + 1, "method", 6))
415 {
416 strlcpy(tokenptr, method, sizeof(token) - (tokenptr - token));
417 tempptr += 7;
418 }
419 else if (!strncasecmp(tempptr + 1, "username", 8))
420 {
421 strlcpy(tokenptr, userpass, sizeof(token) - (tokenptr - token));
422 tempptr += 9;
423 }
424 else if (!strncasecmp(tempptr + 1, "hostname", 8))
425 {
426 strlcpy(tokenptr, server, sizeof(token) - (tokenptr - token));
427 tempptr += 9;
428 }
429 else if (!strncasecmp(tempptr + 1, "port", 4))
430 {
431 snprintf(tokenptr, sizeof(token) - (tokenptr - token),
432 "%d", port);
433 tempptr += 5;
434 }
435 else if (!strncasecmp(tempptr + 1, "resource", 8))
436 {
437 strlcpy(tokenptr, resource, sizeof(token) - (tokenptr - token));
438 tempptr += 9;
439 }
440 else if (!strncasecmp(tempptr + 1, "job-id", 6))
441 {
442 snprintf(tokenptr, sizeof(token) - (tokenptr - token),
443 "%d", job_id);
444 tempptr += 7;
445 }
446 else if (!strncasecmp(tempptr + 1, "notify-subscription-id", 22))
447 {
448 snprintf(tokenptr, sizeof(token) - (tokenptr - token),
449 "%d", subscription_id);
450 tempptr += 23;
451 }
452 else if (!strncasecmp(tempptr + 1, "user", 4))
453 {
454 strlcpy(tokenptr, cupsUser(), sizeof(token) - (tokenptr - token));
455 tempptr += 5;
456 }
457 else if (!strncasecmp(tempptr + 1, "ENV[", 4))
458 {
459 char *end; /* End of $ENV[name] */
460
461
462 if ((end = strchr(tempptr + 5, ']')) != NULL)
463 {
464 *end++ = '\0';
465 strlcpy(tokenptr,
466 getenv(tempptr + 5) ? getenv(tempptr + 5) : tempptr + 5,
467 sizeof(token) - (tokenptr - token));
468 tempptr = end;
469 }
470 else
471 {
472 *tokenptr++ = *tempptr++;
473 *tokenptr = '\0';
474 }
475 }
476 else
477 {
478 *tokenptr++ = *tempptr++;
479 *tokenptr = '\0';
480 }
481
482 tokenptr += strlen(tokenptr);
483 }
484 else
485 {
486 *tokenptr++ = *tempptr++;
487 *tokenptr = '\0';
488 }
489
490 switch (value)
491 {
492 case IPP_TAG_BOOLEAN :
493 if (!strcasecmp(token, "true"))
494 ippAddBoolean(request, group, attr, 1);
495 else
496 ippAddBoolean(request, group, attr, atoi(token));
497 break;
498
499 case IPP_TAG_INTEGER :
500 case IPP_TAG_ENUM :
501 ippAddInteger(request, group, value, attr, atoi(token));
502 break;
503
504 case IPP_TAG_RESOLUTION :
505 puts(" ERROR: resolution tag not yet supported!");
506 break;
507
508 case IPP_TAG_RANGE :
509 puts(" ERROR: range tag not yet supported!");
510 break;
511
512 default :
513 if (!strchr(token, ','))
514 ippAddString(request, group, value, attr, NULL, token);
515 else
516 {
517 /*
518 * Multiple string values...
519 */
520
521 int num_values; /* Number of values */
522 char *values[100], /* Values */
523 *ptr; /* Pointer to next value */
524
525
526 values[0] = token;
527 num_values = 1;
528
529 for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ','))
530 {
531 *ptr++ = '\0';
532 values[num_values] = ptr;
533 num_values ++;
534 }
535
536 ippAddStrings(request, group, value, attr, num_values,
537 NULL, (const char **)values);
538 }
539 break;
540 }
541 }
542 else if (!strcasecmp(token, "FILE"))
543 {
544 /*
545 * File...
546 */
547
548 get_token(fp, filename, sizeof(filename), &linenum);
549 }
550 else if (!strcasecmp(token, "STATUS") &&
551 num_statuses < (int)(sizeof(statuses) / sizeof(statuses[0])))
552 {
553 /*
554 * Status...
555 */
556
557 get_token(fp, token, sizeof(token), &linenum);
558 statuses[num_statuses] = ippErrorValue(token);
559 num_statuses ++;
560 }
561 else if (!strcasecmp(token, "EXPECT") &&
562 num_expects < (int)(sizeof(expects) / sizeof(expects[0])))
563 {
564 /*
565 * Expected attributes...
566 */
567
568 get_token(fp, token, sizeof(token), &linenum);
569 expects[num_expects] = strdup(token);
570 num_expects ++;
571 }
572 else if (!strcasecmp(token, "DISPLAY") &&
573 num_displayed < (int)(sizeof(displayed) / sizeof(displayed[0])))
574 {
575 /*
576 * Display attributes...
577 */
578
579 get_token(fp, token, sizeof(token), &linenum);
580 displayed[num_displayed] = strdup(token);
581 num_displayed ++;
582 }
583 else
584 {
585 printf("Unexpected token %s seen on line %d - aborting test!\n", token,
586 linenum);
587 httpClose(http);
588 ippDelete(request);
589 return (0);
590 }
591 }
592
593 /*
594 * Submit the IPP request...
595 */
596
597 request->request.op.version[1] = version;
598 request->request.op.operation_id = op;
599 request->request.op.request_id = 1;
600
601 if (Verbosity)
602 {
603 printf("%s:\n", ippOpString(op));
604
605 for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
606 print_attr(attrptr);
607 }
608
609 printf(" %-60.60s [", name);
610 fflush(stdout);
611
612 if (filename[0])
613 response = cupsDoFileRequest(http, request, resource, filename);
614 else
615 response = cupsDoIORequest(http, request, resource, -1,
616 Verbosity ? 1 : -1);
617
618 if (response == NULL)
619 {
620 time_t curtime;
621
622 curtime = time(NULL);
623
624 puts("FAIL]");
625 printf(" ERROR %04x (%s) @ %s\n", cupsLastError(),
626 cupsLastErrorString(), ctime(&curtime));
627 pass = 0;
628 }
629 else
630 {
631 if ((attrptr = ippFindAttribute(response, "job-id",
632 IPP_TAG_INTEGER)) != NULL)
633 job_id = attrptr->values[0].integer;
634
635 if ((attrptr = ippFindAttribute(response, "notify-subscription-id",
636 IPP_TAG_INTEGER)) != NULL)
637 subscription_id = attrptr->values[0].integer;
638
639 for (i = 0; i < num_statuses; i ++)
640 if (response->request.status.status_code == statuses[i])
641 break;
642
643 if (i == num_statuses && num_statuses > 0)
644 pass = 0;
645 else
646 {
647 for (i = 0; i < num_expects; i ++)
648 if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
649 {
650 pass = 0;
651 break;
652 }
653 }
654
655 if (pass)
656 {
657 puts("PASS]");
658 printf(" RECEIVED: %lu bytes in response\n",
659 (unsigned long)ippLength(response));
660
661 if (Verbosity)
662 {
663 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
664 print_attr(attrptr);
665 }
666 else if (num_displayed > 0)
667 {
668 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
669 if (attrptr->name)
670 {
671 for (i = 0; i < num_displayed; i ++)
672 if (!strcmp(displayed[i], attrptr->name))
673 {
674 print_attr(attrptr);
675 break;
676 }
677 }
678 }
679 }
680 else
681 {
682 puts("FAIL]");
683 printf(" RECEIVED: %lu bytes in response\n",
684 (unsigned long)ippLength(response));
685
686 for (i = 0; i < num_statuses; i ++)
687 if (response->request.status.status_code == statuses[i])
688 break;
689
690 if (i == num_statuses && num_statuses > 0)
691 puts(" BAD STATUS");
692
693 printf(" status-code = %04x (%s)\n",
694 cupsLastError(), ippErrorString(cupsLastError()));
695
696 for (i = 0; i < num_expects; i ++)
697 if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
698 printf(" EXPECTED: %s\n", expects[i]);
699
700 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
701 print_attr(attrptr);
702 }
703
704 ippDelete(response);
705 }
706
707 for (i = 0; i < num_expects; i ++)
708 free(expects[i]);
709
710 if (!pass)
711 break;
712 }
713
714 fclose(fp);
715 httpClose(http);
716
717 return (pass);
718 }
719
720
721 /*
722 * 'get_tag()' - Get an IPP value or group tag from a name...
723 */
724
725 ipp_tag_t /* O - Value/group tag */
726 get_tag(const char *name) /* I - Name of value/group tag */
727 {
728 int i; /* Looping var */
729
730
731 for (i = 0; i < (sizeof(TagNames) / sizeof(TagNames[0])); i ++)
732 if (!strcasecmp(name, TagNames[i]))
733 return ((ipp_tag_t)i);
734
735 return (IPP_TAG_ZERO);
736 }
737
738
739 /*
740 * 'get_tag_string()' - Get the string associated with a tag.
741 */
742
743 const char * /* O - Tag name string */
744 get_tag_string(ipp_tag_t tag) /* I - IPP tag */
745 {
746 if (tag < (ipp_tag_t)(sizeof(TagNames) / sizeof(TagNames[0])))
747 return (TagNames[tag]);
748 else
749 return ("UNKNOWN");
750 }
751
752
753 /*
754 * 'get_token()' - Get a token from a file.
755 */
756
757 char * /* O - Token from file or NULL on EOF */
758 get_token(FILE *fp, /* I - File to read from */
759 char *buf, /* I - Buffer to read into */
760 int buflen, /* I - Length of buffer */
761 int *linenum) /* IO - Current line number */
762 {
763 int ch, /* Character from file */
764 quote; /* Quoting character */
765 char *bufptr, /* Pointer into buffer */
766 *bufend; /* End of buffer */
767
768
769 for (;;)
770 {
771 /*
772 * Skip whitespace...
773 */
774
775 while (isspace(ch = getc(fp)))
776 {
777 if (ch == '\n')
778 (*linenum) ++;
779 }
780
781 /*
782 * Read a token...
783 */
784
785 if (ch == EOF)
786 return (NULL);
787 else if (ch == '\'' || ch == '\"')
788 {
789 /*
790 * Quoted text...
791 */
792
793 quote = ch;
794 bufptr = buf;
795 bufend = buf + buflen - 1;
796
797 while ((ch = getc(fp)) != EOF)
798 if (ch == quote)
799 break;
800 else if (bufptr < bufend)
801 *bufptr++ = ch;
802
803 *bufptr = '\0';
804 return (buf);
805 }
806 else if (ch == '#')
807 {
808 /*
809 * Comment...
810 */
811
812 while ((ch = getc(fp)) != EOF)
813 if (ch == '\n')
814 break;
815
816 (*linenum) ++;
817 }
818 else
819 {
820 /*
821 * Whitespace delimited text...
822 */
823
824 ungetc(ch, fp);
825
826 bufptr = buf;
827 bufend = buf + buflen - 1;
828
829 while ((ch = getc(fp)) != EOF)
830 if (isspace(ch) || ch == '#')
831 break;
832 else if (bufptr < bufend)
833 *bufptr++ = ch;
834
835 if (ch == '#')
836 ungetc(ch, fp);
837
838 *bufptr = '\0';
839 return (buf);
840 }
841 }
842 }
843
844
845 /*
846 * 'print_attr()' - Print an attribute on the screen.
847 */
848
849 void
850 print_attr(ipp_attribute_t *attr) /* I - Attribute to print */
851 {
852 int i; /* Looping var */
853
854
855 if (attr->name == NULL)
856 {
857 puts(" -- separator --");
858 return;
859 }
860
861 printf(" %s (%s%s) = ", attr->name,
862 attr->num_values > 1 ? "1setOf " : "",
863 get_tag_string(attr->value_tag));
864
865 switch (attr->value_tag)
866 {
867 case IPP_TAG_INTEGER :
868 case IPP_TAG_ENUM :
869 for (i = 0; i < attr->num_values; i ++)
870 printf("%d ", attr->values[i].integer);
871 break;
872
873 case IPP_TAG_BOOLEAN :
874 for (i = 0; i < attr->num_values; i ++)
875 if (attr->values[i].boolean)
876 printf("true ");
877 else
878 printf("false ");
879 break;
880
881 case IPP_TAG_NOVALUE :
882 printf("novalue");
883 break;
884
885 case IPP_TAG_RANGE :
886 for (i = 0; i < attr->num_values; i ++)
887 printf("%d-%d ", attr->values[i].range.lower,
888 attr->values[i].range.upper);
889 break;
890
891 case IPP_TAG_RESOLUTION :
892 for (i = 0; i < attr->num_values; i ++)
893 printf("%dx%d%s ", attr->values[i].resolution.xres,
894 attr->values[i].resolution.yres,
895 attr->values[i].resolution.units == IPP_RES_PER_INCH ?
896 "dpi" : "dpc");
897 break;
898
899 case IPP_TAG_STRING :
900 case IPP_TAG_TEXT :
901 case IPP_TAG_NAME :
902 case IPP_TAG_KEYWORD :
903 case IPP_TAG_CHARSET :
904 case IPP_TAG_URI :
905 case IPP_TAG_MIMETYPE :
906 case IPP_TAG_LANGUAGE :
907 for (i = 0; i < attr->num_values; i ++)
908 printf("\"%s\" ", attr->values[i].string.text);
909 break;
910
911 case IPP_TAG_TEXTLANG :
912 case IPP_TAG_NAMELANG :
913 for (i = 0; i < attr->num_values; i ++)
914 printf("\"%s\",%s ", attr->values[i].string.text,
915 attr->values[i].string.charset);
916 break;
917
918 default :
919 break; /* anti-compiler-warning-code */
920 }
921
922 putchar('\n');
923 }
924
925
926 /*
927 * 'usage()' - Show program usage.
928 */
929
930 void
931 usage(const char *option) /* I - Option string or NULL */
932 {
933 if (option)
934 fprintf(stderr, "ipptest: Unknown option \"%s\"!\n", option);
935
936 fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr);
937 fputs("Options:\n", stderr);
938 fputs("\n", stderr);
939 fputs("-i N Repeat the last test file once every N seconds.\n", stderr);
940 fputs("-v Show all attributes in response, even on success.\n", stderr);
941
942 exit(1);
943 }
944
945
946 /*
947 * End of "$Id: ipptest.c 6649 2007-07-11 21:46:42Z mike $".
948 */