~ubuntu-branches/ubuntu/utopic/cups/utopic

« back to all changes in this revision

Viewing changes to .pc/dont-use-dbus-from-two-threads.patch/scheduler/dirsvc.c

  • Committer: Package Import Robot
  • Author(s): Didier Raboud, Till Kamppeter, Steve Langasek, Didier Raboud
  • Date: 2014-01-03 18:42:39 UTC
  • mfrom: (99.2.3 sid)
  • Revision ID: package-import@ubuntu.com-20140103184239-85wju2l7weie4dgo
Tags: 1.7.0-1
* New 1.7.0 upstream release

[ Till Kamppeter ]
* Refresh most patches with quilt
* Removed usb-backend-do-not-crash-if-usb-disabled-in-bios and
  cupsd-no-crash-on-avahi-threaded-poll-shutdown patches as they got
  applied upstream
* Removed drop-arch-specifics-from-doc patch as it is not needed
  anymore
* Updated drop_unnecessary_dependencies, manpage-hyphen-minus,
  manpage-translations and ppd-poll-with-client-conf patches manually
  to apply to the new CUPS version
* Added error counting exception from
  usb-backend-do-not-crash-if-usb-disabled-in-bios to
  tests-ignore-warnings
* Install the newly added ippfind utility and its manpage in
  cups-client
* Added pwg.h to libcups2-dev package
* Call dh_auto_clean only if the file Makedefs is present, to avoid a
  FTBFS
* Added color management extensions from Joe Simon's GSoC 2013
  project.
* Patch cups-files.conf to activate CUPS daemon syncing of files when
  closing, so that config files (like printers.conf) do not
  mysteriously disappear (LP: #1157972)
* In the AppArmor profile, allow execution of programs in
  /etc/cups/interfaces/, needed to make CUPS working with queues based
  on System V interface scripts, especially PPD-less queues
  auto-generated by cups-browsed from cups-filters 1.0.41 on.
* Silenced AppArmor noise from udev.conf in syslog (LP: #1229766)

[ Steve Langasek ]
* Add cups-filters (>= 1.0.42) as alternative to foomatic-filters
  (which is deprecated) in package relationships

[ Didier Raboud ]
* Remove Roger Leigh from uploaders on his request with thanks for his
  past work!
* Switch avahi LSB Should-Start dependency to be avahi-daemon; also
  bump package relationship to >= 0.6.31-3~ (Closes: #731608)
* Refresh the manpage translation files
* Move the USB backend quirk rules file to cups-server-common
* Add 38 new 1.7.0 libcups2 symbols
* Mark one C++ libcupsppdc1 symbol as optional as it isn't exported in
  1.7.0 anymore
* Import Fedora patches:
  - to avoid sign-extending CRCs in gz decompression
  - to build with full read-only relocations
  - to fix job history logging (upstream patch)
  - to set the internal default for SyncOnClose to Yes, instead of
    only configuring it to Yes
  - to fix a stringpool corruption issue
  - to prevent USB timeouts causing incorrect print output
* Import Fedora patch updates:
  - to dont-use-dbus-from-two-threads patch so it removes a call to
    avahi_threaded_poll_stop()
  - to avoid_stale_lockfile_in_dbus_notifier patch to call _exit when
    handling SIGTERM
* Move manpage-translations patch at the very end of the patch series
  to have it include all our patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * "$Id: dirsvc.c 11193 2013-07-26 03:12:37Z msweet $"
 
3
 *
 
4
 *   Directory services routines for the CUPS scheduler.
 
5
 *
 
6
 *   Copyright 2007-2013 by Apple Inc.
 
7
 *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 
8
 *
 
9
 *   These coded instructions, statements, and computer programs are the
 
10
 *   property of Apple Inc. and are protected by Federal copyright
 
11
 *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
 
12
 *   which should have been included with this file.  If this file is
 
13
 *   file is missing or damaged, see the license at "http://www.cups.org/".
 
14
 *
 
15
 * Contents:
 
16
 *
 
17
 *   cupsdDeregisterPrinter()  - Stop sending broadcast information for a local
 
18
 *                               printer and remove any pending references to
 
19
 *                               remote printers.
 
20
 *   cupsdRegisterPrinter()    - Start sending broadcast information for a
 
21
 *                               printer or update the broadcast contents.
 
22
 *   cupsdStartBrowsing()      - Start sending and receiving broadcast
 
23
 *                               information.
 
24
 *   cupsdStopBrowsing()       - Stop sending and receiving broadcast
 
25
 *                               information.
 
26
 *   cupsdUpdateDNSSDName()    - Update the computer name we use for
 
27
 *                               browsing...
 
28
 *   dnssdAddAlias()           - Add a DNS-SD alias name.
 
29
 *   dnssdBuildTxtRecord()     - Build a TXT record from printer info.
 
30
 *   dnssdDeregisterInstance() - Deregister a DNS-SD service instance.
 
31
 *   dnssdDeregisterPrinter()  - Deregister all services for a printer.
 
32
 *   dnssdErrorString()        - Return an error string for an error code.
 
33
 *   dnssdRegisterCallback()   - Free a TXT record.
 
34
 *   dnssdRegisterCallback()   - DNSServiceRegister callback.
 
35
 *   dnssdRegisterInstance()   - Register an instance of a printer service.
 
36
 *   dnssdRegisterPrinter()    - Start sending broadcast information for a
 
37
 *                               printer or update the broadcast contents.
 
38
 *   dnssdStop()               - Stop all DNS-SD registrations.
 
39
 *   dnssdUpdate()             - Handle DNS-SD queries.
 
40
 *   get_auth_info_required()  - Get the auth-info-required value to advertise.
 
41
 *   get_hostconfig()          - Get an /etc/hostconfig service setting.
 
42
 *   update_lpd()              - Update the LPD configuration as needed.
 
43
 *   update_smb()              - Update the SMB configuration as needed.
 
44
 */
 
45
 
 
46
/*
 
47
 * Include necessary headers...
 
48
 */
 
49
 
 
50
#include "cupsd.h"
 
51
#include <grp.h>
 
52
 
 
53
#if defined(HAVE_DNSSD) && defined(__APPLE__)
 
54
#  include <nameser.h>
 
55
#  include <CoreFoundation/CoreFoundation.h>
 
56
#  include <SystemConfiguration/SystemConfiguration.h>
 
57
#endif /* HAVE_DNSSD && __APPLE__ */
 
58
 
 
59
 
 
60
/*
 
61
 * Local functions...
 
62
 */
 
63
 
 
64
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
 
65
static char             *get_auth_info_required(cupsd_printer_t *p,
 
66
                                                char *buffer, size_t bufsize);
 
67
#endif /* HAVE_DNSSD || HAVE_AVAHI */
 
68
#ifdef __APPLE__
 
69
static int              get_hostconfig(const char *name);
 
70
#endif /* __APPLE__ */
 
71
static void             update_lpd(int onoff);
 
72
static void             update_smb(int onoff);
 
73
 
 
74
 
 
75
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
 
76
#  ifdef __APPLE__
 
77
static void             dnssdAddAlias(const void *key, const void *value,
 
78
                                      void *context);
 
79
#  endif /* __APPLE__ */
 
80
static cupsd_txt_t      dnssdBuildTxtRecord(cupsd_printer_t *p, int for_lpd);
 
81
static void             dnssdDeregisterInstance(cupsd_srv_t *srv);
 
82
static void             dnssdDeregisterPrinter(cupsd_printer_t *p,
 
83
                                               int clear_name);
 
84
static const char       *dnssdErrorString(int error);
 
85
static void             dnssdFreeTxtRecord(cupsd_txt_t *txt);
 
86
#  ifdef HAVE_DNSSD
 
87
static void             dnssdRegisterCallback(DNSServiceRef sdRef,
 
88
                                              DNSServiceFlags flags,
 
89
                                              DNSServiceErrorType errorCode,
 
90
                                              const char *name,
 
91
                                              const char *regtype,
 
92
                                              const char *domain,
 
93
                                              void *context);
 
94
#  else
 
95
static void             dnssdRegisterCallback(AvahiEntryGroup *p,
 
96
                                              AvahiEntryGroupState state,
 
97
                                              void *context);
 
98
#  endif /* HAVE_DNSSD */
 
99
static int              dnssdRegisterInstance(cupsd_srv_t *srv,
 
100
                                              cupsd_printer_t *p,
 
101
                                              char *name, const char *type,
 
102
                                              const char *subtypes, int port,
 
103
                                              cupsd_txt_t *txt, int commit);
 
104
static void             dnssdRegisterPrinter(cupsd_printer_t *p);
 
105
static void             dnssdStop(void);
 
106
#  ifdef HAVE_DNSSD
 
107
static void             dnssdUpdate(void);
 
108
#  endif /* HAVE_DNSSD */
 
109
#endif /* HAVE_DNSSD || HAVE_AVAHI */
 
110
 
 
111
 
 
112
/*
 
113
 * 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a
 
114
 *                              local printer and remove any pending
 
115
 *                              references to remote printers.
 
116
 */
 
117
 
 
118
void
 
119
cupsdDeregisterPrinter(
 
120
    cupsd_printer_t *p,                 /* I - Printer to register */
 
121
    int             removeit)           /* I - Printer being permanently removed */
 
122
{
 
123
 /*
 
124
  * Only deregister if browsing is enabled and it's a local printer...
 
125
  */
 
126
 
 
127
  cupsdLogMessage(CUPSD_LOG_DEBUG,
 
128
                  "cupsdDeregisterPrinter(p=%p(%s), removeit=%d)", p, p->name,
 
129
                  removeit);
 
130
 
 
131
  if (!Browsing || !p->shared ||
 
132
      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
 
133
    return;
 
134
 
 
135
 /*
 
136
  * Announce the deletion...
 
137
  */
 
138
 
 
139
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
 
140
  if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster)
 
141
    dnssdDeregisterPrinter(p, 1);
 
142
#endif /* HAVE_DNSSD || HAVE_AVAHI */
 
143
}
 
144
 
 
145
 
 
146
/*
 
147
 * 'cupsdRegisterPrinter()' - Start sending broadcast information for a
 
148
 *                            printer or update the broadcast contents.
 
149
 */
 
150
 
 
151
void
 
152
cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
 
153
{
 
154
  cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", p,
 
155
                  p->name);
 
156
 
 
157
  if (!Browsing || !BrowseLocalProtocols ||
 
158
      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
 
159
    return;
 
160
 
 
161
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
 
162
  if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster)
 
163
    dnssdRegisterPrinter(p);
 
164
#endif /* HAVE_DNSSD || HAVE_AVAHI */
 
165
}
 
166
 
 
167
 
 
168
/*
 
169
 * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
 
170
 */
 
171
 
 
172
void
 
173
cupsdStartBrowsing(void)
 
174
{
 
175
  cupsd_printer_t       *p;             /* Current printer */
 
176
 
 
177
 
 
178
  if (!Browsing || !BrowseLocalProtocols)
 
179
    return;
 
180
 
 
181
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
 
182
  if (BrowseLocalProtocols & BROWSE_DNSSD)
 
183
  {
 
184
    cupsd_listener_t    *lis;           /* Current listening socket */
 
185
#  ifdef HAVE_DNSSD
 
186
    DNSServiceErrorType error;          /* Error from service creation */
 
187
 
 
188
   /*
 
189
    * First create a "master" connection for all registrations...
 
190
    */
 
191
 
 
192
    if ((error = DNSServiceCreateConnection(&DNSSDMaster))
 
193
            != kDNSServiceErr_NoError)
 
194
    {
 
195
      cupsdLogMessage(CUPSD_LOG_ERROR,
 
196
                      "Unable to create master DNS-SD reference: %d", error);
 
197
 
 
198
      if (FatalErrors & CUPSD_FATAL_BROWSE)
 
199
        cupsdEndProcess(getpid(), 0);
 
200
    }
 
201
    else
 
202
    {
 
203
     /*
 
204
      * Add the master connection to the select list...
 
205
      */
 
206
 
 
207
      int fd = DNSServiceRefSockFD(DNSSDMaster);
 
208
 
 
209
      fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
 
210
 
 
211
      cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
 
212
    }
 
213
 
 
214
#  else /* HAVE_AVAHI */
 
215
    if ((DNSSDMaster = avahi_threaded_poll_new()) == NULL)
 
216
    {
 
217
      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create DNS-SD thread.");
 
218
 
 
219
      if (FatalErrors & CUPSD_FATAL_BROWSE)
 
220
        cupsdEndProcess(getpid(), 0);
 
221
    }
 
222
    else
 
223
    {
 
224
      int error;                        /* Error code, if any */
 
225
 
 
226
      DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), 0,
 
227
                                     NULL, NULL, &error);
 
228
 
 
229
      if (DNSSDClient == NULL)
 
230
      {
 
231
        cupsdLogMessage(CUPSD_LOG_ERROR,
 
232
                        "Unable to communicate with avahi-daemon: %s",
 
233
                        dnssdErrorString(error));
 
234
 
 
235
        if (FatalErrors & CUPSD_FATAL_BROWSE)
 
236
          cupsdEndProcess(getpid(), 0);
 
237
 
 
238
        avahi_threaded_poll_free(DNSSDMaster);
 
239
        DNSSDMaster = NULL;
 
240
      }
 
241
      else
 
242
        avahi_threaded_poll_start(DNSSDMaster);
 
243
    }
 
244
#  endif /* HAVE_DNSSD */
 
245
 
 
246
   /*
 
247
    * Then get the port we use for registrations.  If we are not listening
 
248
    * on any non-local ports, there is no sense sharing local printers via
 
249
    * Bonjour...
 
250
    */
 
251
 
 
252
    DNSSDPort = 0;
 
253
 
 
254
    for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
 
255
         lis;
 
256
         lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
 
257
    {
 
258
      if (httpAddrLocalhost(&(lis->address)))
 
259
        continue;
 
260
 
 
261
      DNSSDPort = httpAddrPort(&(lis->address));
 
262
      break;
 
263
    }
 
264
 
 
265
   /*
 
266
    * Set the computer name and register the web interface...
 
267
    */
 
268
 
 
269
    cupsdUpdateDNSSDName();
 
270
  }
 
271
#endif /* HAVE_DNSSD || HAVE_AVAHI */
 
272
 
 
273
 /*
 
274
  * Enable LPD and SMB printer sharing as needed through external programs...
 
275
  */
 
276
 
 
277
  if (BrowseLocalProtocols & BROWSE_LPD)
 
278
    update_lpd(1);
 
279
 
 
280
  if (BrowseLocalProtocols & BROWSE_SMB)
 
281
    update_smb(1);
 
282
 
 
283
 /*
 
284
  * Register the individual printers
 
285
  */
 
286
 
 
287
  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
 
288
       p;
 
289
       p = (cupsd_printer_t *)cupsArrayNext(Printers))
 
