]> git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/testsub.c
Load cups into easysw/current.
[thirdparty/cups.git] / scheduler / testsub.c
1 /*
2 * "$Id: testsub.c 6376 2007-03-21 06:39:10Z mike $"
3 *
4 * Scheduler notification tester for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2006-2007 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 static 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 static 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 6376 2007-03-21 06:39:10Z mike $".
531 */