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