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