290
    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
 
291
      cupsdRegisterPrinter(p);
 
292
}
 
293
 
 
294
 
 
295
/*
 
296
 * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information.
 
297
 */
 
298
 
 
299
void
 
300
cupsdStopBrowsing(void)
 
301
{
 
302
  cupsd_printer_t       *p;             /* Current printer */
 
303
 
 
304
 
 
305
  if (!Browsing || !BrowseLocalProtocols)
 
306
    return;
 
307
 
 
308
 /*
 
309
  * De-register the individual printers
 
310
  */
 
311
 
 
312
  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
 
313
       p;
 
314
       p = (cupsd_printer_t *)cupsArrayNext(Printers))
 
315
    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
 
316
      cupsdDeregisterPrinter(p, 1);
 
317
 
 
318
 /*
 
319
  * Shut down browsing sockets...
 
320
  */
 
321
 
 
322
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
 
323
  if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster)
 
324
    dnssdStop();
 
325
#endif /* HAVE_DNSSD || HAVE_AVAHI */
 
326
 
 
327
 /*
 
328
  * Disable LPD and SMB printer sharing as needed through external programs...
 
329
  */
 
330
 
 
331
  if (BrowseLocalProtocols & BROWSE_LPD)
 
332
    update_lpd(0);
 
333
 
 
334
  if (BrowseLocalProtocols & BROWSE_SMB)
 
335
    update_smb(0);
 
336
}
 
337
 
 
338
 
 
339
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
 
340
/*
 
341
 * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
 
342
 */
 
343
 
 
344
void
 
345
cupsdUpdateDNSSDName(void)
 
346
{
 
347
  char          webif[1024];            /* Web interface share name */
 
348
#  ifdef __APPLE__
 
349
  SCDynamicStoreRef sc;                 /* Context for dynamic store */
 
350
  CFDictionaryRef btmm;                 /* Back-to-My-Mac domains */
 
351
  CFStringEncoding nameEncoding;        /* Encoding of computer name */
 
352
  CFStringRef   nameRef;                /* Host name CFString */
 
353
  char          nameBuffer[1024];       /* C-string buffer */
 
354
#  endif /* __APPLE__ */
 
355
 
 
356
 
 
357
 /*
 
358
  * Only share the web interface and printers when non-local listening is
 
359
  * enabled...
 
360
  */
 
361
 
 
362
  if (!DNSSDPort)
 
363
    return;
 
364
 
 
365
 /*
 
366
  * Get the computer name as a c-string...
 
367
  */
 
368
 
 
369
#  ifdef __APPLE__
 
370
  sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL);
 
