From d85772c0b5b2ef9623be0377180b6d03ac60b1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Fu=C3=9F?= Date: Thu, 7 May 2026 16:01:37 +0200 Subject: [PATCH] Make printer's DNS-SD Service Names freely configurable Introduce a configuration variable DNSSDServiceName which, if set, provides a template for the DNS-SD Service Name used to register a printer. In the string, the following placeholders are substituted: %n: the printer's name %i: the printer's info field %l: the printer's location field %m: the printer's make & model field %c: the server's name %%: a literal percent sign If DNSSDServiceName is unset (the default), the existing behaviour is used. --- man/cupsd.conf.5 | 19 +++++++++++++++++++ scheduler/conf.c | 1 + scheduler/dirsvc.c | 40 +++++++++++++++++++++++++++++++++++++++- scheduler/dirsvc.h | 5 ++++- 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/man/cupsd.conf.5 b/man/cupsd.conf.5 index a34d16a08d..592448e2bc 100644 --- a/man/cupsd.conf.5 +++ b/man/cupsd.conf.5 @@ -146,6 +146,25 @@ The value "none" disables the "@ Computer Name" suffix added to shared printer n \fBDNSSDHostName \fIHOSTNAME\fR Specifies the fully-qualified domain name for the server that is used for DNS-SD sharing. The default is typically the server's ".local" hostname and is updated whenever that hostname changes. +.\"#DNSSDServiceName +.TP 5 +\fBDNSSDServiceName \fIservice-name\fR +Specifies the service name announced for a shared printer. +\fIservice-name\fR may contain the following placeholders: +.RS +.IP %n 5 +The printer's name. +.IP %i 5 +The printer's \fIinfo\fR field. +.IP %l 5 +The printer's \fIlocation\fR field. +.IP %m 5 +The printer's \fImake & model\fR field. +.IP %c 5 +The server's name. +.IP %% 5 +A literal percent sign. +.RE .\"#ErrorPolicy .TP 5 \fBErrorPolicy abort-job\fR diff --git a/scheduler/conf.c b/scheduler/conf.c index e55afdbd7e..7910871835 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -81,6 +81,7 @@ static const cupsd_var_t cupsd_vars[] = { "DirtyCleanInterval", &DirtyCleanInterval, CUPSD_VARTYPE_TIME }, { "DNSSDComputerName", &DNSSDComputerName, CUPSD_VARTYPE_STRING }, { "DNSSDHostName", &DNSSDHostName, CUPSD_VARTYPE_STRING }, + { "DNSSDServiceName", &DNSSDServiceName, CUPSD_VARTYPE_STRING }, { "ErrorPolicy", &ErrorPolicy, CUPSD_VARTYPE_STRING }, { "FilterLimit", &FilterLimit, CUPSD_VARTYPE_INTEGER }, #ifdef HAVE_GSSAPI diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index 1c05c80ad6..0530cc0bbd 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -485,7 +485,45 @@ dnssdRegisterPrinter( if (!p->reg_name) { - if (p->info && strlen(p->info) > 0) + if (DNSSDServiceName && DNSSDServiceName[0] != '\0') { + char *s = DNSSDServiceName, *e = name + sizeof(name), *q = name, c; + + while (1) { + c = *s++; + /* assert(q < e); */ + if (c == '\0' || q == e - 1) { + *q = '\0'; + break; + } else if (c == '%') { + c = *s++; + if (c == '\0') { /* putting this into the case would need a break 2 */ + *q = '\0'; + break; + } else if (c == '%') { /* could be put into case */ + *q++ = '%'; + } else { + char *r; + switch (c) { + case 'n': r = p->name; break; + case 'l': r = p->location; break; + case 'i': r = p->info; break; + case 'm': r = p->make_model; break; + case 'c': r = DNSSDComputerName; break; + default: continue; + } + if (r == NULL) continue; + q += strlcpy(q, r, e - q); + if (q >= e) { + *(e - 1) = '\0'; + break; + } + } + } else { + *q++ = c; + } + } + } + else if (p->info && strlen(p->info) > 0) { if (DNSSDComputerName) snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName); diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h index 77d8c36dcc..70b20ba05d 100644 --- a/scheduler/dirsvc.h +++ b/scheduler/dirsvc.h @@ -36,8 +36,11 @@ VAR char *DNSSDHostName VALUE(NULL); /* Hostname */ VAR int DNSSDHostNameConfigured VALUE(0); /* Was the DNSSDHostName value configured in cupsd.conf? */ -VAR char *DNSSDSubTypes VALUE(NULL); +VAR char *DNSSDSubTypes VALUE(NULL). /* Bonjour registration subtypes */ + *DNSSDServiceName + VALUE(NULL); + /* DNSSD service name */ VAR cups_array_t *DNSSDAlias VALUE(NULL); /* List of dynamic ServerAlias's */ VAR int DNSSDPort VALUE(0);