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