/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * */ /* $Id: service.c 172 2006-05-24 20:54:00Z njacobs $ */ #pragma ident "%Z%%M% %I% %E% SMI" /*LINTLIBRARY*/ #include #include #include #include #include #include #include #include static int interposed_auth_callback(papi_service_t handle, void *app_data) { int result = -1; service_t *svc = app_data; if (svc != NULL) result = svc->authCB(svc, svc->app_data); return (result); } static char * default_service_uri(char *fallback) { char *result = NULL; if ((result = getenv("PAPI_SERVICE_URI")) == NULL) { char *cups; if ((cups = getenv("CUPS_SERVER")) != NULL) { char buf[BUFSIZ]; snprintf(buf, sizeof (buf), "ipp://%s/printers/", cups); result = strdup(buf); } } if (result == NULL) result = fallback; return (result); } static char * default_print_service() { static char *result = NULL; if (result == NULL) { char *service_uri = default_service_uri(DEFAULT_SERVICE_URI); uri_t *uri = NULL; if (uri_from_string(service_uri, &uri) != -1) result = strdup(uri->scheme); if (uri != NULL) uri_free(uri); } return (result); } static papi_status_t service_load(service_t *svc, char *name) { papi_status_t result; char *scheme = default_print_service(); if (svc->so_handle != NULL) /* already loaded */ return (PAPI_OK); if (name == NULL) /* no info, can't load yet */ return (PAPI_OK); /* Lookup the printer in the configuration DB */ svc->attributes = getprinterbyname((char *)name, NULL); if (svc->attributes != NULL) { char *tmp = NULL; /* Printer found (or was a URI), use the attribute data */ papiAttributeListGetString(svc->attributes, NULL, "printer-uri-supported", &tmp); if (tmp != NULL) svc->name = strdup(tmp); /* parse the URI and set the scheme(print service) */ if (uri_from_string(svc->name, &svc->uri) != -1) scheme = (svc->uri)->scheme; /* override the scheme if it was in the attributes */ papiAttributeListGetString(svc->attributes, NULL, "print-service-module", &scheme); } else /* not found, assume it is the actual print service name */ scheme = name; result = psm_open(svc, scheme); switch (result) { case PAPI_OK: break; /* no error */ case PAPI_URI_SCHEME: result = PAPI_NOT_FOUND; #ifdef DEBUG detailed_error(svc, "Unable to load service for: %s", name); #endif break; default: /* set the detailed message */ detailed_error(svc, "Unable to load service (%s) for: %s", scheme, name); } return (result); } static papi_status_t service_send_peer(service_t *svc) { papi_status_t result = PAPI_OK; if ((svc->peer_fd != -1) && (svc->so_handle != NULL) && (svc->svc_handle != NULL)) { papi_status_t (*f)(); f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetPeer"); if (f != NULL) result = f(svc->svc_handle, svc->peer_fd); } return (result); } papi_status_t service_connect(service_t *svc, char *name) { papi_status_t result = PAPI_NOT_POSSIBLE; /* if there is no print service module loaded, try and load one. */ if (svc->so_handle == NULL) result = service_load(svc, name); else if ((svc->name == NULL) && (name != NULL)) svc->name = strdup(name); /* * the print service module is loaded, but we don't have a service * handle. */ if (svc->so_handle != NULL) { papi_status_t (*f)(); if (svc->svc_handle != NULL) /* already connected? */ return (PAPI_OK); f = (papi_status_t (*)())psm_sym(svc, "papiServiceCreate"); if (f != NULL) { char *user = svc->user; char *password = svc->password; /* if no API user, try the URI user */ if ((user == NULL) && (svc->uri != NULL)) user = (svc->uri)->user; /* if no API password, try the URI password */ if ((password == NULL) && (svc->uri != NULL)) password = (svc->uri)->password; result = f(&svc->svc_handle, svc->name, user, password, (svc->authCB ? interposed_auth_callback : NULL), svc->encryption, svc); (void) service_send_peer(svc); } } return (result); } 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) { papi_status_t result = PAPI_NOT_POSSIBLE; service_t *svc = NULL; uri_t *u = NULL; if (handle == NULL) return (PAPI_BAD_ARGUMENT); if ((*handle = svc = calloc(1, sizeof (*svc))) == NULL) return (PAPI_TEMPORARY_ERROR); svc->peer_fd = -1; if (user_name != NULL) svc->user = strdup(user_name); if (password != NULL) svc->password = strdup(password); svc->encryption = encryption; if (authCB != NULL) svc->authCB = authCB; if (app_data != NULL) svc->app_data = app_data; /* If not specified, get a "default" service from the environment */ if (service_name == NULL) service_name = default_service_uri(NULL); if (service_name != NULL) { result = service_load(svc, service_name); /* if the psm loaded and the svc contains a URI, connect */ if ((result == PAPI_OK) && (svc->uri != NULL)) result = service_connect(svc, service_name); } else result = PAPI_OK; return (result); } void papiServiceDestroy(papi_service_t handle) { if (handle != NULL) { service_t *svc = handle; if (svc->so_handle != NULL) { if (svc->svc_handle != NULL) { void (*f)(); f = (void (*)())psm_sym(svc, "papiServiceDestroy"); f(svc->svc_handle); } psm_close(svc->so_handle); } if (svc->attributes != NULL) papiAttributeListFree(svc->attributes); if (svc->name != NULL) free(svc->name); if (svc->user != NULL) free(svc->user); if (svc->password != NULL) free(svc->password); if (svc->uri != NULL) uri_free(svc->uri); free(handle); } } papi_status_t papiServiceSetPeer(papi_service_t handle, int fd) { papi_status_t result = PAPI_OK; if (handle != NULL) { service_t *svc = handle; svc->peer_fd = fd; result = service_send_peer(svc); } else result = PAPI_BAD_ARGUMENT; return (result); } papi_status_t papiServiceSetUserName(papi_service_t handle, char *user_name) { papi_status_t result = PAPI_OK; if (handle != NULL) { service_t *svc = handle; papi_status_t (*f)(); if (svc->user != NULL) free(svc->user); if (user_name != NULL) svc->user = strdup(user_name); f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetUserName"); if (f != NULL) result = f(svc->svc_handle, user_name); } else result = PAPI_BAD_ARGUMENT; return (result); } papi_status_t papiServiceSetPassword(papi_service_t handle, char *password) { papi_status_t result = PAPI_OK; if (handle != NULL) { service_t *svc = handle; papi_status_t (*f)(); if (svc->password != NULL) free(svc->password); if (password != NULL) svc->password = strdup(password); f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetPassword"); if (f != NULL) result = f(svc->svc_handle, password); } else result = PAPI_BAD_ARGUMENT; return (result); } papi_status_t papiServiceSetEncryption(papi_service_t handle, papi_encryption_t encryption) { papi_status_t result = PAPI_OK; if (handle != NULL) { service_t *svc = handle; papi_status_t (*f)(); svc->encryption = encryption; f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetEncryption"); if (f != NULL) result = f(svc->svc_handle, encryption); } else result = PAPI_BAD_ARGUMENT; return (result); } papi_status_t papiServiceSetAuthCB(papi_service_t handle, int (*authCB)(papi_service_t svc, void *app_data)) { papi_status_t result = PAPI_OK; if (handle != NULL) { service_t *svc = handle; papi_status_t (*f)(); svc->authCB = authCB; f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetAuthCB"); if (f != NULL) result = f(svc->svc_handle, interposed_auth_callback); } else result = PAPI_BAD_ARGUMENT; return (result); } papi_status_t papiServiceSetAppData(papi_service_t handle, void *app_data) { papi_status_t result = PAPI_OK; if (handle != NULL) { service_t *svc = handle; papi_status_t (*f)(); svc->app_data = (void *)app_data; } else result = PAPI_BAD_ARGUMENT; return (result); } char * papiServiceGetServiceName(papi_service_t handle) { char *result = NULL; if (handle != NULL) { service_t *svc = handle; char *(*f)(); f = (char *(*)())psm_sym(svc, "papiServiceGetServiceName"); if (f != NULL) result = f(svc->svc_handle); if (result == NULL) result = svc->name; } return (result); } char * papiServiceGetUserName(papi_service_t handle) { char *result = NULL; if (handle != NULL) { service_t *svc = handle; char *(*f)(); f = (char *(*)())psm_sym(svc, "papiServiceGetUserName"); if (f != NULL) result = f(svc->svc_handle); if (result == NULL) result = svc->user; } return (result); } char * papiServiceGetPassword(papi_service_t handle) { char *result = NULL; if (handle != NULL) { service_t *svc = handle; char *(*f)(); f = (char *(*)())psm_sym(svc, "papiServiceGetPassword"); if (f != NULL) result = f(svc->svc_handle); if (result == NULL) result = svc->password; } return (result); } papi_encryption_t papiServiceGetEncryption(papi_service_t handle) { papi_encryption_t result = PAPI_ENCRYPT_NEVER; if (handle != NULL) { service_t *svc = handle; papi_encryption_t (*f)(); f = (papi_encryption_t (*)())psm_sym(svc, "papiServiceGetEncryption"); if (f != NULL) result = f(svc->svc_handle); if (result == PAPI_ENCRYPT_NEVER) result = svc->encryption; } return (result); } void * papiServiceGetAppData(papi_service_t handle) { void *result = NULL; service_t *svc = handle; if (handle != NULL) result = svc->app_data; return (result); } papi_attribute_t ** papiServiceGetAttributeList(papi_service_t handle) { papi_attribute_t **result = NULL; service_t *svc = handle; if (handle != NULL) { papi_attribute_t **(*f)(); if (svc->so_handle == NULL) { char *uri = default_service_uri(DEFAULT_SERVICE_URI); if (service_connect(svc, uri) != PAPI_OK) return (NULL); } f = (papi_attribute_t **(*)())psm_sym(svc, "papiServiceGetAttributeList"); if (f != NULL) result = f(svc->svc_handle); } else result = svc->attributes; return (result); } char * papiServiceGetStatusMessage(papi_service_t handle) { char *result = NULL; service_t *svc = handle; if (handle != NULL) { char *(*f)(); f = (char *(*)())psm_sym(svc, "papiServiceGetStatusMessage"); if (f != NULL) result = f(svc->svc_handle); } if (result == NULL) { papiAttributeListGetString(svc->attributes, NULL, "detailed-status-message", &result); } return (result); } void detailed_error(service_t *svc, char *fmt, ...) { if ((svc != NULL) && (fmt != NULL)) { va_list ap; size_t size; char *message = alloca(BUFSIZ); va_start(ap, fmt); /* * fill in the message. If the buffer is too small, allocate * one that is large enough and fill it in. */ if ((size = vsnprintf(message, BUFSIZ, fmt, ap)) >= BUFSIZ) if ((message = alloca(size)) != NULL) vsnprintf(message, size, fmt, ap); va_end(ap); papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND, "detailed-status-message", message); #ifdef DEBUG fprintf(stderr, "detailed_error(%s)\n", message); #endif } }