]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/cups-polld.c
2 * "$Id: cups-polld.c 5753 2006-07-18 19:53:24Z mike $"
4 * Polling daemon for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 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 * dequote() - Remote quotes from a string.
28 * poll_server() - Poll the server for the given set of printers or classes.
32 * Include necessary headers...
35 #include <cups/http-private.h>
36 #include <cups/cups.h>
39 #include <cups/language.h>
40 #include <cups/string.h>
47 static char *dequote(char *d
, const char *s
, int dlen
);
48 static int poll_server(http_t
*http
, int sock
, int port
, int interval
,
53 * 'main()' - Open sockets and poll until we are killed...
56 int /* O - Exit status */
57 main(int argc
, /* I - Number of command-line args */
58 char *argv
[]) /* I - Command-line arguments */
60 http_t
*http
; /* HTTP connection */
61 int interval
; /* Polling interval */
62 int sock
; /* Browser sock */
63 int port
; /* Browser port */
64 int val
; /* Socket option value */
65 int seconds
, /* Seconds left from poll */
66 remain
; /* Total remaining time to sleep */
67 char prefix
[1024]; /* Prefix for log messages */
71 * Don't buffer log messages...
77 * The command-line must contain the following:
79 * cups-polld server server-port interval port
84 fputs("Usage: cups-polld server server-port interval port\n", stderr
);
88 interval
= atoi(argv
[3]);
94 snprintf(prefix
, sizeof(prefix
), "[cups-polld %s:%d]", argv
[1], atoi(argv
[2]));
97 * Open a broadcast socket...
100 if ((sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
102 fprintf(stderr
, "ERROR: %s Unable to open broadcast socket: %s\n", prefix
,
108 * Set the "broadcast" flag...
112 if (setsockopt(sock
, SOL_SOCKET
, SO_BROADCAST
, &val
, sizeof(val
)))
114 fprintf(stderr
, "ERROR: %s Unable to put socket in broadcast mode: %s\n",
115 prefix
, strerror(errno
));
122 * Open a connection to the server...
125 while ((http
= httpConnectEncrypt(argv
[1], atoi(argv
[2]),
126 cupsEncryption())) == NULL
)
128 fprintf(stderr
, "ERROR: %s Unable to connect to %s on port %s: %s\n",
129 prefix
, argv
[1], argv
[2],
130 h_errno
? hstrerror(h_errno
) : strerror(errno
));
135 * Loop forever, asking for available printers and classes...
141 * Get the printers and classes...
146 if ((seconds
= poll_server(http
, sock
, port
, interval
, prefix
)) > 0)
150 * Sleep for any remaining time...
160 * 'dequote()' - Remote quotes from a string.
163 static char * /* O - Dequoted string */
164 dequote(char *d
, /* I - Destination string */
165 const char *s
, /* I - Source string */
166 int dlen
) /* I - Destination length */
168 char *dptr
; /* Pointer into destination */
173 for (dptr
= d
, dlen
--; *s
&& dlen
> 0; s
++)
190 * 'poll_server()' - Poll the server for the given set of printers or classes.
193 static int /* O - Number of seconds or -1 on error */
194 poll_server(http_t
*http
, /* I - HTTP connection */
195 int sock
, /* I - Broadcast sock */
196 int port
, /* I - Broadcast port */
197 int interval
, /* I - Polling interval */
198 const char *prefix
) /* I - Prefix for log messages */
200 int seconds
; /* Number of seconds */
201 int count
, /* Current number of printers/classes */
202 max_count
; /* Maximum printers/classes per second */
203 ipp_t
*request
, /* Request data */
204 *response
; /* Response data */
205 ipp_attribute_t
*attr
; /* Current attribute */
206 const char *uri
; /* printer-uri */
207 char info
[1024], /* printer-info */
208 job_sheets
[1024],/* job-sheets-default */
209 location
[1024], /* printer-location */
211 /* printer-make-and-model */
212 cups_ptype_t type
; /* printer-type */
213 ipp_pstate_t state
; /* printer-state */
214 int accepting
; /* printer-is-accepting-jobs */
215 struct sockaddr_in addr
; /* Broadcast address */
216 char packet
[1540]; /* Data packet */
217 static const char * const attrs
[] = /* Requested attributes */
219 "job-sheets-default",
221 "printer-is-accepting-jobs",
223 "printer-make-and-model",
227 "printer-uri-supported"
232 * Broadcast to 127.0.0.1 (localhost)
235 memset(&addr
, 0, sizeof(addr
));
236 addr
.sin_addr
.s_addr
= htonl(0x7f000001);
237 addr
.sin_family
= AF_INET
;
238 addr
.sin_port
= htons(port
);
241 * Build a CUPS_GET_PRINTERS request and pass along a list of the
242 * attributes we are interested in along with the types of printers
243 * (and classes) we want.
246 request
= ippNewRequest(CUPS_GET_PRINTERS
);
248 ippAddStrings(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
249 "requested-attributes", sizeof(attrs
) / sizeof(attrs
[0]),
252 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_ENUM
,
254 ippAddInteger(request
, IPP_TAG_OPERATION
, IPP_TAG_ENUM
,
256 CUPS_PRINTER_REMOTE
| CUPS_PRINTER_IMPLICIT
|
257 CUPS_PRINTER_NOT_SHARED
);
260 * Do the request and get back a response...
263 response
= cupsDoRequest(http
, request
, "/");
265 if (cupsLastError() > IPP_OK_CONFLICT
)
267 fprintf(stderr
, "ERROR: %s CUPS-Get-Printers failed: %s\n", prefix
,
268 cupsLastErrorString());
276 * Figure out how many printers/classes we have...
279 for (attr
= ippFindAttribute(response
, "printer-name", IPP_TAG_NAME
),
282 attr
= ippFindNextAttribute(response
, "printer-name", IPP_TAG_NAME
),
285 fprintf(stderr
, "DEBUG: %s Found %d printers.\n", prefix
, max_count
);
288 seconds
= time(NULL
);
289 max_count
= max_count
/ interval
+ 1;
292 * Loop through the printers or classes returned in the list...
295 for (attr
= response
->attrs
; attr
; attr
= attr
->next
)
298 * Skip leading attributes until we hit a printer...
301 while (attr
&& attr
->group_tag
!= IPP_TAG_PRINTER
)
308 * Pull the needed attributes from this printer...
313 job_sheets
[0] = '\0';
315 make_model
[0] = '\0';
316 type
= CUPS_PRINTER_REMOTE
;
318 state
= IPP_PRINTER_IDLE
;
320 while (attr
!= NULL
&& attr
->group_tag
== IPP_TAG_PRINTER
)
322 if (!strcmp(attr
->name
, "job-sheets-default") &&
323 (attr
->value_tag
== IPP_TAG_NAME
||
324 attr
->value_tag
== IPP_TAG_KEYWORD
))
326 if (attr
->num_values
== 1)
327 snprintf(job_sheets
, sizeof(job_sheets
), " job-sheets=%s",
328 attr
->values
[0].string
.text
);
330 snprintf(job_sheets
, sizeof(job_sheets
), " job-sheets=%s,%s",
331 attr
->values
[0].string
.text
,
332 attr
->values
[1].string
.text
);
334 else if (!strcmp(attr
->name
, "printer-uri-supported") &&
335 attr
->value_tag
== IPP_TAG_URI
)
336 uri
= attr
->values
[0].string
.text
;
337 else if (!strcmp(attr
->name
, "printer-info") &&
338 attr
->value_tag
== IPP_TAG_TEXT
)
339 dequote(info
, attr
->values
[0].string
.text
, sizeof(info
));
340 else if (!strcmp(attr
->name
, "printer-is-accepting-jobs") &&
341 attr
->value_tag
== IPP_TAG_BOOLEAN
)
342 accepting
= attr
->values
[0].boolean
;
343 else if (!strcmp(attr
->name
, "printer-location") &&
344 attr
->value_tag
== IPP_TAG_TEXT
)
345 dequote(location
, attr
->values
[0].string
.text
, sizeof(location
));
346 else if (!strcmp(attr
->name
, "printer-make-and-model") &&
347 attr
->value_tag
== IPP_TAG_TEXT
)
348 dequote(make_model
, attr
->values
[0].string
.text
, sizeof(location
));
349 else if (!strcmp(attr
->name
, "printer-state") &&
350 attr
->value_tag
== IPP_TAG_ENUM
)
351 state
= (ipp_pstate_t
)attr
->values
[0].integer
;
352 else if (!strcmp(attr
->name
, "printer-type") &&
353 attr
->value_tag
== IPP_TAG_ENUM
)
354 type
= (cups_ptype_t
)attr
->values
[0].integer
;
360 * See if we have everything needed...
372 * Send the printer information...
375 type
|= CUPS_PRINTER_REMOTE
;
378 type
|= CUPS_PRINTER_REJECTING
;
380 snprintf(packet
, sizeof(packet
),
381 "%x %x %s \"%s\" \"%s\" \"%s\" lease-duration=%d%s\n",
382 type
, state
, uri
, location
, info
, make_model
, interval
* 2,
385 fprintf(stderr
, "DEBUG2: %s Sending %s", prefix
, packet
);
387 if (sendto(sock
, packet
, strlen(packet
), 0,
388 (struct sockaddr
*)&addr
, sizeof(addr
)) <= 0)
391 perror("cups-polld");
396 * Throttle the local broadcasts as needed so that we don't
397 * overwhelm the local server...
401 if (count
>= max_count
)
404 * Sleep for a second...
420 * Return the number of seconds we used...
423 return (time(NULL
) - seconds
);
428 * End of "$Id: cups-polld.c 5753 2006-07-18 19:53:24Z mike $".