]>
Commit | Line | Data |
---|---|---|
07725fee | 1 | /* |
2 | * "$Id: testsub.c 5940 2006-09-11 18:30:09Z mike $" | |
3 | * | |
4 | * Scheduler notification tester for the Common UNIX Printing System (CUPS). | |
5 | * | |
6 | * Copyright 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() - Subscribe to the . | |
27 | * print_attributes() - Print the attributes in a request... | |
28 | * sigterm_handler() - Flag when the user hits CTRL-C... | |
29 | * usage() - Show program usage... | |
30 | */ | |
31 | ||
32 | /* | |
33 | * Include necessary headers... | |
34 | */ | |
35 | ||
36 | #include <cups/cups.h> | |
37 | #include <cups/debug.h> | |
38 | #include <cups/string.h> | |
39 | #include <signal.h> | |
40 | ||
41 | ||
42 | /* | |
43 | * Local globals... | |
44 | */ | |
45 | ||
46 | static int terminate = 0; | |
47 | ||
48 | ||
49 | /* | |
50 | * Local functions... | |
51 | */ | |
52 | ||
53 | void print_attributes(ipp_t *ipp, int indent); | |
54 | static void sigterm_handler(int sig); | |
55 | static void usage(void); | |
56 | ||
57 | ||
58 | /* | |
59 | * 'main()' - Subscribe to the . | |
60 | */ | |
61 | ||
62 | int | |
63 | main(int argc, /* I - Number of command-line arguments */ | |
64 | char *argv[]) /* I - Command-line arguments */ | |
65 | { | |
66 | int i; /* Looping var */ | |
67 | const char *uri; /* URI to use */ | |
68 | int num_events; /* Number of events */ | |
69 | const char *events[100]; /* Events */ | |
70 | int subscription_id, /* notify-subscription-id */ | |
71 | sequence_number, /* notify-sequence-number */ | |
72 | interval; /* Interval between polls */ | |
73 | http_t *http; /* HTTP connection */ | |
74 | ipp_t *request, /* IPP request */ | |
75 | *response; /* IPP response */ | |
76 | ipp_attribute_t *attr; /* Current attribute */ | |
77 | #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) | |
78 | struct sigaction action; /* Actions for POSIX signals */ | |
79 | #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ | |
80 | ||
81 | ||
82 | /* | |
83 | * Parse command-line... | |
84 | */ | |
85 | ||
86 | num_events = 0; | |
87 | uri = NULL; | |
88 | ||
89 | for (i = 1; i < argc; i ++) | |
90 | if (!strcmp(argv[i], "-E")) | |
91 | cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); | |
92 | else if (!strcmp(argv[i], "-e")) | |
93 | { | |
94 | i ++; | |
95 | if (i >= argc || num_events >= 100) | |
96 | usage(); | |
97 | ||
98 | events[num_events] = argv[i]; | |
99 | num_events ++; | |
100 | } | |
101 | else if (!strcmp(argv[i], "-h")) | |
102 | { | |
103 | i ++; | |
104 | if (i >= argc) | |
105 | usage(); | |
106 | ||
107 | cupsSetServer(argv[i]); | |
108 | } | |
109 | else if (uri || strncmp(argv[i], "ipp://", 6)) | |
110 | usage(); | |
111 | else | |
112 | uri = argv[i]; | |
113 | ||
114 | if (!uri) | |
115 | usage(); | |
116 | ||
117 | if (num_events == 0) | |
118 | { | |
119 | events[0] = "all"; | |
120 | num_events = 1; | |
121 | } | |
122 | ||
123 | /* | |
124 | * Connect to the server... | |
125 | */ | |
126 | ||
127 | if ((http = httpConnectEncrypt(cupsServer(), ippPort(), | |
128 | cupsEncryption())) == NULL) | |
129 | { | |
130 | perror(cupsServer()); | |
131 | return (1); | |
132 | } | |
133 | ||
134 | /* | |
135 | * Catch CTRL-C and SIGTERM... | |
136 | */ | |
137 | ||
138 | #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ | |
139 | sigset(SIGINT, sigterm_handler); | |
140 | sigset(SIGTERM, sigterm_handler); | |
141 | #elif defined(HAVE_SIGACTION) | |
142 | memset(&action, 0, sizeof(action)); | |
143 | ||
144 | sigemptyset(&action.sa_mask); | |
145 | action.sa_handler = sigterm_handler; | |
146 | sigaction(SIGINT, &action, NULL); | |
147 | sigaction(SIGTERM, &action, NULL); | |
148 | #else | |
149 | signal(SIGINT, sigterm_handler); | |
150 | signal(SIGTERM, sigterm_handler); | |
151 | #endif /* HAVE_SIGSET */ | |
152 | ||
153 | /* | |
154 | * Create the subscription... | |
155 | */ | |
156 | ||
157 | if (strstr(uri, "/jobs/")) | |
158 | { | |
159 | request = ippNewRequest(IPP_CREATE_JOB_SUBSCRIPTION); | |
160 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); | |
161 | } | |
162 | else | |
163 | { | |
164 | request = ippNewRequest(IPP_CREATE_PRINTER_SUBSCRIPTION); | |
165 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, | |
166 | uri); | |
167 | } | |
168 | ||
169 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", | |
170 | NULL, cupsUser()); | |
171 | ||
172 | ippAddStrings(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, "notify-events", | |
173 | num_events, NULL, events); | |
174 | ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, | |
175 | "notify-pull-method", NULL, "ippget"); | |
176 | ||
177 | response = cupsDoRequest(http, request, uri); | |
178 | if (cupsLastError() >= IPP_BAD_REQUEST) | |
179 | { | |
180 | fprintf(stderr, "Create-%s-Subscription: %s\n", | |
181 | strstr(uri, "/jobs") ? "Job" : "Printer", cupsLastErrorString()); | |
182 | ippDelete(response); | |
183 | httpClose(http); | |
184 | return (1); | |
185 | } | |
186 | ||
187 | if ((attr = ippFindAttribute(response, "notify-subscription-id", | |
188 | IPP_TAG_INTEGER)) == NULL) | |
189 | { | |
190 | fputs("ERROR: No notify-subscription-id in response!\n", stderr); | |
191 | ippDelete(response); | |
192 | httpClose(http); | |
193 | return (1); | |
194 | } | |
195 | ||
196 | subscription_id = attr->values[0].integer; | |
197 | ||
198 | printf("Create-%s-Subscription: notify-subscription-id=%d\n", | |
199 | strstr(uri, "/jobs/") ? "Job" : "Printer", subscription_id); | |
200 | ||
201 | ippDelete(response); | |
202 | ||
203 | /* | |
204 | * Monitor for events... | |
205 | */ | |
206 | ||
207 | sequence_number = 0; | |
208 | ||
209 | while (!terminate) | |
210 | { | |
211 | /* | |
212 | * Get the current events... | |
213 | */ | |
214 | ||
215 | printf("\nGet-Notifications(%d,%d):", subscription_id, sequence_number); | |
216 | fflush(stdout); | |
217 | ||
218 | request = ippNewRequest(IPP_GET_NOTIFICATIONS); | |
219 | ||
220 | if (strstr(uri, "/jobs/")) | |
221 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); | |
222 | else | |
223 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, | |
224 | uri); | |
225 | ||
226 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, | |
227 | "requesting-user-name", NULL, cupsUser()); | |
228 | ||
229 | ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, | |
230 | "notify-subscription-ids", subscription_id); | |
231 | if (sequence_number) | |
232 | ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, | |
233 | "notify-sequence-numbers", sequence_number + 1); | |
234 | ||
235 | response = cupsDoRequest(http, request, uri); | |
236 | ||
237 | printf(" %s\n", ippErrorString(cupsLastError())); | |
238 | ||
239 | if (cupsLastError() >= IPP_BAD_REQUEST) | |
240 | fprintf(stderr, "Get-Notifications: %s\n", cupsLastErrorString()); | |
241 | else if (response) | |
242 | { | |
243 | print_attributes(response, 0); | |
244 | ||
245 | for (attr = ippFindAttribute(response, "notify-sequence-number", | |
246 | IPP_TAG_INTEGER); | |
247 | attr; | |
248 | attr = ippFindNextAttribute(response, "notify-sequence-number", | |
249 | IPP_TAG_INTEGER)) | |
250 | if (attr->values[0].integer > sequence_number) | |
251 | sequence_number = attr->values[0].integer; | |
252 | } | |
253 | ||
254 | if ((attr = ippFindAttribute(response, "notify-get-interval", | |
255 | IPP_TAG_INTEGER)) != NULL && | |
256 | attr->values[0].integer > 0) | |
257 | interval = attr->values[0].integer; | |
258 | else | |
259 | interval = 5; | |
260 | ||
261 | ippDelete(response); | |
262 | sleep(interval); | |
263 | } | |
264 | ||
265 | /* | |
266 | * Cancel the subscription... | |
267 | */ | |
268 | ||
269 | printf("\nCancel-Subscription:"); | |
270 | fflush(stdout); | |
271 | ||
272 | request = ippNewRequest(IPP_CANCEL_SUBSCRIPTION); | |
273 | ||
274 | if (strstr(uri, "/jobs/")) | |
275 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); | |
276 | else | |
277 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, | |
278 | uri); | |
279 | ||
280 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", | |
281 | NULL, cupsUser()); | |
282 | ||
283 | ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, | |
284 | "notify-subscription-id", subscription_id); | |
285 | ||
286 | ippDelete(cupsDoRequest(http, request, uri)); | |
287 | ||
288 | printf(" %s\n", ippErrorString(cupsLastError())); | |
289 | ||
290 | if (cupsLastError() >= IPP_BAD_REQUEST) | |
291 | fprintf(stderr, "Cancel-Subscription: %s\n", cupsLastErrorString()); | |
292 | ||
293 | /* | |
294 | * Close the connection and return... | |
295 | */ | |
296 | ||
297 | httpClose(http); | |
298 | ||
299 | return (0); | |
300 | } | |
301 | ||
302 | ||
303 | /* | |
304 | * 'print_attributes()' - Print the attributes in a request... | |
305 | */ | |
306 | ||
307 | void | |
308 | print_attributes(ipp_t *ipp, /* I - IPP request */ | |
309 | int indent) /* I - Indentation */ | |
310 | { | |
311 | int i; /* Looping var */ | |
312 | ipp_tag_t group; /* Current group */ | |
313 | ipp_attribute_t *attr; /* Current attribute */ | |
314 | ipp_value_t *val; /* Current value */ | |
315 | static const char * const tags[] = /* Value/group tag strings */ | |
316 | { | |
317 | "reserved-00", | |
318 | "operation-attributes-tag", | |
319 | "job-attributes-tag", | |
320 | "end-of-attributes-tag", | |
321 | "printer-attributes-tag", | |
322 | "unsupported-attributes-tag", | |
323 | "subscription-attributes-tag", | |
324 | "event-attributes-tag", | |
325 | "reserved-08", | |
326 | "reserved-09", | |
327 | "reserved-0A", | |
328 | "reserved-0B", | |
329 | "reserved-0C", | |
330 | "reserved-0D", | |
331 | "reserved-0E", | |
332 | "reserved-0F", | |
333 | "unsupported", | |
334 | "default", | |
335 | "unknown", | |
336 | "no-value", | |
337 | "reserved-14", | |
338 | "not-settable", | |
339 | "delete-attr", | |
340 | "admin-define", | |
341 | "reserved-18", | |
342 | "reserved-19", | |
343 | "reserved-1A", | |
344 | "reserved-1B", | |
345 | "reserved-1C", | |
346 | "reserved-1D", | |
347 | "reserved-1E", | |
348 | "reserved-1F", | |
349 | "reserved-20", | |
350 | "integer", | |
351 | "boolean", | |
352 | "enum", | |
353 | "reserved-24", | |
354 | "reserved-25", | |
355 | "reserved-26", | |
356 | "reserved-27", | |
357 | "reserved-28", | |
358 | "reserved-29", | |
359 | "reserved-2a", | |
360 | "reserved-2b", | |
361 | "reserved-2c", | |
362 | "reserved-2d", | |
363 | "reserved-2e", | |
364 | "reserved-2f", | |
365 | "octetString", | |
366 | "dateTime", | |
367 | "resolution", | |
368 | "rangeOfInteger", | |
369 | "begCollection", | |
370 | "textWithLanguage", | |
371 | "nameWithLanguage", | |
372 | "endCollection", | |
373 | "reserved-38", | |
374 | "reserved-39", | |
375 | "reserved-3a", | |
376 | "reserved-3b", | |
377 | "reserved-3c", | |
378 | "reserved-3d", | |
379 | "reserved-3e", | |
380 | "reserved-3f", | |
381 | "reserved-40", | |
382 | "textWithoutLanguage", | |
383 | "nameWithoutLanguage", | |
384 | "reserved-43", | |
385 | "keyword", | |
386 | "uri", | |
387 | "uriScheme", | |
388 | "charset", | |
389 | "naturalLanguage", | |
390 | "mimeMediaType", | |
391 | "memberName" | |
392 | }; | |
393 | ||
394 | ||
395 | for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next) | |
396 | { | |
397 | if ((attr->group_tag == IPP_TAG_ZERO && indent <= 8) || !attr->name) | |
398 | { | |
399 | group = IPP_TAG_ZERO; | |
400 | putchar('\n'); | |
401 | continue; | |
402 | } | |
403 | ||
404 | if (group != attr->group_tag) | |
405 | { | |
406 | group = attr->group_tag; | |
407 | ||
408 | putchar('\n'); | |
409 | for (i = 4; i < indent; i ++) | |
410 | putchar(' '); | |
411 | ||
412 | printf("%s:\n\n", tags[group]); | |
413 | } | |
414 | ||
415 | for (i = 0; i < indent; i ++) | |
416 | putchar(' '); | |
417 | ||
418 | printf("%s (", attr->name); | |
419 | if (attr->num_values > 1) | |
420 | printf("1setOf "); | |
421 | printf("%s):", tags[attr->value_tag]); | |
422 | ||
423 | switch (attr->value_tag) | |
424 | { | |
425 | case IPP_TAG_ENUM : | |
426 | case IPP_TAG_INTEGER : | |
427 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
428 | printf(" %d", val->integer); | |
429 | putchar('\n'); | |
430 | break; | |
431 | ||
432 | case IPP_TAG_BOOLEAN : | |
433 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
434 | printf(" %s", val->boolean ? "true" : "false"); | |
435 | putchar('\n'); | |
436 | break; | |
437 | ||
438 | case IPP_TAG_RANGE : | |
439 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
440 | printf(" %d-%d", val->range.lower, val->range.upper); | |
441 | putchar('\n'); | |
442 | break; | |
443 | ||
444 | case IPP_TAG_DATE : | |
445 | { | |
446 | time_t vtime; /* Date/Time value */ | |
447 | struct tm *vdate; /* Date info */ | |
448 | char vstring[256]; /* Formatted time */ | |
449 | ||
450 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
451 | { | |
452 | vtime = ippDateToTime(val->date); | |
453 | vdate = localtime(&vtime); | |
454 | strftime(vstring, sizeof(vstring), "%c", vdate); | |
455 | printf(" (%s)", vstring); | |
456 | } | |
457 | } | |
458 | putchar('\n'); | |
459 | break; | |
460 | ||
461 | case IPP_TAG_RESOLUTION : | |
462 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
463 | printf(" %dx%d%s", val->resolution.xres, val->resolution.yres, | |
464 | val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpc"); | |
465 | putchar('\n'); | |
466 | break; | |
467 | ||
468 | case IPP_TAG_STRING : | |
469 | case IPP_TAG_TEXTLANG : | |
470 | case IPP_TAG_NAMELANG : | |
471 | case IPP_TAG_TEXT : | |
472 | case IPP_TAG_NAME : | |
473 | case IPP_TAG_KEYWORD : | |
474 | case IPP_TAG_URI : | |
475 | case IPP_TAG_URISCHEME : | |
476 | case IPP_TAG_CHARSET : | |
477 | case IPP_TAG_LANGUAGE : | |
478 | case IPP_TAG_MIMETYPE : | |
479 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
480 | printf(" \"%s\"", val->string.text); | |
481 | putchar('\n'); | |
482 | break; | |
483 | ||
484 | case IPP_TAG_BEGIN_COLLECTION : | |
485 | putchar('\n'); | |
486 | ||
487 | for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) | |
488 | { | |
489 | if (i) | |
490 | putchar('\n'); | |
491 | print_attributes(val->collection, indent + 4); | |
492 | } | |
493 | break; | |
494 | ||
495 | default : | |
496 | printf("UNKNOWN (%d values)\n", attr->num_values); | |
497 | break; | |
498 | } | |
499 | } | |
500 | } | |
501 | ||
502 | ||
503 | /* | |
504 | * 'sigterm_handler()' - Flag when the user hits CTRL-C... | |
505 | */ | |
506 | ||
507 | static void | |
508 | sigterm_handler(int sig) /* I - Signal number (unused) */ | |
509 | { | |
510 | (void)sig; | |
511 | ||
512 | terminate = 1; | |
513 | } | |
514 | ||
515 | ||
516 | /* | |
517 | * 'usage()' - Show program usage... | |
518 | */ | |
519 | ||
520 | static void | |
521 | usage(void) | |
522 | { | |
523 | puts("Usage: testsub [-E] [-e event ... -e eventN] [-h hostname] URI"); | |
524 | exit(0); | |
525 | } | |
526 | ||
527 | ||
528 | ||
529 | /* | |
530 | * End of "$Id: testsub.c 5940 2006-09-11 18:30:09Z mike $". | |
531 | */ |