2 * Directory services routines for the CUPS scheduler.
4 * Copyright © 2007-2018 by Apple Inc.
5 * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
12 * Include necessary headers...
18 #if defined(HAVE_DNSSD) && defined(__APPLE__)
20 # include <CoreFoundation/CoreFoundation.h>
21 # include <SystemConfiguration/SystemConfiguration.h>
22 #endif /* HAVE_DNSSD && __APPLE__ */
30 static int avahi_running
= 0;
31 #endif /* HAVE_AVAHI */
38 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
39 static char *get_auth_info_required(cupsd_printer_t
*p
,
40 char *buffer
, size_t bufsize
);
41 #endif /* HAVE_DNSSD || HAVE_AVAHI */
43 static int get_hostconfig(const char *name
);
44 #endif /* __APPLE__ */
45 static void update_lpd(int onoff
);
46 static void update_smb(int onoff
);
49 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
51 static void dnssdAddAlias(const void *key
, const void *value
,
53 # endif /* __APPLE__ */
54 static cupsd_txt_t
dnssdBuildTxtRecord(cupsd_printer_t
*p
, int for_lpd
);
56 static void dnssdClientCallback(AvahiClient
*c
, AvahiClientState state
, void *userdata
);
57 # endif /* HAVE_AVAHI */
58 static void dnssdDeregisterAllPrinters(int from_callback
);
59 static void dnssdDeregisterInstance(cupsd_srv_t
*srv
, int from_callback
);
60 static void dnssdDeregisterPrinter(cupsd_printer_t
*p
, int clear_name
, int from_callback
);
61 static const char *dnssdErrorString(int error
);
62 static void dnssdFreeTxtRecord(cupsd_txt_t
*txt
);
63 static void dnssdRegisterAllPrinters(int from_callback
);
65 static void dnssdRegisterCallback(DNSServiceRef sdRef
,
66 DNSServiceFlags flags
,
67 DNSServiceErrorType errorCode
,
73 static void dnssdRegisterCallback(AvahiEntryGroup
*p
,
74 AvahiEntryGroupState state
,
76 # endif /* HAVE_DNSSD */
77 static int dnssdRegisterInstance(cupsd_srv_t
*srv
, cupsd_printer_t
*p
, char *name
, const char *type
, const char *subtypes
, int port
, cupsd_txt_t
*txt
, int commit
, int from_callback
);
78 static void dnssdRegisterPrinter(cupsd_printer_t
*p
, int from_callback
);
79 static void dnssdStop(void);
81 static void dnssdUpdate(void);
82 # endif /* HAVE_DNSSD */
83 static void dnssdUpdateDNSSDName(int from_callback
);
84 #endif /* HAVE_DNSSD || HAVE_AVAHI */
88 * 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a
89 * local printer and remove any pending
90 * references to remote printers.
94 cupsdDeregisterPrinter(
95 cupsd_printer_t
*p
, /* I - Printer to register */
96 int removeit
) /* I - Printer being permanently removed */
99 * Only deregister if browsing is enabled and it's a local printer...
102 cupsdLogMessage(CUPSD_LOG_DEBUG
,
103 "cupsdDeregisterPrinter(p=%p(%s), removeit=%d)", p
, p
->name
,
106 if (!Browsing
|| !p
->shared
||
107 (p
->type
& (CUPS_PRINTER_REMOTE
| CUPS_PRINTER_SCANNER
)))
111 * Announce the deletion...
114 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
115 if (removeit
&& (BrowseLocalProtocols
& BROWSE_DNSSD
) && DNSSDMaster
)
116 dnssdDeregisterPrinter(p
, 1, 0);
117 #endif /* HAVE_DNSSD || HAVE_AVAHI */
122 * 'cupsdRegisterPrinter()' - Start sending broadcast information for a
123 * printer or update the broadcast contents.
127 cupsdRegisterPrinter(cupsd_printer_t
*p
)/* I - Printer */
129 cupsdLogMessage(CUPSD_LOG_DEBUG
, "cupsdRegisterPrinter(p=%p(%s))", p
,
132 if (!Browsing
|| !BrowseLocalProtocols
||
133 (p
->type
& (CUPS_PRINTER_REMOTE
| CUPS_PRINTER_SCANNER
)))
136 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
137 if ((BrowseLocalProtocols
& BROWSE_DNSSD
) && DNSSDMaster
)
138 dnssdRegisterPrinter(p
, 0);
139 #endif /* HAVE_DNSSD || HAVE_AVAHI */
144 * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
148 cupsdStartBrowsing(void)
150 if (!Browsing
|| !BrowseLocalProtocols
)
153 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
154 if (BrowseLocalProtocols
& BROWSE_DNSSD
)
157 DNSServiceErrorType error
; /* Error from service creation */
160 * First create a "master" connection for all registrations...
163 if ((error
= DNSServiceCreateConnection(&DNSSDMaster
))
164 != kDNSServiceErr_NoError
)
166 cupsdLogMessage(CUPSD_LOG_ERROR
,
167 "Unable to create master DNS-SD reference: %d", error
);
169 if (FatalErrors
& CUPSD_FATAL_BROWSE
)
170 cupsdEndProcess(getpid(), 0);
175 * Add the master connection to the select list...
178 int fd
= DNSServiceRefSockFD(DNSSDMaster
);
180 fcntl(fd
, F_SETFD
, fcntl(fd
, F_GETFD
) | FD_CLOEXEC
);
182 cupsdAddSelect(fd
, (cupsd_selfunc_t
)dnssdUpdate
, NULL
, NULL
);
186 * Set the computer name and register the web interface...
190 cupsdUpdateDNSSDName();
192 # else /* HAVE_AVAHI */
193 if ((DNSSDMaster
= avahi_threaded_poll_new()) == NULL
)
195 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to create DNS-SD thread.");
197 if (FatalErrors
& CUPSD_FATAL_BROWSE
)
198 cupsdEndProcess(getpid(), 0);
202 int error
; /* Error code, if any */
204 DNSSDClient
= avahi_client_new(avahi_threaded_poll_get(DNSSDMaster
), AVAHI_CLIENT_NO_FAIL
, dnssdClientCallback
, NULL
, &error
);
206 if (DNSSDClient
== NULL
)
208 cupsdLogMessage(CUPSD_LOG_ERROR
,
209 "Unable to communicate with avahi-daemon: %s",
210 dnssdErrorString(error
));
212 if (FatalErrors
& CUPSD_FATAL_BROWSE
)
213 cupsdEndProcess(getpid(), 0);
215 avahi_threaded_poll_free(DNSSDMaster
);
219 avahi_threaded_poll_start(DNSSDMaster
);
221 # endif /* HAVE_DNSSD */
223 #endif /* HAVE_DNSSD || HAVE_AVAHI */
226 * Enable LPD and SMB printer sharing as needed through external programs...
229 if (BrowseLocalProtocols
& BROWSE_LPD
)
232 if (BrowseLocalProtocols
& BROWSE_SMB
)
235 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
237 * Register the individual printers
240 dnssdRegisterAllPrinters(0);
241 #endif /* HAVE_DNSSD || HAVE_AVAHI */
246 * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information.
250 cupsdStopBrowsing(void)
252 if (!Browsing
|| !BrowseLocalProtocols
)
255 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
257 * De-register the individual printers
260 dnssdDeregisterAllPrinters(0);
263 * Shut down browsing sockets...
266 if ((BrowseLocalProtocols
& BROWSE_DNSSD
) && DNSSDMaster
)
268 #endif /* HAVE_DNSSD || HAVE_AVAHI */
271 * Disable LPD and SMB printer sharing as needed through external programs...
274 if (BrowseLocalProtocols
& BROWSE_LPD
)
277 if (BrowseLocalProtocols
& BROWSE_SMB
)
282 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
284 * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
288 cupsdUpdateDNSSDName(void)
290 dnssdUpdateDNSSDName(0);
296 * 'dnssdAddAlias()' - Add a DNS-SD alias name.
300 dnssdAddAlias(const void *key
, /* I - Key */
301 const void *value
, /* I - Value (domain) */
302 void *context
) /* I - Unused */
304 char valueStr
[1024], /* Domain string */
305 hostname
[1024], /* Complete hostname */
306 *hostptr
; /* Pointer into hostname */
312 if (CFGetTypeID((CFStringRef
)value
) == CFStringGetTypeID() &&
313 CFStringGetCString((CFStringRef
)value
, valueStr
, sizeof(valueStr
),
314 kCFStringEncodingUTF8
))
316 snprintf(hostname
, sizeof(hostname
), "%s.%s", DNSSDHostName
, valueStr
);
317 hostptr
= hostname
+ strlen(hostname
) - 1;
319 *hostptr
= '\0'; /* Strip trailing dot */
322 DNSSDAlias
= cupsArrayNew(NULL
, NULL
);
324 cupsdAddAlias(DNSSDAlias
, hostname
);
325 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Added Back to My Mac ServerAlias %s",
329 cupsdLogMessage(CUPSD_LOG_ERROR
,
330 "Bad Back to My Mac domain in dynamic store!");
332 # endif /* __APPLE__ */
336 * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
339 static cupsd_txt_t
/* O - TXT record */
341 cupsd_printer_t
*p
, /* I - Printer information */
342 int for_lpd
) /* I - 1 = LPD, 0 = IPP */
344 int i
, /* Looping var */
345 count
; /* Count of key/value pairs */
346 char admin_hostname
[256], /* Hostname for admin page */
347 adminurl_str
[256], /* URL for the admin page */
348 type_str
[32], /* Type to string buffer */
349 state_str
[32], /* State to string buffer */
350 rp_str
[1024], /* Queue name string buffer */
351 air_str
[1024], /* auth-info-required string buffer */
352 *keyvalue
[32][2], /* Table of key/value pairs */
353 *ptr
; /* Pointer in string */
354 cupsd_txt_t txt
; /* TXT record */
355 cupsd_listener_t
*lis
; /* Current listener */
356 const char *admin_scheme
= "http"; /* Admin page URL scheme */
360 * Load up the key value pairs...
365 if (!for_lpd
|| (BrowseLocalProtocols
& BROWSE_LPD
))
367 keyvalue
[count
][0] = "txtvers";
368 keyvalue
[count
++][1] = "1";
370 keyvalue
[count
][0] = "qtotal";
371 keyvalue
[count
++][1] = "1";
373 keyvalue
[count
][0] = "rp";
374 keyvalue
[count
++][1] = rp_str
;
376 strlcpy(rp_str
, p
->name
, sizeof(rp_str
));
378 snprintf(rp_str
, sizeof(rp_str
), "%s/%s",
379 (p
->type
& CUPS_PRINTER_CLASS
) ? "classes" : "printers",
382 keyvalue
[count
][0] = "ty";
383 keyvalue
[count
++][1] = p
->make_model
? p
->make_model
: "Unknown";
386 * Get the hostname for the admin page...
389 if (strchr(DNSSDHostName
, '.'))
392 * Use the provided hostname, but make sure it ends with a period...
395 if ((ptr
= DNSSDHostName
+ strlen(DNSSDHostName
) - 1) >= DNSSDHostName
&& *ptr
== '.')
396 strlcpy(admin_hostname
, DNSSDHostName
, sizeof(admin_hostname
));
398 snprintf(admin_hostname
, sizeof(admin_hostname
), "%s.", DNSSDHostName
);
403 * Unqualified hostname gets ".local." added to it...
406 snprintf(admin_hostname
, sizeof(admin_hostname
), "%s.local.", DNSSDHostName
);
410 * Get the URL scheme for the admin page...
414 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
); lis
; lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
416 if (lis
->encryption
!= HTTP_ENCRYPTION_NEVER
)
418 admin_scheme
= "https";
422 # endif /* HAVE_SSL */
424 httpAssembleURIf(HTTP_URI_CODING_ALL
, adminurl_str
, sizeof(adminurl_str
), admin_scheme
, NULL
, admin_hostname
, DNSSDPort
, "/%s/%s", (p
->type
& CUPS_PRINTER_CLASS
) ? "classes" : "printers", p
->name
);
425 keyvalue
[count
][0] = "adminurl";
426 keyvalue
[count
++][1] = adminurl_str
;
430 keyvalue
[count
][0] = "note";
431 keyvalue
[count
++][1] = p
->location
;
434 keyvalue
[count
][0] = "priority";
435 keyvalue
[count
++][1] = for_lpd
? "100" : "0";
437 keyvalue
[count
][0] = "product";
438 keyvalue
[count
++][1] = p
->pc
&& p
->pc
->product
? p
->pc
->product
: "Unknown";
440 keyvalue
[count
][0] = "pdl";
441 keyvalue
[count
++][1] = p
->pdl
? p
->pdl
: "application/postscript";
443 if (get_auth_info_required(p
, air_str
, sizeof(air_str
)))
445 keyvalue
[count
][0] = "air";
446 keyvalue
[count
++][1] = air_str
;
449 keyvalue
[count
][0] = "UUID";
450 keyvalue
[count
++][1] = p
->uuid
+ 9;
453 keyvalue
[count
][0] = "TLS";
454 keyvalue
[count
++][1] = "1.2";
455 #endif /* HAVE_SSL */
457 if (p
->type
& CUPS_PRINTER_FAX
)
459 keyvalue
[count
][0] = "Fax";
460 keyvalue
[count
++][1] = "T";
461 keyvalue
[count
][0] = "rfo";
462 keyvalue
[count
++][1] = rp_str
;
465 if (p
->type
& CUPS_PRINTER_COLOR
)
467 keyvalue
[count
][0] = "Color";
468 keyvalue
[count
++][1] = (p
->type
& CUPS_PRINTER_COLOR
) ? "T" : "F";
471 if (p
->type
& CUPS_PRINTER_DUPLEX
)
473 keyvalue
[count
][0] = "Duplex";
474 keyvalue
[count
++][1] = (p
->type
& CUPS_PRINTER_DUPLEX
) ? "T" : "F";
477 if (p
->type
& CUPS_PRINTER_STAPLE
)
479 keyvalue
[count
][0] = "Staple";
480 keyvalue
[count
++][1] = (p
->type
& CUPS_PRINTER_STAPLE
) ? "T" : "F";
483 if (p
->type
& CUPS_PRINTER_COPIES
)
485 keyvalue
[count
][0] = "Copies";
486 keyvalue
[count
++][1] = (p
->type
& CUPS_PRINTER_COPIES
) ? "T" : "F";
489 if (p
->type
& CUPS_PRINTER_COLLATE
)
491 keyvalue
[count
][0] = "Collate";
492 keyvalue
[count
++][1] = (p
->type
& CUPS_PRINTER_COLLATE
) ? "T" : "F";
495 if (p
->type
& CUPS_PRINTER_PUNCH
)
497 keyvalue
[count
][0] = "Punch";
498 keyvalue
[count
++][1] = (p
->type
& CUPS_PRINTER_PUNCH
) ? "T" : "F";
501 if (p
->type
& CUPS_PRINTER_BIND
)
503 keyvalue
[count
][0] = "Bind";
504 keyvalue
[count
++][1] = (p
->type
& CUPS_PRINTER_BIND
) ? "T" : "F";
507 if (p
->type
& CUPS_PRINTER_SORT
)
509 keyvalue
[count
][0] = "Sort";
510 keyvalue
[count
++][1] = (p
->type
& CUPS_PRINTER_SORT
) ? "T" : "F";
513 if (p
->type
& CUPS_PRINTER_MFP
)
515 keyvalue
[count
][0] = "Scan";
516 keyvalue
[count
++][1] = (p
->type
& CUPS_PRINTER_MFP
) ? "T" : "F";
519 snprintf(type_str
, sizeof(type_str
), "0x%X", p
->type
| CUPS_PRINTER_REMOTE
);
520 snprintf(state_str
, sizeof(state_str
), "%d", p
->state
);
522 keyvalue
[count
][0] = "printer-state";
523 keyvalue
[count
++][1] = state_str
;
525 keyvalue
[count
][0] = "printer-type";
526 keyvalue
[count
++][1] = type_str
;
530 * Then pack them into a proper txt record...
534 TXTRecordCreate(&txt
, 0, NULL
);
536 for (i
= 0; i
< count
; i
++)
538 size_t len
= strlen(keyvalue
[i
][1]);
541 TXTRecordSetValue(&txt
, keyvalue
[i
][0], (uint8_t)len
, keyvalue
[i
][1]);
545 for (i
= 0, txt
= NULL
; i
< count
; i
++)
546 txt
= avahi_string_list_add_printf(txt
, "%s=%s", keyvalue
[i
][0],
548 # endif /* HAVE_DNSSD */
556 * 'dnssdClientCallback()' - Client callback for Avahi.
558 * Called whenever the client or server state changes...
563 AvahiClient
*c
, /* I - Client */
564 AvahiClientState state
, /* I - Current state */
565 void *userdata
) /* I - User data (unused) */
567 int error
; /* Error code, if any */
576 * Make sure DNSSDClient is already set also if this callback function is
577 * already running before avahi_client_new() in dnssdStartBrowsing()
586 case AVAHI_CLIENT_S_REGISTERING
:
587 case AVAHI_CLIENT_S_RUNNING
:
588 case AVAHI_CLIENT_S_COLLISION
:
589 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Avahi server connection now available, registering printers for Bonjour broadcasting.");
592 * Mark that Avahi server is running...
598 * Set the computer name and register the web interface...
602 dnssdUpdateDNSSDName(1);
605 * Register the individual printers
608 dnssdRegisterAllPrinters(1);
611 case AVAHI_CLIENT_FAILURE
:
612 if (avahi_client_errno(c
) == AVAHI_ERR_DISCONNECTED
)
614 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Avahi server disappeared, unregistering printers for Bonjour broadcasting.");
617 * Unregister everything and close the client...
620 dnssdDeregisterAllPrinters(1);
621 dnssdDeregisterInstance(&WebIFSrv
, 1);
622 avahi_client_free(DNSSDClient
);
626 * Mark that Avahi server is not running...
632 * Renew Avahi client...
635 DNSSDClient
= avahi_client_new(avahi_threaded_poll_get(DNSSDMaster
), AVAHI_CLIENT_NO_FAIL
, dnssdClientCallback
, NULL
, &error
);
639 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to communicate with avahi-daemon: %s", dnssdErrorString(error
));
640 if (FatalErrors
& CUPSD_FATAL_BROWSE
)
641 cupsdEndProcess(getpid(), 0);
646 cupsdLogMessage(CUPSD_LOG_ERROR
, "Communication with avahi-daemon has failed: %s", avahi_strerror(avahi_client_errno(c
)));
647 if (FatalErrors
& CUPSD_FATAL_BROWSE
)
648 cupsdEndProcess(getpid(), 0);
656 # endif /* HAVE_AVAHI */
660 * 'dnssdDeregisterAllPrinters()' - Deregister all printers.
664 dnssdDeregisterAllPrinters(
665 int from_callback
) /* I - Deregistering because of callback? */
667 cupsd_printer_t
*p
; /* Current printer */
673 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
675 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
676 if (!(p
->type
& (CUPS_PRINTER_REMOTE
| CUPS_PRINTER_SCANNER
)))
677 dnssdDeregisterPrinter(p
, 1, from_callback
);
682 * 'dnssdDeregisterInstance()' - Deregister a DNS-SD service instance.
686 dnssdDeregisterInstance(
687 cupsd_srv_t
*srv
, /* I - Service */
688 int from_callback
) /* I - Called from callback? */
696 DNSServiceRefDeallocate(*srv
);
700 # else /* HAVE_AVAHI */
702 avahi_threaded_poll_lock(DNSSDMaster
);
706 avahi_entry_group_free(*srv
);
711 avahi_threaded_poll_unlock(DNSSDMaster
);
712 # endif /* HAVE_DNSSD */
717 * 'dnssdDeregisterPrinter()' - Deregister all services for a printer.
721 dnssdDeregisterPrinter(
722 cupsd_printer_t
*p
, /* I - Printer */
723 int clear_name
, /* I - Clear the name? */
724 int from_callback
) /* I - Called from callback? */
727 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
728 "dnssdDeregisterPrinter(p=%p(%s), clear_name=%d)", p
, p
->name
,
733 dnssdDeregisterInstance(&p
->ipp_srv
, from_callback
);
737 dnssdDeregisterInstance(&p
->ipps_srv
, from_callback
);
738 # endif /* HAVE_SSL */
739 dnssdDeregisterInstance(&p
->printer_srv
, from_callback
);
740 # endif /* HAVE_DNSSD */
744 * Remove the printer from the array of DNS-SD printers but keep the
748 cupsArrayRemove(DNSSDPrinters
, p
);
751 * Optionally clear the service name...
755 cupsdClearString(&p
->reg_name
);
760 * 'dnssdErrorString()' - Return an error string for an error code.
763 static const char * /* O - Error message */
764 dnssdErrorString(int error
) /* I - Error number */
769 case kDNSServiceErr_NoError
:
773 case kDNSServiceErr_Unknown
:
774 return ("Unknown error.");
776 case kDNSServiceErr_NoSuchName
:
777 return ("Service not found.");
779 case kDNSServiceErr_NoMemory
:
780 return ("Out of memory.");
782 case kDNSServiceErr_BadParam
:
783 return ("Bad parameter.");
785 case kDNSServiceErr_BadReference
:
786 return ("Bad service reference.");
788 case kDNSServiceErr_BadState
:
789 return ("Bad state.");
791 case kDNSServiceErr_BadFlags
:
792 return ("Bad flags.");
794 case kDNSServiceErr_Unsupported
:
795 return ("Unsupported.");
797 case kDNSServiceErr_NotInitialized
:
798 return ("Not initialized.");
800 case kDNSServiceErr_AlreadyRegistered
:
801 return ("Already registered.");
803 case kDNSServiceErr_NameConflict
:
804 return ("Name conflict.");
806 case kDNSServiceErr_Invalid
:
807 return ("Invalid name.");
809 case kDNSServiceErr_Firewall
:
810 return ("Firewall prevents registration.");
812 case kDNSServiceErr_Incompatible
:
813 return ("Client library incompatible.");
815 case kDNSServiceErr_BadInterfaceIndex
:
816 return ("Bad interface index.");
818 case kDNSServiceErr_Refused
:
819 return ("Server prevents registration.");
821 case kDNSServiceErr_NoSuchRecord
:
822 return ("Record not found.");
824 case kDNSServiceErr_NoAuth
:
825 return ("Authentication required.");
827 case kDNSServiceErr_NoSuchKey
:
828 return ("Encryption key not found.");
830 case kDNSServiceErr_NATTraversal
:
831 return ("Unable to traverse NAT boundary.");
833 case kDNSServiceErr_DoubleNAT
:
834 return ("Unable to traverse double-NAT boundary.");
836 case kDNSServiceErr_BadTime
:
837 return ("Bad system time.");
839 case kDNSServiceErr_BadSig
:
840 return ("Bad signature.");
842 case kDNSServiceErr_BadKey
:
843 return ("Bad encryption key.");
845 case kDNSServiceErr_Transient
:
846 return ("Transient error occurred - please try again.");
848 case kDNSServiceErr_ServiceNotRunning
:
849 return ("Server not running.");
851 case kDNSServiceErr_NATPortMappingUnsupported
:
852 return ("NAT doesn't support NAT-PMP or UPnP.");
854 case kDNSServiceErr_NATPortMappingDisabled
:
855 return ("NAT supports NAT-PNP or UPnP but it is disabled.");
857 case kDNSServiceErr_NoRouter
:
858 return ("No Internet/default router configured.");
860 case kDNSServiceErr_PollingMode
:
861 return ("Service polling mode error.");
863 case kDNSServiceErr_Timeout
:
864 return ("Service timeout.");
867 # else /* HAVE_AVAHI */
868 return (avahi_strerror(error
));
869 # endif /* HAVE_DNSSD */
874 * 'dnssdRegisterCallback()' - Free a TXT record.
878 dnssdFreeTxtRecord(cupsd_txt_t
*txt
) /* I - TXT record */
881 TXTRecordDeallocate(txt
);
883 # else /* HAVE_AVAHI */
884 avahi_string_list_free(*txt
);
886 # endif /* HAVE_DNSSD */
891 * 'dnssdRegisterAllPrinters()' - Register all printers.
895 dnssdRegisterAllPrinters(int from_callback
) /* I - Called from callback? */
897 cupsd_printer_t
*p
; /* Current printer */
903 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
905 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
906 if (!(p
->type
& (CUPS_PRINTER_REMOTE
| CUPS_PRINTER_SCANNER
)))
907 dnssdRegisterPrinter(p
, from_callback
);
912 * 'dnssdRegisterCallback()' - DNSServiceRegister callback.
917 dnssdRegisterCallback(
918 DNSServiceRef sdRef
, /* I - DNS Service reference */
919 DNSServiceFlags flags
, /* I - Reserved for future use */
920 DNSServiceErrorType errorCode
, /* I - Error code */
921 const char *name
, /* I - Service name */
922 const char *regtype
, /* I - Service type */
923 const char *domain
, /* I - Domain. ".local" for now */
924 void *context
) /* I - Printer */
926 cupsd_printer_t
*p
= (cupsd_printer_t
*)context
;
927 /* Current printer */
934 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "dnssdRegisterCallback(%s, %s) for %s (%s)",
935 name
, regtype
, p
? p
->name
: "Web Interface",
936 p
? (p
->reg_name
? p
->reg_name
: "(null)") : "NA");
940 cupsdLogMessage(CUPSD_LOG_ERROR
,
941 "DNSServiceRegister failed with error %d", (int)errorCode
);
944 else if (p
&& (!p
->reg_name
|| _cups_strcasecmp(name
, p
->reg_name
)))
946 cupsdLogMessage(CUPSD_LOG_INFO
, "Using service name \"%s\" for \"%s\"",
949 cupsArrayRemove(DNSSDPrinters
, p
);
950 cupsdSetString(&p
->reg_name
, name
);
951 cupsArrayAdd(DNSSDPrinters
, p
);
953 LastEvent
|= CUPSD_EVENT_PRINTER_MODIFIED
;
957 # else /* HAVE_AVAHI */
959 dnssdRegisterCallback(
960 AvahiEntryGroup
*srv
, /* I - Service */
961 AvahiEntryGroupState state
, /* I - Registration state */
962 void *context
) /* I - Printer */
964 cupsd_printer_t
*p
= (cupsd_printer_t
*)context
;
965 /* Current printer */
967 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
968 "dnssdRegisterCallback(srv=%p, state=%d, context=%p) "
969 "for %s (%s)", srv
, state
, context
,
970 p
? p
->name
: "Web Interface",
971 p
? (p
->reg_name
? p
->reg_name
: "(null)") : "NA");
973 /* TODO: Handle collisions with avahi_alternate_service_name(p->reg_name)? */
975 # endif /* HAVE_DNSSD */
979 * 'dnssdRegisterInstance()' - Register an instance of a printer service.
982 static int /* O - 1 on success, 0 on failure */
983 dnssdRegisterInstance(
984 cupsd_srv_t
*srv
, /* O - Service */
985 cupsd_printer_t
*p
, /* I - Printer */
986 char *name
, /* I - DNS-SD service name */
987 const char *type
, /* I - DNS-SD service type */
988 const char *subtypes
, /* I - Subtypes to register or NULL */
989 int port
, /* I - Port number or 0 */
990 cupsd_txt_t
*txt
, /* I - TXT record */
991 int commit
, /* I - Commit registration? */
992 int from_callback
) /* I - Called from callback? */
994 char temp
[256], /* Temporary string */
995 *ptr
; /* Pointer into string */
996 int error
; /* Any error */
1000 (void)from_callback
;
1001 # endif /* HAVE_DNSSD */
1003 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Registering \"%s\" with DNS-SD type \"%s\".", name
, type
);
1008 * Assign the correct pointer for "srv"...
1012 if (!strcmp(type
, "_printer._tcp"))
1013 srv
= &p
->printer_srv
; /* Target LPD service */
1015 else if (!strcmp(type
, "_ipps._tcp"))
1016 srv
= &p
->ipps_srv
; /* Target IPPS service */
1017 # endif /* HAVE_SSL */
1019 srv
= &p
->ipp_srv
; /* Target IPP service */
1021 # else /* HAVE_AVAHI */
1022 srv
= &p
->ipp_srv
; /* Target service group */
1023 # endif /* HAVE_DNSSD */
1029 # else /* HAVE_AVAHI */
1031 avahi_threaded_poll_lock(DNSSDMaster
);
1034 *srv
= avahi_entry_group_new(DNSSDClient
, dnssdRegisterCallback
, NULL
);
1038 avahi_threaded_poll_unlock(DNSSDMaster
);
1040 cupsdLogMessage(CUPSD_LOG_WARN
, "DNS-SD registration of \"%s\" failed: %s",
1041 name
, dnssdErrorString(avahi_client_errno(DNSSDClient
)));
1044 # endif /* HAVE_DNSSD */
1047 * Make sure the name is <= 63 octets, and when we truncate be sure to
1048 * properly truncate any UTF-8 characters...
1051 ptr
= name
+ strlen(name
);
1052 while ((ptr
- name
) > 63)
1058 while (ptr
> name
&& (*ptr
& 0xc0) == 0x80);
1065 * Register the service...
1070 snprintf(temp
, sizeof(temp
), "%s,%s", type
, subtypes
);
1072 strlcpy(temp
, type
, sizeof(temp
));
1075 error
= DNSServiceRegister(srv
, kDNSServiceFlagsShareConnection
,
1076 0, name
, temp
, NULL
, DNSSDHostName
, htons(port
),
1077 txt
? TXTRecordGetLength(txt
) : 0,
1078 txt
? TXTRecordGetBytesPtr(txt
) : NULL
,
1079 dnssdRegisterCallback
, p
);
1081 # else /* HAVE_AVAHI */
1084 AvahiStringList
*temptxt
;
1085 for (temptxt
= *txt
; temptxt
; temptxt
= temptxt
->next
)
1086 cupsdLogMessage(CUPSD_LOG_DEBUG
, "DNS_SD \"%s\" %s", name
, temptxt
->text
);
1089 error
= avahi_entry_group_add_service_strlst(*srv
, AVAHI_IF_UNSPEC
,
1090 AVAHI_PROTO_UNSPEC
, 0, name
,
1091 type
, NULL
, DNSSDHostName
, port
,
1094 cupsdLogMessage(CUPSD_LOG_DEBUG
, "DNS-SD service add for \"%s\" failed.",
1097 if (!error
&& subtypes
)
1100 * Register all of the subtypes...
1103 char *start
, /* Start of subtype */
1104 subtype
[256]; /* Subtype string */
1106 strlcpy(temp
, subtypes
, sizeof(temp
));
1108 for (start
= temp
; *start
; start
= ptr
)
1111 * Skip leading whitespace...
1114 while (*start
&& isspace(*start
& 255))
1118 * Grab everything up to the next comma or the end of the string...
1121 for (ptr
= start
; *ptr
&& *ptr
!= ','; ptr
++);
1130 * Register the subtype...
1133 snprintf(subtype
, sizeof(subtype
), "%s._sub.%s", start
, type
);
1135 error
= avahi_entry_group_add_service_subtype(*srv
, AVAHI_IF_UNSPEC
,
1136 AVAHI_PROTO_UNSPEC
, 0,
1137 name
, type
, NULL
, subtype
);
1140 cupsdLogMessage(CUPSD_LOG_DEBUG
,
1141 "DNS-SD subtype %s registration for \"%s\" failed." ,
1148 if (!error
&& commit
)
1150 if ((error
= avahi_entry_group_commit(*srv
)) != 0)
1151 cupsdLogMessage(CUPSD_LOG_DEBUG
, "DNS-SD commit of \"%s\" failed.",
1156 avahi_threaded_poll_unlock(DNSSDMaster
);
1157 # endif /* HAVE_DNSSD */
1161 cupsdLogMessage(CUPSD_LOG_WARN
, "DNS-SD registration of \"%s\" failed: %s",
1162 name
, dnssdErrorString(error
));
1163 cupsdLogMessage(CUPSD_LOG_DEBUG
, "DNS-SD type: %s", type
);
1165 cupsdLogMessage(CUPSD_LOG_DEBUG
, "DNS-SD sub-types: %s", subtypes
);
1173 * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
1174 * or update the broadcast contents.
1178 dnssdRegisterPrinter(
1179 cupsd_printer_t
*p
, /* I - Printer */
1180 int from_callback
) /* I - Called from callback? */
1182 char name
[256]; /* Service name */
1183 int printer_port
; /* LPD port number */
1184 int status
; /* Registration status */
1185 cupsd_txt_t ipp_txt
, /* IPP(S) TXT record */
1186 printer_txt
; /* LPD TXT record */
1189 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "dnssdRegisterPrinter(%s) %s", p
->name
,
1190 !p
->ipp_srv
? "new" : "update");
1195 # endif /* HAVE_AVAHI */
1198 * Remove the current registrations if we have them and then return if
1199 * per-printer sharing was just disabled...
1202 dnssdDeregisterPrinter(p
, 0, from_callback
);
1208 * Set the registered name as needed; the registered name takes the form of
1209 * "<printer-info> @ <computer name>"...
1214 if (p
->info
&& strlen(p
->info
) > 0)
1216 if (DNSSDComputerName
)
1217 snprintf(name
, sizeof(name
), "%s @ %s", p
->info
, DNSSDComputerName
);
1219 strlcpy(name
, p
->info
, sizeof(name
));
1221 else if (DNSSDComputerName
)
1222 snprintf(name
, sizeof(name
), "%s @ %s", p
->name
, DNSSDComputerName
);
1224 strlcpy(name
, p
->name
, sizeof(name
));
1227 strlcpy(name
, p
->reg_name
, sizeof(name
));
1230 * Register IPP and LPD...
1232 * We always must register the "_printer" service type in order to reserve
1233 * our name, but use port number 0 if we haven't actually configured cups-lpd
1234 * to share via LPD...
1237 ipp_txt
= dnssdBuildTxtRecord(p
, 0);
1238 printer_txt
= dnssdBuildTxtRecord(p
, 1);
1240 if (BrowseLocalProtocols
& BROWSE_LPD
)
1245 status
= dnssdRegisterInstance(NULL
, p
, name
, "_printer._tcp", NULL
, printer_port
, &printer_txt
, 0, from_callback
);
1249 dnssdRegisterInstance(NULL
, p
, name
, "_ipps._tcp", DNSSDSubTypes
, DNSSDPort
, &ipp_txt
, 0, from_callback
);
1250 # endif /* HAVE_SSL */
1255 * Use the "_fax-ipp" service type for fax queues, otherwise use "_ipp"...
1258 if (p
->type
& CUPS_PRINTER_FAX
)
1259 status
= dnssdRegisterInstance(NULL
, p
, name
, "_fax-ipp._tcp", DNSSDSubTypes
, DNSSDPort
, &ipp_txt
, 1, from_callback
);
1261 status
= dnssdRegisterInstance(NULL
, p
, name
, "_ipp._tcp", DNSSDSubTypes
, DNSSDPort
, &ipp_txt
, 1, from_callback
);
1264 dnssdFreeTxtRecord(&ipp_txt
);
1265 dnssdFreeTxtRecord(&printer_txt
);
1270 * Save the registered name and add the printer to the array of DNS-SD
1274 cupsdSetString(&p
->reg_name
, name
);
1275 cupsArrayAdd(DNSSDPrinters
, p
);
1280 * Registration failed for this printer...
1283 dnssdDeregisterInstance(&p
->ipp_srv
, from_callback
);
1287 dnssdDeregisterInstance(&p
->ipps_srv
, from_callback
);
1288 # endif /* HAVE_SSL */
1289 dnssdDeregisterInstance(&p
->printer_srv
, from_callback
);
1290 # endif /* HAVE_DNSSD */
1296 * 'dnssdStop()' - Stop all DNS-SD registrations.
1302 cupsd_printer_t
*p
; /* Current printer */
1306 * De-register the individual printers
1309 for (p
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
1311 p
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
1312 dnssdDeregisterPrinter(p
, 1, 0);
1315 * Shutdown the rest of the service refs...
1318 dnssdDeregisterInstance(&WebIFSrv
, 0);
1321 cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDMaster
));
1323 DNSServiceRefDeallocate(DNSSDMaster
);
1326 # else /* HAVE_AVAHI */
1328 avahi_threaded_poll_stop(DNSSDMaster
);
1332 avahi_client_free(DNSSDClient
);
1338 avahi_threaded_poll_free(DNSSDMaster
);
1341 # endif /* HAVE_DNSSD */
1343 cupsArrayDelete(DNSSDPrinters
);
1344 DNSSDPrinters
= NULL
;
1352 * 'dnssdUpdate()' - Handle DNS-SD queries.
1358 DNSServiceErrorType sdErr
; /* Service discovery error */
1361 if ((sdErr
= DNSServiceProcessResult(DNSSDMaster
)) != kDNSServiceErr_NoError
)
1363 cupsdLogMessage(CUPSD_LOG_ERROR
,
1364 "DNS Service Discovery registration error %d!",
1369 # endif /* HAVE_DNSSD */
1373 * 'dnssdUpdateDNSSDName()' - Update the listen port, computer name, and web interface registration.
1377 dnssdUpdateDNSSDName(int from_callback
) /* I - Called from callback? */
1379 char webif
[1024]; /* Web interface share name */
1381 SCDynamicStoreRef sc
; /* Context for dynamic store */
1382 CFDictionaryRef btmm
; /* Back-to-My-Mac domains */
1383 CFStringEncoding nameEncoding
; /* Encoding of computer name */
1384 CFStringRef nameRef
; /* Host name CFString */
1385 char nameBuffer
[1024]; /* C-string buffer */
1386 # endif /* __APPLE__ */
1390 * Only share the web interface and printers when non-local listening is
1397 * Get the port we use for registrations. If we are not listening on any
1398 * non-local ports, there is no sense sharing local printers via Bonjour...
1401 cupsd_listener_t
*lis
; /* Current listening socket */
1403 for (lis
= (cupsd_listener_t
*)cupsArrayFirst(Listeners
);
1405 lis
= (cupsd_listener_t
*)cupsArrayNext(Listeners
))
1407 if (httpAddrLocalhost(&(lis
->address
)))
1410 DNSSDPort
= httpAddrPort(&(lis
->address
));
1419 * Get the computer name as a c-string...
1423 sc
= SCDynamicStoreCreate(kCFAllocatorDefault
, CFSTR("cupsd"), NULL
, NULL
);
1428 * Get the computer name from the dynamic store...
1431 cupsdClearString(&DNSSDComputerName
);
1433 if ((nameRef
= SCDynamicStoreCopyComputerName(sc
, &nameEncoding
)) != NULL
)
1435 if (CFStringGetCString(nameRef
, nameBuffer
, sizeof(nameBuffer
),
1436 kCFStringEncodingUTF8
))
1438 cupsdLogMessage(CUPSD_LOG_DEBUG
,
1439 "Dynamic store computer name is \"%s\".", nameBuffer
);
1440 cupsdSetString(&DNSSDComputerName
, nameBuffer
);
1446 if (!DNSSDComputerName
)
1449 * Use the ServerName instead...
1452 cupsdLogMessage(CUPSD_LOG_DEBUG
,
1453 "Using ServerName \"%s\" as computer name.", ServerName
);
1454 cupsdSetString(&DNSSDComputerName
, ServerName
);
1460 * Get the local hostname from the dynamic store...
1463 if ((nameRef
= SCDynamicStoreCopyLocalHostName(sc
)) != NULL
)
1465 if (CFStringGetCString(nameRef
, nameBuffer
, sizeof(nameBuffer
),
1466 kCFStringEncodingUTF8
))
1468 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Dynamic store host name is \"%s\".", nameBuffer
);
1470 if (strchr(nameBuffer
, '.'))
1471 cupsdSetString(&DNSSDHostName
, nameBuffer
);
1473 cupsdSetStringf(&DNSSDHostName
, "%s.local", nameBuffer
);
1475 cupsdLogMessage(CUPSD_LOG_INFO
, "Defaulting to \"DNSSDHostName %s\".", DNSSDHostName
);
1485 * Use the ServerName instead...
1488 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Using ServerName \"%s\" as host name.", ServerName
);
1489 cupsdSetString(&DNSSDHostName
, ServerName
);
1491 cupsdLogMessage(CUPSD_LOG_INFO
, "Defaulting to \"DNSSDHostName %s\".", DNSSDHostName
);
1495 * Get any Back-to-My-Mac domains and add them as aliases...
1498 cupsdFreeAliases(DNSSDAlias
);
1501 btmm
= SCDynamicStoreCopyValue(sc
, CFSTR("Setup:/Network/BackToMyMac"));
1502 if (btmm
&& CFGetTypeID(btmm
) == CFDictionaryGetTypeID())
1504 cupsdLogMessage(CUPSD_LOG_DEBUG
, "%d Back to My Mac aliases to add.",
1505 (int)CFDictionaryGetCount(btmm
));
1506 CFDictionaryApplyFunction(btmm
, dnssdAddAlias
, NULL
);
1509 cupsdLogMessage(CUPSD_LOG_ERROR
,
1510 "Bad Back to My Mac data in dynamic store!");
1512 cupsdLogMessage(CUPSD_LOG_DEBUG
, "No Back to My Mac aliases to add.");
1520 # endif /* __APPLE__ */
1524 const char *host_name
= avahi_client_get_host_name(DNSSDClient
);
1526 cupsdSetString(&DNSSDComputerName
, host_name
? host_name
: ServerName
);
1530 const char *host_fqdn
= avahi_client_get_host_name_fqdn(DNSSDClient
);
1533 cupsdSetString(&DNSSDHostName
, host_fqdn
);
1534 else if (strchr(ServerName
, '.'))
1535 cupsdSetString(&DNSSDHostName
, ServerName
);
1537 cupsdSetStringf(&DNSSDHostName
, "%s.local", ServerName
);
1539 cupsdLogMessage(CUPSD_LOG_INFO
, "Defaulting to \"DNSSDHostName %s\".", DNSSDHostName
);
1543 # endif /* HAVE_AVAHI */
1545 cupsdSetString(&DNSSDComputerName
, ServerName
);
1549 if (strchr(ServerName
, '.'))
1550 cupsdSetString(&DNSSDHostName
, ServerName
);
1552 cupsdSetStringf(&DNSSDHostName
, "%s.local", ServerName
);
1554 cupsdLogMessage(CUPSD_LOG_INFO
, "Defaulting to \"DNSSDHostName %s\".", DNSSDHostName
);
1559 * Then (re)register the web interface if enabled...
1564 if (DNSSDComputerName
)
1565 snprintf(webif
, sizeof(webif
), "CUPS @ %s", DNSSDComputerName
);
1567 strlcpy(webif
, "CUPS", sizeof(webif
));
1569 dnssdDeregisterInstance(&WebIFSrv
, from_callback
);
1570 dnssdRegisterInstance(&WebIFSrv
, NULL
, webif
, "_http._tcp", "_printer", DNSSDPort
, NULL
, 1, from_callback
);
1576 * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
1579 static char * /* O - String or NULL if none */
1580 get_auth_info_required(
1581 cupsd_printer_t
*p
, /* I - Printer */
1582 char *buffer
, /* I - Value buffer */
1583 size_t bufsize
) /* I - Size of value buffer */
1585 cupsd_location_t
*auth
; /* Pointer to authentication element */
1586 char resource
[1024]; /* Printer/class resource path */
1590 * If auth-info-required is set for this printer, return that...
1593 if (p
->num_auth_info_required
> 0 && strcmp(p
->auth_info_required
[0], "none"))
1595 int i
; /* Looping var */
1596 char *bufptr
; /* Pointer into buffer */
1598 for (i
= 0, bufptr
= buffer
; i
< p
->num_auth_info_required
; i
++)
1600 if (bufptr
>= (buffer
+ bufsize
- 2))
1606 strlcpy(bufptr
, p
->auth_info_required
[i
], bufsize
- (size_t)(bufptr
- buffer
));
1607 bufptr
+= strlen(bufptr
);
1614 * Figure out the authentication data requirements to advertise...
1617 if (p
->type
& CUPS_PRINTER_CLASS
)
1618 snprintf(resource
, sizeof(resource
), "/classes/%s", p
->name
);
1620 snprintf(resource
, sizeof(resource
), "/printers/%s", p
->name
);
1622 if ((auth
= cupsdFindBest(resource
, HTTP_POST
)) == NULL
||
1623 auth
->type
== CUPSD_AUTH_NONE
)
1624 auth
= cupsdFindPolicyOp(p
->op_policy_ptr
, IPP_PRINT_JOB
);
1628 int auth_type
; /* Authentication type */
1630 if ((auth_type
= auth
->type
) == CUPSD_AUTH_DEFAULT
)
1631 auth_type
= cupsdDefaultAuthType();
1635 case CUPSD_AUTH_NONE
:
1638 case CUPSD_AUTH_NEGOTIATE
:
1639 strlcpy(buffer
, "negotiate", bufsize
);
1643 strlcpy(buffer
, "username,password", bufsize
);
1652 #endif /* HAVE_DNSSD || HAVE_AVAHI */
1657 * 'get_hostconfig()' - Get an /etc/hostconfig service setting.
1660 static int /* O - 1 for YES or AUTOMATIC, 0 for NO */
1661 get_hostconfig(const char *name
) /* I - Name of service */
1663 cups_file_t
*fp
; /* Hostconfig file */
1664 char line
[1024], /* Line from file */
1665 *ptr
; /* Pointer to value */
1666 int state
= 1; /* State of service */
1670 * Try opening the /etc/hostconfig file; if we can't open it, assume that
1671 * the service is enabled/auto.
1674 if ((fp
= cupsFileOpen("/etc/hostconfig", "r")) != NULL
)
1677 * Read lines from the file until we find the service...
1680 while (cupsFileGets(fp
, line
, sizeof(line
)))
1682 if (line
[0] == '#' || (ptr
= strchr(line
, '=')) == NULL
)
1687 if (!_cups_strcasecmp(line
, name
))
1690 * Found the service, see if it is set to "-NO-"...
1693 if (!_cups_strncasecmp(ptr
, "-NO-", 4))
1704 #endif /* __APPLE__ */
1708 * 'update_lpd()' - Update the LPD configuration as needed.
1712 update_lpd(int onoff
) /* - 1 = turn on, 0 = turn off */
1719 * Allow /etc/hostconfig CUPS_LPD service setting to override cupsd.conf
1720 * setting for backwards-compatibility.
1723 if (onoff
&& !get_hostconfig("CUPS_LPD"))
1725 #endif /* __APPLE__ */
1727 if (!strncmp(LPDConfigFile
, "xinetd:///", 10))
1730 * Enable/disable LPD via the xinetd.d config file for cups-lpd...
1733 char newfile
[1024]; /* New cups-lpd.N file */
1734 cups_file_t
*ofp
, /* Original file pointer */
1735 *nfp
; /* New file pointer */
1736 char line
[1024]; /* Line from file */
1739 snprintf(newfile
, sizeof(newfile
), "%s.N", LPDConfigFile
+ 9);
1741 if ((ofp
= cupsFileOpen(LPDConfigFile
+ 9, "r")) == NULL
)
1743 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open \"%s\" - %s",
1744 LPDConfigFile
+ 9, strerror(errno
));
1748 if ((nfp
= cupsFileOpen(newfile
, "w")) == NULL
)
1750 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to create \"%s\" - %s",
1751 newfile
, strerror(errno
));
1757 * Copy all of the lines from the cups-lpd file...
1760 while (cupsFileGets(ofp
, line
, sizeof(line
)))
1764 cupsFilePrintf(nfp
, "%s\n", line
);
1765 snprintf(line
, sizeof(line
), "\tdisable = %s",
1766 onoff
? "no" : "yes");
1768 else if (!strstr(line
, "disable ="))
1769 cupsFilePrintf(nfp
, "%s\n", line
);
1774 rename(newfile
, LPDConfigFile
+ 9);
1777 else if (!strncmp(LPDConfigFile
, "launchd:///", 11))
1780 * Enable/disable LPD via the launchctl command...
1783 char *argv
[5], /* Arguments for command */
1784 *envp
[MAX_ENV
]; /* Environment for command */
1785 int pid
; /* Process ID */
1788 cupsdLoadEnv(envp
, (int)(sizeof(envp
) / sizeof(envp
[0])));
1789 argv
[0] = (char *)"launchctl";
1790 argv
[1] = (char *)(onoff
? "load" : "unload");
1791 argv
[2] = (char *)"-w";
1792 argv
[3] = LPDConfigFile
+ 10;
1795 cupsdStartProcess("/bin/launchctl", argv
, envp
, -1, -1, -1, -1, -1, 1,
1798 #endif /* __APPLE__ */
1800 cupsdLogMessage(CUPSD_LOG_INFO
, "Unknown LPDConfigFile scheme!");
1805 * 'update_smb()' - Update the SMB configuration as needed.
1809 update_smb(int onoff
) /* I - 1 = turn on, 0 = turn off */
1814 if (!strncmp(SMBConfigFile
, "samba:///", 9))
1817 * Enable/disable SMB via the specified smb.conf config file...
1820 char newfile
[1024]; /* New smb.conf.N file */
1821 cups_file_t
*ofp
, /* Original file pointer */
1822 *nfp
; /* New file pointer */
1823 char line
[1024]; /* Line from file */
1824 int in_printers
; /* In [printers] section? */
1827 snprintf(newfile
, sizeof(newfile
), "%s.N", SMBConfigFile
+ 8);
1829 if ((ofp
= cupsFileOpen(SMBConfigFile
+ 8, "r")) == NULL
)
1831 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to open \"%s\" - %s",
1832 SMBConfigFile
+ 8, strerror(errno
));
1836 if ((nfp
= cupsFileOpen(newfile
, "w")) == NULL
)
1838 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to create \"%s\" - %s",
1839 newfile
, strerror(errno
));
1845 * Copy all of the lines from the smb.conf file...
1850 while (cupsFileGets(ofp
, line
, sizeof(line
)))
1852 if (in_printers
&& strstr(line
, "printable ="))
1853 snprintf(line
, sizeof(line
), " printable = %s",
1854 onoff
? "yes" : "no");
1856 cupsFilePrintf(nfp
, "%s\n", line
);
1859 in_printers
= !strcmp(line
, "[printers]");
1864 rename(newfile
, SMBConfigFile
+ 8);
1867 cupsdLogMessage(CUPSD_LOG_INFO
, "Unknown SMBConfigFile scheme!");