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