371
 
 
372
  if (sc)
 
373
  {
 
374
   /*
 
375
    * Get the computer name from the dynamic store...
 
376
    */
 
377
 
 
378
    cupsdClearString(&DNSSDComputerName);
 
379
 
 
380
    if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL)
 
381
    {
 
382
      if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
 
383
                             kCFStringEncodingUTF8))
 
384
      {
 
385
        cupsdLogMessage(CUPSD_LOG_DEBUG,
 
386
                        "Dynamic store computer name is \"%s\".", nameBuffer);
 
387
        cupsdSetString(&DNSSDComputerName, nameBuffer);
 
388
      }
 
389
 
 
390
      CFRelease(nameRef);
 
391
    }
 
392
 
 
393
    if (!DNSSDComputerName)
 
394
    {
 
395
     /*
 
396
      * Use the ServerName instead...
 
397
      */
 
398
 
 
399
      cupsdLogMessage(CUPSD_LOG_DEBUG,
 
400
                      "Using ServerName \"%s\" as computer name.", ServerName);
 
401
      cupsdSetString(&DNSSDComputerName, ServerName);
 
402
    }
 
403
 
 
404
   /*
 
405
    * Get the local hostname from the dynamic store...
 
406
    */
 
407
 
 
408
    cupsdClearString(&DNSSDHostName);
 
409
 
 
410
    if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL)
 
411
    {
 
412
      if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
 
413
                             kCFStringEncodingUTF8))
 
414
      {
 
415
        cupsdLogMessage(CUPSD_LOG_DEBUG,
 
416
                        "Dynamic store host name is \"%s\".", nameBuffer);
 
417
        cupsdSetString(&DNSSDHostName, nameBuffer);
 
418
      }
 
419
 
 
420
      CFRelease(nameRef);
 
421
    }
 
422
 
 
423
    if (!DNSSDHostName)
 
424
    {
 
425
     /*
 
426
      * Use the ServerName instead...
 
427
      */
 
428
 
 
429
      cupsdLogMessage(CUPSD_LOG_DEBUG,
 
430
                      "Using ServerName \"%s\" as host name.", ServerName);
 
431
      cupsdSetString(&DNSSDHostName, ServerName);
 
432
    }
 
433
 
 
434
   /*
 
435
    * Get any Back-to-My-Mac domains and add them as aliases...
 
436
    */
 
437
 
 
438
    cupsdFreeAliases(DNSSDAlias);
 
439
    DNSSDAlias = NULL;
 
440
 
 
441
    btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac"));
 
442
    if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID())
 
443
    {
 
444
      cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.",
 
445
                      (int)CFDictionaryGetCount(btmm));
 
446
      CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL);
 
447
    }
 
448
    else if (btmm)
 
449
      cupsdLogMessage(CUPSD_LOG_ERROR,
 
450
                      "Bad Back to My Mac data in dynamic store!");
 
451
    else
 
452
      cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add.");
 
453
 
 
454
    if (btmm)
 
455
      CFRelease(btmm);
 
456
 
 
457
    CFRelease(sc);
 
458
  }
 
459
  else
 
460
#  endif /* __APPLE__ */
 
461
#  ifdef HAVE_AVAHI
 
462
  if (DNSSDClient)
 
463
  {
 
464
    const char  *host_name = avahi_client_get_host_name(DNSSDClient);
 
465
    const char  *host_fqdn = avahi_client_get_host_name_fqdn(DNSSDClient);
 
466
 
 
467
    cupsdSetString(&DNSSDComputerName, host_name ? host_name : ServerName);
 
468
 
 
469
    if (host_fqdn)
 
470
      cupsdSetString(&DNSSDHostName, host_fqdn);
 
471
    else if (strchr(ServerName, '.'))
 
472
      cupsdSetString(&DNSSDHostName, ServerName);
 
473
    else
 
474
      cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName);
 
475
  }
 
476
  else
 
477
#  endif /* HAVE_AVAHI */
 
478
  {
 
479
    cupsdSetString(&DNSSDComputerName, ServerName);
 
480
 
 
481
    if (strchr(ServerName, '.'))
 
482
      cupsdSetString(&DNSSDHostName, ServerName);
 
483
    else
 
484
      cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName);
 
485
  }
 
486
 
 
487
 /*
 
488
  * Then (re)register the web interface if enabled...
 
489
  */
 
490
 
 
491
  if (BrowseWebIF)
 
492
  {
 
493
    if (DNSSDComputerName)
 
494
      snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName);
 
495
    else
 
496
      strlcpy(webif, "CUPS", sizeof(webif));
 
497
 
 
498
    dnssdDeregisterInstance(&WebIFSrv);
 
499
    dnssdRegisterInstance(&WebIFSrv, NULL, webif, "_http._tcp", "_printer",
 
500
                          DNSSDPort, NULL, 1);
 
501
  }
 
502
}
 
503
 
 
504
 
 
505
#  ifdef __APPLE__
 
506
/*
 
507
 * 'dnssdAddAlias()' - Add a DNS-SD alias name.
 
508
 */
 
509
 
 
510
static void
 
511
dnssdAddAlias(const void *key,          /* I - Key */
 
512
              const void *value,        /* I - Value (domain) */
 
513
              void       *context)      /* I - Unused */
 
514
{
 
515
  char  valueStr[1024],                 /* Domain string */
 
516
        hostname[1024],                 /* Complete hostname */
 
517
        *hostptr;                       /* Pointer into hostname */
 
518
 
 
519
 
 
520
  (void)key;
 
521
  (void)context;
 
522
 
 
523
  if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() &&
 
524
      CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr),
 
525
                         kCFStringEncodingUTF8))
 
526
  {
 
527
    snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr);
 
528
    hostptr = hostname + strlen(hostname) - 1;
 
529
    if (*hostptr == '.')
 
530
      *hostptr = '\0';                  /* Strip trailing dot */
 
531
 
 
532
    if (!DNSSDAlias)
 
533
      DNSSDAlias = cupsArrayNew(NULL, NULL);
 
534
 
 
535
    cupsdAddAlias(DNSSDAlias, hostname);
 
536
    cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s",
 
537
                    hostname);
 
538
  }
 
539
  else
 
540
    cupsdLogMessage(CUPSD_LOG_ERROR,
 
541
                    "Bad Back to My Mac domain in dynamic store!");
 
542
}
 
543
#  endif /* __APPLE__ */
 
544
 
 
545
 
 
546
/*
 
547
 * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
 
548
 */
 
549
 
 
550
static cupsd_txt_t                      /* O - TXT record */
 
551
dnssdBuildTxtRecord(
 
552
    cupsd_printer_t *p,                 /* I - Printer information */
 
553
    int             for_lpd)            /* I - 1 = LPD, 0 = IPP */
 
