]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/dirsvc.c
This commit was manufactured by cvs2svn to create branch 'branch-1.2'.
[thirdparty/cups.git] / scheduler / dirsvc.c
CommitLineData
a129ddbd 1/*
b5cb0608 2 * "$Id: dirsvc.c,v 1.73.2.2 2001/05/13 18:38:35 mike Exp $"
a129ddbd 3 *
d6de4648 4 * Directory services routines for the Common UNIX Printing System (CUPS).
a129ddbd 5 *
d2935a0f 6 * Copyright 1997-2001 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"
7a91f14b 39#include <grp.h>
fd8b1cf8 40
41
d6de4648 42/*
43 * 'StartBrowsing()' - Start sending and receiving broadcast information.
44 */
45
fd8b1cf8 46void
47StartBrowsing(void)
48{
d6de4648 49 int val; /* Socket option value */
50 struct sockaddr_in addr; /* Broadcast address */
51
52
8828fd5f 53 if (!Browsing)
d6de4648 54 return;
55
56 /*
57 * Create the broadcast socket...
58 */
59
900b10ea 60 if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
d6de4648 61 {
5ea8888e 62 LogMessage(L_ERROR, "StartBrowsing: Unable to create broadcast socket - %s.",
d6de4648 63 strerror(errno));
58218b2c 64 Browsing = 0;
d6de4648 65 return;
66 }
67
68 /*
900b10ea 69 * Set the "broadcast" flag...
d6de4648 70 */
71
72 val = 1;
e9e40963 73 if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
fd3ece61 74 {
5ea8888e 75 LogMessage(L_ERROR, "StartBrowsing: Unable to set broadcast mode - %s.",
fd3ece61 76 strerror(errno));
77
78#if defined(WIN32) || defined(__EMX__)
79 closesocket(BrowseSocket);
80#else
81 close(BrowseSocket);
82#endif /* WIN32 || __EMX__ */
83
84 BrowseSocket = -1;
58218b2c 85 Browsing = 0;
fd3ece61 86 return;
87 }
d6de4648 88
d6de4648 89 /*
90 * Bind the socket to browse port...
91 */
92
d6de4648 93 memset(&addr, 0, sizeof(addr));
94 addr.sin_addr.s_addr = htonl(INADDR_ANY);
95 addr.sin_family = AF_INET;
96 addr.sin_port = htons(BrowsePort);
97
16b0a852 98 if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr)))
d6de4648 99 {
5ea8888e 100 LogMessage(L_ERROR, "StartBrowsing: Unable to bind broadcast socket - %s.",
d6de4648 101 strerror(errno));
102
103#if defined(WIN32) || defined(__EMX__)
104 closesocket(BrowseSocket);
105#else
106 close(BrowseSocket);
107#endif /* WIN32 || __EMX__ */
108
109 BrowseSocket = -1;
58218b2c 110 Browsing = 0;
d6de4648 111 return;
112 }
113
114 /*
115 * Finally, add the socket to the input selection set...
116 */
117
118 FD_SET(BrowseSocket, &InputSet);
fd8b1cf8 119}
120
121
d6de4648 122/*
123 * 'StopBrowsing()' - Stop sending and receiving broadcast information.
124 */
125
fd8b1cf8 126void
127StopBrowsing(void)
128{
8828fd5f 129 if (!Browsing)
d6de4648 130 return;
131
132 /*
133 * Close the socket and remove it from the input selection set.
134 */
135
3c7bb4a2 136 if (BrowseSocket >= 0)
137 {
d6de4648 138#if defined(WIN32) || defined(__EMX__)
3c7bb4a2 139 closesocket(BrowseSocket);
d6de4648 140#else
3c7bb4a2 141 close(BrowseSocket);
d6de4648 142#endif /* WIN32 || __EMX__ */
143
3c7bb4a2 144 FD_CLR(BrowseSocket, &InputSet);
f63a2256 145 BrowseSocket = 0;
3c7bb4a2 146 }
fd8b1cf8 147}
148
149
d6de4648 150/*
151 * 'UpdateBrowseList()' - Update the browse lists for any new browse data.
152 */
153
fd8b1cf8 154void
155UpdateBrowseList(void)
156{
8b43895a 157 int i; /* Looping var */
20e0a4cb 158 int update; /* Update printer attributes? */
e5ebb675 159 int auth; /* Authorization status */
eef5ad1b 160 int len, /* Length of name string */
161 offset; /* Offset in name string */
d6de4648 162 int bytes; /* Number of bytes left */
20e0a4cb 163 char packet[1540], /* Broadcast packet */
164 *pptr; /* Pointer into packet */
99de6da0 165 http_addr_t srcaddr; /* Source address */
e5ebb675 166 char srcname[1024]; /* Source hostname */
99de6da0 167 unsigned address[4], /* Source address */
168 temp; /* Temporary address var (host order) */
d6de4648 169 cups_ptype_t type; /* Printer type */
170 ipp_pstate_t state; /* Printer state */
171 char uri[HTTP_MAX_URI], /* Printer URI */
172 method[HTTP_MAX_URI], /* Method portion of URI */
173 username[HTTP_MAX_URI], /* Username portion of URI */
174 host[HTTP_MAX_URI], /* Host portion of URI */
a2c6b8b1 175 resource[HTTP_MAX_URI], /* Resource portion of URI */
176 info[IPP_MAX_NAME], /* Information string */
177 location[IPP_MAX_NAME], /* Location string */
178 make_model[IPP_MAX_NAME];/* Make and model string */
d6de4648 179 int port; /* Port portion of URI */
180 char name[IPP_MAX_NAME], /* Name of printer */
8b43895a 181 *hptr, /* Pointer into hostname */
182 *sptr; /* Pointer into ServerName */
183 printer_t *p, /* Printer information */
184 *pclass, /* Printer class */
b5cb0608 185 *first, /* First printer in class */
186 *next; /* Next printer in list */
d6de4648 187
188
189 /*
190 * Read a packet from the browse socket...
191 */
192
e5ebb675 193 len = sizeof(srcaddr);
16b0a852 194 if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet), 0,
e5ebb675 195 (struct sockaddr *)&srcaddr, &len)) <= 0)
18d7d592 196 {
89db771d 197 /*
198 * "Connection refused" is returned under Linux if the destination port
199 * or address is unreachable from a previous sendto(); check for the
200 * error here and ignore it for now...
201 */
202
203 if (errno != ECONNREFUSED)
204 {
205 LogMessage(L_ERROR, "Browse recv failed - %s.", strerror(errno));
206 LogMessage(L_ERROR, "Browsing turned off.");
207
208 StopBrowsing();
209 Browsing = 0;
210 }
1a5606a3 211
18d7d592 212 return;
213 }
214
215 packet[bytes] = '\0';
e5ebb675 216
217 /*
218 * Figure out where it came from...
219 */
220
99de6da0 221#ifdef AF_INET6
222 if (srcaddr.addr.sa_family == AF_INET6)
223 {
224 address[0] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[0]);
225 address[1] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[1]);
226 address[2] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[2]);
227 address[3] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[3]);
228 }
e5ebb675 229 else
99de6da0 230#endif /* AF_INET6 */
f9bacabb 231 {
99de6da0 232 temp = ntohl(srcaddr.ipv4.sin_addr.s_addr);
233
234 address[3] = temp & 255;
235 temp >>= 8;
236 address[2] = temp & 255;
237 temp >>= 8;
238 address[1] = temp & 255;
239 temp >>= 8;
240 address[0] = temp & 255;
e5ebb675 241 }
1a5606a3 242
99de6da0 243 if (HostNameLookups)
244 httpAddrLookup(&srcaddr, srcname, sizeof(srcname));
245 else
246 httpAddrString(&srcaddr, srcname, sizeof(srcname));
247
e5ebb675 248 len = strlen(srcname);
249
250 /*
251 * Do ACL stuff...
252 */
253
254 if (BrowseACL)
255 {
99de6da0 256 if (httpAddrLocalhost(&srcaddr) || strcasecmp(srcname, "localhost") == 0)
e5ebb675 257 {
258 /*
259 * Access from localhost (127.0.0.1) is always allowed...
260 */
261
262 auth = AUTH_ALLOW;
263 }
264 else
265 {
266 /*
267 * Do authorization checks on the domain/address...
268 */
269
d21a7597 270 switch (BrowseACL->order_type)
e5ebb675 271 {
d21a7597 272 default :
273 auth = AUTH_DENY; /* anti-compiler-warning-code */
274 break;
275
e5ebb675 276 case AUTH_ALLOW : /* Order Deny,Allow */
d21a7597 277 auth = AUTH_ALLOW;
278
e5ebb675 279 if (CheckAuth(address, srcname, len,
280 BrowseACL->num_deny, BrowseACL->deny))
281 auth = AUTH_DENY;
282
283 if (CheckAuth(address, srcname, len,
284 BrowseACL->num_allow, BrowseACL->allow))
285 auth = AUTH_ALLOW;
286 break;
287
288 case AUTH_DENY : /* Order Allow,Deny */
d21a7597 289 auth = AUTH_DENY;
290
e5ebb675 291 if (CheckAuth(address, srcname, len,
292 BrowseACL->num_allow, BrowseACL->allow))
293 auth = AUTH_ALLOW;
294
295 if (CheckAuth(address, srcname, len,
296 BrowseACL->num_deny, BrowseACL->deny))
297 auth = AUTH_DENY;
298 break;
299 }
300 }
301 }
302 else
303 auth = AUTH_ALLOW;
304
305 if (auth == AUTH_DENY)
306 {
307 LogMessage(L_DEBUG, "UpdateBrowseList: Refused %d bytes from %s", bytes,
308 srcname);
d6de4648 309 return;
f9bacabb 310 }
d6de4648 311
58e8cf34 312 LogMessage(L_DEBUG2, "UpdateBrowseList: (%d bytes from %s) %s", bytes, srcname,
e5ebb675 313 packet);
314
315 /*
316 * Parse packet...
317 */
d6de4648 318
20e0a4cb 319 update = 0;
a2c6b8b1 320
20e0a4cb 321 if (sscanf(packet, "%x%x%1023s", (unsigned *)&type, (unsigned *)&state,
322 uri) < 3)
d6de4648 323 {
5ea8888e 324 LogMessage(L_WARN, "UpdateBrowseList: Garbled browse packet - %s",
d6de4648 325 packet);
326 return;
327 }
328
20e0a4cb 329 strcpy(location, "Location Unknown");
330 strcpy(info, "No Information Available");
331 make_model[0] = '\0';
332
333 if ((pptr = strchr(packet, '\"')) != NULL)
334 {
335 /*
336 * Have extended information; can't use sscanf for it because not all
337 * sscanf's allow empty strings with %[^\"]...
338 */
339
340 for (i = 0, pptr ++;
341 i < (sizeof(location) - 1) && *pptr && *pptr != '\"';
342 i ++, pptr ++)
343 location[i] = *pptr;
344
345 if (i)
346 location[i] = '\0';
347
348 if (*pptr == '\"')
349 pptr ++;
350
351 while (*pptr && isspace(*pptr))
352 pptr ++;
353
05156f4e 354 if (*pptr == '\"')
355 {
356 for (i = 0, pptr ++;
357 i < (sizeof(info) - 1) && *pptr && *pptr != '\"';
358 i ++, pptr ++)
359 info[i] = *pptr;
20e0a4cb 360
05156f4e 361 if (i)
362 info[i] = '\0';
20e0a4cb 363
05156f4e 364 if (*pptr == '\"')
365 pptr ++;
20e0a4cb 366
05156f4e 367 while (*pptr && isspace(*pptr))
368 pptr ++;
20e0a4cb 369
05156f4e 370 if (*pptr == '\"')
371 {
372 for (i = 0, pptr ++;
373 i < (sizeof(make_model) - 1) && *pptr && *pptr != '\"';
374 i ++, pptr ++)
375 make_model[i] = *pptr;
20e0a4cb 376
05156f4e 377 if (i)
378 make_model[i] = '\0';
379 }
380 }
20e0a4cb 381 }
382
383 DEBUG_puts(packet);
a2c6b8b1 384 DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n"
385 "location=\"%s\", info=\"%s\", make_model=\"%s\"\n",
386 type, state, uri, location, info, make_model));
a8b216d5 387
d6de4648 388 /*
389 * Pull the URI apart to see if this is a local or remote printer...
390 */
391
392 httpSeparate(uri, method, username, host, &port, resource);
393
a8b216d5 394 DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName));
395
d6de4648 396 if (strcasecmp(host, ServerName) == 0)
397 return;
398
e5ebb675 399 /*
400 * Do relaying...
401 */
402
403 for (i = 0; i < NumRelays; i ++)
404 if (CheckAuth(address, srcname, len, 1, &(Relays[i].from)))
405 if (sendto(BrowseSocket, packet, bytes, 0,
406 (struct sockaddr *)&(Relays[i].to),
99de6da0 407 sizeof(http_addr_t)) <= 0)
e5ebb675 408 {
409 LogMessage(L_ERROR, "UpdateBrowseList: sendto failed for relay %d - %s.",
410 i + 1, strerror(errno));
411 return;
412 }
413
d6de4648 414 /*
415 * OK, this isn't a local printer; see if we already have it listed in
416 * the Printers list, and add it if not...
417 */
418
8b43895a 419 hptr = strchr(host, '.');
420 sptr = strchr(ServerName, '.');
421
9fe0309f 422 if (sptr != NULL && hptr != NULL)
423 {
424 /*
425 * Strip the common domain name components...
426 */
427
428 while (hptr != NULL)
429 {
430 if (strcasecmp(hptr, sptr) == 0)
431 {
432 *hptr = '\0';
433 break;
434 }
435 else
436 hptr = strchr(hptr + 1, '.');
437 }
438 }
d6de4648 439
c7fa9d06 440 if (type & CUPS_PRINTER_CLASS)
d6de4648 441 {
442 /*
c7fa9d06 443 * Remote destination is a class...
d6de4648 444 */
445
c7fa9d06 446 if (strncmp(resource, "/classes/", 9) == 0)
04de52f8 447 snprintf(name, sizeof(name), "%s@%s", resource + 9, host);
c7fa9d06 448 else
449 return;
450
d6f1ff9a 451 if ((p = FindClass(name)) == NULL && BrowseShortNames)
0c2ea277 452 {
d6f1ff9a 453 if ((p = FindClass(resource + 9)) != NULL)
454 {
93d2f0c0 455 if (strcasecmp(p->hostname, host) != 0 && p->hostname[0])
d6f1ff9a 456 {
457 /*
458 * Nope, this isn't the same host; if the hostname isn't the local host,
459 * add it to the other class and then find a class using the full host
460 * name...
461 */
462
463 if (p->type & CUPS_PRINTER_REMOTE)
464 {
f4660d94 465 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
93d2f0c0 466 strncat(p->name, "@", sizeof(p->name) - 1);
467 strncat(p->name, p->hostname, sizeof(p->name) - 1);
d6f1ff9a 468 SetPrinterAttrs(p);
469 SortPrinters();
470 }
471
472 p = NULL;
473 }
93d2f0c0 474 else if (!p->hostname[0])
475 {
f4660d94 476 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
93d2f0c0 477 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
478 strncpy(p->uri, uri, sizeof(p->uri) - 1);
479 strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
480 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
481 update = 1;
482 }
d6f1ff9a 483 }
484 else
485 {
486 strncpy(name, resource + 9, sizeof(name) - 1);
487 name[sizeof(name) - 1] = '\0';
488 }
0c2ea277 489 }
93d2f0c0 490 else if (!p->hostname[0])
491 {
f4660d94 492 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
93d2f0c0 493 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
494 strncpy(p->uri, uri, sizeof(p->uri) - 1);
495 strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
496 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
497 update = 1;
498 }
d6f1ff9a 499
500 if (p == NULL)
c7fa9d06 501 {
502 /*
503 * Class doesn't exist; add it...
504 */
d6de4648 505
782359ca 506 p = AddClass(name);
c7fa9d06 507
508 /*
782359ca 509 * Force the URI to point to the real server...
c7fa9d06 510 */
511
5057ad3b 512 p->type = type;
f4660d94 513 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
93d2f0c0 514 strncpy(p->uri, uri, sizeof(p->uri) - 1);
515 strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
516 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
517 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
a2c6b8b1 518
20e0a4cb 519 update = 1;
c7fa9d06 520 }
521 }
522 else
523 {
d6de4648 524 /*
c7fa9d06 525 * Remote destination is a printer...
d6de4648 526 */
527
c7fa9d06 528 if (strncmp(resource, "/printers/", 10) == 0)
04de52f8 529 snprintf(name, sizeof(name), "%s@%s", resource + 10, host);
c7fa9d06 530 else
531 return;
532
d6f1ff9a 533 if ((p = FindPrinter(name)) == NULL && BrowseShortNames)
0c2ea277 534 {
d6f1ff9a 535 if ((p = FindPrinter(resource + 10)) != NULL)
536 {
93d2f0c0 537 if (strcasecmp(p->hostname, host) != 0 && p->hostname[0])
d6f1ff9a 538 {
539 /*
540 * Nope, this isn't the same host; if the hostname isn't the local host,
541 * add it to the other printer and then find a printer using the full host
542 * name...
543 */
544
545 if (p->type & CUPS_PRINTER_REMOTE)
546 {
f4660d94 547 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
93d2f0c0 548 strncat(p->name, "@", sizeof(p->name) - 1);
549 strncat(p->name, p->hostname, sizeof(p->name) - 1);
d6f1ff9a 550 SetPrinterAttrs(p);
551 SortPrinters();
552 }
553
554 p = NULL;
555 }
93d2f0c0 556 else if (!p->hostname[0])
557 {
f4660d94 558 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
93d2f0c0 559 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
560 strncpy(p->uri, uri, sizeof(p->uri) - 1);
561 strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
562 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
563 update = 1;
564 }
d6f1ff9a 565 }
566 else
567 {
568 strncpy(name, resource + 10, sizeof(name) - 1);
569 name[sizeof(name) - 1] = '\0';
570 }
0c2ea277 571 }
93d2f0c0 572 else if (!p->hostname[0])
573 {
f4660d94 574 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
93d2f0c0 575 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
576 strncpy(p->uri, uri, sizeof(p->uri) - 1);
577 strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
578 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
579 update = 1;
580 }
d6f1ff9a 581
582 if (p == NULL)
c7fa9d06 583 {
584 /*
585 * Printer doesn't exist; add it...
586 */
587
588 p = AddPrinter(name);
589
590 /*
5057ad3b 591 * Force the URI to point to the real server...
c7fa9d06 592 */
593
5057ad3b 594 p->type = type;
f4660d94 595 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
93d2f0c0 596 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
597 strncpy(p->uri, uri, sizeof(p->uri) - 1);
598 strncpy(p->more_info, uri, sizeof(p->more_info) - 1);
599 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
a2c6b8b1 600
20e0a4cb 601 update = 1;
c7fa9d06 602 }
d6de4648 603 }
604
605 /*
606 * Update the state...
607 */
608
d6de4648 609 p->state = state;
0948b55b 610 p->accepting = state != IPP_PRINTER_STOPPED;
d6de4648 611 p->browse_time = time(NULL);
8b43895a 612
20e0a4cb 613 if (p->type != type)
614 {
615 p->type = type;
616 update = 1;
617 }
618
a6988fb1 619 if (strcmp(p->location, location))
20e0a4cb 620 {
f4660d94 621 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
622 strncpy(p->location, location, sizeof(p->location) - 1);
20e0a4cb 623 update = 1;
624 }
625
a6988fb1 626 if (strcmp(p->info, info))
20e0a4cb 627 {
f4660d94 628 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
629 strncpy(p->info, info, sizeof(p->info) - 1);
20e0a4cb 630 update = 1;
631 }
632
633 if (!make_model[0])
634 {
635 if (type & CUPS_PRINTER_CLASS)
04de52f8 636 snprintf(make_model, sizeof(p->make_model), "Remote Class on %s",
20e0a4cb 637 host);
638 else
04de52f8 639 snprintf(make_model, sizeof(p->make_model), "Remote Printer on %s",
20e0a4cb 640 host);
641 }
642 else
643 {
644 strncat(make_model, " on ", sizeof(make_model) - 1);
645 strncat(make_model, host, sizeof(make_model) - 1);
646 make_model[sizeof(make_model) - 1] = '\0';
647 }
648
649 if (strcmp(p->make_model, make_model))
650 {
f4660d94 651 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
652 strncpy(p->make_model, make_model, sizeof(p->make_model) - 1);
20e0a4cb 653 update = 1;
654 }
655
656 if (update)
657 SetPrinterAttrs(p);
a2c6b8b1 658
fb00e262 659 /*
4621b86f 660 * See if we have a default printer... If not, make the first printer the
661 * default.
fb00e262 662 */
663
664 if (DefaultPrinter == NULL && Printers != NULL)
665 DefaultPrinter = Printers;
666
8b43895a 667 /*
668 * Do auto-classing if needed...
669 */
670
671 if (ImplicitClasses)
672 {
673 /*
674 * Loop through all available printers and create classes as needed...
675 */
676
d21a7597 677 for (p = Printers, len = 0, offset = 0, first = NULL;
678 p != NULL;
b5cb0608 679 p = next)
8b43895a 680 {
b5cb0608 681 /*
682 * Get next printer in list...
683 */
684
685 next = p->next;
686
8b43895a 687 /*
688 * Skip classes...
689 */
690
49089166 691 if (p->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS))
8b43895a 692 {
693 len = 0;
694 continue;
695 }
696
697 /*
698 * If len == 0, get the length of this printer name up to the "@"
699 * sign (if any).
700 */
701
702 if (len > 0 &&
eef5ad1b 703 strncasecmp(p->name, name + offset, len) == 0 &&
8b43895a 704 (p->name[len] == '\0' || p->name[len] == '@'))
705 {
706 /*
707 * We have more than one printer with the same name; see if
708 * we have a class, and if this printer is a member...
709 */
710
a2c6b8b1 711 if ((pclass = FindPrinter(name)) == NULL)
18d7d592 712 {
4139b718 713 /*
714 * Need to add the class...
715 */
716
a2c6b8b1 717 pclass = AddPrinter(name);
4139b718 718 pclass->type |= CUPS_PRINTER_IMPLICIT;
719 pclass->accepting = 1;
720 pclass->state = IPP_PRINTER_IDLE;
721
722 SetPrinterAttrs(pclass);
20da3efb 723
724 DEBUG_printf(("Added new class \"%s\", type = %x\n", name,
725 pclass->type));
18d7d592 726 }
8b43895a 727
728 if (first != NULL)
729 {
730 for (i = 0; i < pclass->num_printers; i ++)
731 if (pclass->printers[i] == first)
732 break;
733
734 if (i >= pclass->num_printers)
735 AddPrinterToClass(pclass, first);
736
737 first = NULL;
738 }
739
740 for (i = 0; i < pclass->num_printers; i ++)
741 if (pclass->printers[i] == p)
742 break;
743
744 if (i >= pclass->num_printers)
745 AddPrinterToClass(pclass, p);
746 }
747 else
748 {
749 /*
750 * First time around; just get name length and mark it as first
751 * in the list...
752 */
753
754 if ((hptr = strchr(p->name, '@')) != NULL)
755 len = hptr - p->name;
756 else
757 len = strlen(p->name);
758
782359ca 759 strncpy(name, p->name, len);
760 name[len] = '\0';
eef5ad1b 761 offset = 0;
782359ca 762
a2c6b8b1 763 if ((pclass = FindPrinter(name)) != NULL &&
764 !(pclass->type & CUPS_PRINTER_IMPLICIT))
782359ca 765 {
766 /*
767 * Can't use same name as printer; add "Any" to the front of the
768 * name...
769 */
770
771 strcpy(name, "Any");
772 strncpy(name + 3, p->name, len);
773 name[len + 3] = '\0';
eef5ad1b 774 offset = 3;
782359ca 775 }
776
8b43895a 777 first = p;
778 }
779 }
780 }
fd8b1cf8 781}
782
783
d6de4648 784/*
785 * 'SendBrowseList()' - Send new browsing information.
786 */
787
fd8b1cf8 788void
789SendBrowseList(void)
790{
d6de4648 791 int i; /* Looping var */
792 printer_t *p, /* Current printer */
793 *np; /* Next printer */
f9d6449d 794 time_t ut, /* Minimum update time */
795 to; /* Timeout time */
d6de4648 796 int bytes; /* Length of packet */
a2c6b8b1 797 char packet[1453];
d6de4648 798 /* Browse data packet */
799
800
be0ad10c 801 if (!Browsing)
f63a2256 802 return;
803
d6de4648 804 /*
805 * Compute the update time...
806 */
807
f9d6449d 808 ut = time(NULL) - BrowseInterval;
809 to = time(NULL) - BrowseTimeout;
d6de4648 810
811 /*
812 * Loop through all of the printers and send local updates as needed...
813 */
814
815 for (p = Printers; p != NULL; p = np)
816 {
817 np = p->next;
818
819 if (p->type & CUPS_PRINTER_REMOTE)
820 {
821 /*
822 * See if this printer needs to be timed out...
823 */
824
f9d6449d 825 if (p->browse_time < to)
e63d9801 826 {
5ea8888e 827 LogMessage(L_INFO, "Remote destination \"%s\" has timed out; deleting it...",
d62e9bdd 828 p->name);
d6de4648 829 DeletePrinter(p);
e63d9801 830 }
d6de4648 831 }
be0ad10c 832 else if (p->browse_time < ut && !(p->type & CUPS_PRINTER_IMPLICIT) &&
833 BrowseInterval > 0)
d6de4648 834 {
835 /*
836 * Need to send an update...
837 */
838
839 p->browse_time = time(NULL);
840
04de52f8 841 snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"\n",
a2c6b8b1 842 p->type | CUPS_PRINTER_REMOTE, p->state, p->uri,
843 p->location, p->info, p->make_model);
844
d6de4648 845 bytes = strlen(packet);
05156f4e 846 LogMessage(L_DEBUG2, "SendBrowseList: (%d bytes) %s", bytes, packet);
d6de4648 847
848 /*
849 * Send a packet to each browse address...
850 */
851
852 for (i = 0; i < NumBrowsers; i ++)
16b0a852 853 if (sendto(BrowseSocket, packet, bytes, 0,
854 (struct sockaddr *)Browsers + i, sizeof(Browsers[0])) <= 0)
f63a2256 855 {
5ea8888e 856 LogMessage(L_ERROR, "SendBrowseList: sendto failed for browser %d - %s.",
fd3ece61 857 i + 1, strerror(errno));
f63a2256 858 LogMessage(L_ERROR, "Browsing turned off.");
859
860 StopBrowsing();
861 Browsing = 0;
862 return;
863 }
d6de4648 864 }
865 }
fd8b1cf8 866}
a129ddbd 867
868
869/*
03081fd2 870 * 'StartPolling()' - Start polling servers as needed.
871 */
872
873void
874StartPolling(void)
875{
e5ebb675 876 int i; /* Looping var */
877 dirsvc_poll_t *poll; /* Current polling server */
878 int pid; /* New process ID */
879 char sport[10]; /* Server port */
880 char bport[10]; /* Browser port */
881 char interval[10]; /* Poll interval */
882
883
884 sprintf(bport, "%d", BrowsePort);
b1ac1113 885
886 if (BrowseInterval)
887 sprintf(interval, "%d", BrowseInterval);
888 else
889 strcpy(interval, "30");
e5ebb675 890
891 for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
892 {
893 sprintf(sport, "%d", poll->port);
894
895 if ((pid = fork()) == 0)
896 {
897 /*
898 * Child...
899 */
900
5aeb433c 901 if (getuid() == 0)
902 {
903 /*
904 * Running as root, so change to non-priviledged user...
905 */
906
907 if (setgid(Group))
908 exit(errno);
909
910 if (setuid(User))
911 exit(errno);
912 }
913
914 /*
915 * Reset group membership to just the main one we belong to.
916 */
917
918 setgroups(0, NULL);
919
920 /*
921 * Execute the polling daemon...
922 */
e5ebb675 923
924 execl(CUPS_SERVERBIN "/daemon/cups-polld", "cups-polld", poll->hostname,
925 sport, interval, bport, NULL);
926 exit(errno);
927 }
928 else if (pid < 0)
929 {
930 LogMessage(L_ERROR, "StartPolling: Unable to fork polling daemon - %s",
931 strerror(errno));
932 poll->pid = 0;
933 break;
934 }
935 else
936 {
937 poll->pid = pid;
938 LogMessage(L_DEBUG, "StartPolling: Started polling daemon for %s:%d, pid = %d",
939 poll->hostname, poll->port, pid);
940 }
941 }
03081fd2 942}
943
944
945/*
946 * 'StopPolling()' - Stop polling servers as needed.
947 */
948
949void
950StopPolling(void)
951{
e5ebb675 952 int i; /* Looping var */
953 dirsvc_poll_t *poll; /* Current polling server */
954
955
956 for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
957 if (poll->pid)
958 kill(poll->pid, SIGTERM);
03081fd2 959}
960
961
962/*
b5cb0608 963 * End of "$Id: dirsvc.c,v 1.73.2.2 2001/05/13 18:38:35 mike Exp $".
a129ddbd 964 */