]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/dirsvc.c
Fixed address to 44141 Airport View Drive...
[thirdparty/cups.git] / scheduler / dirsvc.c
CommitLineData
a129ddbd 1/*
8784b6a6 2 * "$Id: dirsvc.c,v 1.20 1999/06/18 18:36:46 mike Exp $"
a129ddbd 3 *
d6de4648 4 * Directory services routines for the Common UNIX Printing System (CUPS).
a129ddbd 5 *
a9de544f 6 * Copyright 1997-1999 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.
a129ddbd 30 */
31
32/*
33 * Include necessary headers...
34 */
35
fd8b1cf8 36#include "cupsd.h"
37
38
d6de4648 39/*
40 * 'StartBrowsing()' - Start sending and receiving broadcast information.
41 */
42
fd8b1cf8 43void
44StartBrowsing(void)
45{
d6de4648 46 int val; /* Socket option value */
47 struct sockaddr_in addr; /* Broadcast address */
48
49
8828fd5f 50 if (!Browsing)
d6de4648 51 return;
52
53 /*
54 * Create the broadcast socket...
55 */
56
900b10ea 57 if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
d6de4648 58 {
59 LogMessage(LOG_ERROR, "StartBrowsing: Unable to create broadcast socket - %s.",
60 strerror(errno));
61 return;
62 }
63
64 /*
900b10ea 65 * Set the "broadcast" flag...
d6de4648 66 */
67
68 val = 1;
e9e40963 69 if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
fd3ece61 70 {
71 LogMessage(LOG_ERROR, "StartBrowsing: Unable to set broadcast mode - %s.",
72 strerror(errno));
73
74#if defined(WIN32) || defined(__EMX__)
75 closesocket(BrowseSocket);
76#else
77 close(BrowseSocket);
78#endif /* WIN32 || __EMX__ */
79
80 BrowseSocket = -1;
81 return;
82 }
d6de4648 83
d6de4648 84 /*
85 * Bind the socket to browse port...
86 */
87
d6de4648 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);
92
93 if (bind(BrowseSocket, &addr, sizeof(addr)))
94 {
95 LogMessage(LOG_ERROR, "StartBrowsing: Unable to bind broadcast socket - %s.",
96 strerror(errno));
97
98#if defined(WIN32) || defined(__EMX__)
99 closesocket(BrowseSocket);
100#else
101 close(BrowseSocket);
102#endif /* WIN32 || __EMX__ */
103
104 BrowseSocket = -1;
105 return;
106 }
107
108 /*
109 * Finally, add the socket to the input selection set...
110 */
111
112 FD_SET(BrowseSocket, &InputSet);
fd8b1cf8 113}
114
115
d6de4648 116/*
117 * 'StopBrowsing()' - Stop sending and receiving broadcast information.
118 */
119
fd8b1cf8 120void
121StopBrowsing(void)
122{
8828fd5f 123 if (!Browsing)
d6de4648 124 return;
125
126 /*
127 * Close the socket and remove it from the input selection set.
128 */
129
3c7bb4a2 130 if (BrowseSocket >= 0)
131 {
d6de4648 132#if defined(WIN32) || defined(__EMX__)
3c7bb4a2 133 closesocket(BrowseSocket);
d6de4648 134#else
3c7bb4a2 135 close(BrowseSocket);
d6de4648 136#endif /* WIN32 || __EMX__ */
137
3c7bb4a2 138 FD_CLR(BrowseSocket, &InputSet);
139 }
fd8b1cf8 140}
141
142
d6de4648 143/*
144 * 'UpdateBrowseList()' - Update the browse lists for any new browse data.
145 */
146
fd8b1cf8 147void
148UpdateBrowseList(void)
149{
8b43895a 150 int i; /* Looping var */
151 int len; /* Length of name string */
d6de4648 152 int bytes; /* Number of bytes left */
153 char packet[1540]; /* Broadcast packet */
154 cups_ptype_t type; /* Printer type */
155 ipp_pstate_t state; /* Printer state */
156 char uri[HTTP_MAX_URI], /* Printer URI */
157 method[HTTP_MAX_URI], /* Method portion of URI */
158 username[HTTP_MAX_URI], /* Username portion of URI */
159 host[HTTP_MAX_URI], /* Host portion of URI */
160 resource[HTTP_MAX_URI]; /* Resource portion of URI */
161 int port; /* Port portion of URI */
162 char name[IPP_MAX_NAME], /* Name of printer */
8b43895a 163 *hptr, /* Pointer into hostname */
164 *sptr; /* Pointer into ServerName */
165 printer_t *p, /* Printer information */
166 *pclass, /* Printer class */
167 *first; /* First printer in class */
d6de4648 168
169
170 /*
171 * Read a packet from the browse socket...
172 */
173
174 if ((bytes = recv(BrowseSocket, packet, sizeof(packet), 0)) <= 0)
f9bacabb 175 {
8828fd5f 176 LogMessage(LOG_ERROR, "UpdateBrowseList: recv failed - %s.",
177 strerror(errno));
d6de4648 178 return;
f9bacabb 179 }
d6de4648 180
181 packet[bytes] = '\0';
8828fd5f 182 DEBUG_printf(("UpdateBrowseList: (%d bytes) %s", bytes, packet));
d6de4648 183
184 if (sscanf(packet, "%x%x%s", &type, &state, uri) != 3)
185 {
186 LogMessage(LOG_WARN, "UpdateBrowseList: Garbled browse packet - %s",
187 packet);
188 return;
189 }
190
191 /*
192 * Pull the URI apart to see if this is a local or remote printer...
193 */
194
195 httpSeparate(uri, method, username, host, &port, resource);
196
197 if (strcasecmp(host, ServerName) == 0)
198 return;
199
200 /*
201 * OK, this isn't a local printer; see if we already have it listed in
202 * the Printers list, and add it if not...
203 */
204
c7fa9d06 205 type |= CUPS_PRINTER_REMOTE;
d6de4648 206
8b43895a 207 hptr = strchr(host, '.');
208 sptr = strchr(ServerName, '.');
209
210 if (hptr != NULL && sptr != NULL &&
211 strcasecmp(hptr, sptr) == 0)
212 *hptr = '\0';
d6de4648 213
c7fa9d06 214 if (type & CUPS_PRINTER_CLASS)
d6de4648 215 {
216 /*
c7fa9d06 217 * Remote destination is a class...
d6de4648 218 */
219
c7fa9d06 220 if (strncmp(resource, "/classes/", 9) == 0)
221 sprintf(name, "%s@%s", resource + 9, host);
222 else
223 return;
224
225 if ((p = FindClass(name)) == NULL)
226 {
227 /*
228 * Class doesn't exist; add it...
229 */
d6de4648 230
c7fa9d06 231 p = AddPrinter(name);
232
233 /*
234 * First the URI to point to the real server...
235 */
236
237 strcpy(p->uri, uri);
238 strcpy(p->device_uri, uri);
239 free(p->attrs->attrs->values[0].string.text);
240 p->attrs->attrs->values[0].string.text = strdup(uri);
241 }
242 }
243 else
244 {
d6de4648 245 /*
c7fa9d06 246 * Remote destination is a printer...
d6de4648 247 */
248
c7fa9d06 249 if (strncmp(resource, "/printers/", 10) == 0)
250 sprintf(name, "%s@%s", resource + 10, host);
251 else
252 return;
253
254 if ((p = FindPrinter(name)) == NULL)
255 {
256 /*
257 * Printer doesn't exist; add it...
258 */
259
260 p = AddPrinter(name);
261
262 /*
263 * First the URI to point to the real server...
264 */
265
266 strcpy(p->uri, uri);
267 strcpy(p->device_uri, uri);
268 free(p->attrs->attrs->values[0].string.text);
269 p->attrs->attrs->values[0].string.text = strdup(uri);
270 }
d6de4648 271 }
272
273 /*
274 * Update the state...
275 */
276
277 p->type = type;
278 p->state = state;
0948b55b 279 p->accepting = state != IPP_PRINTER_STOPPED;
d6de4648 280 p->browse_time = time(NULL);
8b43895a 281
282 /*
283 * Do auto-classing if needed...
284 */
285
286 if (ImplicitClasses)
287 {
288 /*
289 * Loop through all available printers and create classes as needed...
290 */
291
292 for (p = Printers, len = 0; p != NULL; p = p->next)
293 {
294 /*
295 * Skip classes...
296 */
297
298 if (p->type & CUPS_PRINTER_CLASS)
299 {
300 len = 0;
301 continue;
302 }
303
304 /*
305 * If len == 0, get the length of this printer name up to the "@"
306 * sign (if any).
307 */
308
309 if (len > 0 &&
310 strncasecmp(p->name, name + 3, len) == 0 &&
311 (p->name[len] == '\0' || p->name[len] == '@'))
312 {
313 /*
314 * We have more than one printer with the same name; see if
315 * we have a class, and if this printer is a member...
316 */
317
318 if ((pclass = FindClass(name)) == NULL)
319 pclass = AddClass(name);
320
321 if (first != NULL)
322 {
323 for (i = 0; i < pclass->num_printers; i ++)
324 if (pclass->printers[i] == first)
325 break;
326
327 if (i >= pclass->num_printers)
328 AddPrinterToClass(pclass, first);
329
330 first = NULL;
331 }
332
333 for (i = 0; i < pclass->num_printers; i ++)
334 if (pclass->printers[i] == p)
335 break;
336
337 if (i >= pclass->num_printers)
338 AddPrinterToClass(pclass, p);
339 }
340 else
341 {
342 /*
343 * First time around; just get name length and mark it as first
344 * in the list...
345 */
346
347 if ((hptr = strchr(p->name, '@')) != NULL)
348 len = hptr - p->name;
349 else
350 len = strlen(p->name);
351
352 strcpy(name, "Any");
353 strncpy(name + 3, p->name, len);
354 name[len + 3] = '\0';
355 first = p;
356 }
357 }
358 }
fd8b1cf8 359}
360
361
d6de4648 362/*
363 * 'SendBrowseList()' - Send new browsing information.
364 */
365
fd8b1cf8 366void
367SendBrowseList(void)
368{
d6de4648 369 int i; /* Looping var */
370 printer_t *p, /* Current printer */
371 *np; /* Next printer */
f9d6449d 372 time_t ut, /* Minimum update time */
373 to; /* Timeout time */
d6de4648 374 int bytes; /* Length of packet */
375 char packet[1540];
376 /* Browse data packet */
377
378
379 /*
380 * Compute the update time...
381 */
382
f9d6449d 383 ut = time(NULL) - BrowseInterval;
384 to = time(NULL) - BrowseTimeout;
d6de4648 385
386 /*
387 * Loop through all of the printers and send local updates as needed...
388 */
389
390 for (p = Printers; p != NULL; p = np)
391 {
392 np = p->next;
393
394 if (p->type & CUPS_PRINTER_REMOTE)
395 {
396 /*
397 * See if this printer needs to be timed out...
398 */
399
f9d6449d 400 if (p->browse_time < to)
d6de4648 401 DeletePrinter(p);
402 }
f9d6449d 403 else if (p->browse_time < ut)
d6de4648 404 {
405 /*
406 * Need to send an update...
407 */
408
409 p->browse_time = time(NULL);
410
411 sprintf(packet, "%x %x %s\n", p->type, p->state, p->uri);
412 bytes = strlen(packet);
8828fd5f 413 DEBUG_printf(("SendBrowseList: (%d bytes) %s", bytes, packet));
d6de4648 414
415 /*
416 * Send a packet to each browse address...
417 */
418
419 for (i = 0; i < NumBrowsers; i ++)
f9bacabb 420 if (sendto(BrowseSocket, packet, bytes, 0, Browsers + i,
421 sizeof(Browsers[0])) <= 0)
8828fd5f 422 LogMessage(LOG_ERROR, "SendBrowseList: sendto failed for browser %d - %s.",
fd3ece61 423 i + 1, strerror(errno));
d6de4648 424 }
425 }
fd8b1cf8 426}
a129ddbd 427
428
429/*
8784b6a6 430 * End of "$Id: dirsvc.c,v 1.20 1999/06/18 18:36:46 mike Exp $".
a129ddbd 431 */