xref: /illumos-gate/usr/src/lib/print/libpapi-dynamic/common/nss.c (revision 36615d24946b849e48cedbbafa9adfb4a02b590c)
1355b4669Sjacobs /*
2355b4669Sjacobs  * CDDL HEADER START
3355b4669Sjacobs  *
4355b4669Sjacobs  * The contents of this file are subject to the terms of the
5355b4669Sjacobs  * Common Development and Distribution License (the "License").
6355b4669Sjacobs  * You may not use this file except in compliance with the License.
7355b4669Sjacobs  *
8355b4669Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9355b4669Sjacobs  * or http://www.opensolaris.org/os/licensing.
10355b4669Sjacobs  * See the License for the specific language governing permissions
11355b4669Sjacobs  * and limitations under the License.
12355b4669Sjacobs  *
13355b4669Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
14355b4669Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15355b4669Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
16355b4669Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
17355b4669Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
18355b4669Sjacobs  *
19355b4669Sjacobs  * CDDL HEADER END
20355b4669Sjacobs  */
21355b4669Sjacobs 
22355b4669Sjacobs /*
23*36615d24Sjacobs  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24355b4669Sjacobs  * Use is subject to license terms.
25355b4669Sjacobs  *
26355b4669Sjacobs  */
27355b4669Sjacobs 
289c378f4bSjacobs /* Id: nss.c 180 2006-07-20 17:33:02Z njacobs $ */
29355b4669Sjacobs 
30355b4669Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
31355b4669Sjacobs 
32355b4669Sjacobs #include <stdio.h>
33355b4669Sjacobs #include <stdlib.h>
34355b4669Sjacobs #include <unistd.h>
35355b4669Sjacobs #include <string.h>
36355b4669Sjacobs #include <ctype.h>
37355b4669Sjacobs #include <sys/types.h>
38355b4669Sjacobs #include <syslog.h>
39355b4669Sjacobs #include <papi.h>
40355b4669Sjacobs #include <uri.h>
41355b4669Sjacobs #include <papi_impl.h>
42355b4669Sjacobs #ifdef NSS_EMULATION
43355b4669Sjacobs #include <nss-emulation.h>
44355b4669Sjacobs #elif NSS_SOLARIS
45355b4669Sjacobs #include <nss_dbdefs.h>
46355b4669Sjacobs #endif
47355b4669Sjacobs #include <config-site.h>
48355b4669Sjacobs #if defined(__sun) && defined(__SVR4)
49355b4669Sjacobs #include <sys/systeminfo.h>
50355b4669Sjacobs #endif
51355b4669Sjacobs 
52355b4669Sjacobs 
53355b4669Sjacobs static char *
549c378f4bSjacobs bsdaddr_to_uri(papi_attribute_t **list, char *bsdaddr)
55355b4669Sjacobs {
56355b4669Sjacobs 	char *result = NULL;
57355b4669Sjacobs 
58355b4669Sjacobs 	if (bsdaddr != NULL) {
59355b4669Sjacobs 		char *bsd[3], *tmp, *iter = NULL;
60355b4669Sjacobs 		char buf[512];
61355b4669Sjacobs 
62355b4669Sjacobs 		tmp = strdup(bsdaddr);
63355b4669Sjacobs 
64355b4669Sjacobs 		bsd[0] = strtok_r(tmp, ":,", &iter);
659c378f4bSjacobs 		if ((bsd[1] = strtok_r(NULL, ":,", &iter)) == NULL)
669c378f4bSjacobs 			papiAttributeListGetString(list, NULL,
679c378f4bSjacobs 					"printer-name", &bsd[1]);
68355b4669Sjacobs 		bsd[2] = strtok_r(NULL, ":,", &iter);
69355b4669Sjacobs 
709c378f4bSjacobs 		snprintf(buf, sizeof (buf), "lpd://%s/printers/%s%s%s", bsd[0],
719c378f4bSjacobs 			(bsd[1] != NULL) ? bsd[1] : "",
72355b4669Sjacobs 			(bsd[2] != NULL) ? "#" : "",
73355b4669Sjacobs 			(bsd[2] != NULL) ? bsd[2] : "");
74355b4669Sjacobs 
75355b4669Sjacobs 		free(tmp);
76355b4669Sjacobs 
77355b4669Sjacobs 		result = strdup(buf);
78355b4669Sjacobs 	}
79355b4669Sjacobs 
80355b4669Sjacobs 	return (result);
81355b4669Sjacobs }
82355b4669Sjacobs 
83355b4669Sjacobs #if defined(__sun) && defined(__SVR4)
840ce6acb8Sjacobs #include <sys/socket.h>
850ce6acb8Sjacobs #include <sys/ioctl.h>
860ce6acb8Sjacobs #include <sys/sockio.h>
870ce6acb8Sjacobs #include <net/if.h>
880ce6acb8Sjacobs #include <netinet/in.h>
890ce6acb8Sjacobs #include <arpa/inet.h>
900ce6acb8Sjacobs #include <netdb.h>
910ce6acb8Sjacobs 
920ce6acb8Sjacobs static struct in6_addr **
930ce6acb8Sjacobs local_interfaces()
940ce6acb8Sjacobs {
950ce6acb8Sjacobs 	struct in6_addr **result = NULL;
960ce6acb8Sjacobs 	int s;
970ce6acb8Sjacobs 	struct lifnum n;
980ce6acb8Sjacobs 	struct lifconf c;
990ce6acb8Sjacobs 	struct lifreq *r;
1000ce6acb8Sjacobs 	int count;
1010ce6acb8Sjacobs 
1020ce6acb8Sjacobs 	/* we need a socket to get the interfaces */
1030ce6acb8Sjacobs 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1040ce6acb8Sjacobs 		return (0);
1050ce6acb8Sjacobs 
1060ce6acb8Sjacobs 	/* get the number of interfaces */
1070ce6acb8Sjacobs 	memset(&n, 0, sizeof (n));
1080ce6acb8Sjacobs 	n.lifn_family = AF_UNSPEC;
1090ce6acb8Sjacobs 	if (ioctl(s, SIOCGLIFNUM, (char *)&n) < 0) {
1100ce6acb8Sjacobs 		close(s);
1110ce6acb8Sjacobs 		return (0);	/* no interfaces */
1120ce6acb8Sjacobs 	}
1130ce6acb8Sjacobs 
1140ce6acb8Sjacobs 	/* get the interface(s) configuration */
1150ce6acb8Sjacobs 	memset(&c, 0, sizeof (c));
1160ce6acb8Sjacobs 	c.lifc_family = AF_UNSPEC;
1170ce6acb8Sjacobs 	c.lifc_buf = calloc(n.lifn_count, sizeof (struct lifreq));
1180ce6acb8Sjacobs 	c.lifc_len = (n.lifn_count * sizeof (struct lifreq));
1190ce6acb8Sjacobs 	if (ioctl(s, SIOCGLIFCONF, (char *)&c) < 0) {
1200ce6acb8Sjacobs 		free(c.lifc_buf);
1210ce6acb8Sjacobs 		close(s);
1220ce6acb8Sjacobs 		return (0);	/* can't get interface(s) configuration */
1230ce6acb8Sjacobs 	}
1240ce6acb8Sjacobs 	close(s);
1250ce6acb8Sjacobs 
1260ce6acb8Sjacobs 	r = c.lifc_req;
1270ce6acb8Sjacobs 	for (count = c.lifc_len / sizeof (struct lifreq);
1280ce6acb8Sjacobs 	     count > 0; count--, r++) {
1290ce6acb8Sjacobs 		struct in6_addr v6[1], *addr = NULL;
1300ce6acb8Sjacobs 
1310ce6acb8Sjacobs 		switch (r->lifr_addr.ss_family) {
1320ce6acb8Sjacobs 		case AF_INET: {
1330ce6acb8Sjacobs 			struct sockaddr_in *s =
1340ce6acb8Sjacobs 				(struct sockaddr_in *)&r->lifr_addr;
1350ce6acb8Sjacobs 			IN6_INADDR_TO_V4MAPPED(&s->sin_addr, v6);
1360ce6acb8Sjacobs 			addr = v6;
1370ce6acb8Sjacobs 			}
1380ce6acb8Sjacobs 			break;
1390ce6acb8Sjacobs 		case AF_INET6: {
1400ce6acb8Sjacobs 			struct sockaddr_in6 *s =
1410ce6acb8Sjacobs 				(struct sockaddr_in6 *)&r->lifr_addr;
1420ce6acb8Sjacobs 			addr = &s->sin6_addr;
1430ce6acb8Sjacobs 			}
1440ce6acb8Sjacobs 			break;
1450ce6acb8Sjacobs 		}
1460ce6acb8Sjacobs 
1470ce6acb8Sjacobs 		if (addr != NULL) {
1480ce6acb8Sjacobs 			struct in6_addr *a = malloc(sizeof (*a));
1490ce6acb8Sjacobs 
1500ce6acb8Sjacobs 			memcpy(a, addr, sizeof (*a));
1510ce6acb8Sjacobs 			list_append(&result, a);
1520ce6acb8Sjacobs 		}
1530ce6acb8Sjacobs 	}
1540ce6acb8Sjacobs 	free(c.lifc_buf);
1550ce6acb8Sjacobs 
1560ce6acb8Sjacobs 	return (result);
1570ce6acb8Sjacobs }
1580ce6acb8Sjacobs 
1590ce6acb8Sjacobs static int
1600ce6acb8Sjacobs match_interfaces(char *host)
1610ce6acb8Sjacobs {
1620ce6acb8Sjacobs 	struct in6_addr **lif = local_interfaces();
1630ce6acb8Sjacobs 	struct hostent *hp;
1640ce6acb8Sjacobs 	int rc = 0;
1650ce6acb8Sjacobs 	int errnum;
1660ce6acb8Sjacobs 
1670ce6acb8Sjacobs 	/* are there any local interfaces */
1680ce6acb8Sjacobs 	if (lif == NULL)
1690ce6acb8Sjacobs 		return (0);
1700ce6acb8Sjacobs 
1710ce6acb8Sjacobs 	/* cycle through the host db addresses */
1720ce6acb8Sjacobs 	hp = getipnodebyname(host, AF_INET6, AI_ALL|AI_V4MAPPED, &errnum);
1730ce6acb8Sjacobs 	if (hp != NULL) {
1740ce6acb8Sjacobs 		struct in6_addr **tmp = (struct in6_addr **)hp->h_addr_list;
1750ce6acb8Sjacobs 		int i;
1760ce6acb8Sjacobs 
1770ce6acb8Sjacobs 		for (i = 0; ((rc == 0) && (tmp[i] != NULL)); i++) {
1780ce6acb8Sjacobs 			int j;
1790ce6acb8Sjacobs 
1800ce6acb8Sjacobs 			for (j = 0; ((rc == 0) && (lif[j] != NULL)); j++)
1810ce6acb8Sjacobs 				if (memcmp(tmp[i], lif[j],
1820ce6acb8Sjacobs 						sizeof (struct in6_addr)) == 0)
1830ce6acb8Sjacobs 					rc = 1;
1840ce6acb8Sjacobs 		}
1850ce6acb8Sjacobs 	}
1860ce6acb8Sjacobs 	free(lif);
1870ce6acb8Sjacobs 
1880ce6acb8Sjacobs 	return (rc);
1890ce6acb8Sjacobs }
1900ce6acb8Sjacobs 
1910ce6acb8Sjacobs static int
1920ce6acb8Sjacobs is_localhost(char *host)
1930ce6acb8Sjacobs {
1940ce6acb8Sjacobs 	char hostname[BUFSIZ];
1950ce6acb8Sjacobs 
1960ce6acb8Sjacobs 	/* is it "localhost" */
1970ce6acb8Sjacobs 	if (strncasecmp(host, "localhost", 10) == 0)
1980ce6acb8Sjacobs 		return (1);
1990ce6acb8Sjacobs 
2000ce6acb8Sjacobs 	/* is it the {nodename} */
2010ce6acb8Sjacobs 	sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
2020ce6acb8Sjacobs 	if (strncasecmp(host, hostname, strlen(hostname)) == 0)
2030ce6acb8Sjacobs 		return (1);
2040ce6acb8Sjacobs 
2050ce6acb8Sjacobs 	/* does it match one of the host's configured interfaces */
2060ce6acb8Sjacobs 	if (match_interfaces(host) != 0)
2070ce6acb8Sjacobs 		return (1);
2080ce6acb8Sjacobs 
2090ce6acb8Sjacobs 	return (0);
2100ce6acb8Sjacobs }
2110ce6acb8Sjacobs 
212355b4669Sjacobs /*
213355b4669Sjacobs  * This is an awful HACK to force the dynamic PAPI library to use the
214355b4669Sjacobs  * lpsched support when the destination apears to be a local lpsched
215355b4669Sjacobs  * queue on Solaris.
216355b4669Sjacobs  */
217355b4669Sjacobs static void
218355b4669Sjacobs solaris_lpsched_shortcircuit_hack(papi_attribute_t ***list)
219355b4669Sjacobs {
220355b4669Sjacobs 	papi_attribute_t *attribute;
221355b4669Sjacobs 	uri_t *uri = NULL;
222355b4669Sjacobs 	char *printer = NULL;
223355b4669Sjacobs 	char buf[128], buf2[128];
224355b4669Sjacobs 
225355b4669Sjacobs 	/* setting this in the calling env can be useful for debugging */
226355b4669Sjacobs 	if (getenv("DISABLE_LPSCHED_SHORTCIRCUIT") != NULL)
227355b4669Sjacobs 		return;
228355b4669Sjacobs 
229355b4669Sjacobs 	papiAttributeListGetString(*list, NULL,
230355b4669Sjacobs 				"printer-uri-supported", &printer);
231355b4669Sjacobs 	if (uri_from_string(printer, &uri) < 0)
232355b4669Sjacobs 		return;
233355b4669Sjacobs 
234355b4669Sjacobs 	/* already an lpsched URI ? */
235355b4669Sjacobs 	if (strcasecmp(uri->scheme, "lpsched") == 0)
236355b4669Sjacobs 		return;
237355b4669Sjacobs 
238355b4669Sjacobs 	if ((printer = strrchr(uri->path, '/')) == NULL)
239355b4669Sjacobs 		printer = uri->path;
240355b4669Sjacobs 	else
241355b4669Sjacobs 		printer++;
242355b4669Sjacobs 
243355b4669Sjacobs 	/* is there an lpsched queue (printer/class) */
244355b4669Sjacobs 	snprintf(buf, sizeof (buf), "/etc/lp/interfaces/%s", printer);
245355b4669Sjacobs 	snprintf(buf2, sizeof (buf2), "/etc/lp/classes/%s", printer);
246355b4669Sjacobs 	if ((access(buf, F_OK) < 0) && (access(buf2, F_OK) < 0))
247355b4669Sjacobs 		return;
248355b4669Sjacobs 
2490ce6acb8Sjacobs 	/* is this the "local" host */
2500ce6acb8Sjacobs 	if ((uri->host != NULL) && (is_localhost(uri->host) == 0))
2510ce6acb8Sjacobs 		return;
2520ce6acb8Sjacobs 
2530ce6acb8Sjacobs 	snprintf(buf, sizeof (buf), "lpsched://%s/printers/%s",
2540ce6acb8Sjacobs 			(uri->host ? uri->host : "localhost"), printer);
255355b4669Sjacobs 	papiAttributeListAddString(list, PAPI_ATTR_REPLACE,
256355b4669Sjacobs 			"printer-uri-supported", buf);
257355b4669Sjacobs }
258355b4669Sjacobs #endif
259355b4669Sjacobs 
260355b4669Sjacobs static void
261355b4669Sjacobs fill_printer_uri_supported(papi_attribute_t ***list)
262355b4669Sjacobs {
263355b4669Sjacobs 	papi_attribute_t *attribute;
264355b4669Sjacobs 	char *string = NULL;
265355b4669Sjacobs 
266355b4669Sjacobs 	/* do we have a printer-uri-supported */
267355b4669Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri-supported");
268355b4669Sjacobs 	if (attribute != NULL) /* we have what we need, return */
269355b4669Sjacobs 		return;
270355b4669Sjacobs 
271*36615d24Sjacobs 	/* do we have a printer-uri (in URI form) to rename */
272355b4669Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri");
273*36615d24Sjacobs 	if ((attribute != NULL) &&
274*36615d24Sjacobs 	    (attribute->type == PAPI_STRING) &&
275*36615d24Sjacobs 	    (attribute->values != NULL) &&
276*36615d24Sjacobs 	    (attribute->values[0]->string != NULL) &&
277*36615d24Sjacobs 	    (strstr(attribute->values[0]->string, "://") != NULL)) {
278*36615d24Sjacobs 			/* rename it in place and return */
279355b4669Sjacobs 		free(attribute->name);
280355b4669Sjacobs 		attribute->name = strdup("printer-uri-supported");
281355b4669Sjacobs 		return;
282355b4669Sjacobs 	}
283355b4669Sjacobs 
284355b4669Sjacobs 	/* do we have a printers.conf(4) "bsdaddr" to convert */
285355b4669Sjacobs 	papiAttributeListGetString(*list, NULL, "bsdaddr", &string);
286355b4669Sjacobs 	if (string != NULL) { /* parse it, convert it, add it */
2879c378f4bSjacobs 		char *uri = bsdaddr_to_uri(*list, string);
288355b4669Sjacobs 
289355b4669Sjacobs 		if (uri != NULL) {
290355b4669Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
291355b4669Sjacobs 					"printer-uri-supported", uri);
292355b4669Sjacobs 			papiAttributeListDelete(list, "bsdaddr");
293355b4669Sjacobs 			free(uri);
294355b4669Sjacobs 			return;
295355b4669Sjacobs 		}
296355b4669Sjacobs 	}
297355b4669Sjacobs 
298355b4669Sjacobs 	/* do we have a printers.conf(4) "rm" (and "rp") to convert */
299355b4669Sjacobs 	papiAttributeListGetString(*list, NULL, "rm", &string);
300355b4669Sjacobs 	if (string != NULL) {
301355b4669Sjacobs 		char *rp = NULL;
302355b4669Sjacobs 
303355b4669Sjacobs 		/* default to "printer-name", but use "rp" if we have it */
304355b4669Sjacobs 		papiAttributeListGetString(*list, NULL, "printer-name", &rp);
305355b4669Sjacobs 		papiAttributeListGetString(*list, NULL, "rp", &rp);
306355b4669Sjacobs 
307355b4669Sjacobs 		if (rp != NULL) { /* fill in the uri if we have the data */
308355b4669Sjacobs 			char buf[BUFSIZ];
309355b4669Sjacobs 
310355b4669Sjacobs 			snprintf(buf, sizeof (buf), "lpd://%s/printers/%s",
311355b4669Sjacobs 				string, rp);
312355b4669Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
313355b4669Sjacobs 					"printer-uri-supported", strdup(buf));
314355b4669Sjacobs 			return;
315355b4669Sjacobs 		}
316355b4669Sjacobs 	}
317355b4669Sjacobs 
318355b4669Sjacobs 	/* if were are here, we don't have a printer-uri-supported */
319355b4669Sjacobs }
320355b4669Sjacobs 
321355b4669Sjacobs #ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
322355b4669Sjacobs static void
323355b4669Sjacobs fill_printer_uri(papi_attribute_t ***list)
324355b4669Sjacobs {
325355b4669Sjacobs 	papi_attribute_t *attribute;
326355b4669Sjacobs 	char *uri = NULL;
327355b4669Sjacobs 
328355b4669Sjacobs 	if ((list == NULL) || (*list == NULL))
329355b4669Sjacobs 		return;
330355b4669Sjacobs 
3310ce6acb8Sjacobs 	/* do we have a printer-uri */
332355b4669Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri");
333355b4669Sjacobs 	if (attribute != NULL) /* we have what we need, return */
334355b4669Sjacobs 		return;
335355b4669Sjacobs 
336355b4669Sjacobs 	/*
337355b4669Sjacobs 	 * this is sufficient to fool libgnomeprintpapi, but not promote it's
338355b4669Sjacobs 	 * use in the future.
339355b4669Sjacobs 	 */
340355b4669Sjacobs 	papiAttributeListAddString(list, PAPI_ATTR_EXCL, "printer-uri",
341355b4669Sjacobs 			"broken printer-uri semantic");
342355b4669Sjacobs }
343355b4669Sjacobs #endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
344355b4669Sjacobs 
345355b4669Sjacobs static void
346355b4669Sjacobs cvt_all_to_member_names(papi_attribute_t ***list)
347355b4669Sjacobs {
348355b4669Sjacobs 	papi_status_t status;
349355b4669Sjacobs 	void *iter = NULL;
350355b4669Sjacobs 	char *string = NULL;
351355b4669Sjacobs 
352355b4669Sjacobs 	papiAttributeListGetString(*list, NULL, "member-names", &string);
353355b4669Sjacobs 	if (string != NULL) /* already have a member-names */
354355b4669Sjacobs 		return;
355355b4669Sjacobs 
356355b4669Sjacobs 	for (status = papiAttributeListGetString(*list, &iter, "all", &string);
357355b4669Sjacobs 	     status == PAPI_OK;
358355b4669Sjacobs 	     status = papiAttributeListGetString(*list, &iter, NULL, &string)) {
359355b4669Sjacobs 		char *s_iter = NULL, *value, *tmp = strdup(string);
360355b4669Sjacobs 
361355b4669Sjacobs 		for (value = strtok_r(tmp, ", \t", &s_iter);
362355b4669Sjacobs 		     value != NULL;
363355b4669Sjacobs 		     value = strtok_r(NULL, ", \t", &s_iter))
364355b4669Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
365355b4669Sjacobs 					"member-names", value);
366355b4669Sjacobs 		free(tmp);
367355b4669Sjacobs 	}
368355b4669Sjacobs }
369355b4669Sjacobs 
370355b4669Sjacobs static papi_attribute_t **
371355b4669Sjacobs _cvt_nss_entry_to_printer(char *entry)
372355b4669Sjacobs {
373355b4669Sjacobs 	char    *key = NULL,
374355b4669Sjacobs 		*cp,
375355b4669Sjacobs 		buf[BUFSIZ];
376355b4669Sjacobs 	int in_namelist = 1, buf_pos = 0;
377355b4669Sjacobs 	papi_attribute_t **list = NULL;
378355b4669Sjacobs 
379355b4669Sjacobs 	if (entry == NULL)
380355b4669Sjacobs 		return (NULL);
381355b4669Sjacobs 
382355b4669Sjacobs 	memset(buf, 0, sizeof (buf));
383355b4669Sjacobs 	for (cp = entry; *cp != '\0'; cp++) {
384355b4669Sjacobs 		switch (*cp) {
385355b4669Sjacobs 		case ':':	/* end of kvp */
386355b4669Sjacobs 			if (in_namelist != 0) {
387355b4669Sjacobs 				papiAttributeListAddString(&list,
388355b4669Sjacobs 					PAPI_ATTR_APPEND, "printer-name", buf);
389355b4669Sjacobs 				in_namelist = 0;
390355b4669Sjacobs 			} else if (key != NULL)
391355b4669Sjacobs 				papiAttributeListAddString(&list,
392355b4669Sjacobs 					PAPI_ATTR_APPEND, key, buf);
393355b4669Sjacobs 			memset(buf, 0, sizeof (buf));
394355b4669Sjacobs 			buf_pos = 0;
395355b4669Sjacobs 			key = NULL;
396355b4669Sjacobs 			break;
397355b4669Sjacobs 		case '=':	/* kvp seperator */
398355b4669Sjacobs 			if (key == NULL) {
399355b4669Sjacobs 				key = strdup(buf);
400355b4669Sjacobs 				memset(buf, 0, sizeof (buf));
401355b4669Sjacobs 				buf_pos = 0;
402355b4669Sjacobs 			} else
403355b4669Sjacobs 				buf[buf_pos++] = *cp;
404355b4669Sjacobs 			break;
405355b4669Sjacobs 		case '|':	/* namelist seperator */
406355b4669Sjacobs 			if (in_namelist != 0) {
407355b4669Sjacobs 				papiAttributeListAddString(&list,
408355b4669Sjacobs 					PAPI_ATTR_APPEND, "printer-name", buf);
409355b4669Sjacobs 				memset(buf, 0, sizeof (buf));
410355b4669Sjacobs 				buf_pos = 0;
411355b4669Sjacobs 			} else	/* add it to the buffer */
412355b4669Sjacobs 				buf[buf_pos++] = *cp;
413355b4669Sjacobs 			break;
414355b4669Sjacobs 		case '\\':	/* escape char */
415355b4669Sjacobs 			buf[buf_pos++] = *(++cp);
416355b4669Sjacobs 			break;
417355b4669Sjacobs 		default:
418355b4669Sjacobs 			buf[buf_pos++] = *cp;
419355b4669Sjacobs 		}
420355b4669Sjacobs 
421355b4669Sjacobs 	}
422355b4669Sjacobs 
423355b4669Sjacobs 	if (key != NULL)
424355b4669Sjacobs 		papiAttributeListAddString(&list, PAPI_ATTR_APPEND, key, buf);
425355b4669Sjacobs 
426355b4669Sjacobs 	/* resolve any "use" references in the configuration DB */
427355b4669Sjacobs 	key = NULL;
428355b4669Sjacobs 	papiAttributeListGetString(list, NULL, "use", &key);
429355b4669Sjacobs 	if (key != NULL) {
430355b4669Sjacobs 		papi_attribute_t **use_attrs = getprinterbyname(key, NULL);
431355b4669Sjacobs 
432355b4669Sjacobs 		list_concatenate(&list, use_attrs);
433355b4669Sjacobs 	}
434355b4669Sjacobs 
435355b4669Sjacobs 	fill_printer_uri_supported(&list);
436355b4669Sjacobs 	cvt_all_to_member_names(&list); /* convert "all" to "member-names" */
437355b4669Sjacobs 
438355b4669Sjacobs 	return (list);
439355b4669Sjacobs }
440355b4669Sjacobs 
441355b4669Sjacobs #if defined(NSS_SOLARIS) && !defined(NSS_EMULATION)
442355b4669Sjacobs 
443355b4669Sjacobs #ifndef	NSS_DBNAM__PRINTERS	/* not in nss_dbdefs.h because it's private */
444355b4669Sjacobs #define	NSS_DBNAM__PRINTERS	"_printers"
445355b4669Sjacobs #endif
446355b4669Sjacobs 
447355b4669Sjacobs static DEFINE_NSS_DB_ROOT(db_root);
448355b4669Sjacobs static DEFINE_NSS_GETENT(context);
449355b4669Sjacobs 
450355b4669Sjacobs static char *private_ns = NULL;
451355b4669Sjacobs 
452355b4669Sjacobs static void
453355b4669Sjacobs _nss_initf_printers(p)
454355b4669Sjacobs     nss_db_params_t *p;
455355b4669Sjacobs {
456355b4669Sjacobs 	if (private_ns != NULL) {
457355b4669Sjacobs 		/*
458355b4669Sjacobs 		 * because we need to support a legacy interface that allows
459355b4669Sjacobs 		 * us to select a specific name service, we need to dummy up
460355b4669Sjacobs 		 * the parameters to use a private nsswitch database and set
461355b4669Sjacobs 		 * the * default_config entry to the name service we are
462355b4669Sjacobs 		 * looking into.
463355b4669Sjacobs 		 */
464355b4669Sjacobs 		p->name = NSS_DBNAM__PRINTERS;		/* "_printers" */
465355b4669Sjacobs 		p->default_config = private_ns;
466fe1de1a1Sjacobs 	} else {
467355b4669Sjacobs 		/* regular behaviour */
468355b4669Sjacobs 		p->name = NSS_DBNAM_PRINTERS;	 /* "printers" */
469355b4669Sjacobs 		p->default_config = NSS_DEFCONF_PRINTERS;
470355b4669Sjacobs 	}
471fe1de1a1Sjacobs 	syslog(LOG_DEBUG, "database: %s, default: %s",
472355b4669Sjacobs 		(p->name ? p->name : "NULL"),
473355b4669Sjacobs 		(p->default_config ? p->default_config : "NULL"));
474355b4669Sjacobs }
475355b4669Sjacobs 
476355b4669Sjacobs /*
477355b4669Sjacobs  * Return values: 0 = success, 1 = parse error, 2 = erange ...
478355b4669Sjacobs  * The structure pointer passed in is a structure in the caller's space
479355b4669Sjacobs  * wherein the field pointers would be set to areas in the buffer if
480355b4669Sjacobs  * need be. instring and buffer should be separate areas.
481355b4669Sjacobs  */
482355b4669Sjacobs /* ARGSUSED */
483355b4669Sjacobs static int
484355b4669Sjacobs str2printer(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
485355b4669Sjacobs {
486355b4669Sjacobs 	if (lenstr + 1 > buflen)
487355b4669Sjacobs 		return (NSS_STR_PARSE_ERANGE);
48832232bf4Sjacobs 
48932232bf4Sjacobs 	/* skip entries that begin with '#' */
49032232bf4Sjacobs 	if (instr[0] == '#')
49132232bf4Sjacobs 		return (NSS_STR_PARSE_PARSE);
49232232bf4Sjacobs 
493355b4669Sjacobs 	/*
494355b4669Sjacobs 	 * We copy the input string into the output buffer
495355b4669Sjacobs 	 */
496355b4669Sjacobs 	(void) memcpy(buffer, instr, lenstr);
497355b4669Sjacobs 	buffer[lenstr] = '\0';
498355b4669Sjacobs 
499355b4669Sjacobs 	return (NSS_STR_PARSE_SUCCESS);
500355b4669Sjacobs }
501355b4669Sjacobs #endif /* NSS_SOLARIS */
502355b4669Sjacobs 
503355b4669Sjacobs int
504355b4669Sjacobs setprinterentry(int stayopen, char *ns)
505355b4669Sjacobs {
506355b4669Sjacobs #ifdef NSS_EMULATION
507355b4669Sjacobs 	emul_setprinterentry(stayopen);
508355b4669Sjacobs #elif NSS_SOLARIS
509355b4669Sjacobs 	private_ns = ns;
510355b4669Sjacobs 	nss_setent(&db_root, _nss_initf_printers, &context);
511fe1de1a1Sjacobs 	private_ns = NULL;
512355b4669Sjacobs #endif
513355b4669Sjacobs 	return (0);
514355b4669Sjacobs }
515355b4669Sjacobs 
516355b4669Sjacobs 
517355b4669Sjacobs int
518355b4669Sjacobs endprinterentry(int i)
519355b4669Sjacobs {
520355b4669Sjacobs #ifdef NSS_EMULATION
521355b4669Sjacobs 	emul_endprinterentry();
522355b4669Sjacobs #elif NSS_SOLARIS
523355b4669Sjacobs 	nss_endent(&db_root, _nss_initf_printers, &context);
524355b4669Sjacobs 	nss_delete(&db_root);
525fe1de1a1Sjacobs 	private_ns = NULL;
526355b4669Sjacobs #endif
527355b4669Sjacobs 	return (0);
528355b4669Sjacobs }
529355b4669Sjacobs 
530355b4669Sjacobs /* ARGSUSED2 */
531355b4669Sjacobs papi_attribute_t **
532355b4669Sjacobs getprinterentry(char *ns)
533355b4669Sjacobs {
534355b4669Sjacobs 	papi_attribute_t **result = NULL;
535355b4669Sjacobs 
536355b4669Sjacobs #if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
537355b4669Sjacobs 	char buf[10240];
538355b4669Sjacobs 	nss_status_t	res = NSS_NOTFOUND;
539355b4669Sjacobs 
540355b4669Sjacobs #ifdef NSS_EMULATION
541355b4669Sjacobs 	res = emul_getprinterentry_r(buf, sizeof (buf));
542355b4669Sjacobs #elif NSS_SOLARIS
543355b4669Sjacobs 	nss_XbyY_args_t arg;
544355b4669Sjacobs 
545fe1de1a1Sjacobs 	private_ns = ns;
546355b4669Sjacobs 	NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
547355b4669Sjacobs 	res = nss_getent(&db_root, _nss_initf_printers, &context, &arg);
548355b4669Sjacobs 	(void) NSS_XbyY_FINI(&arg);
549fe1de1a1Sjacobs 	private_ns = NULL;
550355b4669Sjacobs #endif
551355b4669Sjacobs 
552355b4669Sjacobs 	if (res != NSS_SUCCESS)
553355b4669Sjacobs 		buf[0] = '\0';
554355b4669Sjacobs 
555355b4669Sjacobs 	result = _cvt_nss_entry_to_printer(buf);
5560ce6acb8Sjacobs #if defined(__sun) && defined(__SVR4)
5570ce6acb8Sjacobs 	solaris_lpsched_shortcircuit_hack(&result);
5580ce6acb8Sjacobs #endif
559355b4669Sjacobs #ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
560355b4669Sjacobs 	fill_printer_uri(&result);
561355b4669Sjacobs #endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
562355b4669Sjacobs #endif
563355b4669Sjacobs 
564355b4669Sjacobs #ifdef DEBUG
565355b4669Sjacobs 	printf("getprinterentry(%s): 0x%8.8x\n", (ns ? ns : "NULL"), result);
566355b4669Sjacobs 	if (result != NULL) {
567355b4669Sjacobs 		char buf[4096];
568355b4669Sjacobs 
569355b4669Sjacobs 		papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
570355b4669Sjacobs 		printf("\t%s\n", buf);
571355b4669Sjacobs 	}
572355b4669Sjacobs #endif /* DEBUG */
573355b4669Sjacobs 
574355b4669Sjacobs 	return (result);
575355b4669Sjacobs }
576355b4669Sjacobs 
577355b4669Sjacobs 
578355b4669Sjacobs papi_attribute_t **
579355b4669Sjacobs getprinterbyname(char *name, char *ns)
580355b4669Sjacobs {
581355b4669Sjacobs 	papi_attribute_t **result = NULL;
582355b4669Sjacobs 
583355b4669Sjacobs 	if (strstr(name, "://") != NULL) {	/* shortcut for URI form */
584355b4669Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
585355b4669Sjacobs 				"printer-name", name);
586355b4669Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
587355b4669Sjacobs 				"printer-uri-supported", name);
588355b4669Sjacobs 	} else if (strchr(name, ':') != NULL) {	/* shortcut for POSIX form */
5899c378f4bSjacobs 		char *uri = bsdaddr_to_uri(result, name);
590355b4669Sjacobs 
591355b4669Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
592355b4669Sjacobs 				"printer-name", name);
593355b4669Sjacobs 		if (uri != NULL) {
594355b4669Sjacobs 			papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
595355b4669Sjacobs 					"printer-uri-supported", uri);
596355b4669Sjacobs 			free(uri);
597355b4669Sjacobs 		}
598355b4669Sjacobs 	} else {				/* anything else */
599355b4669Sjacobs #if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
600355b4669Sjacobs 		char buf[10240];
601355b4669Sjacobs 		nss_status_t	res = NSS_NOTFOUND;
602355b4669Sjacobs 
603355b4669Sjacobs #ifdef NSS_EMULATION
604355b4669Sjacobs 		res = emul_getprinterbyname_r(name, buf, sizeof (buf));
605355b4669Sjacobs #elif NSS_SOLARIS
606355b4669Sjacobs 		nss_XbyY_args_t arg;
607355b4669Sjacobs 
608355b4669Sjacobs 		private_ns = ns;
609355b4669Sjacobs 		NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
610355b4669Sjacobs 		arg.key.name = name;
611355b4669Sjacobs 		res = nss_search(&db_root, _nss_initf_printers,
612355b4669Sjacobs 				NSS_DBOP_PRINTERS_BYNAME, &arg);
613355b4669Sjacobs 		(void) NSS_XbyY_FINI(&arg);
614fe1de1a1Sjacobs 		private_ns = NULL;
615355b4669Sjacobs 
616355b4669Sjacobs 		if (res != NSS_SUCCESS)
617355b4669Sjacobs 			buf[0] = '\0';
618355b4669Sjacobs #endif
619355b4669Sjacobs 
620355b4669Sjacobs 		result = _cvt_nss_entry_to_printer(buf);
621355b4669Sjacobs #endif
622355b4669Sjacobs 	}
6230ce6acb8Sjacobs #if defined(__sun) && defined(__SVR4)
6240ce6acb8Sjacobs 	solaris_lpsched_shortcircuit_hack(&result);
6250ce6acb8Sjacobs #endif
626355b4669Sjacobs #ifdef DEBUG
627355b4669Sjacobs 	printf("getprinterbyname(%s): %s = 0x%8.8x\n", (ns ? ns : "NULL"),
628355b4669Sjacobs 		name, result);
629355b4669Sjacobs 	if (result != NULL) {
630355b4669Sjacobs 		char buf[4096];
631355b4669Sjacobs 
632355b4669Sjacobs 		papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
633355b4669Sjacobs 		printf("\t%s\n", buf);
634355b4669Sjacobs 	}
635355b4669Sjacobs #endif /* DEBUG */
636355b4669Sjacobs 
637355b4669Sjacobs 	return (result);
638355b4669Sjacobs }
639