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