12264Sjacobs /*
22264Sjacobs  * CDDL HEADER START
32264Sjacobs  *
42264Sjacobs  * The contents of this file are subject to the terms of the
52264Sjacobs  * Common Development and Distribution License (the "License").
62264Sjacobs  * You may not use this file except in compliance with the License.
72264Sjacobs  *
82264Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92264Sjacobs  * or http://www.opensolaris.org/os/licensing.
102264Sjacobs  * See the License for the specific language governing permissions
112264Sjacobs  * and limitations under the License.
122264Sjacobs  *
132264Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
142264Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152264Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
162264Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
172264Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
182264Sjacobs  *
192264Sjacobs  * CDDL HEADER END
202264Sjacobs  */
212264Sjacobs 
222264Sjacobs /*
232264Sjacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
242264Sjacobs  * Use is subject to license terms.
252264Sjacobs  *
262264Sjacobs  */
272264Sjacobs 
28*2409Sjacobs /* Id: nss.c 180 2006-07-20 17:33:02Z njacobs $ */
292264Sjacobs 
302264Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
312264Sjacobs 
322264Sjacobs #include <stdio.h>
332264Sjacobs #include <stdlib.h>
342264Sjacobs #include <unistd.h>
352264Sjacobs #include <string.h>
362264Sjacobs #include <ctype.h>
372264Sjacobs #include <sys/types.h>
382264Sjacobs #include <syslog.h>
392264Sjacobs #include <papi.h>
402264Sjacobs #include <uri.h>
412264Sjacobs #include <papi_impl.h>
422264Sjacobs #ifdef NSS_EMULATION
432264Sjacobs #include <nss-emulation.h>
442264Sjacobs #elif NSS_SOLARIS
452264Sjacobs #include <nss_dbdefs.h>
462264Sjacobs #endif
472264Sjacobs #include <config-site.h>
482264Sjacobs #if defined(__sun) && defined(__SVR4)
492264Sjacobs #include <sys/systeminfo.h>
502264Sjacobs #endif
512264Sjacobs 
522264Sjacobs 
532264Sjacobs static char *
54*2409Sjacobs bsdaddr_to_uri(papi_attribute_t **list, char *bsdaddr)
552264Sjacobs {
562264Sjacobs 	char *result = NULL;
572264Sjacobs 
582264Sjacobs 	if (bsdaddr != NULL) {
592264Sjacobs 		char *bsd[3], *tmp, *iter = NULL;
602264Sjacobs 		char buf[512];
612264Sjacobs 
622264Sjacobs 		tmp = strdup(bsdaddr);
632264Sjacobs 
642264Sjacobs 		bsd[0] = strtok_r(tmp, ":,", &iter);
65*2409Sjacobs 		if ((bsd[1] = strtok_r(NULL, ":,", &iter)) == NULL)
66*2409Sjacobs 			papiAttributeListGetString(list, NULL,
67*2409Sjacobs 					"printer-name", &bsd[1]);
682264Sjacobs 		bsd[2] = strtok_r(NULL, ":,", &iter);
692264Sjacobs 
70*2409Sjacobs 		snprintf(buf, sizeof (buf), "lpd://%s/printers/%s%s%s", bsd[0],
71*2409Sjacobs 			(bsd[1] != NULL) ? bsd[1] : "",
722264Sjacobs 			(bsd[2] != NULL) ? "#" : "",
732264Sjacobs 			(bsd[2] != NULL) ? bsd[2] : "");
742264Sjacobs 
752264Sjacobs 		free(tmp);
762264Sjacobs 
772264Sjacobs 		result = strdup(buf);
782264Sjacobs 	}
792264Sjacobs 
802264Sjacobs 	return (result);
812264Sjacobs }
822264Sjacobs 
832264Sjacobs #if defined(__sun) && defined(__SVR4)
842313Sjacobs #include <sys/socket.h>
852313Sjacobs #include <sys/ioctl.h>
862313Sjacobs #include <sys/sockio.h>
872313Sjacobs #include <net/if.h>
882313Sjacobs #include <netinet/in.h>
892313Sjacobs #include <arpa/inet.h>
902313Sjacobs #include <netdb.h>
912313Sjacobs 
922313Sjacobs static struct in6_addr **
932313Sjacobs local_interfaces()
942313Sjacobs {
952313Sjacobs 	struct in6_addr **result = NULL;
962313Sjacobs 	int s;
972313Sjacobs 	struct lifnum n;
982313Sjacobs 	struct lifconf c;
992313Sjacobs 	struct lifreq *r;
1002313Sjacobs 	int count;
1012313Sjacobs 
1022313Sjacobs 	/* we need a socket to get the interfaces */
1032313Sjacobs 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1042313Sjacobs 		return (0);
1052313Sjacobs 
1062313Sjacobs 	/* get the number of interfaces */
1072313Sjacobs 	memset(&n, 0, sizeof (n));
1082313Sjacobs 	n.lifn_family = AF_UNSPEC;
1092313Sjacobs 	if (ioctl(s, SIOCGLIFNUM, (char *)&n) < 0) {
1102313Sjacobs 		close(s);
1112313Sjacobs 		return (0);	/* no interfaces */
1122313Sjacobs 	}
1132313Sjacobs 
1142313Sjacobs 	/* get the interface(s) configuration */
1152313Sjacobs 	memset(&c, 0, sizeof (c));
1162313Sjacobs 	c.lifc_family = AF_UNSPEC;
1172313Sjacobs 	c.lifc_buf = calloc(n.lifn_count, sizeof (struct lifreq));
1182313Sjacobs 	c.lifc_len = (n.lifn_count * sizeof (struct lifreq));
1192313Sjacobs 	if (ioctl(s, SIOCGLIFCONF, (char *)&c) < 0) {
1202313Sjacobs 		free(c.lifc_buf);
1212313Sjacobs 		close(s);
1222313Sjacobs 		return (0);	/* can't get interface(s) configuration */
1232313Sjacobs 	}
1242313Sjacobs 	close(s);
1252313Sjacobs 
1262313Sjacobs 	r = c.lifc_req;
1272313Sjacobs 	for (count = c.lifc_len / sizeof (struct lifreq);
1282313Sjacobs 	     count > 0; count--, r++) {
1292313Sjacobs 		struct in6_addr v6[1], *addr = NULL;
1302313Sjacobs 
1312313Sjacobs 		switch (r->lifr_addr.ss_family) {
1322313Sjacobs 		case AF_INET: {
1332313Sjacobs 			struct sockaddr_in *s =
1342313Sjacobs 				(struct sockaddr_in *)&r->lifr_addr;
1352313Sjacobs 			IN6_INADDR_TO_V4MAPPED(&s->sin_addr, v6);
1362313Sjacobs 			addr = v6;
1372313Sjacobs 			}
1382313Sjacobs 			break;
1392313Sjacobs 		case AF_INET6: {
1402313Sjacobs 			struct sockaddr_in6 *s =
1412313Sjacobs 				(struct sockaddr_in6 *)&r->lifr_addr;
1422313Sjacobs 			addr = &s->sin6_addr;
1432313Sjacobs 			}
1442313Sjacobs 			break;
1452313Sjacobs 		}
1462313Sjacobs 
1472313Sjacobs 		if (addr != NULL) {
1482313Sjacobs 			struct in6_addr *a = malloc(sizeof (*a));
1492313Sjacobs 
1502313Sjacobs 			memcpy(a, addr, sizeof (*a));
1512313Sjacobs 			list_append(&result, a);
1522313Sjacobs 		}
1532313Sjacobs 	}
1542313Sjacobs 	free(c.lifc_buf);
1552313Sjacobs 
1562313Sjacobs 	return (result);
1572313Sjacobs }
1582313Sjacobs 
1592313Sjacobs static int
1602313Sjacobs match_interfaces(char *host)
1612313Sjacobs {
1622313Sjacobs 	struct in6_addr **lif = local_interfaces();
1632313Sjacobs 	struct hostent *hp;
1642313Sjacobs 	int rc = 0;
1652313Sjacobs 	int errnum;
1662313Sjacobs 
1672313Sjacobs 	/* are there any local interfaces */
1682313Sjacobs 	if (lif == NULL)
1692313Sjacobs 		return (0);
1702313Sjacobs 
1712313Sjacobs 	/* cycle through the host db addresses */
1722313Sjacobs 	hp = getipnodebyname(host, AF_INET6, AI_ALL|AI_V4MAPPED, &errnum);
1732313Sjacobs 	if (hp != NULL) {
1742313Sjacobs 		struct in6_addr **tmp = (struct in6_addr **)hp->h_addr_list;
1752313Sjacobs 		int i;
1762313Sjacobs 
1772313Sjacobs 		for (i = 0; ((rc == 0) && (tmp[i] != NULL)); i++) {
1782313Sjacobs 			int j;
1792313Sjacobs 
1802313Sjacobs 			for (j = 0; ((rc == 0) && (lif[j] != NULL)); j++)
1812313Sjacobs 				if (memcmp(tmp[i], lif[j],
1822313Sjacobs 						sizeof (struct in6_addr)) == 0)
1832313Sjacobs 					rc = 1;
1842313Sjacobs 		}
1852313Sjacobs 	}
1862313Sjacobs 	free(lif);
1872313Sjacobs 
1882313Sjacobs 	return (rc);
1892313Sjacobs }
1902313Sjacobs 
1912313Sjacobs static int
1922313Sjacobs is_localhost(char *host)
1932313Sjacobs {
1942313Sjacobs 	char hostname[BUFSIZ];
1952313Sjacobs 
1962313Sjacobs 	/* is it "localhost" */
1972313Sjacobs 	if (strncasecmp(host, "localhost", 10) == 0)
1982313Sjacobs 		return (1);
1992313Sjacobs 
2002313Sjacobs 	/* is it the {nodename} */
2012313Sjacobs 	sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
2022313Sjacobs 	if (strncasecmp(host, hostname, strlen(hostname)) == 0)
2032313Sjacobs 		return (1);
2042313Sjacobs 
2052313Sjacobs 	/* does it match one of the host's configured interfaces */
2062313Sjacobs 	if (match_interfaces(host) != 0)
2072313Sjacobs 		return (1);
2082313Sjacobs 
2092313Sjacobs 	return (0);
2102313Sjacobs }
2112313Sjacobs 
2122264Sjacobs /*
2132264Sjacobs  * This is an awful HACK to force the dynamic PAPI library to use the
2142264Sjacobs  * lpsched support when the destination apears to be a local lpsched
2152264Sjacobs  * queue on Solaris.
2162264Sjacobs  */
2172264Sjacobs static void
2182264Sjacobs solaris_lpsched_shortcircuit_hack(papi_attribute_t ***list)
2192264Sjacobs {
2202264Sjacobs 	papi_attribute_t *attribute;
2212264Sjacobs 	uri_t *uri = NULL;
2222264Sjacobs 	char *printer = NULL;
2232264Sjacobs 	char buf[128], buf2[128];
2242264Sjacobs 
2252264Sjacobs 	/* setting this in the calling env can be useful for debugging */
2262264Sjacobs 	if (getenv("DISABLE_LPSCHED_SHORTCIRCUIT") != NULL)
2272264Sjacobs 		return;
2282264Sjacobs 
2292264Sjacobs 	papiAttributeListGetString(*list, NULL,
2302264Sjacobs 				"printer-uri-supported", &printer);
2312264Sjacobs 	if (uri_from_string(printer, &uri) < 0)
2322264Sjacobs 		return;
2332264Sjacobs 
2342264Sjacobs 	/* already an lpsched URI ? */
2352264Sjacobs 	if (strcasecmp(uri->scheme, "lpsched") == 0)
2362264Sjacobs 		return;
2372264Sjacobs 
2382264Sjacobs 	if ((printer = strrchr(uri->path, '/')) == NULL)
2392264Sjacobs 		printer = uri->path;
2402264Sjacobs 	else
2412264Sjacobs 		printer++;
2422264Sjacobs 
2432264Sjacobs 	/* is there an lpsched queue (printer/class) */
2442264Sjacobs 	snprintf(buf, sizeof (buf), "/etc/lp/interfaces/%s", printer);
2452264Sjacobs 	snprintf(buf2, sizeof (buf2), "/etc/lp/classes/%s", printer);
2462264Sjacobs 	if ((access(buf, F_OK) < 0) && (access(buf2, F_OK) < 0))
2472264Sjacobs 		return;
2482264Sjacobs 
2492313Sjacobs 	/* is this the "local" host */
2502313Sjacobs 	if ((uri->host != NULL) && (is_localhost(uri->host) == 0))
2512313Sjacobs 		return;
2522313Sjacobs 
2532313Sjacobs 	snprintf(buf, sizeof (buf), "lpsched://%s/printers/%s",
2542313Sjacobs 			(uri->host ? uri->host : "localhost"), printer);
2552264Sjacobs 	papiAttributeListAddString(list, PAPI_ATTR_REPLACE,
2562264Sjacobs 			"printer-uri-supported", buf);
2572264Sjacobs }
2582264Sjacobs #endif
2592264Sjacobs 
2602264Sjacobs static void
2612264Sjacobs fill_printer_uri_supported(papi_attribute_t ***list)
2622264Sjacobs {
2632264Sjacobs 	papi_attribute_t *attribute;
2642264Sjacobs 	char *string = NULL;
2652264Sjacobs 
2662264Sjacobs 	/* do we have a printer-uri-supported */
2672264Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri-supported");
2682264Sjacobs 	if (attribute != NULL) /* we have what we need, return */
2692264Sjacobs 		return;
2702264Sjacobs 
2712264Sjacobs 	/* do we have a printer-uri to rename */
2722264Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri");
2732264Sjacobs 	if (attribute != NULL) { /* rename it in place and return */
2742264Sjacobs 		free(attribute->name);
2752264Sjacobs 		attribute->name = strdup("printer-uri-supported");
2762264Sjacobs 		return;
2772264Sjacobs 	}
2782264Sjacobs 
2792264Sjacobs 	/* do we have a printers.conf(4) "bsdaddr" to convert */
2802264Sjacobs 	papiAttributeListGetString(*list, NULL, "bsdaddr", &string);
2812264Sjacobs 	if (string != NULL) { /* parse it, convert it, add it */
282*2409Sjacobs 		char *uri = bsdaddr_to_uri(*list, string);
2832264Sjacobs 
2842264Sjacobs 		if (uri != NULL) {
2852264Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
2862264Sjacobs 					"printer-uri-supported", uri);
2872264Sjacobs 			papiAttributeListDelete(list, "bsdaddr");
2882264Sjacobs 			free(uri);
2892264Sjacobs 			return;
2902264Sjacobs 		}
2912264Sjacobs 	}
2922264Sjacobs 
2932264Sjacobs 	/* do we have a printers.conf(4) "rm" (and "rp") to convert */
2942264Sjacobs 	papiAttributeListGetString(*list, NULL, "rm", &string);
2952264Sjacobs 	if (string != NULL) {
2962264Sjacobs 		char *rp = NULL;
2972264Sjacobs 
2982264Sjacobs 		/* default to "printer-name", but use "rp" if we have it */
2992264Sjacobs 		papiAttributeListGetString(*list, NULL, "printer-name", &rp);
3002264Sjacobs 		papiAttributeListGetString(*list, NULL, "rp", &rp);
3012264Sjacobs 
3022264Sjacobs 		if (rp != NULL) { /* fill in the uri if we have the data */
3032264Sjacobs 			char buf[BUFSIZ];
3042264Sjacobs 
3052264Sjacobs 			snprintf(buf, sizeof (buf), "lpd://%s/printers/%s",
3062264Sjacobs 				string, rp);
3072264Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
3082264Sjacobs 					"printer-uri-supported", strdup(buf));
3092264Sjacobs 			return;
3102264Sjacobs 		}
3112264Sjacobs 	}
3122264Sjacobs 
3132264Sjacobs 	/* if were are here, we don't have a printer-uri-supported */
3142264Sjacobs }
3152264Sjacobs 
3162264Sjacobs #ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
3172264Sjacobs static void
3182264Sjacobs fill_printer_uri(papi_attribute_t ***list)
3192264Sjacobs {
3202264Sjacobs 	papi_attribute_t *attribute;
3212264Sjacobs 	char *uri = NULL;
3222264Sjacobs 
3232264Sjacobs 	if ((list == NULL) || (*list == NULL))
3242264Sjacobs 		return;
3252264Sjacobs 
3262313Sjacobs 	/* do we have a printer-uri */
3272264Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri");
3282264Sjacobs 	if (attribute != NULL) /* we have what we need, return */
3292264Sjacobs 		return;
3302264Sjacobs 
3312264Sjacobs 	/*
3322264Sjacobs 	 * this is sufficient to fool libgnomeprintpapi, but not promote it's
3332264Sjacobs 	 * use in the future.
3342264Sjacobs 	 */
3352264Sjacobs 	papiAttributeListAddString(list, PAPI_ATTR_EXCL, "printer-uri",
3362264Sjacobs 			"broken printer-uri semantic");
3372264Sjacobs }
3382264Sjacobs #endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
3392264Sjacobs 
3402264Sjacobs static void
3412264Sjacobs cvt_all_to_member_names(papi_attribute_t ***list)
3422264Sjacobs {
3432264Sjacobs 	papi_status_t status;
3442264Sjacobs 	void *iter = NULL;
3452264Sjacobs 	char *string = NULL;
3462264Sjacobs 
3472264Sjacobs 	papiAttributeListGetString(*list, NULL, "member-names", &string);
3482264Sjacobs 	if (string != NULL) /* already have a member-names */
3492264Sjacobs 		return;
3502264Sjacobs 
3512264Sjacobs 	for (status = papiAttributeListGetString(*list, &iter, "all", &string);
3522264Sjacobs 	     status == PAPI_OK;
3532264Sjacobs 	     status = papiAttributeListGetString(*list, &iter, NULL, &string)) {
3542264Sjacobs 		char *s_iter = NULL, *value, *tmp = strdup(string);
3552264Sjacobs 
3562264Sjacobs 		for (value = strtok_r(tmp, ", \t", &s_iter);
3572264Sjacobs 		     value != NULL;
3582264Sjacobs 		     value = strtok_r(NULL, ", \t", &s_iter))
3592264Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
3602264Sjacobs 					"member-names", value);
3612264Sjacobs 		free(tmp);
3622264Sjacobs 	}
3632264Sjacobs }
3642264Sjacobs 
3652264Sjacobs static papi_attribute_t **
3662264Sjacobs _cvt_nss_entry_to_printer(char *entry)
3672264Sjacobs {
3682264Sjacobs 	char    *key = NULL,
3692264Sjacobs 		*cp,
3702264Sjacobs 		buf[BUFSIZ];
3712264Sjacobs 	int in_namelist = 1, buf_pos = 0;
3722264Sjacobs 	papi_attribute_t **list = NULL;
3732264Sjacobs 
3742264Sjacobs 	if (entry == NULL)
3752264Sjacobs 		return (NULL);
3762264Sjacobs 
3772264Sjacobs 	memset(buf, 0, sizeof (buf));
3782264Sjacobs 	for (cp = entry; *cp != '\0'; cp++) {
3792264Sjacobs 		switch (*cp) {
3802264Sjacobs 		case ':':	/* end of kvp */
3812264Sjacobs 			if (in_namelist != 0) {
3822264Sjacobs 				papiAttributeListAddString(&list,
3832264Sjacobs 					PAPI_ATTR_APPEND, "printer-name", buf);
3842264Sjacobs 				in_namelist = 0;
3852264Sjacobs 			} else if (key != NULL)
3862264Sjacobs 				papiAttributeListAddString(&list,
3872264Sjacobs 					PAPI_ATTR_APPEND, key, buf);
3882264Sjacobs 			memset(buf, 0, sizeof (buf));
3892264Sjacobs 			buf_pos = 0;
3902264Sjacobs 			key = NULL;
3912264Sjacobs 			break;
3922264Sjacobs 		case '=':	/* kvp seperator */
3932264Sjacobs 			if (key == NULL) {
3942264Sjacobs 				key = strdup(buf);
3952264Sjacobs 				memset(buf, 0, sizeof (buf));
3962264Sjacobs 				buf_pos = 0;
3972264Sjacobs 			} else
3982264Sjacobs 				buf[buf_pos++] = *cp;
3992264Sjacobs 			break;
4002264Sjacobs 		case '|':	/* namelist seperator */
4012264Sjacobs 			if (in_namelist != 0) {
4022264Sjacobs 				papiAttributeListAddString(&list,
4032264Sjacobs 					PAPI_ATTR_APPEND, "printer-name", buf);
4042264Sjacobs 				memset(buf, 0, sizeof (buf));
4052264Sjacobs 				buf_pos = 0;
4062264Sjacobs 			} else	/* add it to the buffer */
4072264Sjacobs 				buf[buf_pos++] = *cp;
4082264Sjacobs 			break;
4092264Sjacobs 		case '\\':	/* escape char */
4102264Sjacobs 			buf[buf_pos++] = *(++cp);
4112264Sjacobs 			break;
4122264Sjacobs 		default:
4132264Sjacobs 			buf[buf_pos++] = *cp;
4142264Sjacobs 		}
4152264Sjacobs 
4162264Sjacobs 	}
4172264Sjacobs 
4182264Sjacobs 	if (key != NULL)
4192264Sjacobs 		papiAttributeListAddString(&list, PAPI_ATTR_APPEND, key, buf);
4202264Sjacobs 
4212264Sjacobs 	/* resolve any "use" references in the configuration DB */
4222264Sjacobs 	key = NULL;
4232264Sjacobs 	papiAttributeListGetString(list, NULL, "use", &key);
4242264Sjacobs 	if (key != NULL) {
4252264Sjacobs 		papi_attribute_t **use_attrs = getprinterbyname(key, NULL);
4262264Sjacobs 
4272264Sjacobs 		list_concatenate(&list, use_attrs);
4282264Sjacobs 	}
4292264Sjacobs 
4302264Sjacobs 	fill_printer_uri_supported(&list);
4312264Sjacobs 	cvt_all_to_member_names(&list); /* convert "all" to "member-names" */
4322264Sjacobs 
4332264Sjacobs 	return (list);
4342264Sjacobs }
4352264Sjacobs 
4362264Sjacobs #if defined(NSS_SOLARIS) && !defined(NSS_EMULATION)
4372264Sjacobs 
4382264Sjacobs #ifndef	NSS_DBNAM__PRINTERS	/* not in nss_dbdefs.h because it's private */
4392264Sjacobs #define	NSS_DBNAM__PRINTERS	"_printers"
4402264Sjacobs #endif
4412264Sjacobs 
4422264Sjacobs static DEFINE_NSS_DB_ROOT(db_root);
4432264Sjacobs static DEFINE_NSS_GETENT(context);
4442264Sjacobs 
4452264Sjacobs static char *private_ns = NULL;
4462264Sjacobs static char initialized = 0;
4472264Sjacobs 
4482264Sjacobs static void
4492264Sjacobs _nss_initf_printers(p)
4502264Sjacobs     nss_db_params_t *p;
4512264Sjacobs {
4522264Sjacobs 	if (private_ns != NULL) {
4532264Sjacobs 		/*
4542264Sjacobs 		 * because we need to support a legacy interface that allows
4552264Sjacobs 		 * us to select a specific name service, we need to dummy up
4562264Sjacobs 		 * the parameters to use a private nsswitch database and set
4572264Sjacobs 		 * the * default_config entry to the name service we are
4582264Sjacobs 		 * looking into.
4592264Sjacobs 		 */
4602264Sjacobs 		p->name = NSS_DBNAM__PRINTERS;		/* "_printers" */
4612264Sjacobs 		p->default_config = private_ns;
4622264Sjacobs 		private_ns = NULL;
4632264Sjacobs 	} else if (initialized == 0) {
4642264Sjacobs 		/* regular behaviour */
4652264Sjacobs 		p->name = NSS_DBNAM_PRINTERS;	 /* "printers" */
4662264Sjacobs 		p->default_config = NSS_DEFCONF_PRINTERS;
4672264Sjacobs 		initialized = 1;
4682264Sjacobs 	}
4692264Sjacobs 	syslog(LOG_DEBUG, "database: %s, services: %s",
4702264Sjacobs 		(p->name ? p->name : "NULL"),
4712264Sjacobs 		(p->default_config ? p->default_config : "NULL"));
4722264Sjacobs }
4732264Sjacobs 
4742264Sjacobs /*
4752264Sjacobs  * Return values: 0 = success, 1 = parse error, 2 = erange ...
4762264Sjacobs  * The structure pointer passed in is a structure in the caller's space
4772264Sjacobs  * wherein the field pointers would be set to areas in the buffer if
4782264Sjacobs  * need be. instring and buffer should be separate areas.
4792264Sjacobs  */
4802264Sjacobs /* ARGSUSED */
4812264Sjacobs static int
4822264Sjacobs str2printer(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
4832264Sjacobs {
4842264Sjacobs 	if (lenstr + 1 > buflen)
4852264Sjacobs 		return (NSS_STR_PARSE_ERANGE);
4862264Sjacobs 	/*
4872264Sjacobs 	 * We copy the input string into the output buffer
4882264Sjacobs 	 */
4892264Sjacobs 	(void) memcpy(buffer, instr, lenstr);
4902264Sjacobs 	buffer[lenstr] = '\0';
4912264Sjacobs 
4922264Sjacobs 	return (NSS_STR_PARSE_SUCCESS);
4932264Sjacobs }
4942264Sjacobs #endif /* NSS_SOLARIS */
4952264Sjacobs 
4962264Sjacobs int
4972264Sjacobs setprinterentry(int stayopen, char *ns)
4982264Sjacobs {
4992264Sjacobs #ifdef NSS_EMULATION
5002264Sjacobs 	emul_setprinterentry(stayopen);
5012264Sjacobs #elif NSS_SOLARIS
5022264Sjacobs 	initialized = 0;
5032264Sjacobs 	private_ns = ns;
5042264Sjacobs 	nss_setent(&db_root, _nss_initf_printers, &context);
5052264Sjacobs #endif
5062264Sjacobs 	return (0);
5072264Sjacobs }
5082264Sjacobs 
5092264Sjacobs 
5102264Sjacobs int
5112264Sjacobs endprinterentry(int i)
5122264Sjacobs {
5132264Sjacobs #ifdef NSS_EMULATION
5142264Sjacobs 	emul_endprinterentry();
5152264Sjacobs #elif NSS_SOLARIS
5162264Sjacobs 	initialized = 0;
5172264Sjacobs 	nss_endent(&db_root, _nss_initf_printers, &context);
5182264Sjacobs 	nss_delete(&db_root);
5192264Sjacobs #endif
5202264Sjacobs 	return (0);
5212264Sjacobs }
5222264Sjacobs 
5232264Sjacobs /* ARGSUSED2 */
5242264Sjacobs papi_attribute_t **
5252264Sjacobs getprinterentry(char *ns)
5262264Sjacobs {
5272264Sjacobs 	papi_attribute_t **result = NULL;
5282264Sjacobs 
5292264Sjacobs #if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
5302264Sjacobs 	char buf[10240];
5312264Sjacobs 	nss_status_t	res = NSS_NOTFOUND;
5322264Sjacobs 
5332264Sjacobs #ifdef NSS_EMULATION
5342264Sjacobs 	res = emul_getprinterentry_r(buf, sizeof (buf));
5352264Sjacobs #elif NSS_SOLARIS
5362264Sjacobs 	nss_XbyY_args_t arg;
5372264Sjacobs 
5382264Sjacobs 	NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
5392264Sjacobs 	res = nss_getent(&db_root, _nss_initf_printers, &context, &arg);
5402264Sjacobs 	(void) NSS_XbyY_FINI(&arg);
5412264Sjacobs #endif
5422264Sjacobs 
5432264Sjacobs 	if (res != NSS_SUCCESS)
5442264Sjacobs 		buf[0] = '\0';
5452264Sjacobs 
5462264Sjacobs 	result = _cvt_nss_entry_to_printer(buf);
5472313Sjacobs #if defined(__sun) && defined(__SVR4)
5482313Sjacobs 	solaris_lpsched_shortcircuit_hack(&result);
5492313Sjacobs #endif
5502264Sjacobs #ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
5512264Sjacobs 	fill_printer_uri(&result);
5522264Sjacobs #endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
5532264Sjacobs #endif
5542264Sjacobs 
5552264Sjacobs #ifdef DEBUG
5562264Sjacobs 	printf("getprinterentry(%s): 0x%8.8x\n", (ns ? ns : "NULL"), result);
5572264Sjacobs 	if (result != NULL) {
5582264Sjacobs 		char buf[4096];
5592264Sjacobs 
5602264Sjacobs 		papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
5612264Sjacobs 		printf("\t%s\n", buf);
5622264Sjacobs 	}
5632264Sjacobs #endif /* DEBUG */
5642264Sjacobs 
5652264Sjacobs 	return (result);
5662264Sjacobs }
5672264Sjacobs 
5682264Sjacobs 
5692264Sjacobs papi_attribute_t **
5702264Sjacobs getprinterbyname(char *name, char *ns)
5712264Sjacobs {
5722264Sjacobs 	papi_attribute_t **result = NULL;
5732264Sjacobs 
5742264Sjacobs 	if (strstr(name, "://") != NULL) {	/* shortcut for URI form */
5752264Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
5762264Sjacobs 				"printer-name", name);
5772264Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
5782264Sjacobs 				"printer-uri-supported", name);
5792264Sjacobs 	} else if (strchr(name, ':') != NULL) {	/* shortcut for POSIX form */
580*2409Sjacobs 		char *uri = bsdaddr_to_uri(result, name);
5812264Sjacobs 
5822264Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
5832264Sjacobs 				"printer-name", name);
5842264Sjacobs 		if (uri != NULL) {
5852264Sjacobs 			papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
5862264Sjacobs 					"printer-uri-supported", uri);
5872264Sjacobs 			free(uri);
5882264Sjacobs 		}
5892264Sjacobs 	} else {				/* anything else */
5902264Sjacobs #if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
5912264Sjacobs 		char buf[10240];
5922264Sjacobs 		nss_status_t	res = NSS_NOTFOUND;
5932264Sjacobs 
5942264Sjacobs #ifdef NSS_EMULATION
5952264Sjacobs 		res = emul_getprinterbyname_r(name, buf, sizeof (buf));
5962264Sjacobs #elif NSS_SOLARIS
5972264Sjacobs 		nss_XbyY_args_t arg;
5982264Sjacobs 
5992264Sjacobs 		private_ns = ns;
6002264Sjacobs 		NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
6012264Sjacobs 		arg.key.name = name;
6022264Sjacobs 		res = nss_search(&db_root, _nss_initf_printers,
6032264Sjacobs 				NSS_DBOP_PRINTERS_BYNAME, &arg);
6042264Sjacobs 		(void) NSS_XbyY_FINI(&arg);
6052264Sjacobs 
6062264Sjacobs 		if (res != NSS_SUCCESS)
6072264Sjacobs 			buf[0] = '\0';
6082264Sjacobs #endif
6092264Sjacobs 
6102264Sjacobs 		result = _cvt_nss_entry_to_printer(buf);
6112264Sjacobs #endif
6122264Sjacobs 	}
6132313Sjacobs #if defined(__sun) && defined(__SVR4)
6142313Sjacobs 	solaris_lpsched_shortcircuit_hack(&result);
6152313Sjacobs #endif
6162264Sjacobs #ifdef DEBUG
6172264Sjacobs 	printf("getprinterbyname(%s): %s = 0x%8.8x\n", (ns ? ns : "NULL"),
6182264Sjacobs 		name, result);
6192264Sjacobs 	if (result != NULL) {
6202264Sjacobs 		char buf[4096];
6212264Sjacobs 
6222264Sjacobs 		papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
6232264Sjacobs 		printf("\t%s\n", buf);
6242264Sjacobs 	}
6252264Sjacobs #endif /* DEBUG */
6262264Sjacobs 
6272264Sjacobs 	return (result);
6282264Sjacobs }
629