]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/dirsvc.c
2 * "$Id: dirsvc.c,v 1.40 1999/07/30 13:31:52 mike Exp $"
4 * Directory services routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-1999 by Easy Software Products, all rights reserved.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
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.
33 * Include necessary headers...
40 * 'StartBrowsing()' - Start sending and receiving broadcast information.
46 int val
; /* Socket option value */
47 struct sockaddr_in addr
; /* Broadcast address */
54 * Create the broadcast socket...
57 if ((BrowseSocket
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
59 LogMessage(LOG_ERROR
, "StartBrowsing: Unable to create broadcast socket - %s.",
65 * Set the "broadcast" flag...
69 if (setsockopt(BrowseSocket
, SOL_SOCKET
, SO_BROADCAST
, &val
, sizeof(val
)))
71 LogMessage(LOG_ERROR
, "StartBrowsing: Unable to set broadcast mode - %s.",
74 #if defined(WIN32) || defined(__EMX__)
75 closesocket(BrowseSocket
);
78 #endif /* WIN32 || __EMX__ */
85 * Bind the socket to browse port...
88 memset(&addr
, 0, sizeof(addr
));
89 addr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
90 addr
.sin_family
= AF_INET
;
91 addr
.sin_port
= htons(BrowsePort
);
93 if (bind(BrowseSocket
, (struct sockaddr
*)&addr
, sizeof(addr
)))
95 LogMessage(LOG_ERROR
, "StartBrowsing: Unable to bind broadcast socket - %s.",
98 #if defined(WIN32) || defined(__EMX__)
99 closesocket(BrowseSocket
);
102 #endif /* WIN32 || __EMX__ */
109 * Finally, add the socket to the input selection set...
112 FD_SET(BrowseSocket
, &InputSet
);
117 * 'StopBrowsing()' - Stop sending and receiving broadcast information.
127 * Close the socket and remove it from the input selection set.
130 if (BrowseSocket
>= 0)
132 #if defined(WIN32) || defined(__EMX__)
133 closesocket(BrowseSocket
);
136 #endif /* WIN32 || __EMX__ */
138 FD_CLR(BrowseSocket
, &InputSet
);
144 * 'UpdateBrowseList()' - Update the browse lists for any new browse data.
148 UpdateBrowseList(void)
150 int i
; /* Looping var */
151 int len
, /* Length of name string */
152 offset
; /* Offset in name string */
153 int bytes
; /* Number of bytes left */
154 char packet
[1540]; /* Broadcast packet */
155 cups_ptype_t type
; /* Printer type */
156 ipp_pstate_t state
; /* Printer state */
157 char uri
[HTTP_MAX_URI
], /* Printer URI */
158 method
[HTTP_MAX_URI
], /* Method portion of URI */
159 username
[HTTP_MAX_URI
], /* Username portion of URI */
160 host
[HTTP_MAX_URI
], /* Host portion of URI */
161 resource
[HTTP_MAX_URI
]; /* Resource portion of URI */
162 int port
; /* Port portion of URI */
163 char name
[IPP_MAX_NAME
], /* Name of printer */
164 *hptr
, /* Pointer into hostname */
165 *sptr
; /* Pointer into ServerName */
166 printer_t
*p
, /* Printer information */
167 *pclass
, /* Printer class */
168 *first
; /* First printer in class */
172 * Read a packet from the browse socket...
176 struct sockaddr_in addr
;
180 if ((bytes
= recvfrom(BrowseSocket
, packet
, sizeof(packet
), 0,
181 (struct sockaddr
*)&addr
, &len
)) <= 0)
183 LogMessage(LOG_ERROR
, "UpdateBrowseList: recv failed - %s.",
188 packet
[bytes
] = '\0';
189 printf("UpdateBrowseList: (%d bytes from %08x) %s", bytes
,
190 ntohl(addr
.sin_addr
.s_addr
), packet
);
192 if ((bytes
= recv(BrowseSocket
, packet
, sizeof(packet
), 0)) <= 0)
194 LogMessage(LOG_ERROR
, "UpdateBrowseList: recv failed - %s.",
199 packet
[bytes
] = '\0';
202 if (sscanf(packet
, "%x%x%s", &type
, &state
, uri
) != 3)
204 LogMessage(LOG_WARN
, "UpdateBrowseList: Garbled browse packet - %s",
209 DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n", type
, state
, uri
));
212 * Pull the URI apart to see if this is a local or remote printer...
215 httpSeparate(uri
, method
, username
, host
, &port
, resource
);
217 DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host
, ServerName
));
219 if (strcasecmp(host
, ServerName
) == 0)
223 * OK, this isn't a local printer; see if we already have it listed in
224 * the Printers list, and add it if not...
227 hptr
= strchr(host
, '.');
228 sptr
= strchr(ServerName
, '.');
230 if (hptr
!= NULL
&& sptr
!= NULL
&&
231 strcasecmp(hptr
, sptr
) == 0)
234 if (type
& CUPS_PRINTER_CLASS
)
237 * Remote destination is a class...
240 if (strncmp(resource
, "/classes/", 9) == 0)
241 sprintf(name
, "%s@%s", resource
+ 9, host
);
245 if ((p
= FindClass(name
)) == NULL
)
246 if ((p
= FindClass(resource
+ 9)) != NULL
)
248 if (strcasecmp(p
->hostname
, host
) != 0)
251 * Nope, this isn't the same host; if the hostname isn't the local host,
252 * add it to the other class and then find a class using the full host
256 if (p
->type
& CUPS_PRINTER_REMOTE
)
258 strcat(p
->name
, "@");
259 strcat(p
->name
, p
->hostname
);
268 strcpy(name
, resource
+ 9);
273 * Class doesn't exist; add it...
279 * Force the URI to point to the real server...
284 strcpy(p
->device_uri
, uri
);
285 strcpy(p
->hostname
, host
);
292 * Remote destination is a printer...
295 if (strncmp(resource
, "/printers/", 10) == 0)
296 sprintf(name
, "%s@%s", resource
+ 10, host
);
300 if ((p
= FindPrinter(name
)) == NULL
)
301 if ((p
= FindPrinter(resource
+ 10)) != NULL
)
303 if (strcasecmp(p
->hostname
, host
) != 0)
306 * Nope, this isn't the same host; if the hostname isn't the local host,
307 * add it to the other printer and then find a printer using the full host
311 if (p
->type
& CUPS_PRINTER_REMOTE
)
313 strcat(p
->name
, "@");
314 strcat(p
->name
, p
->hostname
);
323 strcpy(name
, resource
+ 10);
328 * Printer doesn't exist; add it...
331 p
= AddPrinter(name
);
334 * Force the URI to point to the real server...
339 strcpy(p
->device_uri
, uri
);
340 strcpy(p
->hostname
, host
);
346 * Update the state...
351 p
->accepting
= state
!= IPP_PRINTER_STOPPED
;
352 p
->browse_time
= time(NULL
);
355 * See if we have a default printer... If not, make the first printer the
359 if (DefaultPrinter
== NULL
&& Printers
!= NULL
)
360 DefaultPrinter
= Printers
;
363 * Do auto-classing if needed...
369 * Loop through all available printers and create classes as needed...
372 for (p
= Printers
, len
= 0, offset
= 0; p
!= NULL
; p
= p
->next
)
378 if (p
->type
& CUPS_PRINTER_CLASS
)
385 * If len == 0, get the length of this printer name up to the "@"
390 strncasecmp(p
->name
, name
+ offset
, len
) == 0 &&
391 (p
->name
[len
] == '\0' || p
->name
[len
] == '@'))
394 * We have more than one printer with the same name; see if
395 * we have a class, and if this printer is a member...
398 if ((pclass
= FindClass(name
)) == NULL
)
401 * Need to add the class...
404 pclass
= AddClass(name
);
405 pclass
->type
|= CUPS_PRINTER_IMPLICIT
;
406 pclass
->accepting
= 1;
407 pclass
->state
= IPP_PRINTER_IDLE
;
409 SetPrinterAttrs(pclass
);
411 DEBUG_printf(("Added new class \"%s\", type = %x\n", name
,
417 for (i
= 0; i
< pclass
->num_printers
; i
++)
418 if (pclass
->printers
[i
] == first
)
421 if (i
>= pclass
->num_printers
)
422 AddPrinterToClass(pclass
, first
);
427 for (i
= 0; i
< pclass
->num_printers
; i
++)
428 if (pclass
->printers
[i
] == p
)
431 if (i
>= pclass
->num_printers
)
432 AddPrinterToClass(pclass
, p
);
437 * First time around; just get name length and mark it as first
441 if ((hptr
= strchr(p
->name
, '@')) != NULL
)
442 len
= hptr
- p
->name
;
444 len
= strlen(p
->name
);
446 strncpy(name
, p
->name
, len
);
450 if (FindPrinter(name
) != NULL
)
453 * Can't use same name as printer; add "Any" to the front of the
458 strncpy(name
+ 3, p
->name
, len
);
459 name
[len
+ 3] = '\0';
471 * 'SendBrowseList()' - Send new browsing information.
477 int i
; /* Looping var */
478 printer_t
*p
, /* Current printer */
479 *np
; /* Next printer */
480 time_t ut
, /* Minimum update time */
481 to
; /* Timeout time */
482 int bytes
; /* Length of packet */
484 /* Browse data packet */
488 * Compute the update time...
491 ut
= time(NULL
) - BrowseInterval
;
492 to
= time(NULL
) - BrowseTimeout
;
495 * Loop through all of the printers and send local updates as needed...
498 for (p
= Printers
; p
!= NULL
; p
= np
)
502 if (p
->type
& CUPS_PRINTER_REMOTE
)
505 * See if this printer needs to be timed out...
508 if (p
->browse_time
< to
)
510 DEBUG_printf(("Printer \"%s\" has timed out (%d < %d...)\n",
511 p
->name
, p
->browse_time
, to
));
515 else if (p
->browse_time
< ut
&& !(p
->type
& CUPS_PRINTER_IMPLICIT
))
518 * Need to send an update...
521 p
->browse_time
= time(NULL
);
523 sprintf(packet
, "%x %x %s\n", p
->type
| CUPS_PRINTER_REMOTE
, p
->state
,
525 bytes
= strlen(packet
);
526 DEBUG_printf(("SendBrowseList: (%d bytes) %s", bytes
, packet
));
529 * Send a packet to each browse address...
532 for (i
= 0; i
< NumBrowsers
; i
++)
533 if (sendto(BrowseSocket
, packet
, bytes
, 0,
534 (struct sockaddr
*)Browsers
+ i
, sizeof(Browsers
[0])) <= 0)
535 LogMessage(LOG_ERROR
, "SendBrowseList: sendto failed for browser %d - %s.",
536 i
+ 1, strerror(errno
));
543 * End of "$Id: dirsvc.c,v 1.40 1999/07/30 13:31:52 mike Exp $".