/*
* 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 2008 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 <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <alloca.h>
#include <libintl.h>
#include <papi_impl.h>
#include <config-site.h>
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 (getuid() == geteuid())
result = getenv("PAPI_SERVICE_URI");
if (result == 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
}
}