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 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <libintl.h>
37 #include <papi_impl.h>
38 #include <config-site.h>
39
40 static int
interposed_auth_callback(papi_service_t handle,void * app_data)41 interposed_auth_callback(papi_service_t handle, void *app_data)
42 {
43 int result = -1;
44 service_t *svc = app_data;
45
46 if (svc != NULL)
47 result = svc->authCB(svc, svc->app_data);
48
49 return (result);
50 }
51
52 static char *
default_service_uri(char * fallback)53 default_service_uri(char *fallback)
54 {
55 char *result = NULL;
56
57 if (getuid() == geteuid())
58 result = getenv("PAPI_SERVICE_URI");
59
60 if (result == 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 *
default_print_service()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
service_load(service_t * svc,char * name)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
service_send_peer(service_t * svc)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
service_connect(service_t * svc,char * name)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 if (svc->svc_handle != NULL) /* already connected? */
186 return (PAPI_OK);
187
188 f = (papi_status_t (*)())psm_sym(svc, "papiServiceCreate");
189
190 if (f != NULL) {
191 char *user = svc->user;
192 char *password = svc->password;
193
194 /* if no API user, try the URI user */
195 if ((user == NULL) && (svc->uri != NULL))
196 user = (svc->uri)->user;
197 /* if no API password, try the URI password */
198 if ((password == NULL) && (svc->uri != NULL))
199 password = (svc->uri)->password;
200
201 result = f(&svc->svc_handle, svc->name, user, password,
202 (svc->authCB ? interposed_auth_callback
203 : NULL),
204 svc->encryption, svc);
205 (void) service_send_peer(svc);
206 }
207 }
208
209 return (result);
210 }
211
212 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)213 papiServiceCreate(papi_service_t *handle, char *service_name, char *user_name,
214 char *password,
215 int (*authCB)(papi_service_t svc, void *app_data),
216 papi_encryption_t encryption, void *app_data)
217 {
218 papi_status_t result = PAPI_NOT_POSSIBLE;
219 service_t *svc = NULL;
220 uri_t *u = NULL;
221
222 if (handle == NULL)
223 return (PAPI_BAD_ARGUMENT);
224
225 if ((*handle = svc = calloc(1, sizeof (*svc))) == NULL)
226 return (PAPI_TEMPORARY_ERROR);
227
228 svc->peer_fd = -1;
229
230 if (user_name != NULL)
231 svc->user = strdup(user_name);
232
233 if (password != NULL)
234 svc->password = strdup(password);
235
236 svc->encryption = encryption;
237
238 if (authCB != NULL)
239 svc->authCB = authCB;
240
241 if (app_data != NULL)
242 svc->app_data = app_data;
243
244 /* If not specified, get a "default" service from the environment */
245 if (service_name == NULL)
246 service_name = default_service_uri(NULL);
247
248 if (service_name != NULL) {
249 result = service_load(svc, service_name);
250 /* if the psm loaded and the svc contains a URI, connect */
251 if ((result == PAPI_OK) && (svc->uri != NULL))
252 result = service_connect(svc, service_name);
253 } else
254 result = PAPI_OK;
255
256 return (result);
257 }
258
259 void
papiServiceDestroy(papi_service_t handle)260 papiServiceDestroy(papi_service_t handle)
261 {
262 if (handle != NULL) {
263 service_t *svc = handle;
264
265 if (svc->so_handle != NULL) {
266 if (svc->svc_handle != NULL) {
267 void (*f)();
268
269 f = (void (*)())psm_sym(svc,
270 "papiServiceDestroy");
271 f(svc->svc_handle);
272 }
273 psm_close(svc->so_handle);
274 }
275 if (svc->attributes != NULL)
276 papiAttributeListFree(svc->attributes);
277 if (svc->name != NULL)
278 free(svc->name);
279 if (svc->user != NULL)
280 free(svc->user);
281 if (svc->password != NULL)
282 free(svc->password);
283 if (svc->uri != NULL)
284 uri_free(svc->uri);
285
286 free(handle);
287 }
288 }
289
290 papi_status_t
papiServiceSetPeer(papi_service_t handle,int fd)291 papiServiceSetPeer(papi_service_t handle, int fd)
292 {
293 papi_status_t result = PAPI_OK;
294
295 if (handle != NULL) {
296 service_t *svc = handle;
297
298 svc->peer_fd = fd;
299 result = service_send_peer(svc);
300 } else
301 result = PAPI_BAD_ARGUMENT;
302
303 return (result);
304 }
305
306 papi_status_t
papiServiceSetUserName(papi_service_t handle,char * user_name)307 papiServiceSetUserName(papi_service_t handle, char *user_name)
308 {
309 papi_status_t result = PAPI_OK;
310
311 if (handle != NULL) {
312 service_t *svc = handle;
313 papi_status_t (*f)();
314
315 if (svc->user != NULL)
316 free(svc->user);
317 if (user_name != NULL)
318 svc->user = strdup(user_name);
319 f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetUserName");
320 if (f != NULL)
321 result = f(svc->svc_handle, user_name);
322 } else
323 result = PAPI_BAD_ARGUMENT;
324
325 return (result);
326 }
327
328 papi_status_t
papiServiceSetPassword(papi_service_t handle,char * password)329 papiServiceSetPassword(papi_service_t handle, char *password)
330 {
331 papi_status_t result = PAPI_OK;
332
333 if (handle != NULL) {
334 service_t *svc = handle;
335 papi_status_t (*f)();
336
337 if (svc->password != NULL)
338 free(svc->password);
339 if (password != NULL)
340 svc->password = strdup(password);
341 f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetPassword");
342 if (f != NULL)
343 result = f(svc->svc_handle, password);
344 } else
345 result = PAPI_BAD_ARGUMENT;
346
347 return (result);
348 }
349
350 papi_status_t
papiServiceSetEncryption(papi_service_t handle,papi_encryption_t encryption)351 papiServiceSetEncryption(papi_service_t handle, papi_encryption_t encryption)
352 {
353 papi_status_t result = PAPI_OK;
354
355 if (handle != NULL) {
356 service_t *svc = handle;
357 papi_status_t (*f)();
358
359 svc->encryption = encryption;
360 f = (papi_status_t (*)())psm_sym(svc,
361 "papiServiceSetEncryption");
362 if (f != NULL)
363 result = f(svc->svc_handle, encryption);
364 } else
365 result = PAPI_BAD_ARGUMENT;
366
367 return (result);
368 }
369
370 papi_status_t
papiServiceSetAuthCB(papi_service_t handle,int (* authCB)(papi_service_t svc,void * app_data))371 papiServiceSetAuthCB(papi_service_t handle,
372 int (*authCB)(papi_service_t svc, void *app_data))
373 {
374 papi_status_t result = PAPI_OK;
375
376 if (handle != NULL) {
377 service_t *svc = handle;
378 papi_status_t (*f)();
379
380 svc->authCB = authCB;
381 f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetAuthCB");
382 if (f != NULL)
383 result = f(svc->svc_handle, interposed_auth_callback);
384 } else
385 result = PAPI_BAD_ARGUMENT;
386
387 return (result);
388 }
389
390
391 papi_status_t
papiServiceSetAppData(papi_service_t handle,void * app_data)392 papiServiceSetAppData(papi_service_t handle, void *app_data)
393 {
394 papi_status_t result = PAPI_OK;
395
396 if (handle != NULL) {
397 service_t *svc = handle;
398 papi_status_t (*f)();
399
400 svc->app_data = (void *)app_data;
401 } else
402 result = PAPI_BAD_ARGUMENT;
403
404 return (result);
405 }
406
407 char *
papiServiceGetServiceName(papi_service_t handle)408 papiServiceGetServiceName(papi_service_t handle)
409 {
410 char *result = NULL;
411
412 if (handle != NULL) {
413 service_t *svc = handle;
414 char *(*f)();
415
416 f = (char *(*)())psm_sym(svc, "papiServiceGetServiceName");
417 if (f != NULL)
418 result = f(svc->svc_handle);
419 if (result == NULL)
420 result = svc->name;
421 }
422
423 return (result);
424 }
425
426 char *
papiServiceGetUserName(papi_service_t handle)427 papiServiceGetUserName(papi_service_t handle)
428 {
429 char *result = NULL;
430
431 if (handle != NULL) {
432 service_t *svc = handle;
433 char *(*f)();
434
435 f = (char *(*)())psm_sym(svc, "papiServiceGetUserName");
436 if (f != NULL)
437 result = f(svc->svc_handle);
438 if (result == NULL)
439 result = svc->user;
440 }
441
442 return (result);
443 }
444
445 char *
papiServiceGetPassword(papi_service_t handle)446 papiServiceGetPassword(papi_service_t handle)
447 {
448 char *result = NULL;
449
450 if (handle != NULL) {
451 service_t *svc = handle;
452 char *(*f)();
453
454 f = (char *(*)())psm_sym(svc, "papiServiceGetPassword");
455 if (f != NULL)
456 result = f(svc->svc_handle);
457 if (result == NULL)
458 result = svc->password;
459 }
460
461 return (result);
462 }
463
464 papi_encryption_t
papiServiceGetEncryption(papi_service_t handle)465 papiServiceGetEncryption(papi_service_t handle)
466 {
467 papi_encryption_t result = PAPI_ENCRYPT_NEVER;
468
469 if (handle != NULL) {
470 service_t *svc = handle;
471 papi_encryption_t (*f)();
472
473 f = (papi_encryption_t (*)())psm_sym(svc,
474 "papiServiceGetEncryption");
475 if (f != NULL)
476 result = f(svc->svc_handle);
477 if (result == PAPI_ENCRYPT_NEVER)
478 result = svc->encryption;
479 }
480
481 return (result);
482 }
483
484 void *
papiServiceGetAppData(papi_service_t handle)485 papiServiceGetAppData(papi_service_t handle)
486 {
487 void *result = NULL;
488 service_t *svc = handle;
489
490 if (handle != NULL)
491 result = svc->app_data;
492
493 return (result);
494 }
495
496 papi_attribute_t **
papiServiceGetAttributeList(papi_service_t handle)497 papiServiceGetAttributeList(papi_service_t handle)
498 {
499 papi_attribute_t **result = NULL;
500 service_t *svc = handle;
501
502 if (handle != NULL) {
503 papi_attribute_t **(*f)();
504
505 if (svc->so_handle == NULL) {
506 char *uri = default_service_uri(DEFAULT_SERVICE_URI);
507
508 if (service_connect(svc, uri) != PAPI_OK)
509 return (NULL);
510 }
511
512 f = (papi_attribute_t **(*)())psm_sym(svc,
513 "papiServiceGetAttributeList");
514 if (f != NULL)
515 result = f(svc->svc_handle);
516 } else
517 result = svc->attributes;
518
519 return (result);
520 }
521
522 char *
papiServiceGetStatusMessage(papi_service_t handle)523 papiServiceGetStatusMessage(papi_service_t handle)
524 {
525 char *result = NULL;
526 service_t *svc = handle;
527
528 if (handle != NULL) {
529 char *(*f)();
530
531 f = (char *(*)())psm_sym(svc, "papiServiceGetStatusMessage");
532 if (f != NULL)
533 result = f(svc->svc_handle);
534 }
535 if (result == NULL) {
536 papiAttributeListGetString(svc->attributes, NULL,
537 "detailed-status-message", &result);
538 }
539
540 return (result);
541 }
542
543 void
detailed_error(service_t * svc,char * fmt,...)544 detailed_error(service_t *svc, char *fmt, ...)
545 {
546 if ((svc != NULL) && (fmt != NULL)) {
547 va_list ap;
548 char *message;
549 int rv;
550
551 va_start(ap, fmt);
552 rv = vasprintf(&message, fmt, ap);
553 va_end(ap);
554
555 if (rv >= 0) {
556 papiAttributeListAddString(&svc->attributes,
557 PAPI_ATTR_APPEND, "detailed-status-message",
558 message);
559 #ifdef DEBUG
560 fprintf(stderr, "detailed_error(%s)\n", message);
561 #endif
562 free(message);
563 }
564 }
565 }
566