1*2264Sjacobs /*
2*2264Sjacobs  * CDDL HEADER START
3*2264Sjacobs  *
4*2264Sjacobs  * The contents of this file are subject to the terms of the
5*2264Sjacobs  * Common Development and Distribution License (the "License").
6*2264Sjacobs  * You may not use this file except in compliance with the License.
7*2264Sjacobs  *
8*2264Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2264Sjacobs  * or http://www.opensolaris.org/os/licensing.
10*2264Sjacobs  * See the License for the specific language governing permissions
11*2264Sjacobs  * and limitations under the License.
12*2264Sjacobs  *
13*2264Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
14*2264Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2264Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
16*2264Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
17*2264Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2264Sjacobs  *
19*2264Sjacobs  * CDDL HEADER END
20*2264Sjacobs  */
21*2264Sjacobs 
22*2264Sjacobs /*
23*2264Sjacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*2264Sjacobs  * Use is subject to license terms.
25*2264Sjacobs  *
26*2264Sjacobs  */
27*2264Sjacobs 
28*2264Sjacobs /* $Id: nss.c 166 2006-05-20 05:48:55Z njacobs $ */
29*2264Sjacobs 
30*2264Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*2264Sjacobs 
32*2264Sjacobs #include <stdio.h>
33*2264Sjacobs #include <stdlib.h>
34*2264Sjacobs #include <unistd.h>
35*2264Sjacobs #include <string.h>
36*2264Sjacobs #include <ctype.h>
37*2264Sjacobs #include <sys/types.h>
38*2264Sjacobs #include <syslog.h>
39*2264Sjacobs #include <papi.h>
40*2264Sjacobs #include <uri.h>
41*2264Sjacobs #include <papi_impl.h>
42*2264Sjacobs #ifdef NSS_EMULATION
43*2264Sjacobs #include <nss-emulation.h>
44*2264Sjacobs #elif NSS_SOLARIS
45*2264Sjacobs #include <nss_dbdefs.h>
46*2264Sjacobs #endif
47*2264Sjacobs #include <config-site.h>
48*2264Sjacobs #if defined(__sun) && defined(__SVR4)
49*2264Sjacobs #include <sys/systeminfo.h>
50*2264Sjacobs #endif
51*2264Sjacobs 
52*2264Sjacobs 
53*2264Sjacobs static char *
54*2264Sjacobs bsdaddr_to_uri(char *bsdaddr)
55*2264Sjacobs {
56*2264Sjacobs 	char *result = NULL;
57*2264Sjacobs 
58*2264Sjacobs 	if (bsdaddr != NULL) {
59*2264Sjacobs 		char *bsd[3], *tmp, *iter = NULL;
60*2264Sjacobs 		char buf[512];
61*2264Sjacobs 
62*2264Sjacobs 		tmp = strdup(bsdaddr);
63*2264Sjacobs 
64*2264Sjacobs 		bsd[0] = strtok_r(tmp, ":,", &iter);
65*2264Sjacobs 		bsd[1] = strtok_r(NULL, ":,", &iter);
66*2264Sjacobs 		bsd[2] = strtok_r(NULL, ":,", &iter);
67*2264Sjacobs 
68*2264Sjacobs 		snprintf(buf, sizeof (buf), "lpd://%s/%s%s%s", bsd[0], bsd[1],
69*2264Sjacobs 			(bsd[2] != NULL) ? "#" : "",
70*2264Sjacobs 			(bsd[2] != NULL) ? bsd[2] : "");
71*2264Sjacobs 
72*2264Sjacobs 		free(tmp);
73*2264Sjacobs 
74*2264Sjacobs 		result = strdup(buf);
75*2264Sjacobs 	}
76*2264Sjacobs 
77*2264Sjacobs 	return (result);
78*2264Sjacobs }
79*2264Sjacobs 
80*2264Sjacobs #if defined(__sun) && defined(__SVR4)
81*2264Sjacobs /*
82*2264Sjacobs  * This is an awful HACK to force the dynamic PAPI library to use the
83*2264Sjacobs  * lpsched support when the destination apears to be a local lpsched
84*2264Sjacobs  * queue on Solaris.
85*2264Sjacobs  */
86*2264Sjacobs static void
87*2264Sjacobs solaris_lpsched_shortcircuit_hack(papi_attribute_t ***list)
88*2264Sjacobs {
89*2264Sjacobs 	papi_attribute_t *attribute;
90*2264Sjacobs 	uri_t *uri = NULL;
91*2264Sjacobs 	char *printer = NULL;
92*2264Sjacobs 	char hostname[BUFSIZ];
93*2264Sjacobs 	char buf[128], buf2[128];
94*2264Sjacobs 
95*2264Sjacobs 	/* setting this in the calling env can be useful for debugging */
96*2264Sjacobs 	if (getenv("DISABLE_LPSCHED_SHORTCIRCUIT") != NULL)
97*2264Sjacobs 		return;
98*2264Sjacobs 
99*2264Sjacobs 	papiAttributeListGetString(*list, NULL,
100*2264Sjacobs 				"printer-uri-supported", &printer);
101*2264Sjacobs 	if (uri_from_string(printer, &uri) < 0)
102*2264Sjacobs 		return;
103*2264Sjacobs 
104*2264Sjacobs 	/* already an lpsched URI ? */
105*2264Sjacobs 	if (strcasecmp(uri->scheme, "lpsched") == 0)
106*2264Sjacobs 		return;
107*2264Sjacobs 
108*2264Sjacobs 	sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
109*2264Sjacobs 	if ((uri->host != NULL) &&
110*2264Sjacobs 	    (strncasecmp(uri->host, hostname, strlen(hostname)) != 0) &&
111*2264Sjacobs 	    (strncasecmp(uri->host, "localhost", 10) != 0))
112*2264Sjacobs 		return;
113*2264Sjacobs 
114*2264Sjacobs 	if ((printer = strrchr(uri->path, '/')) == NULL)
115*2264Sjacobs 		printer = uri->path;
116*2264Sjacobs 	else
117*2264Sjacobs 		printer++;
118*2264Sjacobs 
119*2264Sjacobs 	/* is there an lpsched queue (printer/class) */
120*2264Sjacobs 	snprintf(buf, sizeof (buf), "/etc/lp/interfaces/%s", printer);
121*2264Sjacobs 	snprintf(buf2, sizeof (buf2), "/etc/lp/classes/%s", printer);
122*2264Sjacobs 	if ((access(buf, F_OK) < 0) && (access(buf2, F_OK) < 0))
123*2264Sjacobs 		return;
124*2264Sjacobs 
125*2264Sjacobs 	snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s", printer);
126*2264Sjacobs 	papiAttributeListAddString(list, PAPI_ATTR_REPLACE,
127*2264Sjacobs 			"printer-uri-supported", buf);
128*2264Sjacobs }
129*2264Sjacobs #endif
130*2264Sjacobs 
131*2264Sjacobs static void
132*2264Sjacobs fill_printer_uri_supported(papi_attribute_t ***list)
133*2264Sjacobs {
134*2264Sjacobs 	papi_attribute_t *attribute;
135*2264Sjacobs 	char *string = NULL;
136*2264Sjacobs 
137*2264Sjacobs 	/* do we have a printer-uri-supported */
138*2264Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri-supported");
139*2264Sjacobs 	if (attribute != NULL) /* we have what we need, return */
140*2264Sjacobs 		return;
141*2264Sjacobs 
142*2264Sjacobs 	/* do we have a printer-uri to rename */
143*2264Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri");
144*2264Sjacobs 	if (attribute != NULL) { /* rename it in place and return */
145*2264Sjacobs 		free(attribute->name);
146*2264Sjacobs 		attribute->name = strdup("printer-uri-supported");
147*2264Sjacobs 		return;
148*2264Sjacobs 	}
149*2264Sjacobs 
150*2264Sjacobs 	/* do we have a printers.conf(4) "bsdaddr" to convert */
151*2264Sjacobs 	papiAttributeListGetString(*list, NULL, "bsdaddr", &string);
152*2264Sjacobs 	if (string != NULL) { /* parse it, convert it, add it */
153*2264Sjacobs 		char *uri = bsdaddr_to_uri(string);
154*2264Sjacobs 
155*2264Sjacobs 		if (uri != NULL) {
156*2264Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
157*2264Sjacobs 					"printer-uri-supported", uri);
158*2264Sjacobs 			papiAttributeListDelete(list, "bsdaddr");
159*2264Sjacobs 			free(uri);
160*2264Sjacobs 			return;
161*2264Sjacobs 		}
162*2264Sjacobs 	}
163*2264Sjacobs 
164*2264Sjacobs 	/* do we have a printers.conf(4) "rm" (and "rp") to convert */
165*2264Sjacobs 	papiAttributeListGetString(*list, NULL, "rm", &string);
166*2264Sjacobs 	if (string != NULL) {
167*2264Sjacobs 		char *rp = NULL;
168*2264Sjacobs 
169*2264Sjacobs 		/* default to "printer-name", but use "rp" if we have it */
170*2264Sjacobs 		papiAttributeListGetString(*list, NULL, "printer-name", &rp);
171*2264Sjacobs 		papiAttributeListGetString(*list, NULL, "rp", &rp);
172*2264Sjacobs 
173*2264Sjacobs 		if (rp != NULL) { /* fill in the uri if we have the data */
174*2264Sjacobs 			char buf[BUFSIZ];
175*2264Sjacobs 
176*2264Sjacobs 			snprintf(buf, sizeof (buf), "lpd://%s/printers/%s",
177*2264Sjacobs 				string, rp);
178*2264Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
179*2264Sjacobs 					"printer-uri-supported", strdup(buf));
180*2264Sjacobs 			return;
181*2264Sjacobs 		}
182*2264Sjacobs 	}
183*2264Sjacobs 
184*2264Sjacobs 	/* if were are here, we don't have a printer-uri-supported */
185*2264Sjacobs }
186*2264Sjacobs 
187*2264Sjacobs #ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
188*2264Sjacobs static void
189*2264Sjacobs fill_printer_uri(papi_attribute_t ***list)
190*2264Sjacobs {
191*2264Sjacobs 	papi_attribute_t *attribute;
192*2264Sjacobs 	char *uri = NULL;
193*2264Sjacobs 
194*2264Sjacobs 	if ((list == NULL) || (*list == NULL))
195*2264Sjacobs 		return;
196*2264Sjacobs 
197*2264Sjacobs 	/* do we have a printer-uri-supported */
198*2264Sjacobs 	attribute = papiAttributeListFind(*list, "printer-uri");
199*2264Sjacobs 	if (attribute != NULL) /* we have what we need, return */
200*2264Sjacobs 		return;
201*2264Sjacobs 
202*2264Sjacobs 	/*
203*2264Sjacobs 	 * this is sufficient to fool libgnomeprintpapi, but not promote it's
204*2264Sjacobs 	 * use in the future.
205*2264Sjacobs 	 */
206*2264Sjacobs 	papiAttributeListAddString(list, PAPI_ATTR_EXCL, "printer-uri",
207*2264Sjacobs 			"broken printer-uri semantic");
208*2264Sjacobs }
209*2264Sjacobs #endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
210*2264Sjacobs 
211*2264Sjacobs static void
212*2264Sjacobs cvt_all_to_member_names(papi_attribute_t ***list)
213*2264Sjacobs {
214*2264Sjacobs 	papi_status_t status;
215*2264Sjacobs 	void *iter = NULL;
216*2264Sjacobs 	char *string = NULL;
217*2264Sjacobs 
218*2264Sjacobs 	papiAttributeListGetString(*list, NULL, "member-names", &string);
219*2264Sjacobs 	if (string != NULL) /* already have a member-names */
220*2264Sjacobs 		return;
221*2264Sjacobs 
222*2264Sjacobs 	for (status = papiAttributeListGetString(*list, &iter, "all", &string);
223*2264Sjacobs 	     status == PAPI_OK;
224*2264Sjacobs 	     status = papiAttributeListGetString(*list, &iter, NULL, &string)) {
225*2264Sjacobs 		char *s_iter = NULL, *value, *tmp = strdup(string);
226*2264Sjacobs 
227*2264Sjacobs 		for (value = strtok_r(tmp, ", \t", &s_iter);
228*2264Sjacobs 		     value != NULL;
229*2264Sjacobs 		     value = strtok_r(NULL, ", \t", &s_iter))
230*2264Sjacobs 			papiAttributeListAddString(list, PAPI_ATTR_APPEND,
231*2264Sjacobs 					"member-names", value);
232*2264Sjacobs 		free(tmp);
233*2264Sjacobs 	}
234*2264Sjacobs }
235*2264Sjacobs 
236*2264Sjacobs static papi_attribute_t **
237*2264Sjacobs _cvt_nss_entry_to_printer(char *entry)
238*2264Sjacobs {
239*2264Sjacobs 	char    *key = NULL,
240*2264Sjacobs 		*cp,
241*2264Sjacobs 		buf[BUFSIZ];
242*2264Sjacobs 	int in_namelist = 1, buf_pos = 0;
243*2264Sjacobs 	papi_attribute_t **list = NULL;
244*2264Sjacobs 
245*2264Sjacobs 	if (entry == NULL)
246*2264Sjacobs 		return (NULL);
247*2264Sjacobs 
248*2264Sjacobs 	memset(buf, 0, sizeof (buf));
249*2264Sjacobs 	for (cp = entry; *cp != '\0'; cp++) {
250*2264Sjacobs 		switch (*cp) {
251*2264Sjacobs 		case ':':	/* end of kvp */
252*2264Sjacobs 			if (in_namelist != 0) {
253*2264Sjacobs 				papiAttributeListAddString(&list,
254*2264Sjacobs 					PAPI_ATTR_APPEND, "printer-name", buf);
255*2264Sjacobs 				in_namelist = 0;
256*2264Sjacobs 			} else if (key != NULL)
257*2264Sjacobs 				papiAttributeListAddString(&list,
258*2264Sjacobs 					PAPI_ATTR_APPEND, key, buf);
259*2264Sjacobs 			memset(buf, 0, sizeof (buf));
260*2264Sjacobs 			buf_pos = 0;
261*2264Sjacobs 			key = NULL;
262*2264Sjacobs 			break;
263*2264Sjacobs 		case '=':	/* kvp seperator */
264*2264Sjacobs 			if (key == NULL) {
265*2264Sjacobs 				key = strdup(buf);
266*2264Sjacobs 				memset(buf, 0, sizeof (buf));
267*2264Sjacobs 				buf_pos = 0;
268*2264Sjacobs 			} else
269*2264Sjacobs 				buf[buf_pos++] = *cp;
270*2264Sjacobs 			break;
271*2264Sjacobs 		case '|':	/* namelist seperator */
272*2264Sjacobs 			if (in_namelist != 0) {
273*2264Sjacobs 				papiAttributeListAddString(&list,
274*2264Sjacobs 					PAPI_ATTR_APPEND, "printer-name", buf);
275*2264Sjacobs 				memset(buf, 0, sizeof (buf));
276*2264Sjacobs 				buf_pos = 0;
277*2264Sjacobs 			} else	/* add it to the buffer */
278*2264Sjacobs 				buf[buf_pos++] = *cp;
279*2264Sjacobs 			break;
280*2264Sjacobs 		case '\\':	/* escape char */
281*2264Sjacobs 			buf[buf_pos++] = *(++cp);
282*2264Sjacobs 			break;
283*2264Sjacobs 		default:
284*2264Sjacobs 			buf[buf_pos++] = *cp;
285*2264Sjacobs 		}
286*2264Sjacobs 
287*2264Sjacobs 	}
288*2264Sjacobs 
289*2264Sjacobs 	if (key != NULL)
290*2264Sjacobs 		papiAttributeListAddString(&list, PAPI_ATTR_APPEND, key, buf);
291*2264Sjacobs 
292*2264Sjacobs 	/* resolve any "use" references in the configuration DB */
293*2264Sjacobs 	key = NULL;
294*2264Sjacobs 	papiAttributeListGetString(list, NULL, "use", &key);
295*2264Sjacobs 	if (key != NULL) {
296*2264Sjacobs 		papi_attribute_t **use_attrs = getprinterbyname(key, NULL);
297*2264Sjacobs 
298*2264Sjacobs 		list_concatenate(&list, use_attrs);
299*2264Sjacobs 	}
300*2264Sjacobs 
301*2264Sjacobs 	fill_printer_uri_supported(&list);
302*2264Sjacobs #if defined(__sun) && defined(__SVR4)
303*2264Sjacobs 	solaris_lpsched_shortcircuit_hack(&list);
304*2264Sjacobs #endif
305*2264Sjacobs 	cvt_all_to_member_names(&list); /* convert "all" to "member-names" */
306*2264Sjacobs 
307*2264Sjacobs 	return (list);
308*2264Sjacobs }
309*2264Sjacobs 
310*2264Sjacobs #if defined(NSS_SOLARIS) && !defined(NSS_EMULATION)
311*2264Sjacobs 
312*2264Sjacobs #ifndef	NSS_DBNAM__PRINTERS	/* not in nss_dbdefs.h because it's private */
313*2264Sjacobs #define	NSS_DBNAM__PRINTERS	"_printers"
314*2264Sjacobs #endif
315*2264Sjacobs 
316*2264Sjacobs static DEFINE_NSS_DB_ROOT(db_root);
317*2264Sjacobs static DEFINE_NSS_GETENT(context);
318*2264Sjacobs 
319*2264Sjacobs static char *private_ns = NULL;
320*2264Sjacobs static char initialized = 0;
321*2264Sjacobs 
322*2264Sjacobs static void
323*2264Sjacobs _nss_initf_printers(p)
324*2264Sjacobs     nss_db_params_t *p;
325*2264Sjacobs {
326*2264Sjacobs 	if (private_ns != NULL) {
327*2264Sjacobs 		/*
328*2264Sjacobs 		 * because we need to support a legacy interface that allows
329*2264Sjacobs 		 * us to select a specific name service, we need to dummy up
330*2264Sjacobs 		 * the parameters to use a private nsswitch database and set
331*2264Sjacobs 		 * the * default_config entry to the name service we are
332*2264Sjacobs 		 * looking into.
333*2264Sjacobs 		 */
334*2264Sjacobs 		p->name = NSS_DBNAM__PRINTERS;		/* "_printers" */
335*2264Sjacobs 		p->default_config = private_ns;
336*2264Sjacobs 		private_ns = NULL;
337*2264Sjacobs 	} else if (initialized == 0) {
338*2264Sjacobs 		/* regular behaviour */
339*2264Sjacobs 		p->name = NSS_DBNAM_PRINTERS;	 /* "printers" */
340*2264Sjacobs 		p->default_config = NSS_DEFCONF_PRINTERS;
341*2264Sjacobs 		initialized = 1;
342*2264Sjacobs 	}
343*2264Sjacobs 	syslog(LOG_DEBUG, "database: %s, services: %s",
344*2264Sjacobs 		(p->name ? p->name : "NULL"),
345*2264Sjacobs 		(p->default_config ? p->default_config : "NULL"));
346*2264Sjacobs }
347*2264Sjacobs 
348*2264Sjacobs /*
349*2264Sjacobs  * Return values: 0 = success, 1 = parse error, 2 = erange ...
350*2264Sjacobs  * The structure pointer passed in is a structure in the caller's space
351*2264Sjacobs  * wherein the field pointers would be set to areas in the buffer if
352*2264Sjacobs  * need be. instring and buffer should be separate areas.
353*2264Sjacobs  */
354*2264Sjacobs /* ARGSUSED */
355*2264Sjacobs static int
356*2264Sjacobs str2printer(const char *instr, int lenstr, void *ent, char *buffer, int buflen)
357*2264Sjacobs {
358*2264Sjacobs 	if (lenstr + 1 > buflen)
359*2264Sjacobs 		return (NSS_STR_PARSE_ERANGE);
360*2264Sjacobs 	/*
361*2264Sjacobs 	 * We copy the input string into the output buffer
362*2264Sjacobs 	 */
363*2264Sjacobs 	(void) memcpy(buffer, instr, lenstr);
364*2264Sjacobs 	buffer[lenstr] = '\0';
365*2264Sjacobs 
366*2264Sjacobs 	return (NSS_STR_PARSE_SUCCESS);
367*2264Sjacobs }
368*2264Sjacobs #endif /* NSS_SOLARIS */
369*2264Sjacobs 
370*2264Sjacobs int
371*2264Sjacobs setprinterentry(int stayopen, char *ns)
372*2264Sjacobs {
373*2264Sjacobs #ifdef NSS_EMULATION
374*2264Sjacobs 	emul_setprinterentry(stayopen);
375*2264Sjacobs #elif NSS_SOLARIS
376*2264Sjacobs 	initialized = 0;
377*2264Sjacobs 	private_ns = ns;
378*2264Sjacobs 	nss_setent(&db_root, _nss_initf_printers, &context);
379*2264Sjacobs #endif
380*2264Sjacobs 	return (0);
381*2264Sjacobs }
382*2264Sjacobs 
383*2264Sjacobs 
384*2264Sjacobs int
385*2264Sjacobs endprinterentry(int i)
386*2264Sjacobs {
387*2264Sjacobs #ifdef NSS_EMULATION
388*2264Sjacobs 	emul_endprinterentry();
389*2264Sjacobs #elif NSS_SOLARIS
390*2264Sjacobs 	initialized = 0;
391*2264Sjacobs 	nss_endent(&db_root, _nss_initf_printers, &context);
392*2264Sjacobs 	nss_delete(&db_root);
393*2264Sjacobs #endif
394*2264Sjacobs 	return (0);
395*2264Sjacobs }
396*2264Sjacobs 
397*2264Sjacobs /* ARGSUSED2 */
398*2264Sjacobs papi_attribute_t **
399*2264Sjacobs getprinterentry(char *ns)
400*2264Sjacobs {
401*2264Sjacobs 	papi_attribute_t **result = NULL;
402*2264Sjacobs 
403*2264Sjacobs #if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
404*2264Sjacobs 	char buf[10240];
405*2264Sjacobs 	nss_status_t	res = NSS_NOTFOUND;
406*2264Sjacobs 
407*2264Sjacobs #ifdef NSS_EMULATION
408*2264Sjacobs 	res = emul_getprinterentry_r(buf, sizeof (buf));
409*2264Sjacobs #elif NSS_SOLARIS
410*2264Sjacobs 	nss_XbyY_args_t arg;
411*2264Sjacobs 
412*2264Sjacobs 	NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
413*2264Sjacobs 	res = nss_getent(&db_root, _nss_initf_printers, &context, &arg);
414*2264Sjacobs 	(void) NSS_XbyY_FINI(&arg);
415*2264Sjacobs #endif
416*2264Sjacobs 
417*2264Sjacobs 	if (res != NSS_SUCCESS)
418*2264Sjacobs 		buf[0] = '\0';
419*2264Sjacobs 
420*2264Sjacobs 	result = _cvt_nss_entry_to_printer(buf);
421*2264Sjacobs #ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC
422*2264Sjacobs 	fill_printer_uri(&result);
423*2264Sjacobs #endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */
424*2264Sjacobs #endif
425*2264Sjacobs 
426*2264Sjacobs #ifdef DEBUG
427*2264Sjacobs 	printf("getprinterentry(%s): 0x%8.8x\n", (ns ? ns : "NULL"), result);
428*2264Sjacobs 	if (result != NULL) {
429*2264Sjacobs 		char buf[4096];
430*2264Sjacobs 
431*2264Sjacobs 		papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
432*2264Sjacobs 		printf("\t%s\n", buf);
433*2264Sjacobs 	}
434*2264Sjacobs #endif /* DEBUG */
435*2264Sjacobs 
436*2264Sjacobs 	return (result);
437*2264Sjacobs }
438*2264Sjacobs 
439*2264Sjacobs 
440*2264Sjacobs papi_attribute_t **
441*2264Sjacobs getprinterbyname(char *name, char *ns)
442*2264Sjacobs {
443*2264Sjacobs 	papi_attribute_t **result = NULL;
444*2264Sjacobs 
445*2264Sjacobs 	if (strstr(name, "://") != NULL) {	/* shortcut for URI form */
446*2264Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
447*2264Sjacobs 				"printer-name", name);
448*2264Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
449*2264Sjacobs 				"printer-uri-supported", name);
450*2264Sjacobs 	} else if (strchr(name, ':') != NULL) {	/* shortcut for POSIX form */
451*2264Sjacobs 		char *uri = bsdaddr_to_uri(name);
452*2264Sjacobs 
453*2264Sjacobs 		papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
454*2264Sjacobs 				"printer-name", name);
455*2264Sjacobs 		if (uri != NULL) {
456*2264Sjacobs 			papiAttributeListAddString(&result, PAPI_ATTR_APPEND,
457*2264Sjacobs 					"printer-uri-supported", uri);
458*2264Sjacobs 			free(uri);
459*2264Sjacobs 		}
460*2264Sjacobs 	} else {				/* anything else */
461*2264Sjacobs #if defined(NSS_EMULATION) || defined(NSS_SOLARIS)
462*2264Sjacobs 		char buf[10240];
463*2264Sjacobs 		nss_status_t	res = NSS_NOTFOUND;
464*2264Sjacobs 
465*2264Sjacobs #ifdef NSS_EMULATION
466*2264Sjacobs 		res = emul_getprinterbyname_r(name, buf, sizeof (buf));
467*2264Sjacobs #elif NSS_SOLARIS
468*2264Sjacobs 		nss_XbyY_args_t arg;
469*2264Sjacobs 
470*2264Sjacobs 		private_ns = ns;
471*2264Sjacobs 		NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer);
472*2264Sjacobs 		arg.key.name = name;
473*2264Sjacobs 		res = nss_search(&db_root, _nss_initf_printers,
474*2264Sjacobs 				NSS_DBOP_PRINTERS_BYNAME, &arg);
475*2264Sjacobs 		(void) NSS_XbyY_FINI(&arg);
476*2264Sjacobs 
477*2264Sjacobs 		if (res != NSS_SUCCESS)
478*2264Sjacobs 			buf[0] = '\0';
479*2264Sjacobs #endif
480*2264Sjacobs 
481*2264Sjacobs 		result = _cvt_nss_entry_to_printer(buf);
482*2264Sjacobs #endif
483*2264Sjacobs 	}
484*2264Sjacobs 
485*2264Sjacobs #ifdef DEBUG
486*2264Sjacobs 	printf("getprinterbyname(%s): %s = 0x%8.8x\n", (ns ? ns : "NULL"),
487*2264Sjacobs 		name, result);
488*2264Sjacobs 	if (result != NULL) {
489*2264Sjacobs 		char buf[4096];
490*2264Sjacobs 
491*2264Sjacobs 		papiAttributeListToString(result, "\n\t", buf, sizeof (buf));
492*2264Sjacobs 		printf("\t%s\n", buf);
493*2264Sjacobs 	}
494*2264Sjacobs #endif /* DEBUG */
495*2264Sjacobs 
496*2264Sjacobs 	return (result);
497*2264Sjacobs }
498