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
interposed_auth_callback(papi_service_t handle,void * app_data)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 *
default_service_uri(char * fallback)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 *
default_print_service()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
service_load(service_t * svc,char * name)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
service_send_peer(service_t * svc)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
service_connect(service_t * svc,char * name)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
papiServiceCreate(papi_service_t * handle,char * service_name,char * user_name,char * password,int (* authCB)(papi_service_t svc,void * app_data),papi_encryption_t encryption,void * app_data)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
papiServiceDestroy(papi_service_t handle)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
papiServiceSetPeer(papi_service_t handle,int fd)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
papiServiceSetUserName(papi_service_t handle,char * user_name)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
papiServiceSetPassword(papi_service_t handle,char * password)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
papiServiceSetEncryption(papi_service_t handle,papi_encryption_t encryption)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
papiServiceSetAuthCB(papi_service_t handle,int (* authCB)(papi_service_t svc,void * app_data))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
papiServiceSetAppData(papi_service_t handle,void * app_data)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 *
papiServiceGetServiceName(papi_service_t handle)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 *
papiServiceGetUserName(papi_service_t handle)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 *
papiServiceGetPassword(papi_service_t handle)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
papiServiceGetEncryption(papi_service_t handle)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 *
papiServiceGetAppData(papi_service_t handle)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 **
papiServiceGetAttributeList(papi_service_t handle)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 *
papiServiceGetStatusMessage(papi_service_t handle)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
detailed_error(service_t * svc,char * fmt,...)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