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