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