554
{
 
555
  int           i,                      /* Looping var */
 
556
                count;                  /* Count of key/value pairs */
 
557
  char          admin_hostname[256],    /* .local hostname for admin page */
 
558
                adminurl_str[256],      /* URL for the admin page */
 
559
                type_str[32],           /* Type to string buffer */
 
560
                state_str[32],          /* State to string buffer */
 
561
                rp_str[1024],           /* Queue name string buffer */
 
562
                air_str[1024],          /* auth-info-required string buffer */
 
563
                *keyvalue[32][2];       /* Table of key/value pairs */
 
564
  cupsd_txt_t   txt;                    /* TXT record */
 
565
 
 
566
 
 
567
 /*
 
568
  * Load up the key value pairs...
 
569
  */
 
570
 
 
571
  count = 0;
 
572
 
 
573
  if (!for_lpd || (BrowseLocalProtocols & BROWSE_LPD))
 
574
  {
 
575
    keyvalue[count  ][0] = "txtvers";
 
576
    keyvalue[count++][1] = "1";
 
577
 
 
578
    keyvalue[count  ][0] = "qtotal";
 
579
    keyvalue[count++][1] = "1";
 
580
 
 
581
    keyvalue[count  ][0] = "rp";
 
582
    keyvalue[count++][1] = rp_str;
 
583
    if (for_lpd)
 
584
      strlcpy(rp_str, p->name, sizeof(rp_str));
 
585
    else
 
586
      snprintf(rp_str, sizeof(rp_str), "%s/%s",
 
587
               (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
 
588
               p->name);
 
589
 
 
590
    keyvalue[count  ][0] = "ty";
 
591
    keyvalue[count++][1] = p->make_model ? p->make_model : "Unknown";
 
592
 
 
593
    if (strstr(DNSSDHostName, ".local"))
 
594
      strlcpy(admin_hostname, DNSSDHostName, sizeof(admin_hostname));
 
595
    else
 
596
      snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.",
 
597
               DNSSDHostName);
 
598
    httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
 
599
#  ifdef HAVE_SSL
 
600
                     "https",
 
601
#  else
 
602
                     "http",
 
603
#  endif /* HAVE_SSL */
 
604
                     NULL, admin_hostname, DNSSDPort, "/%s/%s",
 
605
                     (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
 
606
                     p->name);
 
607
    keyvalue[count  ][0] = "adminurl";
 
608
    keyvalue[count++][1] = adminurl_str;
 
609
 
 
610
    if (p->location)
 
611
    {
 
612
      keyvalue[count  ][0] = "note";
 
613
      keyvalue[count++][1] = p->location;
 
614
    }
 
615
 
 
616
    keyvalue[count  ][0] = "priority";
 
617
    keyvalue[count++][1] = for_lpd ? "100" : "0";
 
618
 
 
619
    keyvalue[count  ][0] = "product";
 
620
    keyvalue[count++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown";
 
621
 
 
622
    keyvalue[count  ][0] = "pdl";
 
623
    keyvalue[count++][1] = p->pdl ? p->pdl : "application/postscript";
 
624
 
 
625
    /* iOS 6 does not accept this printer as AirPrint printer if there is
 
626
       no URF txt record or "URF=none", "DM3" is the minimum needed found
 
627
       by try and error */
 
628
    keyvalue[count  ][0] = "URF";
 
629
    keyvalue[count++][1] = "DM3";
 
630
 
 
631
    if (get_auth_info_required(p, air_str, sizeof(air_str)))
 
632
    {
 
633
      keyvalue[count  ][0] = "air";
 
634
      keyvalue[count++][1] = air_str;
 
635
    }
 
636
 
 
637
    keyvalue[count  ][0] = "UUID";
 
638
    keyvalue[count++][1] = p->uuid + 9;
 
639
 
 
640
  #ifdef HAVE_SSL
 
641
    keyvalue[count  ][0] = "TLS";
 
642
    keyvalue[count++][1] = "1.2";
 
643
  #endif /* HAVE_SSL */
 
644
 
 
645
    if (p->type & CUPS_PRINTER_FAX)
 
646
    {
 
647
      keyvalue[count  ][0] = "Fax";
 
648
      keyvalue[count++][1] = "T";
 
649
      keyvalue[count  ][0] = "rfo";
 
650
      keyvalue[count++][1] = rp_str;
 
651
    }
 
652
 
 
653
    if (p->type & CUPS_PRINTER_COLOR)
 
654
    {
 
655
      keyvalue[count  ][0] = "Color";
 
656
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F";
 
657
    }
 
658
 
 
659
    if (p->type & CUPS_PRINTER_DUPLEX)
 
660
    {
 
661
      keyvalue[count  ][0] = "Duplex";
 
662
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F";
 
663
    }
 
664
 
 
665
    if (p->type & CUPS_PRINTER_STAPLE)
 
666
    {
 
667
      keyvalue[count  ][0] = "Staple";
 
668
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F";
 
669
    }
 
670
 
 
671
    if (p->type & CUPS_PRINTER_COPIES)
 
672
    {
 
673
      keyvalue[count  ][0] = "Copies";
 
674
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F";
 
675
    }
 
676
 
 
677
    if (p->type & CUPS_PRINTER_COLLATE)
 
678
    {
 
679
      keyvalue[count  ][0] = "Collate";
 
680
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F";
 
681
    }
 
682
 
 
683
    if (p->type & CUPS_PRINTER_PUNCH)
 
684
    {
 
685
      keyvalue[count  ][0] = "Punch";
 
686
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F";
 
687
    }
 
688
 
 
689
    if (p->type & CUPS_PRINTER_BIND)
 
690
    {
 
691
      keyvalue[count  ][0] = "Bind";
 
692
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F";
 
693
    }
 
694
 
 
695
    if (p->type & CUPS_PRINTER_SORT)
 
696
    {
 
697
      keyvalue[count  ][0] = "Sort";
 
698
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F";
 
699
    }
 
700
 
 
701
    if (p->type & CUPS_PRINTER_MFP)
 
702
    {
 
703
      keyvalue[count  ][0] = "Scan";
 
704
      keyvalue[count++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F";
 
705
    }
 
706
 
 
707
    snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE);
 
708
    snprintf(state_str, sizeof(state_str), "%d", p->state);
 
709
 
 
710
    keyvalue[count  ][0] = "printer-state";
 
711
    keyvalue[count++][1] = state_str;
 
712
 
 
713
    keyvalue[count  ][0] = "printer-type";
 
714
    keyvalue[count++][1] = type_str;
 
715
  }
 
716
 
 
717
 /*
 
718
  * Then pack them into a proper txt record...
 
719
  */
 
720
 
 
721
#  ifdef HAVE_DNSSD
 
722
  TXTRecordCreate(&txt, 0, NULL);
 
723
 
 
724
  for (i = 0; i < count; i ++)
 
725
  {
 
726
    size_t len = strlen(keyvalue[i][1]);
 
727
 
 
728
    if (len < 256)
 
729
      TXTRecordSetValue(&txt, keyvalue[i][0], (uint8_t)len, keyvalue[i][1]);
 
730
  }
 
731
 
 
732
#  else
 
733
  for (i = 0, txt = NULL; i < count; i ++)
 
734
    txt = avahi_string_list_add_printf(txt, "%s=%s", keyvalue[i][0],
 
735
                                       keyvalue[i][1]);
 
736
#  endif /* HAVE_DNSSD */
 
737
 
 
738
  return (txt);
 
739
}
 
740
 
 
741
 
 
742
/*
 
743
 * 'dnssdDeregisterInstance()' - Deregister a DNS-SD service instance.
 
744
 */
 
745
 
 
746
static void
 
747
dnssdDeregisterInstance(
 
748
    cupsd_srv_t     *srv)               /* I - Service */
 
749
{
 
750
  if (!srv || !*srv)
 
751
    return;
 
752
 
 
753
#  ifdef HAVE_DNSSD
 
754
  DNSServiceRefDeallocate(*srv);
 
755
 
 
756
#  else /* HAVE_AVAHI */
 
757
  avahi_threaded_poll_lock(DNSSDMaster);
 
758
  avahi_entry_group_free(*srv);
 
759
  avahi_threaded_poll_unlock(DNSSDMaster);
 
760
#  endif /* HAVE_DNSSD */
 
761
 
 
762
  *srv = NULL;
 
763
}
 
764
 
 
765
 
 
766
/*
 
767
 * 'dnssdDeregisterPrinter()' - Deregister all services for a printer.
 
768
 */
 
769
 
 
770
static void
 
771
dnssdDeregisterPrinter(
 
772
    cupsd_printer_t *p,                 /* I - Printer */
 
773
    int             clear_name)         /* I - Clear the name? */
 
774
 
 
775
{
 
776
  cupsdLogMessage(CUPSD_LOG_DEBUG2,
 
777
                  "dnssdDeregisterPrinter(p=%p(%s), clear_name=%d)", p, p->name,
 
778
                  clear_name);
 
779
 
 
780
  if (p->ipp_srv)
 
781
  {
 
782
    dnssdDeregisterInstance(&p->ipp_srv);
 
783
 
 
784
#  ifdef HAVE_DNSSD
 
785
#    ifdef HAVE_SSL
 
786
    dnssdDeregisterInstance(&p->ipps_srv);
 
787
#    endif /* HAVE_SSL */
 
788
    dnssdDeregisterInstance(&p->printer_srv);
 
789
#  endif /* HAVE_DNSSD */
 
790
  }
 
791
 
 
792
 /*
 
793
  * Remove the printer from the array of DNS-SD printers but keep the
 
794
  * registered name...
 
795
  */
 
796
 
 
797
  cupsArrayRemove(DNSSDPrinters, p);
 
798
 
 
799
 /*
 
800
  * Optionally clear the service name...
 
801
  */
 
802
 
 
803
  if (clear_name)
 
804
    cupsdClearString(&p->reg_name);
 
805
}
 
806
 
 
807
 
 
808
/*
 
809
 * 'dnssdErrorString()' - Return an error string for an error code.
 
810
 */
 
811
 
 
812
static const char *                     /* O - Error message */
 
813
dnssdErrorString(int error)             /* I - Error number */
 
814
{
 
815
#  ifdef HAVE_DNSSD
 
816
  switch (error)
 
817
  {
 
818
    case kDNSServiceErr_NoError :
 
819
        return ("OK.");
 
820
 
 
821
    default :
 
822
    case kDNSServiceErr_Unknown :
 
823
        return ("Unknown error.");
 
824
 
 
825
    case kDNSServiceErr_NoSuchName :
 
826
        return ("Service not found.");
 
827
 
 
828
    case kDNSServiceErr_NoMemory :
 
829
        return ("Out of memory.");
 
830
 
 
831
    case kDNSServiceErr_BadParam :
 
832
        return ("Bad parameter.");
 
833
 
 
834
    case kDNSServiceErr_BadReference :
 
835
        return ("Bad service reference.");
 
836
 
 
837
    case kDNSServiceErr_BadState :
 
838
        return ("Bad state.");
 
839
 
 
840
    case kDNSServiceErr_BadFlags :
 
841
        return ("Bad flags.");
 
842
 
 
843
    case kDNSServiceErr_Unsupported :
 
844
        return ("Unsupported.");
 
845
 
 
846
    case kDNSServiceErr_NotInitialized :
 
847
        return ("Not initialized.");
 
848
 
 
849
    case kDNSServiceErr_AlreadyRegistered :
 
850
        return ("Already registered.");
 
851
 
 
852
    case kDNSServiceErr_NameConflict :
 
853
        return ("Name conflict.");
 
854
 
 
855
    case kDNSServiceErr_Invalid :
 
856
        return ("Invalid name.");
 
857
 
 
858
    case kDNSServiceErr_Firewall :
 
859
        return ("Firewall prevents registration.");
 
860
 
 
861
    case kDNSServiceErr_Incompatible :
 
862
        return ("Client library incompatible.");
 
863
 
 
864
    case kDNSServiceErr_BadInterfaceIndex :
 
865
        return ("Bad interface index.");
 
866
 
 
867
    case kDNSServiceErr_Refused :
 
868
        return ("Server prevents registration.");
 
869
 
 
870
    case kDNSServiceErr_NoSuchRecord :
 
871
        return ("Record not found.");
 
872
 
 
873
    case kDNSServiceErr_NoAuth :
 
874
        return ("Authentication required.");
 
875
 
 
876
    case kDNSServiceErr_NoSuchKey :
 
877
        return ("Encryption key not found.");
 
878
 
 
879
    case kDNSServiceErr_NATTraversal :
 
880
        return ("Unable to traverse NAT boundary.");
 
881
 
 
882
    case kDNSServiceErr_DoubleNAT :
 
883
        return ("Unable to traverse double-NAT boundary.");
 
884
 
 
885
    case kDNSServiceErr_BadTime :
 
886
        return ("Bad system time.");
 
887
 
 
888
    case kDNSServiceErr_BadSig :
 
889
        return ("Bad signature.");
 
890
 
 
891
    case kDNSServiceErr_BadKey :
 
892
        return ("Bad encryption key.");
 
893
 
 
894
    case kDNSServiceErr_Transient :
 
895
        return ("Transient error occurred - please try again.");
 
896
 
 
897
    case kDNSServiceErr_ServiceNotRunning :
 
898
        return ("Server not running.");
 
899
 
 
900
    case kDNSServiceErr_NATPortMappingUnsupported :
 
901
        return ("NAT doesn't support NAT-PMP or UPnP.");
 
902
 
 
903
    case kDNSServiceErr_NATPortMappingDisabled :
 
904
        return ("NAT supports NAT-PNP or UPnP but it is disabled.");
 
905
 
 
906
    case kDNSServiceErr_NoRouter :
 
907
        return ("No Internet/default router configured.");
 
908
 
 
909
    case kDNSServiceErr_PollingMode :
 
910
        return ("Service polling mode error.");
 
911
 
 
912
    case kDNSServiceErr_Timeout :
 
913
        return ("Service timeout.");
 
914
  }
 
915
 
 
916
#  else /* HAVE_AVAHI */
 
917
  return (avahi_strerror(error));
 
918
#  endif /* HAVE_DNSSD */
 
919
}
 
920
 
 
921
 
 
922
/*
 
923
 * 'dnssdRegisterCallback()' - Free a TXT record.
 
924
 */
 
925
 
 
926
static void
 
927
dnssdFreeTxtRecord(cupsd_txt_t *txt)    /* I - TXT record */
 
928
{
 
929
#  ifdef HAVE_DNSSD
 
930
  TXTRecordDeallocate(txt);
 
931
 
 
932
#  else /* HAVE_AVAHI */
 
933
  avahi_string_list_free(*txt);
 
934
  *txt = NULL;
 
935
#  endif /* HAVE_DNSSD */
 
936
}
 
937
 
 
938
 
 
939
/*
 
940
 * 'dnssdRegisterCallback()' - DNSServiceRegister callback.
 
941
 */
 
942
 
 
943
#  ifdef HAVE_DNSSD
 
944
static void
 
945
dnssdRegisterCallback(
 
946
    DNSServiceRef       sdRef,          /* I - DNS Service reference */
 
947
    DNSServiceFlags     flags,          /* I - Reserved for future use */
 
948
    DNSServiceErrorType errorCode,      /* I - Error code */
 
949
    const char          *name,          /* I - Service name */
 
950
    const char          *regtype,       /* I - Service type */
 
951
    const char          *domain,        /* I - Domain. ".local" for now */
 
952
    void                *context)       /* I - Printer */
 
953
{
 
954
  cupsd_printer_t *p = (cupsd_printer_t *)context;
 
955
                                        /* Current printer */
 
956
 
 
957
 
 
958
  (void)sdRef;
 
959
  (void)flags;
 
960
  (void)domain;
 
961
 
 
962
  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)",
 
963
                  name, regtype, p ? p->name : "Web Interface",
 
964
                  p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
 
965
 
 
966
  if (errorCode)
 
967
  {
 
968
    cupsdLogMessage(CUPSD_LOG_ERROR,
 
969
                    "DNSServiceRegister failed with error %d", (int)errorCode);
 
970
    return;
 
971
  }
 
972
  else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name)))
 
