#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.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)
return (PAPI_OK);
if (name == NULL)
return (PAPI_OK);
svc->attributes = getprinterbyname((char *)name, NULL);
if (svc->attributes != NULL) {
char *tmp = NULL;
papiAttributeListGetString(svc->attributes, NULL,
"printer-uri-supported", &tmp);
if (tmp != NULL)
svc->name = strdup(tmp);
if (uri_from_string(svc->name, &svc->uri) != -1)
scheme = (svc->uri)->scheme;
papiAttributeListGetString(svc->attributes, NULL,
"print-service-module", &scheme);
} else
scheme = name;
result = psm_open(svc, scheme);
switch (result) {
case PAPI_OK:
break;
case PAPI_URI_SCHEME:
result = PAPI_NOT_FOUND;
#ifdef DEBUG
detailed_error(svc, "Unable to load service for: %s", name);
#endif
break;
default:
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 (svc->so_handle == NULL)
result = service_load(svc, name);
else if ((svc->name == NULL) && (name != NULL))
svc->name = strdup(name);
if (svc->so_handle != NULL) {
papi_status_t (*f)();
if (svc->svc_handle != NULL)
return (PAPI_OK);
f = (papi_status_t (*)())psm_sym(svc, "papiServiceCreate");
if (f != NULL) {
char *user = svc->user;
char *password = svc->password;
if ((user == NULL) && (svc->uri != NULL))
user = (svc->uri)->user;
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 (service_name == NULL)
service_name = default_service_uri(NULL);
if (service_name != NULL) {
result = service_load(svc, service_name);
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;
char *message;
int rv;
va_start(ap, fmt);
rv = vasprintf(&message, fmt, ap);
va_end(ap);
if (rv >= 0) {
papiAttributeListAddString(&svc->attributes,
PAPI_ATTR_APPEND, "detailed-status-message",
message);
#ifdef DEBUG
fprintf(stderr, "detailed_error(%s)\n", message);
#endif
free(message);
}
}
}