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