973
  {
 
974
    cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"",
 
975
                    name, p->name);
 
976
 
 
977
    cupsArrayRemove(DNSSDPrinters, p);
 
978
    cupsdSetString(&p->reg_name, name);
 
979
    cupsArrayAdd(DNSSDPrinters, p);
 
980
 
 
981
    LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
 
982
  }
 
983
}
 
984
 
 
985
#  else /* HAVE_AVAHI */
 
986
static void
 
987
dnssdRegisterCallback(
 
988
    AvahiEntryGroup      *srv,          /* I - Service */
 
989
    AvahiEntryGroupState state,         /* I - Registration state */
 
990
    void                 *context)      /* I - Printer */
 
991
{
 
992
  cupsd_printer_t *p = (cupsd_printer_t *)context;
 
993
                                        /* Current printer */
 
994
 
 
995
  cupsdLogMessage(CUPSD_LOG_DEBUG2,
 
996
                  "dnssdRegisterCallback(srv=%p, state=%d, context=%p) "
 
997
                  "for %s (%s)", srv, state, context,
 
998
                  p ? p->name : "Web Interface",
 
999
                  p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
 
1000
 
 
1001
  /* TODO: Handle collisions with avahi_alternate_service_name(p->reg_name)? */
 
1002
}
 
1003
#  endif /* HAVE_DNSSD */
 
1004
 
 
1005
 
 
1006
/*
 
1007
 * 'dnssdRegisterInstance()' - Register an instance of a printer service.
 
1008
 */
 
1009
 
 
1010
static int                              /* O - 1 on success, 0 on failure */
 
1011
dnssdRegisterInstance(
 
1012
    cupsd_srv_t     *srv,               /* O - Service */
 
1013
    cupsd_printer_t *p,                 /* I - Printer */
 
1014
    char            *name,              /* I - DNS-SD service name */
 
1015
    const char      *type,              /* I - DNS-SD service type */
 
1016
    const char      *subtypes,          /* I - Subtypes to register or NULL */
 
1017
    int             port,               /* I - Port number or 0 */
 
1018
    cupsd_txt_t     *txt,               /* I - TXT record */
 
1019
    int             commit)             /* I - Commit registration? */
 
1020
{
 
1021
  char  temp[256],                      /* Temporary string */
 
1022
        *ptr;                           /* Pointer into string */
 
1023
  int   error;                          /* Any error */
 
1024
 
 
1025
 
 
1026
  cupsdLogMessage(CUPSD_LOG_DEBUG,
 
1027
                  "Registering \"%s\" with DNS-SD type \"%s\".", name, type);
 
1028
 
 
1029
  if (p && !srv)
 
1030
  {
 
1031
   /*
 
1032
    * Assign the correct pointer for "srv"...
 
1033
    */
 
1034
 
 
1035
#  ifdef HAVE_DNSSD
 
1036
    if (!strcmp(type, "_printer._tcp"))
 
1037
      srv = &p->printer_srv;            /* Target LPD service */
 
1038
#    ifdef HAVE_SSL
 
1039
    else if (!strcmp(type, "_ipps._tcp"))
 
1040
      srv = &p->ipps_srv;               /* Target IPPS service */
 
1041
#    endif /* HAVE_SSL */
 
1042
    else
 
1043
      srv = &p->ipp_srv;                /* Target IPP service */
 
1044
 
 
1045
#  else /* HAVE_AVAHI */
 
1046
    srv = &p->ipp_srv;                  /* Target service group */
 
1047
#  endif /* HAVE_DNSSD */
 
1048
  }
 
1049
 
 
1050
#  ifdef HAVE_DNSSD
 
1051
  (void)commit;
 
1052
 
 
1053
#  else /* HAVE_AVAHI */
 
1054
  avahi_threaded_poll_lock(DNSSDMaster);
 
1055
 
 
1056
  if (!*srv)
 
1057
    *srv = avahi_entry_group_new(DNSSDClient, dnssdRegisterCallback, NULL);
 
1058
  if (!*srv)
 
1059
  {
 
1060
    avahi_threaded_poll_unlock(DNSSDMaster);
 
1061
 
 
1062
    cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s",
 
1063
                    name, dnssdErrorString(avahi_client_errno(DNSSDClient)));
 
1064
    return (0);
 
1065
  }
 
1066
#  endif /* HAVE_DNSSD */
 
1067
 
 
1068
 /*
 
1069
  * Make sure the name is <= 63 octets, and when we truncate be sure to
 
1070
  * properly truncate any UTF-8 characters...
 
1071
  */
 
1072
 
 
1073
  ptr = name + strlen(name);
 
1074
  while ((ptr - name) > 63)
 
1075
  {
 
1076
    do
 
1077
    {
 
1078
      ptr --;
 
1079
    }
 
1080
    while (ptr > name && (*ptr & 0xc0) == 0x80);
 
1081
 
 
1082
    if (ptr > name)
 
1083
      *ptr = '\0';
 
1084
  }
 
1085
 
 
1086
 /*
 
1087
  * Register the service...
 
1088
  */
 
1089
 
 
1090
#  ifdef HAVE_DNSSD
 
1091
  if (subtypes)
 
1092
    snprintf(temp, sizeof(temp), "%s,%s", type, subtypes);
 
1093
  else
 
1094
    strlcpy(temp, type, sizeof(temp));
 
1095
 
 
1096
  *srv  = DNSSDMaster;
 
1097
  error = DNSServiceRegister(srv, kDNSServiceFlagsShareConnection,
 
1098
                             0, name, temp, NULL, NULL, htons(port),
 
1099
                             txt ? TXTRecordGetLength(txt) : 0,
 
1100
                             txt ? TXTRecordGetBytesPtr(txt) : NULL,
 
1101
                             dnssdRegisterCallback, p);
 
1102
 
 
1103
#  else /* HAVE_AVAHI */
 
1104
  if (txt)
 
1105
  {
 
1106
    AvahiStringList *temptxt;
 
1107
    for (temptxt = *txt; temptxt; temptxt = temptxt->next)
 
1108
      cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS_SD \"%s\" %s", name, temptxt->text);
 
1109
  }
 
