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 /*
23*6817Sjacobs  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
242264Sjacobs  * Use is subject to license terms.
252264Sjacobs  *
262264Sjacobs  */
272264Sjacobs 
282409Sjacobs /* 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 *
542409Sjacobs 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);
652409Sjacobs 		if ((bsd[1] = strtok_r(NULL, ":,", &iter)) == NULL)
662409Sjacobs 			papiAttributeListGetString(list, NULL,
672409Sjacobs 					"printer-name", &bsd[1]);
682264Sjacobs 		bsd[2] = strtok_r(NULL, ":,", &iter);
692264Sjacobs 
702409Sjacobs 		snprintf(buf, sizeof (buf), "lpd://%s/printers/%s%s%s", bsd[0],
712409Sjacobs 			(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 
271*6817Sjacobs 	/* do we have a printer-uri (in URI form) to rename */
2722264Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri");
273*6817Sjacobs 	if ((attribute != NULL) &&
274*6817Sjacobs 	    (attribute->type == PAPI_STRING) &&
275*6817Sjacobs 	    (attribute->values != NULL) &&
276*6817Sjacobs 	    (attribute->values[0]->string != NULL) &&
277*6817Sjacobs 	    (strstr(attribute->values[0]->string, "://") != NULL)) {
278*6817Sjacobs 			/* rename it in place and return */
2792264Sjacobs 		free(attribute->name);
2802264Sjacobs 		attribute->name = strdup("printer-uri-supported");
2812264Sjacobs 		return;
2822264Sjacobs 	}
2832264Sjacobs 
2842264Sjacobs 	/* do we have a printers.conf(4) "bsdaddr" to convert */
2852264Sjacobs 	papiAttributeListGetString(*list, NULL, "bsdaddr", &string);
2862264Sjacobs 	if (string != NULL) { /* parse it, convert it, add it */
2872409Sjacobs 		char *uri = bsdaddr_to_uri(*list, string);
2882264Sjacobs 
2892264Sjacobs 		if (uri != NULL) {
2902264Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
2912264Sjacobs 					"printer-uri-supported", uri);
2922264Sjacobs 			papiAttributeListDelete(list, "bsdaddr");
2932264Sjacobs 			free(uri);
2942264Sjacobs 			return;
2952264Sjacobs 		}
2962264Sjacobs 	}
2972264Sjacobs 
2982264Sjacobs 	/* do we have a printers.conf(4) "rm" (and "rp") to convert */
2992264Sjacobs 	papiAttributeListGetString(*list, NULL, "rm", &string);
3002264Sjacobs 	if (string != NULL) {
3012264Sjacobs 		char *rp = NULL;
3022264Sjacobs 
3032264Sjacobs 		/* default to "printer-name", but use "rp" if we have it */
3042264Sjacobs 		papiAttributeListGetString(*list, NULL, "printer-name", &rp);
3052264Sjacobs 		papiAttributeListGetString(*list, NULL, "rp", &rp);
3062264Sjacobs 
3072264Sjacobs 		if (rp != NULL) { /* fill in the uri if we have the data */
3082264Sjacobs 			char buf[BUFSIZ];
3092264Sjacobs 
3102264Sjacobs 			snprintf(buf, sizeof (buf), "lpd://%s/printers/%s",
3112264Sjacobs 				string, rp);
3122264Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
3132264Sjacobs 					"printer-uri-supported", strdup(buf));
3142264Sjacobs 			return;
3152264Sjacobs 		}
3162264Sjacobs 	}
3172264Sjacobs 
3182264Sjacobs 	/* if were are here, we don't have a printer-uri-supported */
3192264Sjacobs }
3202264Sjacobs 
3212264Sjacobs #ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
3222264Sjacobs static void
3232264Sjacobs fill_printer_uri(papi_attribute_t ***list)
3242264Sjacobs {
3252264Sjacobs 	papi_attribute_t *attribute;
3262264Sjacobs 	char *uri = NULL;
3272264Sjacobs 
3282264Sjacobs 	if ((list == NULL) || (*list == NULL))
3292264Sjacobs 		return;
3302264Sjacobs 
3312313Sjacobs 	/* do we have a printer-uri */
3322264Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri");
3332264Sjacobs 	if (attribute != NULL) /* we have what we need, return */
3342264Sjacobs 		return;
3352264Sjacobs 
3362264Sjacobs 	/*
3372264Sjacobs 	 * this is sufficient to fool libgnomeprintpapi, but not promote it's
3382264Sjacobs 	 * use in the future.
3392264Sjacobs 	 */
3402264Sjacobs 	papiAttributeListAddString(list, PAPI_ATTR_EXCL, "printer-uri",
3412264Sjacobs 			"broken printer-uri semantic");
3422264Sjacobs }
3432264Sjacobs #endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
3442264Sjacobs 
3452264Sjacobs static void
3462264Sjacobs cvt_all_to_member_names(papi_attribute_t ***list)
3472264Sjacobs {
3482264Sjacobs 	papi_status_t status;
3492264Sjacobs 	void *iter = NULL;
3502264Sjacobs 	char *string = NULL;
3512264Sjacobs 
3522264Sjacobs 	papiAttributeListGetString(*list, NULL, "member-names", &string);
3532264Sjacobs 	if (string != NULL) /* already have a member-names */
3542264Sjacobs 		return;
3552264Sjacobs 
3562264Sjacobs 	for (status = papiAttributeListGetString(*list, &iter, "all", &string);
3572264Sjacobs 	     status == PAPI_OK;
3582264Sjacobs 	     status = papiAttributeListGetString(*list, &iter, NULL, &string)) {
3592264Sjacobs 		char *s_iter = NULL, *value, *tmp = strdup(string);
3602264Sjacobs 
3612264Sjacobs 		for (value = strtok_r(tmp, ", \t", &s_iter);
3622264Sjacobs 		     value != NULL;
3632264Sjacobs 		     value = strtok_r(NULL, ", \t", &s_iter))
3642264Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
3652264Sjacobs 					"member-names", value);
3662264Sjacobs 		free(tmp);
3672264Sjacobs 	}
3682264Sjacobs }
3692264Sjacobs 
3702264Sjacobs static papi_attribute_t **
3712264Sjacobs _cvt_nss_entry_to_printer(char *entry)
3722264Sjacobs {
3732264Sjacobs 	char    *key = NULL,
3742264Sjacobs 		*cp,
3752264Sjacobs 		buf[BUFSIZ];
3762264Sjacobs 	int in_namelist = 1, buf_pos = 0;
3772264Sjacobs 	papi_attribute_t **list = NULL;
3782264Sjacobs 
3792264Sjacobs 	if (entry == NULL)
3802264Sjacobs 		return (NULL);
3812264Sjacobs 
3822264Sjacobs 	memset(buf, 0, sizeof (buf));
3832264Sjacobs 	for (cp = entry; *cp != '\0'; cp++) {
3842264Sjacobs 		switch (*cp) {
3852264Sjacobs 		case ':':	/* end of kvp */
3862264Sjacobs 			if (in_namelist != 0) {
3872264Sjacobs 				papiAttributeListAddString(&list,
3882264Sjacobs 					PAPI_ATTR_APPEND, "printer-name", buf);
3892264Sjacobs 				in_namelist = 0;
3902264Sjacobs 			} else if (key != NULL)
3912264Sjacobs 				papiAttributeListAddString(&list,
3922264Sjacobs 					PAPI_ATTR_APPEND, key, buf);
3932264Sjacobs 			memset(buf, 0, sizeof (buf));
3942264Sjacobs 			buf_pos = 0;
3952264Sjacobs 			key = NULL;
3962264Sjacobs 			break;
3972264Sjacobs 		case '=':	/* kvp seperator */
3982264Sjacobs 			if (key == NULL) {
3992264Sjacobs 				key = strdup(buf);
4002264Sjacobs 				memset(buf, 0, sizeof (buf));
4012264Sjacobs 				buf_pos = 0;
4022264Sjacobs 			} else
4032264Sjacobs 				buf[buf_pos++] = *cp;
4042264Sjacobs 			break;
4052264Sjacobs 		case '|':	/* namelist seperator */
4062264Sjacobs 			if (in_namelist != 0) {
4072264Sjacobs 				papiAttributeListAddString(&list,
4082264Sjacobs 					PAPI_ATTR_APPEND, "printer-name", buf);
4092264Sjacobs 				memset(buf, 0, sizeof (buf));
4102264Sjacobs 				buf_pos = 0;
4112264Sjacobs 			} else	/* add it to the buffer */
4122264Sjacobs 				buf[buf_pos++] = *cp;
4132264Sjacobs 			break;
4142264Sjacobs 		case '\\':	/* escape char */
4152264Sjacobs 			buf[buf_pos++] = *(++cp);
4162264Sjacobs 			break;
4172264Sjacobs 		default:
4182264Sjacobs 			buf[buf_pos++] = *cp;
4192264Sjacobs 		}
4202264Sjacobs 
4212264Sjacobs 	}
4222264Sjacobs 
4232264Sjacobs 	if (key != NULL)
4242264Sjacobs 		papiAttributeListAddString(&list, PAPI_ATTR_APPEND, key, buf);
4252264Sjacobs 
4262264Sjacobs 	/* resolve any "use" references in the configuration DB */
4272264Sjacobs 	key = NULL;
4282264Sjacobs 	papiAttributeListGetString(list, NULL, "use", &key);
4292264Sjacobs 	if (key != NULL) {
4302264Sjacobs 		papi_attribute_t **use_attrs = getprinterbyname(key, NULL);
4312264Sjacobs 
4322264Sjacobs 		list_concatenate(&list, use_attrs);
4332264Sjacobs 	}
4342264Sjacobs 
4352264Sjacobs 	fill_printer_uri_supported(&list);
4362264Sjacobs 	cvt_all_to_member_names(&list); /* convert "all" to "member-names" */
4372264Sjacobs 
4382264Sjacobs 	return (list);
4392264Sjacobs }
4402264Sjacobs 
4412264Sjacobs #if defined(NSS_SOLARIS) && !defined(NSS_EMULATION)
4422264Sjacobs 
4432264Sjacobs #ifndef	NSS_DBNAM__PRINTERS	/* not in nss_dbdefs.h because it's private */
4442264Sjacobs #define	NSS_DBNAM__PRINTERS	"_printers"
4452264Sjacobs #endif
4462264Sjacobs 
4472264Sjacobs static DEFINE_NSS_DB_ROOT(db_root);
4482264Sjacobs static DEFINE_NSS_GETENT(context);
4492264Sjacobs 
4502264Sjacobs static char *private_ns = NULL;
4512264Sjacobs 
4522264Sjacobs static void
4532264Sjacobs _nss_initf_printers(p)
4542264Sjacobs     nss_db_params_t *p;
4552264Sjacobs {
4562264Sjacobs 	if (private_ns != NULL) {
4572264Sjacobs 		/*
4582264Sjacobs 		 * because we need to support a legacy interface that allows
4592264Sjacobs 		 * us to select a specific name service, we need to dummy up
4602264Sjacobs 		 * the parameters to use a private nsswitch database and set
4612264Sjacobs 		 * the * default_config entry to the name service we are
4622264Sjacobs 		 * looking into.
4632264Sjacobs 		 */
4642264Sjacobs 		p->name = NSS_DBNAM__PRINTERS;		/* "_printers" */
4652264Sjacobs 		p->default_config = private_ns;
4662847Sjacobs 	} else {
4672264Sjacobs 		/* regular behaviour */
4682264Sjacobs 		p->name = NSS_DBNAM_PRINTERS;	 /* "printers" */
4692264Sjacobs 		p->default_config = NSS_DEFCONF_PRINTERS;
4702264Sjacobs 	}
4712847Sjacobs 	syslog(LOG_DEBUG, "database: %s, default: %s",
4722264Sjacobs 		(p->name ? p->name : "NULL"),
4732264Sjacobs 		(p->default_config ? p->default_config : "NULL"));
4742264Sjacobs }
4752264Sjacobs 
4762264Sjacobs /*
4772264Sjacobs  * Return values: 0 = success, 1 = parse error, 2 = erange ...
4782264Sjacobs  * The structure pointer passed in is a structure in the caller's space
4792264Sjacobs  * wherein the field pointers would be set to areas in the buffer if
4802264Sjacobs  * need be. instring and buffer should be separate areas.
4812264Sjacobs  */
4822264Sjacobs /* ARGSUSED */
4832264Sjacobs static int
4842264Sjacobs str2printer(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
4852264Sjacobs {
4862264Sjacobs 	if (lenstr + 1 > buflen)
4872264Sjacobs 		return (NSS_STR_PARSE_ERANGE);
4882571Sjacobs 
4892571Sjacobs 	/* skip entries that begin with '#' */
4902571Sjacobs 	if (instr[0] == '#')
4912571Sjacobs 		return (NSS_STR_PARSE_PARSE);
4922571Sjacobs 
4932264Sjacobs 	/*
4942264Sjacobs 	 * We copy the input string into the output buffer
4952264Sjacobs 	 */
4962264Sjacobs 	(void) memcpy(buffer, instr, lenstr);
4972264Sjacobs 	buffer[lenstr] = '\0';
4982264Sjacobs 
4992264Sjacobs 	return (NSS_STR_PARSE_SUCCESS);
5002264Sjacobs }
5012264Sjacobs #endif /* NSS_SOLARIS */
5022264Sjacobs 
5032264Sjacobs int
5042264Sjacobs setprinterentry(int stayopen, char *ns)
5052264Sjacobs {
5062264Sjacobs #ifdef NSS_EMULATION
5072264Sjacobs 	emul_setprinterentry(stayopen);
5082264Sjacobs #elif NSS_SOLARIS
5092264Sjacobs 	private_ns = ns;
5102264Sjacobs 	nss_setent(&db_root, _nss_initf_printers, &context);
5112847Sjacobs 	private_ns = NULL;
5122264Sjacobs #endif
5132264Sjacobs 	return (0);
5142264Sjacobs }
5152264Sjacobs 
5162264Sjacobs 
5172264Sjacobs int
5182264Sjacobs endprinterentry(int i)
5192264Sjacobs {
5202264Sjacobs #ifdef NSS_EMULATION
5212264Sjacobs 	emul_endprinterentry();
5222264Sjacobs #elif NSS_SOLARIS
5232264Sjacobs 	nss_endent(&db_root, _nss_initf_printers, &context);
5242264Sjacobs 	nss_delete(&db_root);
5252847Sjacobs 	private_ns = NULL;
5262264Sjacobs #endif
5272264Sjacobs 	return (0);
5282264Sjacobs }
5292264Sjacobs 
5302264Sjacobs /* ARGSUSED2 */
5312264Sjacobs papi_attribute_t **
5322264Sjacobs getprinterentry(char *ns)
5332264Sjacobs {
5342264Sjacobs 	papi_attribute_t **result = NULL;
5352264Sjacobs 
5362264Sjacobs #if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
5372264Sjacobs 	char buf[10240];
5382264Sjacobs 	nss_status_t	res = NSS_NOTFOUND;
5392264Sjacobs 
5402264Sjacobs #ifdef NSS_EMULATION
5412264Sjacobs 	res = emul_getprinterentry_r(buf, sizeof (buf));
5422264Sjacobs #elif NSS_SOLARIS
5432264Sjacobs 	nss_XbyY_args_t arg;
5442264Sjacobs 
5452847Sjacobs 	private_ns = ns;
5462264Sjacobs 	NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
5472264Sjacobs 	res = nss_getent(&db_root, _nss_initf_printers, &context, &arg);
5482264Sjacobs 	(void) NSS_XbyY_FINI(&arg);
5492847Sjacobs 	private_ns = NULL;
5502264Sjacobs #endif
5512264Sjacobs 
5522264Sjacobs 	if (res != NSS_SUCCESS)
5532264Sjacobs 		buf[0] = '\0';
5542264Sjacobs 
5552264Sjacobs 	result = _cvt_nss_entry_to_printer(buf);
5562313Sjacobs #if defined(__sun) && defined(__SVR4)
5572313Sjacobs 	solaris_lpsched_shortcircuit_hack(&result);
5582313Sjacobs #endif
5592264Sjacobs #ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
5602264Sjacobs 	fill_printer_uri(&result);
5612264Sjacobs #endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
5622264Sjacobs #endif
5632264Sjacobs 
5642264Sjacobs #ifdef DEBUG
5652264Sjacobs 	printf("getprinterentry(%s): 0x%8.8x\n", (ns ? ns : "NULL"), result);
5662264Sjacobs 	if (result != NULL) {
5672264Sjacobs 		char buf[4096];
5682264Sjacobs 
5692264Sjacobs 		papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
5702264Sjacobs 		printf("\t%s\n", buf);
5712264Sjacobs 	}
5722264Sjacobs #endif /* DEBUG */
5732264Sjacobs 
5742264Sjacobs 	return (result);
5752264Sjacobs }
5762264Sjacobs 
5772264Sjacobs 
5782264Sjacobs papi_attribute_t **
5792264Sjacobs getprinterbyname(char *name, char *ns)
5802264Sjacobs {
5812264Sjacobs 	papi_attribute_t **result = NULL;
5822264Sjacobs 
5832264Sjacobs 	if (strstr(name, "://") != NULL) {	/* shortcut for URI form */
5842264Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
5852264Sjacobs 				"printer-name", name);
5862264Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
5872264Sjacobs 				"printer-uri-supported", name);
5882264Sjacobs 	} else if (strchr(name, ':') != NULL) {	/* shortcut for POSIX form */
5892409Sjacobs 		char *uri = bsdaddr_to_uri(result, name);
5902264Sjacobs 
5912264Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
5922264Sjacobs 				"printer-name", name);
5932264Sjacobs 		if (uri != NULL) {
5942264Sjacobs 			papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
5952264Sjacobs 					"printer-uri-supported", uri);
5962264Sjacobs 			free(uri);
5972264Sjacobs 		}
5982264Sjacobs 	} else {				/* anything else */
5992264Sjacobs #if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
6002264Sjacobs 		char buf[10240];
6012264Sjacobs 		nss_status_t	res = NSS_NOTFOUND;
6022264Sjacobs 
6032264Sjacobs #ifdef NSS_EMULATION
6042264Sjacobs 		res = emul_getprinterbyname_r(name, buf, sizeof (buf));
6052264Sjacobs #elif NSS_SOLARIS
6062264Sjacobs 		nss_XbyY_args_t arg;
6072264Sjacobs 
6082264Sjacobs 		private_ns = ns;
6092264Sjacobs 		NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
6102264Sjacobs 		arg.key.name = name;
6112264Sjacobs 		res = nss_search(&db_root, _nss_initf_printers,
6122264Sjacobs 				NSS_DBOP_PRINTERS_BYNAME, &arg);
6132264Sjacobs 		(void) NSS_XbyY_FINI(&arg);
6142847Sjacobs 		private_ns = NULL;
6152264Sjacobs 
6162264Sjacobs 		if (res != NSS_SUCCESS)
6172264Sjacobs 			buf[0] = '\0';
6182264Sjacobs #endif
6192264Sjacobs 
6202264Sjacobs 		result = _cvt_nss_entry_to_printer(buf);
6212264Sjacobs #endif
6222264Sjacobs 	}
6232313Sjacobs #if defined(__sun) && defined(__SVR4)
6242313Sjacobs 	solaris_lpsched_shortcircuit_hack(&result);
6252313Sjacobs #endif
6262264Sjacobs #ifdef DEBUG
6272264Sjacobs 	printf("getprinterbyname(%s): %s = 0x%8.8x\n", (ns ? ns : "NULL"),
6282264Sjacobs 		name, result);
6292264Sjacobs 	if (result != NULL) {
6302264Sjacobs 		char buf[4096];
6312264Sjacobs 
6322264Sjacobs 		papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
6332264Sjacobs 		printf("\t%s\n", buf);
6342264Sjacobs 	}
6352264Sjacobs #endif /* DEBUG */
6362264Sjacobs 
6372264Sjacobs 	return (result);
6382264Sjacobs }
639