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