1110
 
 
1111
  error = avahi_entry_group_add_service_strlst(*srv, AVAHI_IF_UNSPEC,
 
1112
                                               AVAHI_PROTO_UNSPEC, 0, name,
 
1113
                                               type, NULL, NULL, port,
 
1114
                                               txt ? *txt : NULL);
 
1115
  if (error)
 
1116
    cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD service add for \"%s\" failed.",
 
1117
                    name);
 
1118
 
 
1119
  if (!error && subtypes)
 
1120
  {
 
1121
   /*
 
1122
    * Register all of the subtypes...
 
1123
    */
 
1124
 
 
1125
    char        *start,                 /* Start of subtype */
 
1126
                subtype[256];           /* Subtype string */
 
1127
 
 
1128
    strlcpy(temp, subtypes, sizeof(temp));
 
1129
 
 
1130
    for (start = temp; *start; start = ptr)
 
1131
    {
 
1132
     /*
 
1133
      * Skip leading whitespace...
 
1134
      */
 
1135
 
 
1136
      while (*start && isspace(*start & 255))
 
1137
        start ++;
 
1138
 
 
1139
     /*
 
1140
      * Grab everything up to the next comma or the end of the string...
 
1141
      */
 
1142
 
 
1143
      for (ptr = start; *ptr && *ptr != ','; ptr ++);
 
1144
 
 
1145
      if (*ptr)
 
1146
        *ptr++ = '\0';
 
1147
 
 
1148
      if (!*start)
 
1149
        break;
 
1150
 
 
1151
     /*
 
1152
      * Register the subtype...
 
1153
      */
 
1154
 
 
1155
      snprintf(subtype, sizeof(subtype), "%s._sub.%s", start, type);
 
1156
 
 
1157
      error = avahi_entry_group_add_service_subtype(*srv, AVAHI_IF_UNSPEC,
 
1158
                                                    AVAHI_PROTO_UNSPEC, 0,
 
1159
                                                    name, type, NULL, subtype);
 
1160
      if (error)
 
1161
      {
 
1162
        cupsdLogMessage(CUPSD_LOG_DEBUG,
 
1163
                        "DNS-SD subtype %s registration for \"%s\" failed." ,
 
1164
                        subtype, name);
 
1165
        break;
 
1166
      }
 
1167
    }
 
1168
  }
 
1169
 
 
1170
  if (!error && commit)
 
1171
  {
 
1172
    if ((error = avahi_entry_group_commit(*srv)) != 0)
 
1173
      cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD commit of \"%s\" failed.",
 
1174
                      name);
 
1175
  }
 
1176
 
 
1177
  avahi_threaded_poll_unlock(DNSSDMaster);
 
1178
#  endif /* HAVE_DNSSD */
 
1179
 
 
1180
  if (error)
 
1181
  {
 
1182
    cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s",
 
1183
                    name, dnssdErrorString(error));
 
1184
    cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD type: %s", type);
 
1185
    if (subtypes)
 
1186
      cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD sub-types: %s", subtypes);
 
1187
  }
 
1188
 
 
1189
  return (!error);
 
1190
}
 
1191
 
 
1192
 
 
1193
/*
 
1194
 * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
 
1195
 *                            or update the broadcast contents.
 
1196
 */
 
1197
 
 
1198
static void
 
1199
dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
 
1200
{
 
1201
  char          name[256];              /* Service name */
 
1202
  int           printer_port;           /* LPD port number */
 
1203
  int           status;                 /* Registration status */
 
1204
  cupsd_txt_t   ipp_txt,                /* IPP(S) TXT record */
 
1205
                printer_txt;            /* LPD TXT record */
 
1206
 
 
1207
  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
 
1208
                  !p->ipp_srv ? "new" : "update");
 
1209
 
 
1210
 /*
 
1211
  * Remove the current registrations if we have them and then return if
 
1212
  * per-printer sharing was just disabled...
 
1213
  */
 
1214
 
 
1215
  dnssdDeregisterPrinter(p, 0);
 
1216
 
 
1217
  if (!p->shared)
 
1218
    return;
 
1219
 
 
1220
 /*
 
1221
  * Set the registered name as needed; the registered name takes the form of
 
1222
  * "<printer-info> @ <computer name>"...
 
1223
  */
 
1224
 
 
1225
  if (!p->reg_name)
 
1226
  {
 
1227
    if (p->info && strlen(p->info) > 0)
 
1228
    {
 
1229
      if (DNSSDComputerName)
 
1230
        snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
 
1231
      else
 
1232
        strlcpy(name, p->info, sizeof(name));
 
1233
    }
 
1234
    else if (DNSSDComputerName)
 
1235
      snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
 
1236
    else
 
1237
      strlcpy(name, p->name, sizeof(name));
 
1238
  }
 
1239
  else
 
1240
    strlcpy(name, p->reg_name, sizeof(name));
 
