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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 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 * 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 ** 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 * 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 544 detailed_error(service_t *svc, char *fmt, ...) 545 { 546 if ((svc != NULL) && (fmt != NULL)) { 547 va_list ap; 548 size_t size; 549 char *message = alloca(BUFSIZ); 550 551 va_start(ap, fmt); 552 /* 553 * fill in the message. If the buffer is too small, allocate 554 * one that is large enough and fill it in. 555 */ 556 if ((size = vsnprintf(message, BUFSIZ, fmt, ap)) >= BUFSIZ) 557 if ((message = alloca(size)) != NULL) 558 vsnprintf(message, size, fmt, ap); 559 va_end(ap); 560 561 papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND, 562 "detailed-status-message", message); 563 #ifdef DEBUG 564 fprintf(stderr, "detailed_error(%s)\n", message); 565 #endif 566 } 567 } 568