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: service.c 172 2006-05-24 20:54:00Z njacobs $ */
29*2264Sjacobs 
30*2264Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*2264Sjacobs 
32*2264Sjacobs /*LINTLIBRARY*/
33*2264Sjacobs 
34*2264Sjacobs #include <stdlib.h>
35*2264Sjacobs #include <stdio.h>
36*2264Sjacobs #include <stdarg.h>
37*2264Sjacobs #include <string.h>
38*2264Sjacobs #include <alloca.h>
39*2264Sjacobs #include <libintl.h>
40*2264Sjacobs #include <papi_impl.h>
41*2264Sjacobs #include <config-site.h>
42*2264Sjacobs 
43*2264Sjacobs static int
44*2264Sjacobs interposed_auth_callback(papi_service_t handle, void *app_data)
45*2264Sjacobs {
46*2264Sjacobs 	int result = -1;
47*2264Sjacobs 	service_t *svc = app_data;
48*2264Sjacobs 
49*2264Sjacobs 	if (svc != NULL)
50*2264Sjacobs 		result = svc->authCB(svc, svc->app_data);
51*2264Sjacobs 
52*2264Sjacobs 	return (result);
53*2264Sjacobs }
54*2264Sjacobs 
55*2264Sjacobs static char *
56*2264Sjacobs default_service_uri(char *fallback)
57*2264Sjacobs {
58*2264Sjacobs 	char *result = NULL;
59*2264Sjacobs 
60*2264Sjacobs 	if ((result = getenv("PAPI_SERVICE_URI")) == NULL) {
61*2264Sjacobs 		char *cups;
62*2264Sjacobs 
63*2264Sjacobs 		if ((cups = getenv("CUPS_SERVER")) != NULL) {
64*2264Sjacobs 			char buf[BUFSIZ];
65*2264Sjacobs 
66*2264Sjacobs 			snprintf(buf, sizeof (buf), "ipp://%s/printers/", cups);
67*2264Sjacobs 			result = strdup(buf);
68*2264Sjacobs 		}
69*2264Sjacobs 	}
70*2264Sjacobs 
71*2264Sjacobs 	if (result == NULL)
72*2264Sjacobs 		result = fallback;
73*2264Sjacobs 
74*2264Sjacobs 	return (result);
75*2264Sjacobs }
76*2264Sjacobs 
77*2264Sjacobs static char *
78*2264Sjacobs default_print_service()
79*2264Sjacobs {
80*2264Sjacobs 	static char *result = NULL;
81*2264Sjacobs 
82*2264Sjacobs 	if (result == NULL) {
83*2264Sjacobs 		char *service_uri = default_service_uri(DEFAULT_SERVICE_URI);
84*2264Sjacobs 		uri_t *uri = NULL;
85*2264Sjacobs 
86*2264Sjacobs 		if (uri_from_string(service_uri, &uri) != -1)
87*2264Sjacobs 			result = strdup(uri->scheme);
88*2264Sjacobs 
89*2264Sjacobs 		if (uri != NULL)
90*2264Sjacobs 			uri_free(uri);
91*2264Sjacobs 	}
92*2264Sjacobs 
93*2264Sjacobs 	return (result);
94*2264Sjacobs }
95*2264Sjacobs 
96*2264Sjacobs static papi_status_t
97*2264Sjacobs service_load(service_t *svc, char *name)
98*2264Sjacobs {
99*2264Sjacobs 	papi_status_t result;
100*2264Sjacobs 	char *scheme = default_print_service();
101*2264Sjacobs 
102*2264Sjacobs 	if (svc->so_handle != NULL)	/* already loaded */
103*2264Sjacobs 		return (PAPI_OK);
104*2264Sjacobs 
105*2264Sjacobs 	if (name == NULL)		/* no info, can't load yet */
106*2264Sjacobs 		return (PAPI_OK);
107*2264Sjacobs 
108*2264Sjacobs 	/* Lookup the printer in the configuration DB */
109*2264Sjacobs 	svc->attributes = getprinterbyname((char *)name, NULL);
110*2264Sjacobs 
111*2264Sjacobs 	if (svc->attributes != NULL) {
112*2264Sjacobs 		char *tmp = NULL;
113*2264Sjacobs 
114*2264Sjacobs 		/* Printer found (or was a URI), use the attribute data */
115*2264Sjacobs 		papiAttributeListGetString(svc->attributes, NULL,
116*2264Sjacobs 					"printer-uri-supported", &tmp);
117*2264Sjacobs 		if (tmp != NULL)
118*2264Sjacobs 			svc->name = strdup(tmp);
119*2264Sjacobs 
120*2264Sjacobs 		/* parse the URI and set the scheme(print service) */
121*2264Sjacobs 		if (uri_from_string(svc->name, &svc->uri) != -1)
122*2264Sjacobs 			scheme = (svc->uri)->scheme;
123*2264Sjacobs 
124*2264Sjacobs 		/* override the scheme if it was in the attributes */
125*2264Sjacobs 		papiAttributeListGetString(svc->attributes, NULL,
126*2264Sjacobs 					"print-service-module", &scheme);
127*2264Sjacobs 
128*2264Sjacobs 	} else	/* not found, assume it is the actual print service name */
129*2264Sjacobs 		scheme = name;
130*2264Sjacobs 
131*2264Sjacobs 	result = psm_open(svc, scheme);
132*2264Sjacobs 	switch (result) {
133*2264Sjacobs 	case PAPI_OK:
134*2264Sjacobs 		break;	/* no error */
135*2264Sjacobs 	case PAPI_URI_SCHEME:
136*2264Sjacobs 		result = PAPI_NOT_FOUND;
137*2264Sjacobs #ifdef DEBUG
138*2264Sjacobs 		detailed_error(svc, "Unable to load service for: %s", name);
139*2264Sjacobs #endif
140*2264Sjacobs 		break;
141*2264Sjacobs 	default:	/* set the detailed message */
142*2264Sjacobs 		detailed_error(svc, "Unable to load service (%s) for: %s",
143*2264Sjacobs 				scheme, name);
144*2264Sjacobs 	}
145*2264Sjacobs 
146*2264Sjacobs 	return (result);
147*2264Sjacobs }
148*2264Sjacobs 
149*2264Sjacobs static papi_status_t
150*2264Sjacobs service_send_peer(service_t *svc)
151*2264Sjacobs {
152*2264Sjacobs 	papi_status_t result = PAPI_OK;
153*2264Sjacobs 
154*2264Sjacobs 	if ((svc->peer_fd != -1) && (svc->so_handle != NULL) &&
155*2264Sjacobs 	    (svc->svc_handle != NULL)) {
156*2264Sjacobs 		papi_status_t (*f)();
157*2264Sjacobs 
158*2264Sjacobs 		f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetPeer");
159*2264Sjacobs 
160*2264Sjacobs 		if (f != NULL)
161*2264Sjacobs 			result = f(svc->svc_handle, svc->peer_fd);
162*2264Sjacobs 	}
163*2264Sjacobs 
164*2264Sjacobs 	return (result);
165*2264Sjacobs }
166*2264Sjacobs 
167*2264Sjacobs papi_status_t
168*2264Sjacobs service_connect(service_t *svc, char *name)
169*2264Sjacobs {
170*2264Sjacobs 	papi_status_t result = PAPI_NOT_POSSIBLE;
171*2264Sjacobs 
172*2264Sjacobs 	/* if there is no print service module loaded, try and load one. */
173*2264Sjacobs 	if (svc->so_handle == NULL)
174*2264Sjacobs 		result = service_load(svc, name);
175*2264Sjacobs 	else if ((svc->name == NULL) && (name != NULL))
176*2264Sjacobs 		svc->name = strdup(name);
177*2264Sjacobs 
178*2264Sjacobs 	/*
179*2264Sjacobs 	 * the print service module is loaded, but we don't have a service
180*2264Sjacobs 	 * handle.
181*2264Sjacobs 	 */
182*2264Sjacobs 	if (svc->so_handle != NULL) {
183*2264Sjacobs 		papi_status_t (*f)();
184*2264Sjacobs 
185*2264Sjacobs 		f = (papi_status_t (*)())psm_sym(svc, "papiServiceCreate");
186*2264Sjacobs 
187*2264Sjacobs 		if (f != NULL) {
188*2264Sjacobs 			char *user = svc->user;
189*2264Sjacobs 			char *password = svc->password;
190*2264Sjacobs 
191*2264Sjacobs 			/* if no API user, try the URI user */
192*2264Sjacobs 			if ((user == NULL) && (svc->uri != NULL))
193*2264Sjacobs 				user = (svc->uri)->user;
194*2264Sjacobs 			/* if no API password, try the URI password */
195*2264Sjacobs 			if ((password == NULL) && (svc->uri != NULL))
196*2264Sjacobs 				password = (svc->uri)->password;
197*2264Sjacobs 
198*2264Sjacobs 			result = f(&svc->svc_handle, svc->name, user, password,
199*2264Sjacobs 					(svc->authCB ? interposed_auth_callback
200*2264Sjacobs 						: NULL),
201*2264Sjacobs 					svc->encryption, svc);
202*2264Sjacobs 			(void) service_send_peer(svc);
203*2264Sjacobs 		}
204*2264Sjacobs 	}
205*2264Sjacobs 
206*2264Sjacobs 	return (result);
207*2264Sjacobs }
208*2264Sjacobs 
209*2264Sjacobs papi_status_t
210*2264Sjacobs papiServiceCreate(papi_service_t *handle, char *service_name, char *user_name,
211*2264Sjacobs 		char *password,
212*2264Sjacobs 		int (*authCB)(papi_service_t svc, void *app_data),
213*2264Sjacobs 		papi_encryption_t encryption, void *app_data)
214*2264Sjacobs {
215*2264Sjacobs 	papi_status_t result = PAPI_NOT_POSSIBLE;
216*2264Sjacobs 	service_t *svc = NULL;
217*2264Sjacobs 	uri_t *u = NULL;
218*2264Sjacobs 
219*2264Sjacobs 	if (handle == NULL)
220*2264Sjacobs 		return (PAPI_BAD_ARGUMENT);
221*2264Sjacobs 
222*2264Sjacobs 	if ((*handle = svc = calloc(1, sizeof (*svc))) == NULL)
223*2264Sjacobs 		return (PAPI_TEMPORARY_ERROR);
224*2264Sjacobs 
225*2264Sjacobs 	svc->peer_fd = -1;
226*2264Sjacobs 
227*2264Sjacobs 	if (user_name != NULL)
228*2264Sjacobs 		svc->user = strdup(user_name);
229*2264Sjacobs 
230*2264Sjacobs 	if (password != NULL)
231*2264Sjacobs 		svc->password = strdup(password);
232*2264Sjacobs 
233*2264Sjacobs 	svc->encryption = encryption;
234*2264Sjacobs 
235*2264Sjacobs 	if (authCB != NULL)
236*2264Sjacobs 		svc->authCB = authCB;
237*2264Sjacobs 
238*2264Sjacobs 	if (app_data != NULL)
239*2264Sjacobs 		svc->app_data = app_data;
240*2264Sjacobs 
241*2264Sjacobs 	/* If not specified, get a "default" service from the environment */
242*2264Sjacobs 	if (service_name == NULL)
243*2264Sjacobs 		service_name = default_service_uri(NULL);
244*2264Sjacobs 
245*2264Sjacobs 	if (service_name != NULL) {
246*2264Sjacobs 		result = service_load(svc, service_name);
247*2264Sjacobs 		/* if the psm loaded and the svc contains a URI, connect */
248*2264Sjacobs 		if ((result == PAPI_OK) && (svc->uri != NULL))
249*2264Sjacobs 			result = service_connect(svc, service_name);
250*2264Sjacobs 	} else
251*2264Sjacobs 		result = PAPI_OK;
252*2264Sjacobs 
253*2264Sjacobs 	return (result);
254*2264Sjacobs }
255*2264Sjacobs 
256*2264Sjacobs void
257*2264Sjacobs papiServiceDestroy(papi_service_t handle)
258*2264Sjacobs {
259*2264Sjacobs 	if (handle != NULL) {
260*2264Sjacobs 		service_t *svc = handle;
261*2264Sjacobs 
262*2264Sjacobs 		if (svc->so_handle != NULL) {
263*2264Sjacobs 			if (svc->svc_handle != NULL) {
264*2264Sjacobs 				void (*f)();
265*2264Sjacobs 
266*2264Sjacobs 				f = (void (*)())psm_sym(svc,
267*2264Sjacobs 							"papiServiceDestroy");
268*2264Sjacobs 				f(svc->svc_handle);
269*2264Sjacobs 			}
270*2264Sjacobs 			psm_close(svc->so_handle);
271*2264Sjacobs 		}
272*2264Sjacobs 		if (svc->attributes != NULL)
273*2264Sjacobs 			papiAttributeListFree(svc->attributes);
274*2264Sjacobs 		if (svc->name != NULL)
275*2264Sjacobs 			free(svc->name);
276*2264Sjacobs 		if (svc->user != NULL)
277*2264Sjacobs 			free(svc->user);
278*2264Sjacobs 		if (svc->password != NULL)
279*2264Sjacobs 			free(svc->password);
280*2264Sjacobs 		if (svc->uri != NULL)
281*2264Sjacobs 			uri_free(svc->uri);
282*2264Sjacobs 
283*2264Sjacobs 		free(handle);
284*2264Sjacobs 	}
285*2264Sjacobs }
286*2264Sjacobs 
287*2264Sjacobs papi_status_t
288*2264Sjacobs papiServiceSetPeer(papi_service_t handle, int fd)
289*2264Sjacobs {
290*2264Sjacobs 	papi_status_t result = PAPI_OK;
291*2264Sjacobs 
292*2264Sjacobs 	if (handle != NULL) {
293*2264Sjacobs 		service_t *svc = handle;
294*2264Sjacobs 
295*2264Sjacobs 		svc->peer_fd = fd;
296*2264Sjacobs 		result = service_send_peer(svc);
297*2264Sjacobs 	} else
298*2264Sjacobs 		result = PAPI_BAD_ARGUMENT;
299*2264Sjacobs 
300*2264Sjacobs 	return (result);
301*2264Sjacobs }
302*2264Sjacobs 
303*2264Sjacobs papi_status_t
304*2264Sjacobs papiServiceSetUserName(papi_service_t handle, char *user_name)
305*2264Sjacobs {
306*2264Sjacobs 	papi_status_t result = PAPI_OK;
307*2264Sjacobs 
308*2264Sjacobs 	if (handle != NULL) {
309*2264Sjacobs 		service_t *svc = handle;
310*2264Sjacobs 		papi_status_t (*f)();
311*2264Sjacobs 
312*2264Sjacobs 		if (svc->user != NULL)
313*2264Sjacobs 			free(svc->user);
314*2264Sjacobs 		if (user_name != NULL)
315*2264Sjacobs 			svc->user = strdup(user_name);
316*2264Sjacobs 		f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetUserName");
317*2264Sjacobs 		if (f != NULL)
318*2264Sjacobs 			result = f(svc->svc_handle, user_name);
319*2264Sjacobs 	} else
320*2264Sjacobs 		result = PAPI_BAD_ARGUMENT;
321*2264Sjacobs 
322*2264Sjacobs 	return (result);
323*2264Sjacobs }
324*2264Sjacobs 
325*2264Sjacobs papi_status_t
326*2264Sjacobs papiServiceSetPassword(papi_service_t handle, char *password)
327*2264Sjacobs {
328*2264Sjacobs 	papi_status_t result = PAPI_OK;
329*2264Sjacobs 
330*2264Sjacobs 	if (handle != NULL) {
331*2264Sjacobs 		service_t *svc = handle;
332*2264Sjacobs 		papi_status_t (*f)();
333*2264Sjacobs 
334*2264Sjacobs 		if (svc->password != NULL)
335*2264Sjacobs 			free(svc->password);
336*2264Sjacobs 		if (password != NULL)
337*2264Sjacobs 			svc->password = strdup(password);
338*2264Sjacobs 		f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetPassword");
339*2264Sjacobs 		if (f != NULL)
340*2264Sjacobs 			result = f(svc->svc_handle, password);
341*2264Sjacobs 	} else
342*2264Sjacobs 		result = PAPI_BAD_ARGUMENT;
343*2264Sjacobs 
344*2264Sjacobs 	return (result);
345*2264Sjacobs }
346*2264Sjacobs 
347*2264Sjacobs papi_status_t
348*2264Sjacobs papiServiceSetEncryption(papi_service_t handle, papi_encryption_t encryption)
349*2264Sjacobs {
350*2264Sjacobs 	papi_status_t result = PAPI_OK;
351*2264Sjacobs 
352*2264Sjacobs 	if (handle != NULL) {
353*2264Sjacobs 		service_t *svc = handle;
354*2264Sjacobs 		papi_status_t (*f)();
355*2264Sjacobs 
356*2264Sjacobs 		svc->encryption = encryption;
357*2264Sjacobs 		f = (papi_status_t (*)())psm_sym(svc,
358*2264Sjacobs 						"papiServiceSetEncryption");
359*2264Sjacobs 		if (f != NULL)
360*2264Sjacobs 			result = f(svc->svc_handle, encryption);
361*2264Sjacobs 	} else
362*2264Sjacobs 		result = PAPI_BAD_ARGUMENT;
363*2264Sjacobs 
364*2264Sjacobs 	return (result);
365*2264Sjacobs }
366*2264Sjacobs 
367*2264Sjacobs papi_status_t
368*2264Sjacobs papiServiceSetAuthCB(papi_service_t handle,
369*2264Sjacobs 		int (*authCB)(papi_service_t svc, void *app_data))
370*2264Sjacobs {
371*2264Sjacobs 	papi_status_t result = PAPI_OK;
372*2264Sjacobs 
373*2264Sjacobs 	if (handle != NULL) {
374*2264Sjacobs 		service_t *svc = handle;
375*2264Sjacobs 		papi_status_t (*f)();
376*2264Sjacobs 
377*2264Sjacobs 		svc->authCB = authCB;
378*2264Sjacobs 		f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetAuthCB");
379*2264Sjacobs 		if (f != NULL)
380*2264Sjacobs 			result = f(svc->svc_handle, interposed_auth_callback);
381*2264Sjacobs 	} else
382*2264Sjacobs 		result = PAPI_BAD_ARGUMENT;
383*2264Sjacobs 
384*2264Sjacobs 	return (result);
385*2264Sjacobs }
386*2264Sjacobs 
387*2264Sjacobs 
388*2264Sjacobs papi_status_t
389*2264Sjacobs papiServiceSetAppData(papi_service_t handle, void *app_data)
390*2264Sjacobs {
391*2264Sjacobs 	papi_status_t result = PAPI_OK;
392*2264Sjacobs 
393*2264Sjacobs 	if (handle != NULL) {
394*2264Sjacobs 		service_t *svc = handle;
395*2264Sjacobs 		papi_status_t (*f)();
396*2264Sjacobs 
397*2264Sjacobs 		svc->app_data = (void *)app_data;
398*2264Sjacobs 	} else
399*2264Sjacobs 		result = PAPI_BAD_ARGUMENT;
400*2264Sjacobs 
401*2264Sjacobs 	return (result);
402*2264Sjacobs }
403*2264Sjacobs 
404*2264Sjacobs char *
405*2264Sjacobs papiServiceGetServiceName(papi_service_t handle)
406*2264Sjacobs {
407*2264Sjacobs 	char *result = NULL;
408*2264Sjacobs 
409*2264Sjacobs 	if (handle != NULL) {
410*2264Sjacobs 		service_t *svc = handle;
411*2264Sjacobs 		char *(*f)();
412*2264Sjacobs 
413*2264Sjacobs 		f = (char *(*)())psm_sym(svc, "papiServiceGetServiceName");
414*2264Sjacobs 		if (f != NULL)
415*2264Sjacobs 			result = f(svc->svc_handle);
416*2264Sjacobs 		if (result == NULL)
417*2264Sjacobs 			result = svc->name;
418*2264Sjacobs 	}
419*2264Sjacobs 
420*2264Sjacobs 	return (result);
421*2264Sjacobs }
422*2264Sjacobs 
423*2264Sjacobs char *
424*2264Sjacobs papiServiceGetUserName(papi_service_t handle)
425*2264Sjacobs {
426*2264Sjacobs 	char *result = NULL;
427*2264Sjacobs 
428*2264Sjacobs 	if (handle != NULL) {
429*2264Sjacobs 		service_t *svc = handle;
430*2264Sjacobs 		char *(*f)();
431*2264Sjacobs 
432*2264Sjacobs 		f = (char *(*)())psm_sym(svc, "papiServiceGetUserName");
433*2264Sjacobs 		if (f != NULL)
434*2264Sjacobs 			result = f(svc->svc_handle);
435*2264Sjacobs 		if (result == NULL)
436*2264Sjacobs 			result = svc->user;
437*2264Sjacobs 	}
438*2264Sjacobs 
439*2264Sjacobs 	return (result);
440*2264Sjacobs }
441*2264Sjacobs 
442*2264Sjacobs char *
443*2264Sjacobs papiServiceGetPassword(papi_service_t handle)
444*2264Sjacobs {
445*2264Sjacobs 	char *result = NULL;
446*2264Sjacobs 
447*2264Sjacobs 	if (handle != NULL) {
448*2264Sjacobs 		service_t *svc = handle;
449*2264Sjacobs 		char *(*f)();
450*2264Sjacobs 
451*2264Sjacobs 		f = (char *(*)())psm_sym(svc, "papiServiceGetPassword");
452*2264Sjacobs 		if (f != NULL)
453*2264Sjacobs 			result = f(svc->svc_handle);
454*2264Sjacobs 		if (result == NULL)
455*2264Sjacobs 			result = svc->password;
456*2264Sjacobs 	}
457*2264Sjacobs 
458*2264Sjacobs 	return (result);
459*2264Sjacobs }
460*2264Sjacobs 
461*2264Sjacobs papi_encryption_t
462*2264Sjacobs papiServiceGetEncryption(papi_service_t handle)
463*2264Sjacobs {
464*2264Sjacobs 	papi_encryption_t result = PAPI_ENCRYPT_NEVER;
465*2264Sjacobs 
466*2264Sjacobs 	if (handle != NULL) {
467*2264Sjacobs 		service_t *svc = handle;
468*2264Sjacobs 		papi_encryption_t (*f)();
469*2264Sjacobs 
470*2264Sjacobs 		f = (papi_encryption_t (*)())psm_sym(svc,
471*2264Sjacobs 						"papiServiceGetEncryption");
472*2264Sjacobs 		if (f != NULL)
473*2264Sjacobs 			result = f(svc->svc_handle);
474*2264Sjacobs 		if (result == PAPI_ENCRYPT_NEVER)
475*2264Sjacobs 			result = svc->encryption;
476*2264Sjacobs 	}
477*2264Sjacobs 
478*2264Sjacobs 	return (result);
479*2264Sjacobs }
480*2264Sjacobs 
481*2264Sjacobs void *
482*2264Sjacobs papiServiceGetAppData(papi_service_t handle)
483*2264Sjacobs {
484*2264Sjacobs 	void *result = NULL;
485*2264Sjacobs 	service_t *svc = handle;
486*2264Sjacobs 
487*2264Sjacobs 	if (handle != NULL)
488*2264Sjacobs 		result = svc->app_data;
489*2264Sjacobs 
490*2264Sjacobs 	return (result);
491*2264Sjacobs }
492*2264Sjacobs 
493*2264Sjacobs papi_attribute_t **
494*2264Sjacobs papiServiceGetAttributeList(papi_service_t handle)
495*2264Sjacobs {
496*2264Sjacobs 	papi_attribute_t **result = NULL;
497*2264Sjacobs 	service_t *svc = handle;
498*2264Sjacobs 
499*2264Sjacobs 	if (handle != NULL) {
500*2264Sjacobs 		papi_attribute_t **(*f)();
501*2264Sjacobs 
502*2264Sjacobs 		if (svc->so_handle == NULL) {
503*2264Sjacobs 			char *uri = default_service_uri(DEFAULT_SERVICE_URI);
504*2264Sjacobs 
505*2264Sjacobs 			if (service_connect(svc, uri) != PAPI_OK)
506*2264Sjacobs 				return (NULL);
507*2264Sjacobs 		}
508*2264Sjacobs 
509*2264Sjacobs 		f = (papi_attribute_t **(*)())psm_sym(svc,
510*2264Sjacobs 					"papiServiceGetAttributeList");
511*2264Sjacobs 		if (f != NULL)
512*2264Sjacobs 			result = f(svc->svc_handle);
513*2264Sjacobs 	} else
514*2264Sjacobs 		result = svc->attributes;
515*2264Sjacobs 
516*2264Sjacobs 	return (result);
517*2264Sjacobs }
518*2264Sjacobs 
519*2264Sjacobs char *
520*2264Sjacobs papiServiceGetStatusMessage(papi_service_t handle)
521*2264Sjacobs {
522*2264Sjacobs 	char *result = NULL;
523*2264Sjacobs 	service_t *svc = handle;
524*2264Sjacobs 
525*2264Sjacobs 	if (handle != NULL) {
526*2264Sjacobs 		char *(*f)();
527*2264Sjacobs 
528*2264Sjacobs 		f = (char *(*)())psm_sym(svc, "papiServiceGetStatusMessage");
529*2264Sjacobs 		if (f != NULL)
530*2264Sjacobs 			result = f(svc->svc_handle);
531*2264Sjacobs 	}
532*2264Sjacobs 	if (result == NULL) {
533*2264Sjacobs 		papiAttributeListGetString(svc->attributes, NULL,
534*2264Sjacobs 					"detailed-status-message", &result);
535*2264Sjacobs 	}
536*2264Sjacobs 
537*2264Sjacobs 	return (result);
538*2264Sjacobs }
539*2264Sjacobs 
540*2264Sjacobs void
541*2264Sjacobs detailed_error(service_t *svc, char *fmt, ...)
542*2264Sjacobs {
543*2264Sjacobs 	if ((svc != NULL) && (fmt != NULL)) {
544*2264Sjacobs 		va_list ap;
545*2264Sjacobs 		size_t size;
546*2264Sjacobs 		char *message = alloca(BUFSIZ);
547*2264Sjacobs 
548*2264Sjacobs 		va_start(ap, fmt);
549*2264Sjacobs 		/*
550*2264Sjacobs 		 * fill in the message.  If the buffer is too small, allocate
551*2264Sjacobs 		 * one that is large enough and fill it in.
552*2264Sjacobs 		 */
553*2264Sjacobs 		if ((size = vsnprintf(message, BUFSIZ, fmt, ap)) >= BUFSIZ)
554*2264Sjacobs 			if ((message = alloca(size)) != NULL)
555*2264Sjacobs 				vsnprintf(message, size, fmt, ap);
556*2264Sjacobs 		va_end(ap);
557*2264Sjacobs 
558*2264Sjacobs 		papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND,
559*2264Sjacobs 					"detailed-status-message", message);
560*2264Sjacobs #ifdef DEBUG
561*2264Sjacobs 		fprintf(stderr, "detailed_error(%s)\n", message);
562*2264Sjacobs #endif
563*2264Sjacobs 	}
564*2264Sjacobs }
565