]> git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/cups-polld.c
Merge changes from 1.1 tree.
[thirdparty/cups.git] / scheduler / cups-polld.c
1 /*
2 * "$Id: cups-polld.c,v 1.5.2.1 2001/05/13 18:38:35 mike Exp $"
3 *
4 * Polling daemon for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2001 by Easy Software Products, all rights reserved.
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-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 */
27
28 /*
29 * Include necessary headers...
30 */
31
32 #include <cups/cups.h>
33 #include <stdlib.h>
34 #include <cups/language.h>
35 #include <cups/string.h>
36
37
38 /*
39 * Local functions...
40 */
41
42 int poll_server(http_t *http, cups_lang_t *language, ipp_op_t op,
43 int sock, int port);
44
45
46 /*
47 * 'main()' - Open socks and poll until we are killed...
48 */
49
50 int /* O - Exit status */
51 main(int argc, /* I - Number of command-line arguments */
52 char *argv[]) /* I - Command-line arguments */
53 {
54 http_t *http; /* HTTP connection */
55 cups_lang_t *language; /* Language info */
56 int interval; /* Polling interval */
57 int sock; /* Browser sock */
58 int port; /* Browser port */
59 int val; /* Socket option value */
60
61
62 /*
63 * The command-line must contain the following:
64 *
65 * cups-polld server server-port interval port
66 */
67
68 if (argc != 5)
69 {
70 fputs("Usage: cups-polld server server-port interval port\n", stderr);
71 return (1);
72 }
73
74 interval = atoi(argv[3]);
75 port = atoi(argv[4]);
76
77 /*
78 * Open a connection to the server...
79 */
80
81 if ((http = httpConnectEncrypt(argv[1], atoi(argv[2]),
82 cupsEncryption())) == NULL)
83 {
84 perror("cups-polld");
85 return (1);
86 }
87
88 /*
89 * Open a broadcast sock...
90 */
91
92 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
93 {
94 perror("cups-polld");
95 httpClose(http);
96 return (1);
97 }
98
99 /*
100 * Set the "broadcast" flag...
101 */
102
103 val = 1;
104 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
105 {
106 perror("cups-polld");
107
108 close(sock);
109 httpClose(http);
110 return (1);
111 }
112
113 /*
114 * Loop forever, asking for available printers and classes...
115 */
116
117 language = cupsLangDefault();
118
119 for (;;)
120 {
121 if (poll_server(http, language, CUPS_GET_PRINTERS, sock, port))
122 continue;
123
124 if (poll_server(http, language, CUPS_GET_CLASSES, sock, port))
125 continue;
126
127 sleep(interval);
128 }
129 }
130
131
132 /*
133 * 'poll_server()' - Poll the server for the given set of printers or classes.
134 */
135
136 int /* O - 0 for success, -1 on error */
137 poll_server(http_t *http, /* I - HTTP connection */
138 cups_lang_t *language, /* I - Language */
139 ipp_op_t op, /* I - Operation code */
140 int sock, /* I - Broadcast sock */
141 int port) /* I - Broadcast port */
142 {
143 ipp_t *request, /* Request data */
144 *response; /* Response data */
145 ipp_attribute_t *attr; /* Current attribute */
146 const char *uri, /* printer-uri */
147 *info, /* printer-info */
148 *location, /* printer-location */
149 *make_model; /* printer-make-and-model */
150 cups_ptype_t type; /* printer-type */
151 ipp_pstate_t state; /* printer-state */
152 struct sockaddr_in addr; /* Broadcast address */
153 char packet[1540]; /* Data packet */
154
155
156 /*
157 * Broadcast to 127.0.0.1 (localhost)
158 */
159
160 memset(&addr, 0, sizeof(addr));
161 addr.sin_addr.s_addr = htonl(0x7f000001);
162 addr.sin_family = AF_INET;
163 addr.sin_port = htons(port);
164
165 /*
166 * Build a CUPS_GET_PRINTERS or CUPS_GET_CLASSES request, which requires
167 * only the attributes-charset and attributes-natural-language attributes.
168 */
169
170 request = ippNew();
171
172 request->request.op.operation_id = op;
173 request->request.op.request_id = 1;
174
175 language = cupsLangDefault();
176
177 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
178 "attributes-charset", NULL, cupsLangEncoding(language));
179
180 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
181 "attributes-natural-language", NULL, language->language);
182
183 /*
184 * Do the request and get back a response...
185 */
186
187 if ((response = cupsDoRequest(http, request, "/")) != NULL)
188 {
189 if (response->request.status.status_code > IPP_OK_CONFLICT)
190 {
191 fprintf(stderr, "cups-polld: get-%s failed: %s\n",
192 op == CUPS_GET_PRINTERS ? "printers" : "classes",
193 ippErrorString(response->request.status.status_code));
194 ippDelete(response);
195 return (-1);
196 }
197
198 /*
199 * Loop through the printers or classes returned in the list...
200 */
201
202 for (attr = response->attrs; attr != NULL; attr = attr->next)
203 {
204 /*
205 * Skip leading attributes until we hit a printer...
206 */
207
208 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
209 attr = attr->next;
210
211 if (attr == NULL)
212 break;
213
214 /*
215 * Pull the needed attributes from this printer...
216 */
217
218 uri = NULL;
219 info = "";
220 location = "";
221 make_model = "";
222 type = CUPS_PRINTER_REMOTE;
223 state = IPP_PRINTER_IDLE;
224
225 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
226 {
227 if (strcmp(attr->name, "printer-uri-supported") == 0 &&
228 attr->value_tag == IPP_TAG_URI)
229 uri = attr->values[0].string.text;
230
231 if (strcmp(attr->name, "printer-info") == 0 &&
232 attr->value_tag == IPP_TAG_TEXT)
233 info = attr->values[0].string.text;
234
235 if (strcmp(attr->name, "printer-location") == 0 &&
236 attr->value_tag == IPP_TAG_TEXT)
237 location = attr->values[0].string.text;
238
239 if (strcmp(attr->name, "printer-make-and-model") == 0 &&
240 attr->value_tag == IPP_TAG_TEXT)
241 make_model = attr->values[0].string.text;
242
243 if (strcmp(attr->name, "printer-state") == 0 &&
244 attr->value_tag == IPP_TAG_ENUM)
245 state = (ipp_pstate_t)attr->values[0].integer;
246
247 if (strcmp(attr->name, "printer-type") == 0 &&
248 attr->value_tag == IPP_TAG_ENUM)
249 type = (cups_ptype_t)attr->values[0].integer;
250
251 attr = attr->next;
252 }
253
254 /*
255 * See if we have everything needed...
256 */
257
258 if (uri == NULL)
259 {
260 if (attr == NULL)
261 break;
262 else
263 continue;
264 }
265
266 /*
267 * See if this is a local printer or class...
268 */
269
270 if (!(type & CUPS_PRINTER_REMOTE))
271 {
272 /*
273 * Send the printer information...
274 */
275
276 snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"\n",
277 type | CUPS_PRINTER_REMOTE, state, uri,
278 location, info, make_model);
279 puts(packet);
280
281 if (sendto(sock, packet, strlen(packet), 0,
282 (struct sockaddr *)&addr, sizeof(addr)) <= 0)
283 {
284 perror("cups-polld");
285 return (-1);
286 }
287 }
288
289 if (attr == NULL)
290 break;
291 }
292
293 ippDelete(response);
294 }
295 else
296 {
297 fprintf(stderr, "cups-polld: get-%s failed: %s\n",
298 op == CUPS_GET_PRINTERS ? "printers" : "classes",
299 ippErrorString(cupsLastError()));
300 return (-1);
301 }
302
303 return (0);
304 }
305
306
307 /*
308 * End of "$Id: cups-polld.c,v 1.5.2.1 2001/05/13 18:38:35 mike Exp $".
309 */