]> git.ipfire.org Git - thirdparty/cups.git/blame - test/ipptest.c
Merge changes from CUPS 1.4svn-r7696.
[thirdparty/cups.git] / test / ipptest.c
CommitLineData
ef416fc2 1/*
75bd9771 2 * "$Id: ipptest.c 7219 2008-01-14 22:00:02Z mike $"
ef416fc2 3 *
4 * IPP test command for the Common UNIX Printing System (CUPS).
5 *
91c84a35 6 * Copyright 2007-2008 by Apple Inc.
b94498cf 7 * Copyright 1997-2007 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
ef416fc2 14 *
15 * Contents:
16 *
e00b005a 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.
ef416fc2 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
e00b005a 39/*
40 * Globals...
41 */
42
89d46774 43int Verbosity = 0; /* Show all attributes? */
44const 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
e00b005a 88
89
ef416fc2 90/*
91 * Local functions...
92 */
93
94int do_tests(const char *, const char *);
95ipp_op_t ippOpValue(const char *);
96ipp_status_t ippErrorValue(const char *);
97ipp_tag_t get_tag(const char *);
89d46774 98const char *get_tag_string(ipp_tag_t tag);
ef416fc2 99char *get_token(FILE *, char *, int, int *linenum);
100void print_attr(ipp_attribute_t *);
e00b005a 101void usage(const char *option);
ef416fc2 102
103
104/*
105 * 'main()' - Parse options and do tests.
106 */
107
108int /* O - Exit status */
109main(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... */
e00b005a 114 const char *uri; /* URI to use */
115 const char *testfile; /* Test file to use */
8ca02f3c 116 int interval; /* Test interval */
ef416fc2 117
118
119 /*
120 * We need at least:
121 *
122 * testipp URL testfile
123 */
124
e00b005a 125 uri = NULL;
126 testfile = NULL;
127 status = 0;
8ca02f3c 128 interval = 0;
e00b005a 129
130 for (i = 1; i < argc; i ++)
ef416fc2 131 {
e00b005a 132 if (argv[i][0] == '-')
133 {
134 if (!strcmp(argv[i], "-v"))
135 Verbosity ++;
b94498cf 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 }
8ca02f3c 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 }
e00b005a 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 */
ef416fc2 164
e00b005a 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 }
ef416fc2 183
e00b005a 184 if (!uri || !testfile)
185 usage(NULL);
ef416fc2 186
8ca02f3c 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
ef416fc2 200 /*
201 * Exit...
202 */
203
e00b005a 204 return (status);
ef416fc2 205}
206
207
208/*
209 * 'do_tests()' - Do tests as specified in the test file.
210 */
211
212int /* 1 = success, 0 = failure */
213do_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
a4d04587 264 httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), userpass,
265 sizeof(userpass), server, sizeof(server), &port, resource,
266 sizeof(resource));
ef416fc2 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));
91c84a35 271 fclose(fp);
ef416fc2 272 return (0);
273 }
274
275 /*
276 * Loop on tests...
277 */
278
279 printf("\"%s\":\n", testfile);
280 pass = 1;
281 job_id = 0;
282 subscription_id = 0;
283 version = 1;
284 linenum = 1;
285
286 while (get_token(fp, token, sizeof(token), &linenum) != NULL)
287 {
288 /*
289 * Expect an open brace...
290 */
291
292 if (strcmp(token, "{"))
293 {
294 printf("Unexpected token %s seen on line %d - aborting test!\n", token,
295 linenum);
296 httpClose(http);
297 return (0);
298 }
299
300 /*
301 * Initialize things...
302 */
303
a4d04587 304 httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), userpass,
305 sizeof(userpass), server, sizeof(server), &port, resource,
306 sizeof(resource));
ef416fc2 307
308 request = ippNew();
309 op = (ipp_op_t)0;
310 group = IPP_TAG_ZERO;
311 value = IPP_TAG_ZERO;
312 num_statuses = 0;
313 num_expects = 0;
314 num_displayed = 0;
315 filename[0] = '\0';
316
317 strcpy(name, testfile);
318 if (strrchr(name, '.') != NULL)
319 *strrchr(name, '.') = '\0';
320
321 /*
322 * Parse until we see a close brace...
323 */
324
325 while (get_token(fp, token, sizeof(token), &linenum) != NULL)
326 {
327 if (!strcmp(token, "}"))
328 break;
329 else if (!strcasecmp(token, "NAME"))
330 {
331 /*
332 * Name of test...
333 */
334
335 get_token(fp, name, sizeof(name), &linenum);
336 }
337 else if (!strcasecmp(token, "VERSION"))
338 {
339 /*
340 * IPP version number for test...
341 */
342
343 get_token(fp, temp, sizeof(temp), &linenum);
344 sscanf(temp, "%*d.%d", &version);
345 }
346 else if (!strcasecmp(token, "RESOURCE"))
347 {
348 /*
349 * Resource name...
350 */
351
352 get_token(fp, resource, sizeof(resource), &linenum);
353 }
354 else if (!strcasecmp(token, "OPERATION"))
355 {
356 /*
357 * Operation...
358 */
359
360 get_token(fp, token, sizeof(token), &linenum);
361 op = ippOpValue(token);
362 }
363 else if (!strcasecmp(token, "GROUP"))
364 {
365 /*
366 * Attribute group...
367 */
368
369 get_token(fp, token, sizeof(token), &linenum);
370 value = get_tag(token);
371
372 if (value == group)
373 ippAddSeparator(request);
374
375 group = value;
376 }
377 else if (!strcasecmp(token, "DELAY"))
378 {
379 /*
380 * Delay before operation...
381 */
382
383 int delay;
384
385 get_token(fp, token, sizeof(token), &linenum);
386 if ((delay = atoi(token)) > 0)
387 sleep(delay);
388 }
389 else if (!strcasecmp(token, "ATTR"))
390 {
391 /*
392 * Attribute...
393 */
394
395 get_token(fp, token, sizeof(token), &linenum);
396 value = get_tag(token);
397 get_token(fp, attr, sizeof(attr), &linenum);
398 get_token(fp, temp, sizeof(temp), &linenum);
399
400 token[sizeof(token) - 1] = '\0';
401
402 for (tempptr = temp, tokenptr = token;
403 *tempptr && tokenptr < (token + sizeof(token) - 1);)
404 if (*tempptr == '$')
405 {
406 /*
407 * Substitute a string/number...
408 */
409
410 if (!strncasecmp(tempptr + 1, "uri", 3))
411 {
412 strlcpy(tokenptr, uri, sizeof(token) - (tokenptr - token));
413 tempptr += 4;
414 }
415 else if (!strncasecmp(tempptr + 1, "method", 6))
416 {
417 strlcpy(tokenptr, method, sizeof(token) - (tokenptr - token));
418 tempptr += 7;
419 }
420 else if (!strncasecmp(tempptr + 1, "username", 8))
421 {
422 strlcpy(tokenptr, userpass, sizeof(token) - (tokenptr - token));
423 tempptr += 9;
424 }
425 else if (!strncasecmp(tempptr + 1, "hostname", 8))
426 {
427 strlcpy(tokenptr, server, sizeof(token) - (tokenptr - token));
428 tempptr += 9;
429 }
430 else if (!strncasecmp(tempptr + 1, "port", 4))
431 {
432 snprintf(tokenptr, sizeof(token) - (tokenptr - token),
433 "%d", port);
434 tempptr += 5;
435 }
436 else if (!strncasecmp(tempptr + 1, "resource", 8))
437 {
438 strlcpy(tokenptr, resource, sizeof(token) - (tokenptr - token));
439 tempptr += 9;
440 }
441 else if (!strncasecmp(tempptr + 1, "job-id", 6))
442 {
443 snprintf(tokenptr, sizeof(token) - (tokenptr - token),
444 "%d", job_id);
445 tempptr += 7;
446 }
447 else if (!strncasecmp(tempptr + 1, "notify-subscription-id", 22))
448 {
449 snprintf(tokenptr, sizeof(token) - (tokenptr - token),
450 "%d", subscription_id);
451 tempptr += 23;
452 }
453 else if (!strncasecmp(tempptr + 1, "user", 4))
454 {
455 strlcpy(tokenptr, cupsUser(), sizeof(token) - (tokenptr - token));
456 tempptr += 5;
457 }
b94498cf 458 else if (!strncasecmp(tempptr + 1, "ENV[", 4))
459 {
460 char *end; /* End of $ENV[name] */
461
462
463 if ((end = strchr(tempptr + 5, ']')) != NULL)
464 {
465 *end++ = '\0';
466 strlcpy(tokenptr,
467 getenv(tempptr + 5) ? getenv(tempptr + 5) : tempptr + 5,
468 sizeof(token) - (tokenptr - token));
469 tempptr = end;
470 }
471 else
472 {
473 *tokenptr++ = *tempptr++;
474 *tokenptr = '\0';
475 }
476 }
ef416fc2 477 else
478 {
b94498cf 479 *tokenptr++ = *tempptr++;
ef416fc2 480 *tokenptr = '\0';
481 }
482
483 tokenptr += strlen(tokenptr);
484 }
485 else
486 {
487 *tokenptr++ = *tempptr++;
488 *tokenptr = '\0';
489 }
490
491 switch (value)
492 {
493 case IPP_TAG_BOOLEAN :
494 if (!strcasecmp(token, "true"))
495 ippAddBoolean(request, group, attr, 1);
496 else
497 ippAddBoolean(request, group, attr, atoi(token));
498 break;
499
500 case IPP_TAG_INTEGER :
501 case IPP_TAG_ENUM :
502 ippAddInteger(request, group, value, attr, atoi(token));
503 break;
504
505 case IPP_TAG_RESOLUTION :
506 puts(" ERROR: resolution tag not yet supported!");
507 break;
508
509 case IPP_TAG_RANGE :
510 puts(" ERROR: range tag not yet supported!");
511 break;
512
513 default :
514 if (!strchr(token, ','))
515 ippAddString(request, group, value, attr, NULL, token);
516 else
517 {
518 /*
519 * Multiple string values...
520 */
521
522 int num_values; /* Number of values */
523 char *values[100], /* Values */
524 *ptr; /* Pointer to next value */
525
526
527 values[0] = token;
528 num_values = 1;
529
530 for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ','))
531 {
532 *ptr++ = '\0';
533 values[num_values] = ptr;
534 num_values ++;
535 }
536
537 ippAddStrings(request, group, value, attr, num_values,
538 NULL, (const char **)values);
539 }
540 break;
541 }
542 }
543 else if (!strcasecmp(token, "FILE"))
544 {
545 /*
546 * File...
547 */
548
549 get_token(fp, filename, sizeof(filename), &linenum);
550 }
551 else if (!strcasecmp(token, "STATUS") &&
552 num_statuses < (int)(sizeof(statuses) / sizeof(statuses[0])))
553 {
554 /*
555 * Status...
556 */
557
558 get_token(fp, token, sizeof(token), &linenum);
559 statuses[num_statuses] = ippErrorValue(token);
560 num_statuses ++;
561 }
562 else if (!strcasecmp(token, "EXPECT") &&
563 num_expects < (int)(sizeof(expects) / sizeof(expects[0])))
564 {
565 /*
566 * Expected attributes...
567 */
568
569 get_token(fp, token, sizeof(token), &linenum);
570 expects[num_expects] = strdup(token);
571 num_expects ++;
572 }
573 else if (!strcasecmp(token, "DISPLAY") &&
574 num_displayed < (int)(sizeof(displayed) / sizeof(displayed[0])))
575 {
576 /*
577 * Display attributes...
578 */
579
580 get_token(fp, token, sizeof(token), &linenum);
581 displayed[num_displayed] = strdup(token);
582 num_displayed ++;
583 }
584 else
585 {
586 printf("Unexpected token %s seen on line %d - aborting test!\n", token,
587 linenum);
588 httpClose(http);
589 ippDelete(request);
590 return (0);
591 }
592 }
593
594 /*
595 * Submit the IPP request...
596 */
597
598 request->request.op.version[1] = version;
599 request->request.op.operation_id = op;
600 request->request.op.request_id = 1;
601
bd7854cb 602 if (Verbosity)
603 {
604 printf("%s:\n", ippOpString(op));
605
606 for (attrptr = request->attrs; attrptr; attrptr = attrptr->next)
607 print_attr(attrptr);
608 }
ef416fc2 609
610 printf(" %-60.60s [", name);
611 fflush(stdout);
612
613 if (filename[0])
614 response = cupsDoFileRequest(http, request, resource, filename);
615 else
b94498cf 616 response = cupsDoIORequest(http, request, resource, -1,
617 Verbosity ? 1 : -1);
ef416fc2 618
619 if (response == NULL)
620 {
621 time_t curtime;
622
623 curtime = time(NULL);
624
625 puts("FAIL]");
626 printf(" ERROR %04x (%s) @ %s\n", cupsLastError(),
bd7854cb 627 cupsLastErrorString(), ctime(&curtime));
ef416fc2 628 pass = 0;
629 }
630 else
631 {
632 if ((attrptr = ippFindAttribute(response, "job-id",
633 IPP_TAG_INTEGER)) != NULL)
634 job_id = attrptr->values[0].integer;
635
636 if ((attrptr = ippFindAttribute(response, "notify-subscription-id",
637 IPP_TAG_INTEGER)) != NULL)
638 subscription_id = attrptr->values[0].integer;
639
640 for (i = 0; i < num_statuses; i ++)
641 if (response->request.status.status_code == statuses[i])
642 break;
643
644 if (i == num_statuses && num_statuses > 0)
645 pass = 0;
646 else
647 {
648 for (i = 0; i < num_expects; i ++)
649 if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
650 {
651 pass = 0;
652 break;
653 }
654 }
655
656 if (pass)
657 {
658 puts("PASS]");
659 printf(" RECEIVED: %lu bytes in response\n",
660 (unsigned long)ippLength(response));
661
e00b005a 662 if (Verbosity)
663 {
664 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
665 print_attr(attrptr);
666 }
667 else if (num_displayed > 0)
ef416fc2 668 {
669 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
670 if (attrptr->name)
671 {
672 for (i = 0; i < num_displayed; i ++)
673 if (!strcmp(displayed[i], attrptr->name))
674 {
675 print_attr(attrptr);
676 break;
677 }
678 }
679 }
680 }
681 else
682 {
683 puts("FAIL]");
684 printf(" RECEIVED: %lu bytes in response\n",
685 (unsigned long)ippLength(response));
686
687 for (i = 0; i < num_statuses; i ++)
688 if (response->request.status.status_code == statuses[i])
689 break;
690
691 if (i == num_statuses && num_statuses > 0)
692 puts(" BAD STATUS");
693
694 printf(" status-code = %04x (%s)\n",
b94498cf 695 cupsLastError(), ippErrorString(cupsLastError()));
ef416fc2 696
697 for (i = 0; i < num_expects; i ++)
698 if (ippFindAttribute(response, expects[i], IPP_TAG_ZERO) == NULL)
699 printf(" EXPECTED: %s\n", expects[i]);
700
701 for (attrptr = response->attrs; attrptr != NULL; attrptr = attrptr->next)
702 print_attr(attrptr);
703 }
704
705 ippDelete(response);
706 }
707
708 for (i = 0; i < num_expects; i ++)
709 free(expects[i]);
710
711 if (!pass)
712 break;
713 }
714
715 fclose(fp);
716 httpClose(http);
717
718 return (pass);
719}
720
721
722/*
723 * 'get_tag()' - Get an IPP value or group tag from a name...
724 */
725
726ipp_tag_t /* O - Value/group tag */
727get_tag(const char *name) /* I - Name of value/group tag */
728{
729 int i; /* Looping var */
ef416fc2 730
731
89d46774 732 for (i = 0; i < (sizeof(TagNames) / sizeof(TagNames[0])); i ++)
733 if (!strcasecmp(name, TagNames[i]))
ef416fc2 734 return ((ipp_tag_t)i);
735
736 return (IPP_TAG_ZERO);
737}
738
739
89d46774 740/*
741 * 'get_tag_string()' - Get the string associated with a tag.
742 */
743
744const char * /* O - Tag name string */
745get_tag_string(ipp_tag_t tag) /* I - IPP tag */
746{
747 if (tag < (ipp_tag_t)(sizeof(TagNames) / sizeof(TagNames[0])))
748 return (TagNames[tag]);
749 else
750 return ("UNKNOWN");
751}
752
753
ef416fc2 754/*
755 * 'get_token()' - Get a token from a file.
756 */
757
758char * /* O - Token from file or NULL on EOF */
759get_token(FILE *fp, /* I - File to read from */
760 char *buf, /* I - Buffer to read into */
761 int buflen, /* I - Length of buffer */
762 int *linenum) /* IO - Current line number */
763{
764 int ch, /* Character from file */
765 quote; /* Quoting character */
766 char *bufptr, /* Pointer into buffer */
767 *bufend; /* End of buffer */
768
769
770 for (;;)
771 {
772 /*
773 * Skip whitespace...
774 */
775
776 while (isspace(ch = getc(fp)))
777 {
778 if (ch == '\n')
779 (*linenum) ++;
780 }
781
782 /*
783 * Read a token...
784 */
785
786 if (ch == EOF)
787 return (NULL);
788 else if (ch == '\'' || ch == '\"')
789 {
790 /*
791 * Quoted text...
792 */
793
794 quote = ch;
795 bufptr = buf;
796 bufend = buf + buflen - 1;
797
798 while ((ch = getc(fp)) != EOF)
799 if (ch == quote)
800 break;
801 else if (bufptr < bufend)
802 *bufptr++ = ch;
803
804 *bufptr = '\0';
805 return (buf);
806 }
807 else if (ch == '#')
808 {
809 /*
810 * Comment...
811 */
812
813 while ((ch = getc(fp)) != EOF)
814 if (ch == '\n')
815 break;
816
817 (*linenum) ++;
818 }
819 else
820 {
821 /*
822 * Whitespace delimited text...
823 */
824
825 ungetc(ch, fp);
826
827 bufptr = buf;
828 bufend = buf + buflen - 1;
829
830 while ((ch = getc(fp)) != EOF)
831 if (isspace(ch) || ch == '#')
832 break;
833 else if (bufptr < bufend)
834 *bufptr++ = ch;
835
836 if (ch == '#')
837 ungetc(ch, fp);
838
839 *bufptr = '\0';
840 return (buf);
841 }
842 }
843}
844
845
846/*
847 * 'print_attr()' - Print an attribute on the screen.
848 */
849
850void
851print_attr(ipp_attribute_t *attr) /* I - Attribute to print */
852{
853 int i; /* Looping var */
854
855
856 if (attr->name == NULL)
857 {
858 puts(" -- separator --");
859 return;
860 }
861
d09495fa 862 printf(" %s (%s%s) = ", attr->name,
863 attr->num_values > 1 ? "1setOf " : "",
864 get_tag_string(attr->value_tag));
ef416fc2 865
866 switch (attr->value_tag)
867 {
868 case IPP_TAG_INTEGER :
869 case IPP_TAG_ENUM :
870 for (i = 0; i < attr->num_values; i ++)
871 printf("%d ", attr->values[i].integer);
872 break;
873
874 case IPP_TAG_BOOLEAN :
875 for (i = 0; i < attr->num_values; i ++)
876 if (attr->values[i].boolean)
877 printf("true ");
878 else
879 printf("false ");
880 break;
881
882 case IPP_TAG_NOVALUE :
883 printf("novalue");
884 break;
885
886 case IPP_TAG_RANGE :
887 for (i = 0; i < attr->num_values; i ++)
888 printf("%d-%d ", attr->values[i].range.lower,
889 attr->values[i].range.upper);
890 break;
891
892 case IPP_TAG_RESOLUTION :
893 for (i = 0; i < attr->num_values; i ++)
894 printf("%dx%d%s ", attr->values[i].resolution.xres,
895 attr->values[i].resolution.yres,
896 attr->values[i].resolution.units == IPP_RES_PER_INCH ?
897 "dpi" : "dpc");
898 break;
899
900 case IPP_TAG_STRING :
901 case IPP_TAG_TEXT :
902 case IPP_TAG_NAME :
903 case IPP_TAG_KEYWORD :
904 case IPP_TAG_CHARSET :
905 case IPP_TAG_URI :
906 case IPP_TAG_MIMETYPE :
907 case IPP_TAG_LANGUAGE :
908 for (i = 0; i < attr->num_values; i ++)
909 printf("\"%s\" ", attr->values[i].string.text);
910 break;
911
912 case IPP_TAG_TEXTLANG :
913 case IPP_TAG_NAMELANG :
914 for (i = 0; i < attr->num_values; i ++)
915 printf("\"%s\",%s ", attr->values[i].string.text,
916 attr->values[i].string.charset);
917 break;
918
919 default :
920 break; /* anti-compiler-warning-code */
921 }
922
923 putchar('\n');
924}
925
926
927/*
e00b005a 928 * 'usage()' - Show program usage.
929 */
930
931void
932usage(const char *option) /* I - Option string or NULL */
933{
934 if (option)
935 fprintf(stderr, "ipptest: Unknown option \"%s\"!\n", option);
936
937 fputs("Usage: ipptest [options] URL testfile [ ... testfileN ]\n", stderr);
938 fputs("Options:\n", stderr);
939 fputs("\n", stderr);
8ca02f3c 940 fputs("-i N Repeat the last test file once every N seconds.\n", stderr);
941 fputs("-v Show all attributes in response, even on success.\n", stderr);
e00b005a 942
943 exit(1);
944}
945
946
947/*
75bd9771 948 * End of "$Id: ipptest.c 7219 2008-01-14 22:00:02Z mike $".
ef416fc2 949 */