1241
 
 
1242
 /*
 
1243
  * Register IPP and LPD...
 
1244
  *
 
1245
  * We always must register the "_printer" service type in order to reserve
 
1246
  * our name, but use port number 0 if we haven't actually configured cups-lpd
 
1247
  * to share via LPD...
 
1248
  */
 
1249
 
 
1250
  ipp_txt     = dnssdBuildTxtRecord(p, 0);
 
1251
  printer_txt = dnssdBuildTxtRecord(p, 1);
 
1252
 
 
1253
  if (BrowseLocalProtocols & BROWSE_LPD)
 
1254
    printer_port = 515;
 
1255
  else
 
1256
    printer_port = 0;
 
1257
 
 
1258
  status = dnssdRegisterInstance(NULL, p, name, "_printer._tcp", NULL,
 
1259
                                 printer_port, &printer_txt, 0);
 
1260
 
 
1261
#  ifdef HAVE_SSL
 
1262
  if (status)
 
1263
    dnssdRegisterInstance(NULL, p, name, "_ipps._tcp", DNSSDSubTypes,
 
1264
                          DNSSDPort, &ipp_txt, 0);
 
1265
#  endif /* HAVE_SSL */
 
1266
 
 
1267
  if (status)
 
1268
  {
 
1269
   /*
 
1270
    * Use the "_fax-ipp" service type for fax queues, otherwise use "_ipp"...
 
1271
    */
 
1272
 
 
1273
    if (p->type & CUPS_PRINTER_FAX)
 
1274
      status = dnssdRegisterInstance(NULL, p, name, "_fax-ipp._tcp",
 
1275
                                     DNSSDSubTypes, DNSSDPort, &ipp_txt, 1);
 
1276
    else
 
1277
      status = dnssdRegisterInstance(NULL, p, name, "_ipp._tcp", DNSSDSubTypes,
 
1278
                                     DNSSDPort, &ipp_txt, 1);
 
1279
  }
 
1280
 
 
1281
  dnssdFreeTxtRecord(&ipp_txt);
 
1282
  dnssdFreeTxtRecord(&printer_txt);
 
1283
 
 
1284
  if (status)
 
1285
  {
 
1286
   /*
 
1287
    * Save the registered name and add the printer to the array of DNS-SD
 
1288
    * printers...
 
1289
    */
 
1290
 
 
1291
    cupsdSetString(&p->reg_name, name);
 
1292
    cupsArrayAdd(DNSSDPrinters, p);
 
1293
  }
 
1294
  else
 
1295
  {
 
1296
   /*
 
1297
    * Registration failed for this printer...
 
1298
    */
 
1299
 
 
1300
    dnssdDeregisterInstance(&p->ipp_srv);
 
1301
 
 
1302
#  ifdef HAVE_DNSSD
 
1303
#    ifdef HAVE_SSL
 
1304
    dnssdDeregisterInstance(&p->ipps_srv);
 
1305
#    endif /* HAVE_SSL */
 
1306
    dnssdDeregisterInstance(&p->printer_srv);
 
1307
#  endif /* HAVE_DNSSD */
 
1308
  }
 
1309
}
 
1310
 
 
1311
 
 
1312
/*
 
1313
 * 'dnssdStop()' - Stop all DNS-SD registrations.
 
1314
 */
 
1315
 
 
1316
static void
 
1317
dnssdStop(void)
 
1318
{
 
1319
  cupsd_printer_t       *p;             /* Current printer */
 
1320
 
 
1321
 
 
1322
 /*
 
1323
  * De-register the individual printers
 
1324
  */
 
1325
 
 
1326
  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
 
1327
       p;
 
1328
       p = (cupsd_printer_t *)cupsArrayNext(Printers))
 
1329
    dnssdDeregisterPrinter(p, 1);
 
1330
 
 
1331
 /*
 
1332
  * Shutdown the rest of the service refs...
 
1333
  */
 
1334
 
 
1335
  dnssdDeregisterInstance(&WebIFSrv);
 
1336
 
 
1337
#  ifdef HAVE_DNSSD
 
1338
  cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDMaster));
 
1339
 
 
1340
  DNSServiceRefDeallocate(DNSSDMaster);
 
1341
  DNSSDMaster = NULL;
 
1342
 
 
1343
#  else /* HAVE_AVAHI */
 
1344
  avahi_threaded_poll_stop(DNSSDMaster);
 
1345
 
 
1346
  avahi_client_free(DNSSDClient);
 
1347
  DNSSDClient = NULL;
 
1348
 
 
1349
  avahi_threaded_poll_free(DNSSDMaster);
 
1350
  DNSSDMaster = NULL;
 
1351
#  endif /* HAVE_DNSSD */
 
1352
 
 
1353
  cupsArrayDelete(DNSSDPrinters);
 
1354
  DNSSDPrinters = NULL;
 
1355
 
 
1356
  DNSSDPort = 0;
 
1357
}
 
1358
 
 
1359
 
 
1360
#  ifdef HAVE_DNSSD
 
1361
/*
 
1362
 * 'dnssdUpdate()' - Handle DNS-SD queries.
 
1363
 */
 
1364
 
 
1365
static void
 
1366
dnssdUpdate(void)
 
1367
{
 
1368
  DNSServiceErrorType   sdErr;          /* Service discovery error */
 
1369
 
 
1370
 
 
1371
  if ((sdErr = DNSServiceProcessResult(DNSSDMaster)) != kDNSServiceErr_NoError)
 
1372
  {
 
1373
    cupsdLogMessage(CUPSD_LOG_ERROR,
 
1374
                    "DNS Service Discovery registration error %d!",
 
1375
                    sdErr);
 
1376
    dnssdStop();
 
1377
  }
 
1378
}
 
1379
#  endif /* HAVE_DNSSD */
 
1380
 
 
1381
 
 
1382
/*
 
1383
 * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
 
1384
 */
 
1385
 
 
1386
static char *                           /* O - String or NULL if none */
 
1387
get_auth_info_required(
 
1388
    cupsd_printer_t *p,                 /* I - Printer */
 
1389
    char            *buffer,            /* I - Value buffer */
 
1390
    size_t          bufsize)            /* I - Size of value buffer */
 
1391
{
 
1392
  cupsd_location_t *auth;               /* Pointer to authentication element */
 
1393
  char          resource[1024];         /* Printer/class resource path */
 
1394
 
 
1395
 
 
1396
 /*
 
1397
  * If auth-info-required is set for this printer, return that...
 
1398
  */
 
1399
 
 
1400
  if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none"))
 
1401
  {
 
1402
    int         i;                      /* Looping var */
 
1403
    char        *bufptr;                /* Pointer into buffer */
 
1404
 
 
1405
    for (i = 0, bufptr = buffer; i < p->num_auth_info_required; i ++)
 
1406
    {
 
1407
      if (bufptr >= (buffer + bufsize - 2))
 
1408
        break;
 
1409
 
 
1410
      if (i)
 
1411
        *bufptr++ = ',';
 
1412
 
 
1413
      strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer));
 
1414
      bufptr += strlen(bufptr);
 
1415
    }
 
1416
 
 
1417
    return (buffer);
 
1418
  }
 
1419
 
 
1420
 /*
 
1421
  * Figure out the authentication data requirements to advertise...
 
1422
  */
 
1423
 
 
1424
  if (p->type & CUPS_PRINTER_CLASS)
 
1425
    snprintf(resource, sizeof(resource), "/classes/%s", p->name);
 
1426
  else
 
1427
    snprintf(resource, sizeof(resource), "/printers/%s", p->name);
 
1428
 
 
1429
  if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
 
1430
      auth->type == CUPSD_AUTH_NONE)
 
1431
    auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
 
1432
 
 
1433
  if (auth)
 
1434
  {
 
1435
    int auth_type;                      /* Authentication type */
 
1436
 
 
1437
    if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT)
 
1438
      auth_type = cupsdDefaultAuthType();
 
1439
 
 
1440
    switch (auth_type)
 
1441
    {
 
1442
      case CUPSD_AUTH_NONE :
 
1443
          return (NULL);
 
1444
 
 
1445
      case CUPSD_AUTH_NEGOTIATE :
 
1446
          strlcpy(buffer, "negotiate", bufsize);
 
1447
          break;
 
1448
 
 
1449
      default :
 
1450
          strlcpy(buffer, "username,password", bufsize);
 
1451
          break;
 
1452
    }
 
1453
 
 
1454
    return (buffer);
 
1455
  }
 
1456
 
 
1457
  return ("none");
 
1458
}
 
1459
#endif /* HAVE_DNSSD || HAVE_AVAHI */
 
1460
 
 
1461
 
 
1462
#ifdef __APPLE__
 
