2 * "$Id: testsub.c 6376 2007-03-21 06:39:10Z mike $"
4 * Scheduler notification tester for the Common UNIX Printing System (CUPS).
6 * Copyright 2006-2007 by Easy Software Products.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
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...
33 * Include necessary headers...
36 #include <cups/cups.h>
37 #include <cups/debug.h>
38 #include <cups/string.h>
46 static int terminate
= 0;
53 static void print_attributes(ipp_t
*ipp
, int indent
);
54 static void sigterm_handler(int sig
);
55 static void usage(void);
59 * 'main()' - Subscribe to the .
63 main(int argc
, /* I - Number of command-line arguments */
64 char *argv
[]) /* I - Command-line arguments */
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 */
83 * Parse command-line...
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"))
95 if (i
>= argc
|| num_events
>= 100)
98 events
[num_events
] = argv
[i
];
101 else if (!strcmp(argv
[i
], "-h"))
107 cupsSetServer(argv
[i
]);
109 else if (uri
|| strncmp(argv
[i
], "ipp://", 6))
124 * Connect to the server...
127 if ((http
= httpConnectEncrypt(cupsServer(), ippPort(),
128 cupsEncryption())) == NULL
)
130 perror(cupsServer());
135 * Catch CTRL-C and SIGTERM...
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
));
144 sigemptyset(&action
.sa_mask
);
145 action
.sa_handler
= sigterm_handler
;
146 sigaction(SIGINT
, &action
, NULL
);
147 sigaction(SIGTERM
, &action
, NULL
);
149 signal(SIGINT
, sigterm_handler
);
150 signal(SIGTERM
, sigterm_handler
);
151 #endif /* HAVE_SIGSET */
154 * Create the subscription...
157 if (strstr(uri
, "/jobs/"))
159 request
= ippNewRequest(IPP_CREATE_JOB_SUBSCRIPTION
);
160 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-uri", NULL
, uri
);
164 request
= ippNewRequest(IPP_CREATE_PRINTER_SUBSCRIPTION
);
165 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri", NULL
,
169 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
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");
177 response
= cupsDoRequest(http
, request
, uri
);
178 if (cupsLastError() >= IPP_BAD_REQUEST
)
180 fprintf(stderr
, "Create-%s-Subscription: %s\n",
181 strstr(uri
, "/jobs") ? "Job" : "Printer", cupsLastErrorString());
187 if ((attr
= ippFindAttribute(response
, "notify-subscription-id",
188 IPP_TAG_INTEGER
)) == NULL
)
190 fputs("ERROR: No notify-subscription-id in response!\n", stderr
);
196 subscription_id
= attr
->values
[0].integer
;
198 printf("Create-%s-Subscription: notify-subscription-id=%d\n",
199 strstr(uri
, "/jobs/") ? "Job" : "Printer", subscription_id
);
204 * Monitor for events...
212 * Get the current events...
215 printf("\nGet-Notifications(%d,%d):", subscription_id
, sequence_number
);
218 request
= ippNewRequest(IPP_GET_NOTIFICATIONS
);
220 if (strstr(uri
, "/jobs/"))
221 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-uri", NULL
, uri
);
223 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri", NULL
,
226 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
227 "requesting-user-name", NULL
, cupsUser());
229 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_INTEGER
,
230 "notify-subscription-ids", subscription_id
);
232 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_INTEGER
,
233 "notify-sequence-numbers", sequence_number
+ 1);
235 response
= cupsDoRequest(http
, request
, uri
);
237 printf(" %s\n", ippErrorString(cupsLastError()));
239 if (cupsLastError() >= IPP_BAD_REQUEST
)
240 fprintf(stderr
, "Get-Notifications: %s\n", cupsLastErrorString());
243 print_attributes(response
, 0);
245 for (attr
= ippFindAttribute(response
, "notify-sequence-number",
248 attr
= ippFindNextAttribute(response
, "notify-sequence-number",
250 if (attr
->values
[0].integer
> sequence_number
)
251 sequence_number
= attr
->values
[0].integer
;
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
;
266 * Cancel the subscription...
269 printf("\nCancel-Subscription:");
272 request
= ippNewRequest(IPP_CANCEL_SUBSCRIPTION
);
274 if (strstr(uri
, "/jobs/"))
275 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-uri", NULL
, uri
);
277 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri", NULL
,
280 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "requesting-user-name",
283 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_INTEGER
,
284 "notify-subscription-id", subscription_id
);
286 ippDelete(cupsDoRequest(http
, request
, uri
));
288 printf(" %s\n", ippErrorString(cupsLastError()));
290 if (cupsLastError() >= IPP_BAD_REQUEST
)
291 fprintf(stderr
, "Cancel-Subscription: %s\n", cupsLastErrorString());
294 * Close the connection and return...
304 * 'print_attributes()' - Print the attributes in a request...
308 print_attributes(ipp_t
*ipp
, /* I - IPP request */
309 int indent
) /* I - Indentation */
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 */
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",
382 "textWithoutLanguage",
383 "nameWithoutLanguage",
395 for (group
= IPP_TAG_ZERO
, attr
= ipp
->attrs
; attr
; attr
= attr
->next
)
397 if ((attr
->group_tag
== IPP_TAG_ZERO
&& indent
<= 8) || !attr
->name
)
399 group
= IPP_TAG_ZERO
;
404 if (group
!= attr
->group_tag
)
406 group
= attr
->group_tag
;
409 for (i
= 4; i
< indent
; i
++)
412 printf("%s:\n\n", tags
[group
]);
415 for (i
= 0; i
< indent
; i
++)
418 printf("%s (", attr
->name
);
419 if (attr
->num_values
> 1)
421 printf("%s):", tags
[attr
->value_tag
]);
423 switch (attr
->value_tag
)
426 case IPP_TAG_INTEGER
:
427 for (i
= 0, val
= attr
->values
; i
< attr
->num_values
; i
++, val
++)
428 printf(" %d", val
->integer
);
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");
439 for (i
= 0, val
= attr
->values
; i
< attr
->num_values
; i
++, val
++)
440 printf(" %d-%d", val
->range
.lower
, val
->range
.upper
);
446 time_t vtime
; /* Date/Time value */
447 struct tm
*vdate
; /* Date info */
448 char vstring
[256]; /* Formatted time */
450 for (i
= 0, val
= attr
->values
; i
< attr
->num_values
; i
++, val
++)
452 vtime
= ippDateToTime(val
->date
);
453 vdate
= localtime(&vtime
);
454 strftime(vstring
, sizeof(vstring
), "%c", vdate
);
455 printf(" (%s)", vstring
);
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");
468 case IPP_TAG_STRING
:
469 case IPP_TAG_TEXTLANG
:
470 case IPP_TAG_NAMELANG
:
473 case IPP_TAG_KEYWORD
:
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
);
484 case IPP_TAG_BEGIN_COLLECTION
:
487 for (i
= 0, val
= attr
->values
; i
< attr
->num_values
; i
++, val
++)
491 print_attributes(val
->collection
, indent
+ 4);
496 printf("UNKNOWN (%d values)\n", attr
->num_values
);
504 * 'sigterm_handler()' - Flag when the user hits CTRL-C...
508 sigterm_handler(int sig
) /* I - Signal number (unused) */
517 * 'usage()' - Show program usage...
523 puts("Usage: testsub [-E] [-e event ... -e eventN] [-h hostname] URI");
530 * End of "$Id: testsub.c 6376 2007-03-21 06:39:10Z mike $".