]>
Commit | Line | Data |
---|---|---|
a129ddbd | 1 | /* |
5374d18c | 2 | * "$Id: dirsvc.c,v 1.53 2000/04/19 15:18:55 mike Exp $" |
a129ddbd | 3 | * |
d6de4648 | 4 | * Directory services routines for the Common UNIX Printing System (CUPS). |
a129ddbd | 5 | * |
71fe22b7 | 6 | * Copyright 1997-2000 by Easy Software Products, all rights reserved. |
a129ddbd | 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 | |
8784b6a6 | 17 | * 44141 Airport View Drive, Suite 204 |
a129ddbd | 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 | * | |
cbbfcc63 | 26 | * StartBrowsing() - Start sending and receiving broadcast information. |
27 | * StopBrowsing() - Stop sending and receiving broadcast information. | |
28 | * UpdateBrowseList() - Update the browse lists for any new browse data. | |
29 | * SendBrowseList() - Send new browsing information. | |
03081fd2 | 30 | * StartPolling() - Start polling servers as needed. |
31 | * StopPolling() - Stop polling servers as needed. | |
a129ddbd | 32 | */ |
33 | ||
34 | /* | |
35 | * Include necessary headers... | |
36 | */ | |
37 | ||
fd8b1cf8 | 38 | #include "cupsd.h" |
39 | ||
40 | ||
d6de4648 | 41 | /* |
42 | * 'StartBrowsing()' - Start sending and receiving broadcast information. | |
43 | */ | |
44 | ||
fd8b1cf8 | 45 | void |
46 | StartBrowsing(void) | |
47 | { | |
d6de4648 | 48 | int val; /* Socket option value */ |
49 | struct sockaddr_in addr; /* Broadcast address */ | |
50 | ||
51 | ||
8828fd5f | 52 | if (!Browsing) |
d6de4648 | 53 | return; |
54 | ||
55 | /* | |
56 | * Create the broadcast socket... | |
57 | */ | |
58 | ||
900b10ea | 59 | if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) |
d6de4648 | 60 | { |
5ea8888e | 61 | LogMessage(L_ERROR, "StartBrowsing: Unable to create broadcast socket - %s.", |
d6de4648 | 62 | strerror(errno)); |
63 | return; | |
64 | } | |
65 | ||
66 | /* | |
900b10ea | 67 | * Set the "broadcast" flag... |
d6de4648 | 68 | */ |
69 | ||
70 | val = 1; | |
e9e40963 | 71 | if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val))) |
fd3ece61 | 72 | { |
5ea8888e | 73 | LogMessage(L_ERROR, "StartBrowsing: Unable to set broadcast mode - %s.", |
fd3ece61 | 74 | strerror(errno)); |
75 | ||
76 | #if defined(WIN32) || defined(__EMX__) | |
77 | closesocket(BrowseSocket); | |
78 | #else | |
79 | close(BrowseSocket); | |
80 | #endif /* WIN32 || __EMX__ */ | |
81 | ||
82 | BrowseSocket = -1; | |
83 | return; | |
84 | } | |
d6de4648 | 85 | |
d6de4648 | 86 | /* |
87 | * Bind the socket to browse port... | |
88 | */ | |
89 | ||
d6de4648 | 90 | memset(&addr, 0, sizeof(addr)); |
91 | addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
92 | addr.sin_family = AF_INET; | |
93 | addr.sin_port = htons(BrowsePort); | |
94 | ||
16b0a852 | 95 | if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr))) |
d6de4648 | 96 | { |
5ea8888e | 97 | LogMessage(L_ERROR, "StartBrowsing: Unable to bind broadcast socket - %s.", |
d6de4648 | 98 | strerror(errno)); |
99 | ||
100 | #if defined(WIN32) || defined(__EMX__) | |
101 | closesocket(BrowseSocket); | |
102 | #else | |
103 | close(BrowseSocket); | |
104 | #endif /* WIN32 || __EMX__ */ | |
105 | ||
106 | BrowseSocket = -1; | |
107 | return; | |
108 | } | |
109 | ||
110 | /* | |
111 | * Finally, add the socket to the input selection set... | |
112 | */ | |
113 | ||
114 | FD_SET(BrowseSocket, &InputSet); | |
fd8b1cf8 | 115 | } |
116 | ||
117 | ||
d6de4648 | 118 | /* |
119 | * 'StopBrowsing()' - Stop sending and receiving broadcast information. | |
120 | */ | |
121 | ||
fd8b1cf8 | 122 | void |
123 | StopBrowsing(void) | |
124 | { | |
8828fd5f | 125 | if (!Browsing) |
d6de4648 | 126 | return; |
127 | ||
128 | /* | |
129 | * Close the socket and remove it from the input selection set. | |
130 | */ | |
131 | ||
3c7bb4a2 | 132 | if (BrowseSocket >= 0) |
133 | { | |
d6de4648 | 134 | #if defined(WIN32) || defined(__EMX__) |
3c7bb4a2 | 135 | closesocket(BrowseSocket); |
d6de4648 | 136 | #else |
3c7bb4a2 | 137 | close(BrowseSocket); |
d6de4648 | 138 | #endif /* WIN32 || __EMX__ */ |
139 | ||
3c7bb4a2 | 140 | FD_CLR(BrowseSocket, &InputSet); |
f63a2256 | 141 | BrowseSocket = 0; |
3c7bb4a2 | 142 | } |
fd8b1cf8 | 143 | } |
144 | ||
145 | ||
d6de4648 | 146 | /* |
147 | * 'UpdateBrowseList()' - Update the browse lists for any new browse data. | |
148 | */ | |
149 | ||
fd8b1cf8 | 150 | void |
151 | UpdateBrowseList(void) | |
152 | { | |
8b43895a | 153 | int i; /* Looping var */ |
e5ebb675 | 154 | int auth; /* Authorization status */ |
eef5ad1b | 155 | int len, /* Length of name string */ |
156 | offset; /* Offset in name string */ | |
d6de4648 | 157 | int bytes; /* Number of bytes left */ |
158 | char packet[1540]; /* Broadcast packet */ | |
e5ebb675 | 159 | struct sockaddr_in srcaddr; /* Source address */ |
160 | char srcname[1024]; /* Source hostname */ | |
161 | unsigned address; /* Source address (host order) */ | |
162 | struct hostent *srchost; /* Host entry for source address */ | |
d6de4648 | 163 | cups_ptype_t type; /* Printer type */ |
164 | ipp_pstate_t state; /* Printer state */ | |
165 | char uri[HTTP_MAX_URI], /* Printer URI */ | |
166 | method[HTTP_MAX_URI], /* Method portion of URI */ | |
167 | username[HTTP_MAX_URI], /* Username portion of URI */ | |
168 | host[HTTP_MAX_URI], /* Host portion of URI */ | |
a2c6b8b1 | 169 | resource[HTTP_MAX_URI], /* Resource portion of URI */ |
170 | info[IPP_MAX_NAME], /* Information string */ | |
171 | location[IPP_MAX_NAME], /* Location string */ | |
172 | make_model[IPP_MAX_NAME];/* Make and model string */ | |
d6de4648 | 173 | int port; /* Port portion of URI */ |
174 | char name[IPP_MAX_NAME], /* Name of printer */ | |
8b43895a | 175 | *hptr, /* Pointer into hostname */ |
176 | *sptr; /* Pointer into ServerName */ | |
177 | printer_t *p, /* Printer information */ | |
178 | *pclass, /* Printer class */ | |
179 | *first; /* First printer in class */ | |
d6de4648 | 180 | |
181 | ||
182 | /* | |
183 | * Read a packet from the browse socket... | |
184 | */ | |
185 | ||
e5ebb675 | 186 | len = sizeof(srcaddr); |
16b0a852 | 187 | if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet), 0, |
e5ebb675 | 188 | (struct sockaddr *)&srcaddr, &len)) <= 0) |
18d7d592 | 189 | { |
5ea8888e | 190 | LogMessage(L_ERROR, "Browse recv failed - %s.", |
18d7d592 | 191 | strerror(errno)); |
5ea8888e | 192 | LogMessage(L_ERROR, "Browsing turned off."); |
1a5606a3 | 193 | |
194 | StopBrowsing(); | |
195 | Browsing = 0; | |
18d7d592 | 196 | return; |
197 | } | |
198 | ||
199 | packet[bytes] = '\0'; | |
e5ebb675 | 200 | |
201 | /* | |
202 | * Figure out where it came from... | |
203 | */ | |
204 | ||
205 | address = ntohl(srcaddr.sin_addr.s_addr); | |
206 | ||
207 | if (HostNameLookups) | |
208 | #ifndef __sgi | |
209 | srchost = gethostbyaddr((char *)&(srcaddr.sin_addr), sizeof(struct in_addr), | |
210 | AF_INET); | |
18d7d592 | 211 | #else |
e5ebb675 | 212 | srchost = gethostbyaddr(&(srcaddr.sin_addr), sizeof(struct in_addr), |
213 | AF_INET); | |
214 | #endif /* !__sgi */ | |
215 | else | |
216 | srchost = NULL; | |
217 | ||
218 | if (srchost == NULL) | |
219 | sprintf(srcname, "%d.%d.%d.%d", address >> 24, (address >> 16) & 255, | |
220 | (address >> 8) & 255, address & 255); | |
221 | else | |
f9bacabb | 222 | { |
e5ebb675 | 223 | strncpy(srcname, srchost->h_name, sizeof(srcname) - 1); |
224 | srcname[sizeof(srcname) - 1] = '\0'; | |
225 | } | |
1a5606a3 | 226 | |
e5ebb675 | 227 | len = strlen(srcname); |
228 | ||
229 | /* | |
230 | * Do ACL stuff... | |
231 | */ | |
232 | ||
233 | if (BrowseACL) | |
234 | { | |
235 | if (address == 0x7f000001 || strcasecmp(srcname, "localhost") == 0) | |
236 | { | |
237 | /* | |
238 | * Access from localhost (127.0.0.1) is always allowed... | |
239 | */ | |
240 | ||
241 | auth = AUTH_ALLOW; | |
242 | } | |
243 | else | |
244 | { | |
245 | /* | |
246 | * Do authorization checks on the domain/address... | |
247 | */ | |
248 | ||
d21a7597 | 249 | switch (BrowseACL->order_type) |
e5ebb675 | 250 | { |
d21a7597 | 251 | default : |
252 | auth = AUTH_DENY; /* anti-compiler-warning-code */ | |
253 | break; | |
254 | ||
e5ebb675 | 255 | case AUTH_ALLOW : /* Order Deny,Allow */ |
d21a7597 | 256 | auth = AUTH_ALLOW; |
257 | ||
e5ebb675 | 258 | if (CheckAuth(address, srcname, len, |
259 | BrowseACL->num_deny, BrowseACL->deny)) | |
260 | auth = AUTH_DENY; | |
261 | ||
262 | if (CheckAuth(address, srcname, len, | |
263 | BrowseACL->num_allow, BrowseACL->allow)) | |
264 | auth = AUTH_ALLOW; | |
265 | break; | |
266 | ||
267 | case AUTH_DENY : /* Order Allow,Deny */ | |
d21a7597 | 268 | auth = AUTH_DENY; |
269 | ||
e5ebb675 | 270 | if (CheckAuth(address, srcname, len, |
271 | BrowseACL->num_allow, BrowseACL->allow)) | |
272 | auth = AUTH_ALLOW; | |
273 | ||
274 | if (CheckAuth(address, srcname, len, | |
275 | BrowseACL->num_deny, BrowseACL->deny)) | |
276 | auth = AUTH_DENY; | |
277 | break; | |
278 | } | |
279 | } | |
280 | } | |
281 | else | |
282 | auth = AUTH_ALLOW; | |
283 | ||
284 | if (auth == AUTH_DENY) | |
285 | { | |
286 | LogMessage(L_DEBUG, "UpdateBrowseList: Refused %d bytes from %s", bytes, | |
287 | srcname); | |
d6de4648 | 288 | return; |
f9bacabb | 289 | } |
d6de4648 | 290 | |
e5ebb675 | 291 | LogMessage(L_DEBUG, "UpdateBrowseList: (%d bytes from %s) %s", bytes, srcname, |
292 | packet); | |
293 | ||
294 | /* | |
295 | * Parse packet... | |
296 | */ | |
d6de4648 | 297 | |
a2c6b8b1 | 298 | location[0] = '\0'; |
299 | info[0] = '\0'; | |
300 | make_model[0] = '\0'; | |
301 | ||
302 | if (sscanf(packet, | |
303 | "%x%x%1023s%*[^\"]\"%127[^\"]%*[^\"]\"%127[^\"]%*[^\"]\"%127[^\"]", | |
d21a7597 | 304 | (unsigned *)&type, (unsigned *)&state, uri, location, info, |
305 | make_model) < 3) | |
d6de4648 | 306 | { |
5ea8888e | 307 | LogMessage(L_WARN, "UpdateBrowseList: Garbled browse packet - %s", |
d6de4648 | 308 | packet); |
309 | return; | |
310 | } | |
311 | ||
a2c6b8b1 | 312 | DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n" |
313 | "location=\"%s\", info=\"%s\", make_model=\"%s\"\n", | |
314 | type, state, uri, location, info, make_model)); | |
a8b216d5 | 315 | |
d6de4648 | 316 | /* |
317 | * Pull the URI apart to see if this is a local or remote printer... | |
318 | */ | |
319 | ||
320 | httpSeparate(uri, method, username, host, &port, resource); | |
321 | ||
a8b216d5 | 322 | DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName)); |
323 | ||
d6de4648 | 324 | if (strcasecmp(host, ServerName) == 0) |
325 | return; | |
326 | ||
e5ebb675 | 327 | /* |
328 | * Do relaying... | |
329 | */ | |
330 | ||
331 | for (i = 0; i < NumRelays; i ++) | |
332 | if (CheckAuth(address, srcname, len, 1, &(Relays[i].from))) | |
333 | if (sendto(BrowseSocket, packet, bytes, 0, | |
334 | (struct sockaddr *)&(Relays[i].to), | |
335 | sizeof(struct sockaddr_in)) <= 0) | |
336 | { | |
337 | LogMessage(L_ERROR, "UpdateBrowseList: sendto failed for relay %d - %s.", | |
338 | i + 1, strerror(errno)); | |
339 | return; | |
340 | } | |
341 | ||
d6de4648 | 342 | /* |
343 | * OK, this isn't a local printer; see if we already have it listed in | |
344 | * the Printers list, and add it if not... | |
345 | */ | |
346 | ||
8b43895a | 347 | hptr = strchr(host, '.'); |
348 | sptr = strchr(ServerName, '.'); | |
349 | ||
350 | if (hptr != NULL && sptr != NULL && | |
351 | strcasecmp(hptr, sptr) == 0) | |
352 | *hptr = '\0'; | |
d6de4648 | 353 | |
c7fa9d06 | 354 | if (type & CUPS_PRINTER_CLASS) |
d6de4648 | 355 | { |
356 | /* | |
c7fa9d06 | 357 | * Remote destination is a class... |
d6de4648 | 358 | */ |
359 | ||
c7fa9d06 | 360 | if (strncmp(resource, "/classes/", 9) == 0) |
970017a4 | 361 | snprintf(name, sizeof(name), "%s@%s", resource + 9, host); |
c7fa9d06 | 362 | else |
363 | return; | |
364 | ||
365 | if ((p = FindClass(name)) == NULL) | |
366 | { | |
367 | /* | |
368 | * Class doesn't exist; add it... | |
369 | */ | |
d6de4648 | 370 | |
782359ca | 371 | p = AddClass(name); |
c7fa9d06 | 372 | |
373 | /* | |
782359ca | 374 | * Force the URI to point to the real server... |
c7fa9d06 | 375 | */ |
376 | ||
5057ad3b | 377 | p->type = type; |
c7fa9d06 | 378 | strcpy(p->uri, uri); |
5374d18c | 379 | strcpy(p->more_info, uri); |
c7fa9d06 | 380 | strcpy(p->device_uri, uri); |
67a6c918 | 381 | strcpy(p->hostname, host); |
a2c6b8b1 | 382 | |
383 | strcpy(p->location, "Location Unknown"); | |
384 | strcpy(p->info, "No Information Available"); | |
385 | snprintf(p->make_model, sizeof(p->make_model), "Remote Class on %s", | |
386 | host); | |
387 | ||
5057ad3b | 388 | SetPrinterAttrs(p); |
c7fa9d06 | 389 | } |
390 | } | |
391 | else | |
392 | { | |
d6de4648 | 393 | /* |
c7fa9d06 | 394 | * Remote destination is a printer... |
d6de4648 | 395 | */ |
396 | ||
c7fa9d06 | 397 | if (strncmp(resource, "/printers/", 10) == 0) |
970017a4 | 398 | snprintf(name, sizeof(name), "%s@%s", resource + 10, host); |
c7fa9d06 | 399 | else |
400 | return; | |
401 | ||
402 | if ((p = FindPrinter(name)) == NULL) | |
403 | { | |
404 | /* | |
405 | * Printer doesn't exist; add it... | |
406 | */ | |
407 | ||
408 | p = AddPrinter(name); | |
409 | ||
410 | /* | |
5057ad3b | 411 | * Force the URI to point to the real server... |
c7fa9d06 | 412 | */ |
413 | ||
5057ad3b | 414 | p->type = type; |
c7fa9d06 | 415 | strcpy(p->uri, uri); |
5374d18c | 416 | strcpy(p->more_info, uri); |
c7fa9d06 | 417 | strcpy(p->device_uri, uri); |
67a6c918 | 418 | strcpy(p->hostname, host); |
a2c6b8b1 | 419 | |
420 | strcpy(p->location, "Location Unknown"); | |
421 | strcpy(p->info, "No Information Available"); | |
422 | snprintf(p->make_model, sizeof(p->make_model), "Remote Printer on %s", | |
423 | host); | |
424 | ||
5057ad3b | 425 | SetPrinterAttrs(p); |
c7fa9d06 | 426 | } |
d6de4648 | 427 | } |
428 | ||
429 | /* | |
430 | * Update the state... | |
431 | */ | |
432 | ||
f925c8de | 433 | p->type = type; |
d6de4648 | 434 | p->state = state; |
0948b55b | 435 | p->accepting = state != IPP_PRINTER_STOPPED; |
d6de4648 | 436 | p->browse_time = time(NULL); |
8b43895a | 437 | |
a2c6b8b1 | 438 | if (location[0]) |
439 | strcpy(p->location, location); | |
440 | if (info[0]) | |
441 | strcpy(p->info, info); | |
442 | if (make_model[0]) | |
443 | strcpy(p->make_model, make_model); | |
444 | ||
29a78848 | 445 | /* |
446 | * If the remote printer is idle, check for local jobs that might need to | |
447 | * go to it... | |
448 | */ | |
449 | ||
450 | if (p->state == IPP_PRINTER_IDLE) | |
451 | CheckJobs(); | |
452 | ||
fb00e262 | 453 | /* |
4621b86f | 454 | * See if we have a default printer... If not, make the first printer the |
455 | * default. | |
fb00e262 | 456 | */ |
457 | ||
458 | if (DefaultPrinter == NULL && Printers != NULL) | |
459 | DefaultPrinter = Printers; | |
460 | ||
8b43895a | 461 | /* |
462 | * Do auto-classing if needed... | |
463 | */ | |
464 | ||
465 | if (ImplicitClasses) | |
466 | { | |
467 | /* | |
468 | * Loop through all available printers and create classes as needed... | |
469 | */ | |
470 | ||
d21a7597 | 471 | for (p = Printers, len = 0, offset = 0, first = NULL; |
472 | p != NULL; | |
473 | p = p->next) | |
8b43895a | 474 | { |
475 | /* | |
476 | * Skip classes... | |
477 | */ | |
478 | ||
479 | if (p->type & CUPS_PRINTER_CLASS) | |
480 | { | |
481 | len = 0; | |
482 | continue; | |
483 | } | |
484 | ||
485 | /* | |
486 | * If len == 0, get the length of this printer name up to the "@" | |
487 | * sign (if any). | |
488 | */ | |
489 | ||
490 | if (len > 0 && | |
eef5ad1b | 491 | strncasecmp(p->name, name + offset, len) == 0 && |
8b43895a | 492 | (p->name[len] == '\0' || p->name[len] == '@')) |
493 | { | |
494 | /* | |
495 | * We have more than one printer with the same name; see if | |
496 | * we have a class, and if this printer is a member... | |
497 | */ | |
498 | ||
a2c6b8b1 | 499 | if ((pclass = FindPrinter(name)) == NULL) |
18d7d592 | 500 | { |
4139b718 | 501 | /* |
502 | * Need to add the class... | |
503 | */ | |
504 | ||
a2c6b8b1 | 505 | pclass = AddPrinter(name); |
4139b718 | 506 | pclass->type |= CUPS_PRINTER_IMPLICIT; |
507 | pclass->accepting = 1; | |
508 | pclass->state = IPP_PRINTER_IDLE; | |
509 | ||
510 | SetPrinterAttrs(pclass); | |
20da3efb | 511 | |
512 | DEBUG_printf(("Added new class \"%s\", type = %x\n", name, | |
513 | pclass->type)); | |
18d7d592 | 514 | } |
8b43895a | 515 | |
516 | if (first != NULL) | |
517 | { | |
518 | for (i = 0; i < pclass->num_printers; i ++) | |
519 | if (pclass->printers[i] == first) | |
520 | break; | |
521 | ||
522 | if (i >= pclass->num_printers) | |
523 | AddPrinterToClass(pclass, first); | |
524 | ||
525 | first = NULL; | |
526 | } | |
527 | ||
528 | for (i = 0; i < pclass->num_printers; i ++) | |
529 | if (pclass->printers[i] == p) | |
530 | break; | |
531 | ||
532 | if (i >= pclass->num_printers) | |
533 | AddPrinterToClass(pclass, p); | |
534 | } | |
535 | else | |
536 | { | |
537 | /* | |
538 | * First time around; just get name length and mark it as first | |
539 | * in the list... | |
540 | */ | |
541 | ||
542 | if ((hptr = strchr(p->name, '@')) != NULL) | |
543 | len = hptr - p->name; | |
544 | else | |
545 | len = strlen(p->name); | |
546 | ||
782359ca | 547 | strncpy(name, p->name, len); |
548 | name[len] = '\0'; | |
eef5ad1b | 549 | offset = 0; |
782359ca | 550 | |
a2c6b8b1 | 551 | if ((pclass = FindPrinter(name)) != NULL && |
552 | !(pclass->type & CUPS_PRINTER_IMPLICIT)) | |
782359ca | 553 | { |
554 | /* | |
555 | * Can't use same name as printer; add "Any" to the front of the | |
556 | * name... | |
557 | */ | |
558 | ||
559 | strcpy(name, "Any"); | |
560 | strncpy(name + 3, p->name, len); | |
561 | name[len + 3] = '\0'; | |
eef5ad1b | 562 | offset = 3; |
782359ca | 563 | } |
564 | ||
8b43895a | 565 | first = p; |
566 | } | |
567 | } | |
568 | } | |
fd8b1cf8 | 569 | } |
570 | ||
571 | ||
d6de4648 | 572 | /* |
573 | * 'SendBrowseList()' - Send new browsing information. | |
574 | */ | |
575 | ||
fd8b1cf8 | 576 | void |
577 | SendBrowseList(void) | |
578 | { | |
d6de4648 | 579 | int i; /* Looping var */ |
580 | printer_t *p, /* Current printer */ | |
581 | *np; /* Next printer */ | |
f9d6449d | 582 | time_t ut, /* Minimum update time */ |
583 | to; /* Timeout time */ | |
d6de4648 | 584 | int bytes; /* Length of packet */ |
a2c6b8b1 | 585 | char packet[1453]; |
d6de4648 | 586 | /* Browse data packet */ |
587 | ||
588 | ||
03081fd2 | 589 | if (!Browsing || BrowseInterval == 0) |
f63a2256 | 590 | return; |
591 | ||
d6de4648 | 592 | /* |
593 | * Compute the update time... | |
594 | */ | |
595 | ||
f9d6449d | 596 | ut = time(NULL) - BrowseInterval; |
597 | to = time(NULL) - BrowseTimeout; | |
d6de4648 | 598 | |
599 | /* | |
600 | * Loop through all of the printers and send local updates as needed... | |
601 | */ | |
602 | ||
603 | for (p = Printers; p != NULL; p = np) | |
604 | { | |
605 | np = p->next; | |
606 | ||
607 | if (p->type & CUPS_PRINTER_REMOTE) | |
608 | { | |
609 | /* | |
610 | * See if this printer needs to be timed out... | |
611 | */ | |
612 | ||
f9d6449d | 613 | if (p->browse_time < to) |
e63d9801 | 614 | { |
5ea8888e | 615 | LogMessage(L_INFO, "Remote destination \"%s\" has timed out; deleting it...", |
d62e9bdd | 616 | p->name); |
d6de4648 | 617 | DeletePrinter(p); |
e63d9801 | 618 | } |
d6de4648 | 619 | } |
18d7d592 | 620 | else if (p->browse_time < ut && !(p->type & CUPS_PRINTER_IMPLICIT)) |
d6de4648 | 621 | { |
622 | /* | |
623 | * Need to send an update... | |
624 | */ | |
625 | ||
626 | p->browse_time = time(NULL); | |
627 | ||
a2c6b8b1 | 628 | snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"\n", |
629 | p->type | CUPS_PRINTER_REMOTE, p->state, p->uri, | |
630 | p->location, p->info, p->make_model); | |
631 | ||
d6de4648 | 632 | bytes = strlen(packet); |
8828fd5f | 633 | DEBUG_printf(("SendBrowseList: (%d bytes) %s", bytes, packet)); |
d6de4648 | 634 | |
635 | /* | |
636 | * Send a packet to each browse address... | |
637 | */ | |
638 | ||
639 | for (i = 0; i < NumBrowsers; i ++) | |
16b0a852 | 640 | if (sendto(BrowseSocket, packet, bytes, 0, |
641 | (struct sockaddr *)Browsers + i, sizeof(Browsers[0])) <= 0) | |
f63a2256 | 642 | { |
5ea8888e | 643 | LogMessage(L_ERROR, "SendBrowseList: sendto failed for browser %d - %s.", |
fd3ece61 | 644 | i + 1, strerror(errno)); |
f63a2256 | 645 | LogMessage(L_ERROR, "Browsing turned off."); |
646 | ||
647 | StopBrowsing(); | |
648 | Browsing = 0; | |
649 | return; | |
650 | } | |
d6de4648 | 651 | } |
652 | } | |
fd8b1cf8 | 653 | } |
a129ddbd | 654 | |
655 | ||
656 | /* | |
03081fd2 | 657 | * 'StartPolling()' - Start polling servers as needed. |
658 | */ | |
659 | ||
660 | void | |
661 | StartPolling(void) | |
662 | { | |
e5ebb675 | 663 | int i; /* Looping var */ |
664 | dirsvc_poll_t *poll; /* Current polling server */ | |
665 | int pid; /* New process ID */ | |
666 | char sport[10]; /* Server port */ | |
667 | char bport[10]; /* Browser port */ | |
668 | char interval[10]; /* Poll interval */ | |
669 | ||
670 | ||
671 | sprintf(bport, "%d", BrowsePort); | |
672 | sprintf(interval, "%d", BrowseInterval); | |
673 | ||
674 | for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++) | |
675 | { | |
676 | sprintf(sport, "%d", poll->port); | |
677 | ||
678 | if ((pid = fork()) == 0) | |
679 | { | |
680 | /* | |
681 | * Child... | |
682 | */ | |
683 | ||
684 | setgid(Group); | |
685 | setuid(User); | |
686 | ||
687 | execl(CUPS_SERVERBIN "/daemon/cups-polld", "cups-polld", poll->hostname, | |
688 | sport, interval, bport, NULL); | |
689 | exit(errno); | |
690 | } | |
691 | else if (pid < 0) | |
692 | { | |
693 | LogMessage(L_ERROR, "StartPolling: Unable to fork polling daemon - %s", | |
694 | strerror(errno)); | |
695 | poll->pid = 0; | |
696 | break; | |
697 | } | |
698 | else | |
699 | { | |
700 | poll->pid = pid; | |
701 | LogMessage(L_DEBUG, "StartPolling: Started polling daemon for %s:%d, pid = %d", | |
702 | poll->hostname, poll->port, pid); | |
703 | } | |
704 | } | |
03081fd2 | 705 | } |
706 | ||
707 | ||
708 | /* | |
709 | * 'StopPolling()' - Stop polling servers as needed. | |
710 | */ | |
711 | ||
712 | void | |
713 | StopPolling(void) | |
714 | { | |
e5ebb675 | 715 | int i; /* Looping var */ |
716 | dirsvc_poll_t *poll; /* Current polling server */ | |
717 | ||
718 | ||
719 | for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++) | |
720 | if (poll->pid) | |
721 | kill(poll->pid, SIGTERM); | |
03081fd2 | 722 | } |
723 | ||
724 | ||
725 | /* | |
5374d18c | 726 | * End of "$Id: dirsvc.c,v 1.53 2000/04/19 15:18:55 mike Exp $". |
a129ddbd | 727 | */ |