1463
/*
 
1464
 * 'get_hostconfig()' - Get an /etc/hostconfig service setting.
 
1465
 */
 
1466
 
 
1467
static int                              /* O - 1 for YES or AUTOMATIC, 0 for NO */
 
1468
get_hostconfig(const char *name)        /* I - Name of service */
 
1469
{
 
1470
  cups_file_t   *fp;                    /* Hostconfig file */
 
1471
  char          line[1024],             /* Line from file */
 
1472
                *ptr;                   /* Pointer to value */
 
1473
  int           state = 1;              /* State of service */
 
1474
 
 
1475
 
 
1476
 /*
 
1477
  * Try opening the /etc/hostconfig file; if we can't open it, assume that
 
1478
  * the service is enabled/auto.
 
1479
  */
 
1480
 
 
1481
  if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL)
 
1482
  {
 
1483
   /*
 
1484
    * Read lines from the file until we find the service...
 
1485
    */
 
1486
 
 
1487
    while (cupsFileGets(fp, line, sizeof(line)))
 
1488
    {
 
1489
      if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL)
 
1490
        continue;
 
1491
 
 
1492
      *ptr++ = '\0';
 
1493
 
 
1494
      if (!_cups_strcasecmp(line, name))
 
1495
      {
 
1496
       /*
 
1497
        * Found the service, see if it is set to "-NO-"...
 
1498
        */
 
1499
 
 
1500
        if (!_cups_strncasecmp(ptr, "-NO-", 4))
 
1501
          state = 0;
 
1502
        break;
 
1503
      }
 
1504
    }
 
1505
 
 
1506
    cupsFileClose(fp);
 
1507
  }
 
1508
 
 
1509
  return (state);
 
1510
}
 
1511
#endif /* __APPLE__ */
 
1512
 
 
1513
 
 
1514
/*
 
1515
 * 'update_lpd()' - Update the LPD configuration as needed.
 
1516
 */
 
1517
 
 
1518
static void
 
1519
update_lpd(int onoff)                   /* - 1 = turn on, 0 = turn off */
 
1520
{
 
1521
  if (!LPDConfigFile)
 
1522
    return;
 
1523
 
 
1524
#ifdef __APPLE__
 
1525
 /*
 
1526
  * Allow /etc/hostconfig CUPS_LPD service setting to override cupsd.conf
 
1527
  * setting for backwards-compatibility.
 
1528
  */
 
1529
 
 
1530
  if (onoff && !get_hostconfig("CUPS_LPD"))
 
1531
    onoff = 0;
 
1532
#endif /* __APPLE__ */
 
1533
 
 
1534
  if (!strncmp(LPDConfigFile, "xinetd:///", 10))
 
1535
  {
 
1536
   /*
 
1537
    * Enable/disable LPD via the xinetd.d config file for cups-lpd...
 
1538
    */
 
1539
 
 
1540
    char        newfile[1024];          /* New cups-lpd.N file */
 
1541
    cups_file_t *ofp,                   /* Original file pointer */
 
1542
                *nfp;                   /* New file pointer */
 
1543
    char        line[1024];             /* Line from file */
 
1544
 
 
1545
 
 
1546
    snprintf(newfile, sizeof(newfile), "%s.N", LPDConfigFile + 9);
 
1547
 
 
1548
    if ((ofp = cupsFileOpen(LPDConfigFile + 9, "r")) == NULL)
 
1549
    {
 
1550
      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s",
 
1551
                      LPDConfigFile + 9, strerror(errno));
 
1552
      return;
 
1553
    }
 
1554
 
 
1555
    if ((nfp = cupsFileOpen(newfile, "w")) == NULL)
 
1556
    {
 
1557
      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s",
 
1558
                      newfile, strerror(errno));
 
1559
      cupsFileClose(ofp);
 
1560
      return;
 
1561
    }
 
1562
 
 
1563
   /*
 
1564
    * Copy all of the lines from the cups-lpd file...
 
1565
    */
 
1566
 
 
1567
    while (cupsFileGets(ofp, line, sizeof(line)))
 
1568
    {
 
1569
      if (line[0] == '{')
 
1570
      {
 
1571
        cupsFilePrintf(nfp, "%s\n", line);
 
1572
        snprintf(line, sizeof(line), "\tdisable = %s",
 
1573
                 onoff ? "no" : "yes");
 
1574
      }
 
1575
      else if (!strstr(line, "disable ="))
 
1576
        cupsFilePrintf(nfp, "%s\n", line);
 
1577
    }
 
1578
 
 
1579
    cupsFileClose(nfp);
 
1580
    cupsFileClose(ofp);
 
1581
    rename(newfile, LPDConfigFile + 9);
 
1582
  }
 
1583
#ifdef __APPLE__
 
1584
  else if (!strncmp(LPDConfigFile, "launchd:///", 11))
 
1585
  {
 
1586
   /*
 
1587
    * Enable/disable LPD via the launchctl command...
 
1588
    */
 
1589
 
 
1590
    char        *argv[5],               /* Arguments for command */
 
1591
                *envp[MAX_ENV];         /* Environment for command */
 
1592
    int         pid;                    /* Process ID */
 
1593
 
 
1594
 
 
1595
    cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
 
1596
    argv[0] = (char *)"launchctl";
 
1597
    argv[1] = (char *)(onoff ? "load" : "unload");
 
1598
    argv[2] = (char *)"-w";
 
1599
    argv[3] = LPDConfigFile + 10;
 
1600
    argv[4] = NULL;
 
1601
 
 
1602
    cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1,
 
1603
                      NULL, NULL, &pid);
 
1604
  }
 
1605
#endif /* __APPLE__ */
 
1606
  else
 
1607
    cupsdLogMessage(CUPSD_LOG_INFO, "Unknown LPDConfigFile scheme!");
 
1608
}
 
1609
 
 
1610
 
 
1611
/*
 
1612
 * 'update_smb()' - Update the SMB configuration as needed.
 
1613
 */
 
1614
 
 
1615
static void
 
1616
update_smb(int onoff)                   /* I - 1 = turn on, 0 = turn off */
 
1617
{
 
1618
  if (!SMBConfigFile)
 
1619
    return;
 
1620
 
 
1621
  if (!strncmp(SMBConfigFile, "samba:///", 9))
 
1622
  {
 
1623
   /*
 
1624
    * Enable/disable SMB via the specified smb.conf config file...
 
1625
    */
 
1626
 
 
1627
    char        newfile[1024];          /* New smb.conf.N file */
 
1628
    cups_file_t *ofp,                   /* Original file pointer */
 
1629
                *nfp;                   /* New file pointer */
 
1630
    char        line[1024];             /* Line from file */
 
1631
    int         in_printers;            /* In [printers] section? */
 
1632
 
 
1633
 
 
1634
    snprintf(newfile, sizeof(newfile), "%s.N", SMBConfigFile + 8);
 
1635
 
 
1636
    if ((ofp = cupsFileOpen(SMBConfigFile + 8, "r")) == NULL)
 
1637
    {
 
1638
      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s",
 
1639
                      SMBConfigFile + 8, strerror(errno));
 
1640
      return;
 
1641
    }
 
1642
 
 
1643
    if ((nfp = cupsFileOpen(newfile, "w")) == NULL)
 
1644
    {
 
1645
      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s",
 
1646
                      newfile, strerror(errno));
 
1647
      cupsFileClose(ofp);
 
1648
      return;
 
1649
    }
 
1650
 
 
1651
   /*
 
1652
    * Copy all of the lines from the smb.conf file...
 
1653
    */
 
1654
 
 
1655
    in_printers = 0;
 
1656
 
 
1657
    while (cupsFileGets(ofp, line, sizeof(line)))
 
1658
    {
 
1659
      if (in_printers && strstr(line, "printable ="))
 
1660
        snprintf(line, sizeof(line), "    printable = %s",
 
1661
                 onoff ? "yes" : "no");
 
1662
 
 
1663
      cupsFilePrintf(nfp, "%s\n", line);
 
1664
 
 
1665
      if (line[0] == '[')
 
1666
        in_printers = !strcmp(line, "[printers]");
 
1667
    }
 
1668
 
 
1669
    cupsFileClose(nfp);
 
1670
    cupsFileClose(ofp);
 
1671
    rename(newfile, SMBConfigFile + 8);
 
1672
  }
 
1673
  else
 
1674
    cupsdLogMessage(CUPSD_LOG_INFO, "Unknown SMBConfigFile scheme!");
 
1675
}
 
1676
 
 
1677
 
 
1678
/*
 
1679
 * End of "$Id: dirsvc.c 11193 2013-07-26 03:12:37Z msweet $".
 
1680
 */