]> 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 5878 2006-08-24 15:55:42Z mike $"
3 *
4 * IPP test command for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2006 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * main() - Parse options and do tests.
27 * do_tests() - Do tests as specified in the test file.
28 * get_tag() - Get an IPP value or group tag from a name...
29 * get_token() - Get a token from a file.
30 * print_attr() - Print an attribute on the screen.
31 * usage() - Show program usage.
32 */
33
34 /*
35 * Include necessary headers...
36 */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <cups/string.h>
41 #include <errno.h>
42 #include <ctype.h>
43
44 #include <cups/cups.h>
45 #include <cups/language.h>
46
47
48 /*
49 * Globals...
50 */
51
52 int Verbosity = 0; /* Show all attributes? */
53 const char * const TagNames[] =
54 { /* Value/group tag names */
55 "zero", /* 0x00 */
56 "operation", /* 0x01 */
57 "job", /* 0x02 */
58 "end", /* 0x03 */
59 "printer", /* 0x04 */
60 "unsupported-group", /* 0x05 */
61 "subscription", /* 0x06 */
62 "event-notification", /* 0x07 */
63 "", "", "", "", "", "", "", "",
64 "unsupported-value", /* 0x10 */
65 "default", /* 0x11 */
66 "unknown", /* 0x12 */
67 "novalue", /* 0x13 */
68 "",
69 "notsettable", /* 0x15 */
70 "deleteattr", /* 0x16 */
71 "anyvalue", /* 0x17 */
72 "", "", "", "", "", "", "", "", "",
73 "integer", /* 0x21 */
74 "boolean", /* 0x22 */
75 "enum", /* 0x23 */
76 "", "", "", "", "", "", "", "", "", "", "", "",
77 "string", /* 0x30 */
78 "date", /* 0x31 */
79 "resolution", /* 0x32 */
80 "range", /* 0x33 */
81 "collection", /* 0x34 */
82 "textlang", /* 0x35 */
83 "namelang", /* 0x36 */
84 "", "", "", "", "", "", "", "", "", "",
85 "text", /* 0x41 */
86 "name", /* 0x42 */
87 "",
88 "keyword", /* 0x44 */
89 "uri", /* 0x45 */
90 "urischeme", /* 0x46 */
91 "charset", /* 0x47 */
92 "language", /* 0x48 */
93 "mimetype" /* 0x49 */
94 };
95
96
97
98
99 /*
100 * Local functions...
101 */
102
103 int do_tests(const char *, const char *);
104 ipp_op_t ippOpValue(const char *);
105 ipp_status_t ippErrorValue(const char *);
106 ipp_tag_t get_tag(const char *);
107 const char *get_tag_string(ipp_tag_t tag);
108 char *get_token(FILE *, char *, int, int *linenum);
109 void print_attr(ipp_attribute_t *);
110 void usage(const char *option);
111
112
113 /*
114 * 'main()' - Parse options and do tests.
115 */
116
117 int /* O - Exit status */
118 main(int argc, /* I - Number of command-line arguments */
119 char *argv[]) /* I - Command-line arguments */
120 {
121 int i; /* Looping var */
122 int status; /* Status of tests... */
123 const char *uri; /* URI to use */
124 const char *testfile; /* Test file to use */
125 int interval; /* Test interval */
126
127
128 /*
129 * We need at least:
130 *
131 * testipp URL testfile
132 */
133
134 uri = NULL;
135 testfile = NULL;
136 status = 0;
137 interval = 0;
138
139 for (i = 1; i < argc; i ++)
140 {
141 if (argv[i][0] == '-')
142 {
143 if (!strcmp(argv[i], "-v"))
144 Verbosity ++;
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
458 {
459 *tokenptr++ = *tempptr ++;
460 *tokenptr = '\0';
461 }
462
463 tokenptr += strlen(tokenptr);
464 }
465 else
466 {
467 *tokenptr++ = *tempptr++;
468 *tokenptr = '\0';
469 }
470
471 switch (value)
472 {
473 case IPP_TAG_BOOLEAN :
474 if (!strcasecmp(token, "true"))
475 ippAddBoolean(request, group, attr, 1);
476 else
477 ippAddBoolean(request, group, attr, atoi(token));
478 break;
479
480 case IPP_TAG_INTEGER :
481 case IPP_TAG_ENUM :
482 ippAddInteger(request, group, value, attr, atoi(token));
483 break;
484
485 case IPP_TAG_RESOLUTION :
486 puts(" ERROR: resolution tag not yet supported!");
487 break;
488
489 case IPP_TAG_RANGE :
490 puts(" ERROR: range tag not yet supported!");
491 break;
492
493 default :
494 if (!strchr(token, ','))
495 ippAddString(request, group, value, attr, NULL, token);
496 else
497 {
498 /*
499 * Multiple string values...
500 */
501
502 int num_values; /* Number of values */
503 char *values[100], /* Values */
504 *ptr; /* Pointer to next value */
505
506
507 values[0] = token;
508 num_values = 1;
509
510 for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ','))
511 {
512 *ptr++ = '\0';
513 values[num_values] = ptr;
514 num_values ++;
515 }
516
517 ippAddStrings(request, group, value, attr, num_values,
518 NULL, (const char **)values);
519 }
520 break;
521 }
522 }
523 else if (!strcasecmp(token, "FILE"))
524 {
525 /*
526 * File...
527 */
528
529 get_token(fp, filename, sizeof(filename), &linenum);
530 }
531 else if (!strcasecmp(token, "STATUS") &&
532 num_statuses < (int)(sizeof(statuses) / sizeof(statuses[0])))
533 {
534 /*
535 * Status...
536 */
537
538 get_token(fp, token, sizeof(token), &linenum);
539 statuses[num_statuses] = ippErrorValue(token);
540 num_statuses ++;
541 }
542 else if (!strcasecmp(token, "EXPECT") &&
543 num_expects < (int)(sizeof(expects) / sizeof(expects[0])))
544 {
545 /*
546 * Expected attributes...
547 */
548
549 get_token(fp, token, sizeof(token), &linenum);
550 expects[num_expects] = strdup(token);
551 num_expects ++;
552 }
553 else if (!strcasecmp(token, "DISPLAY") &&
554 num_displayed < (int)(sizeof(displayed) / sizeof(displayed[0])))
555 {
556 /*
557 * Display attributes...
558 */
559
560 get_token(fp, token, sizeof(token), &linenum);
561 displayed[num_displayed] = strdup(token);
562 num_displayed ++;
563 }
564 else
565 {
566 printf("Unexpected token %s seen on line %d - aborting test!\n", token,
567 linenum);
568 httpClose(http);
569 ippDelete(request);
570 return (0);
571 }
572 }
573
574 /*
575 * Submit the IPP request...
576 */
577
578 request->request.op.version[1] = version;
579 request->request.op.operation_id = op;
580 request->request.op.request_id = 1;
581
582 if (Verbosity)
583 {
584 printf("%s:\n", ippOpString(op));
585
586 for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
587 print_attr(attrptr);
588 }
589
590 printf(" %-60.60s [", name);
591 fflush(stdout);
592
593 if (filename[0])
594 response = cupsDoFileRequest(http, request, resource, filename);
595 else
596 response = cupsDoRequest(http, request, resource);
597
598 if (response == NULL)
599 {
600 time_t curtime;
601
602 curtime = time(NULL);
603
604 puts("FAIL]");
605 printf(" ERROR %04x (%s) @ %s\n", cupsLastError(),
606 cupsLastErrorString(), ctime(&curtime));
607 pass = 0;
608 }
609 else
610 {
611 if ((attrptr = ippFindAttribute(response, "job-id",
612 IPP_TAG_INTEGER)) != NULL)
613 job_id = attrptr->values[0].integer;
614
615 if ((attrptr = ippFindAttribute(response, "notify-subscription-id",
616 IPP_TAG_INTEGER)) != NULL)
617 subscription_id = attrptr->values[0].integer;
618
619 for (i = 0; i < num_statuses; i ++)
620 if (response->request.status.status_code == statuses[i])
621 break;
622
623 if (i == num_statuses && num_statuses > 0)
624 pass = 0;
625 else
626 {
627 for (i = 0; i < num_expects; i ++)
628 if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
629 {
630 pass = 0;
631 break;
632 }
633 }
634
635 if (pass)
636 {
637 puts("PASS]");
638 printf(" RECEIVED: %lu bytes in response\n",
639 (unsigned long)ippLength(response));
640
641 if (Verbosity)
642 {
643 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
644 print_attr(attrptr);
645 }
646 else if (num_displayed > 0)
647 {
648 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
649 if (attrptr->name)
650 {
651 for (i = 0; i < num_displayed; i ++)
652 if (!strcmp(displayed[i], attrptr->name))
653 {
654 print_attr(attrptr);
655 break;
656 }
657 }
658 }
659 }
660 else
661 {
662 puts("FAIL]");
663 printf(" RECEIVED: %lu bytes in response\n",
664 (unsigned long)ippLength(response));
665
666 for (i = 0; i < num_statuses; i ++)
667 if (response->request.status.status_code == statuses[i])
668 break;
669
670 if (i == num_statuses && num_statuses > 0)
671 puts(" BAD STATUS");
672
673 printf(" status-code = %04x (%s)\n",
674 cupsLastError(), cupsLastErrorString());
675
676 for (i = 0; i < num_expects; i ++)
677 if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
678 printf(" EXPECTED: %s\n", expects[i]);
679
680 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
681 print_attr(attrptr);
682 }
683
684 ippDelete(response);
685 }
686
687 for (i = 0; i < num_expects; i ++)
688 free(expects[i]);
689
690 if (!pass)
691 break;
692 }
693
694 fclose(fp);
695 httpClose(http);
696
697 return (pass);
698 }
699
700
701 /*
702 * 'get_tag()' - Get an IPP value or group tag from a name...
703 */
704
705 ipp_tag_t /* O - Value/group tag */
706 get_tag(const char *name) /* I - Name of value/group tag */
707 {
708 int i; /* Looping var */
709
710
711 for (i = 0; i < (sizeof(TagNames) / sizeof(TagNames[0])); i ++)
712 if (!strcasecmp(name, TagNames[i]))
713 return ((ipp_tag_t)i);
714
715 return (IPP_TAG_ZERO);
716 }
717
718
719 /*
720 * 'get_tag_string()' - Get the string associated with a tag.
721 */
722
723 const char * /* O - Tag name string */
724 get_tag_string(ipp_tag_t tag) /* I - IPP tag */
725 {
726 if (tag < (ipp_tag_t)(sizeof(TagNames) / sizeof(TagNames[0])))
727 return (TagNames[tag]);
728 else
729 return ("UNKNOWN");
730 }
731
732
733 /*
734 * 'get_token()' - Get a token from a file.
735 */
736
737 char * /* O - Token from file or NULL on EOF */
738 get_token(FILE *fp, /* I - File to read from */
739 char *buf, /* I - Buffer to read into */
740 int buflen, /* I - Length of buffer */
741 int *linenum) /* IO - Current line number */
742 {
743 int ch, /* Character from file */
744 quote; /* Quoting character */
745 char *bufptr, /* Pointer into buffer */
746 *bufend; /* End of buffer */
747
748
749 for (;;)
750 {
751 /*
752 * Skip whitespace...
753 */
754
755 while (isspace(ch = getc(fp)))
756 {
757 if (ch == '\n')
758 (*linenum) ++;
759 }
760
761 /*
762 * Read a token...
763 */
764
765 if (ch == EOF)
766 return (NULL);
767 else if (ch == '\'' || ch == '\"')
768 {
769 /*
770 * Quoted text...
771 */
772
773 quote = ch;
774 bufptr = buf;
775 bufend = buf + buflen - 1;
776
777 while ((ch = getc(fp)) != EOF)
778 if (ch == quote)
779 break;
780 else if (bufptr < bufend)
781 *bufptr++ = ch;
782
783 *bufptr = '\0';
784 return (buf);
785 }
786 else if (ch == '#')
787 {
788 /*
789 * Comment...
790 */
791
792 while ((ch = getc(fp)) != EOF)
793 if (ch == '\n')
794 break;
795
796 (*linenum) ++;
797 }
798 else
799 {
800 /*
801 * Whitespace delimited text...
802 */
803
804 ungetc(ch, fp);
805
806 bufptr = buf;
807 bufend = buf + buflen - 1;
808
809 while ((ch = getc(fp)) != EOF)
810 if (isspace(ch) || ch == '#')
811 break;
812 else if (bufptr < bufend)
813 *bufptr++ = ch;
814
815 if (ch == '#')
816 ungetc(ch, fp);
817
818 *bufptr = '\0';
819 return (buf);
820 }
821 }
822 }
823
824
825 /*
826 * 'print_attr()' - Print an attribute on the screen.
827 */
828
829 void
830 print_attr(ipp_attribute_t *attr) /* I - Attribute to print */
831 {
832 int i; /* Looping var */
833
834
835 if (attr->name == NULL)
836 {
837 puts(" -- separator --");
838 return;
839 }
840
841 printf(" %s (%s%s) = ", attr->name,
842 attr->num_values > 1 ? "1setOf " : "",
843 get_tag_string(attr->value_tag));
844
845 switch (attr->value_tag)
846 {
847 case IPP_TAG_INTEGER :
848 case IPP_TAG_ENUM :
849 for (i = 0; i < attr->num_values; i ++)
850 printf("%d ", attr->values[i].integer);
851 break;
852
853 case IPP_TAG_BOOLEAN :
854 for (i = 0; i < attr->num_values; i ++)
855 if (attr->values[i].boolean)
856 printf("true ");
857 else
858 printf("false ");
859 break;
860
861 case IPP_TAG_NOVALUE :
862 printf("novalue");
863 break;
864
865 case IPP_TAG_RANGE :
866 for (i = 0; i < attr->num_values; i ++)
867 printf("%d-%d ", attr->values[i].range.lower,
868 attr->values[i].range.upper);
869 break;
870
871 case IPP_TAG_RESOLUTION :
872 for (i = 0; i < attr->num_values; i ++)
873 printf("%dx%d%s ", attr->values[i].resolution.xres,
874 attr->values[i].resolution.yres,
875 attr->values[i].resolution.units == IPP_RES_PER_INCH ?
876 "dpi" : "dpc");
877 break;
878
879 case IPP_TAG_STRING :
880 case IPP_TAG_TEXT :
881 case IPP_TAG_NAME :
882 case IPP_TAG_KEYWORD :
883 case IPP_TAG_CHARSET :
884 case IPP_TAG_URI :
885 case IPP_TAG_MIMETYPE :
886 case IPP_TAG_LANGUAGE :
887 for (i = 0; i < attr->num_values; i ++)
888 printf("\"%s\" ", attr->values[i].string.text);
889 break;
890
891 case IPP_TAG_TEXTLANG :
892 case IPP_TAG_NAMELANG :
893 for (i = 0; i < attr->num_values; i ++)
894 printf("\"%s\",%s ", attr->values[i].string.text,
895 attr->values[i].string.charset);
896 break;
897
898 default :
899 break; /* anti-compiler-warning-code */
900 }
901
902 putchar('\n');
903 }
904
905
906 /*
907 * 'usage()' - Show program usage.
908 */
909
910 void
911 usage(const char *option) /* I - Option string or NULL */
912 {
913 if (option)
914 fprintf(stderr, "ipptest: Unknown option \"%s\"!\n", option);
915
916 fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr);
917 fputs("Options:\n", stderr);
918 fputs("\n", stderr);
919 fputs("-i N Repeat the last test file once every N seconds.\n", stderr);
920 fputs("-v Show all attributes in response, even on success.\n", stderr);
921
922 exit(1);
923 }
924
925
926 /*
927 * End of "$Id: ipptest.c 5878 2006-08-24 15:55:42Z mike $".
928 */