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