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