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