]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/cups-polld.c
2 * "$Id: cups-polld.c 4638 2005-09-15 14:13:19Z mike $"
4 * Polling daemon for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
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() - Open sockets and poll until we are killed...
27 * poll_server() - Poll the server for the given set of printers or classes.
31 * Include necessary headers...
34 #include <cups/http-private.h>
35 #include <cups/cups.h>
38 #include <cups/language.h>
39 #include <cups/string.h>
46 int poll_server(http_t
*http
, cups_lang_t
*language
, ipp_op_t op
,
47 int sock
, int port
, int interval
, const char *prefix
);
51 * 'main()' - Open sockets and poll until we are killed...
54 int /* O - Exit status */
55 main(int argc
, /* I - Number of command-line arguments */
56 char *argv
[]) /* I - Command-line arguments */
58 http_t
*http
; /* HTTP connection */
59 cups_lang_t
*language
; /* Language info */
60 int interval
; /* Polling interval */
61 int sock
; /* Browser sock */
62 int port
; /* Browser port */
63 int val
; /* Socket option value */
64 int seconds
, /* Seconds left from poll */
65 remain
; /* Total remaining time to sleep */
66 char prefix
[1024]; /* Prefix for log messages */
70 * Don't buffer log messages...
76 * The command-line must contain the following:
78 * cups-polld server server-port interval port
83 fputs("Usage: cups-polld server server-port interval port\n", stderr
);
87 interval
= atoi(argv
[3]);
93 snprintf(prefix
, sizeof(prefix
), "[cups-polld %s:%d]", argv
[1], atoi(argv
[2]));
96 * Open a broadcast socket...
99 if ((sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
101 fprintf(stderr
, "ERROR: %s Unable to open broadcast socket: %s\n", prefix
,
107 * Set the "broadcast" flag...
111 if (setsockopt(sock
, SOL_SOCKET
, SO_BROADCAST
, &val
, sizeof(val
)))
113 fprintf(stderr
, "ERROR: %s Unable to put socket in broadcast mode: %s\n",
114 prefix
, strerror(errno
));
121 * Open a connection to the server...
124 while ((http
= httpConnectEncrypt(argv
[1], atoi(argv
[2]),
125 cupsEncryption())) == NULL
)
127 fprintf(stderr
, "ERROR: %s Unable to connect to %s on port %s: %s\n",
128 prefix
, argv
[1], argv
[2],
129 h_errno
? hstrerror(h_errno
) : strerror(errno
));
134 * Loop forever, asking for available printers and classes...
137 language
= cupsLangDefault();
142 * Get the printers, then the classes...
147 if ((seconds
= poll_server(http
, language
, CUPS_GET_PRINTERS
, sock
, port
,
148 interval
, prefix
)) > 0)
152 * Sleep for any remaining time...
162 * 'poll_server()' - Poll the server for the given set of printers or classes.
165 int /* O - Number of seconds or -1 on error */
166 poll_server(http_t
*http
, /* I - HTTP connection */
167 cups_lang_t
*language
, /* I - Language */
168 ipp_op_t op
, /* I - Operation code */
169 int sock
, /* I - Broadcast sock */
170 int port
, /* I - Broadcast port */
171 int interval
, /* I - Polling interval */
172 const char *prefix
) /* I - Prefix for log messages */
174 int seconds
; /* Number of seconds */
175 int count
, /* Current number of printers/classes */
176 max_count
; /* Maximum printers/classes per second */
177 ipp_t
*request
, /* Request data */
178 *response
; /* Response data */
179 ipp_attribute_t
*attr
; /* Current attribute */
180 const char *uri
, /* printer-uri */
181 *info
, /* printer-info */
182 *location
, /* printer-location */
183 *make_model
; /* printer-make-and-model */
184 cups_ptype_t type
; /* printer-type */
185 ipp_pstate_t state
; /* printer-state */
186 int accepting
; /* printer-is-accepting-jobs */
187 struct sockaddr_in addr
; /* Broadcast address */
188 char packet
[1540]; /* Data packet */
189 static const char * const attrs
[] = /* Requested attributes */
192 "printer-is-accepting-jobs",
194 "printer-make-and-model",
198 "printer-uri-supported"
203 * Broadcast to 127.0.0.1 (localhost)
206 memset(&addr
, 0, sizeof(addr
));
207 addr
.sin_addr
.s_addr
= htonl(0x7f000001);
208 addr
.sin_family
= AF_INET
;
209 addr
.sin_port
= htons(port
);
212 * Build a CUPS_GET_PRINTERS or CUPS_GET_CLASSES request, which requires
213 * only the attributes-charset and attributes-natural-language attributes.
218 request
->request
.op
.operation_id
= op
;
219 request
->request
.op
.request_id
= 1;
221 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
222 "attributes-charset", NULL
, cupsLangEncoding(language
));
224 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
225 "attributes-natural-language", NULL
, language
->language
);
227 ippAddStrings(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
228 "requested-attributes", sizeof(attrs
) / sizeof(attrs
[0]),
231 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_ENUM
,
233 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_ENUM
,
235 CUPS_PRINTER_REMOTE
| CUPS_PRINTER_IMPLICIT
|
236 CUPS_PRINTER_NOT_SHARED
);
239 * Do the request and get back a response...
242 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
244 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
246 fprintf(stderr
, "ERROR: %s get-%s failed: %s\n", prefix
,
247 op
== CUPS_GET_PRINTERS
? "printers" : "classes",
248 ippErrorString(response
->request
.status
.status_code
));
254 * Figure out how many printers/classes we have...
257 for (attr
= ippFindAttribute(response
, "printer-name", IPP_TAG_NAME
),
260 attr
= ippFindNextAttribute(response
, "printer-name", IPP_TAG_NAME
),
263 fprintf(stderr
, "DEBUG: %s found %d %s.\n", prefix
, max_count
,
264 op
== CUPS_GET_PRINTERS
? "printers" : "classes");
267 seconds
= time(NULL
);
268 max_count
= max_count
/ interval
+ 1;
271 * Loop through the printers or classes returned in the list...
274 for (attr
= response
->attrs
; attr
!= NULL
; attr
= attr
->next
)
277 * Skip leading attributes until we hit a printer...
280 while (attr
!= NULL
&& attr
->group_tag
!= IPP_TAG_PRINTER
)
287 * Pull the needed attributes from this printer...
294 type
= CUPS_PRINTER_REMOTE
;
296 state
= IPP_PRINTER_IDLE
;
298 while (attr
!= NULL
&& attr
->group_tag
== IPP_TAG_PRINTER
)
300 if (strcmp(attr
->name
, "printer-uri-supported") == 0 &&
301 attr
->value_tag
== IPP_TAG_URI
)
302 uri
= attr
->values
[0].string
.text
;
304 if (strcmp(attr
->name
, "printer-info") == 0 &&
305 attr
->value_tag
== IPP_TAG_TEXT
)
306 info
= attr
->values
[0].string
.text
;
308 if (strcmp(attr
->name
, "printer-is-accepting-jobs") == 0 &&
309 attr
->value_tag
== IPP_TAG_BOOLEAN
)
310 accepting
= attr
->values
[0].boolean
;
312 if (strcmp(attr
->name
, "printer-location") == 0 &&
313 attr
->value_tag
== IPP_TAG_TEXT
)
314 location
= attr
->values
[0].string
.text
;
316 if (strcmp(attr
->name
, "printer-make-and-model") == 0 &&
317 attr
->value_tag
== IPP_TAG_TEXT
)
318 make_model
= attr
->values
[0].string
.text
;
320 if (strcmp(attr
->name
, "printer-state") == 0 &&
321 attr
->value_tag
== IPP_TAG_ENUM
)
322 state
= (ipp_pstate_t
)attr
->values
[0].integer
;
324 if (strcmp(attr
->name
, "printer-type") == 0 &&
325 attr
->value_tag
== IPP_TAG_ENUM
)
326 type
= (cups_ptype_t
)attr
->values
[0].integer
;
332 * See if we have everything needed...
344 * Send the printer information...
347 type
|= CUPS_PRINTER_REMOTE
;
350 type
|= CUPS_PRINTER_REJECTING
;
352 snprintf(packet
, sizeof(packet
), "%x %x %s \"%s\" \"%s\" \"%s\"\n",
353 type
, state
, uri
, location
, info
, make_model
);
355 fprintf(stderr
, "DEBUG2: %s Sending %s", prefix
, packet
);
357 if (sendto(sock
, packet
, strlen(packet
), 0,
358 (struct sockaddr
*)&addr
, sizeof(addr
)) <= 0)
361 perror("cups-polld");
366 * Throttle the local broadcasts as needed so that we don't
367 * overwhelm the local server...
371 if (count
>= max_count
)
374 * Sleep for a second...
389 fprintf(stderr
, "ERROR: %s get-%s failed: %s\n", prefix
,
390 op
== CUPS_GET_PRINTERS
? "printers" : "classes",
391 ippErrorString(cupsLastError()));
396 * Return the number of seconds we used...
399 return (time(NULL
) - seconds
);
404 * End of "$Id: cups-polld.c 4638 2005-09-15 14:13:19Z mike $".