/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
*/
/* $Id: printer.c 146 2006-03-24 00:26:54Z njacobs $ */
#pragma ident "%Z%%M% %I% %E% SMI"
/*LINTLIBRARY*/
#include <stdlib.h>
#include <papi_impl.h>
#include <config-site.h>
void
papiPrinterFree(papi_printer_t printer)
{
printer_t *tmp = printer;
if (tmp != NULL) {
if (tmp->attributes != NULL)
papiAttributeListFree(tmp->attributes);
free(tmp);
}
}
void
papiPrinterListFree(papi_printer_t *printers)
{
if (printers != NULL) {
int i;
for (i = 0; printers[i] != NULL; i++)
papiPrinterFree(printers[i]);
free(printers);
}
}
/*
* Enumeration of printers is not part of the IPP specification, so many
* servers will probably not respond back with a list of printers, but
* CUPS has implemented an extension to IPP to enumerate printers and
* classes. the Apache/mod_ipp IPP listener module available in Solaris
* implements this IPP extension, so CUPS and Solaris can provide this
* to IPP clients.
*/
#ifndef OPID_CUPS_GET_PRINTERS /* for servers that will enumerate */
#define OPID_CUPS_GET_PRINTERS 0x4002
#endif /* OPID_CUPS_GET_PRINTERS */
#ifndef OPID_CUPS_DELETE_PRINTER /* for servers that can delete */
#define OPID_CUPS_DELETE_PRINTER 0x4004
#endif /* OPID_CUPS_DELETE_PRINTER */
#ifndef OPID_CUPS_GET_CLASSES /* for servers that will enumerate */
#define OPID_CUPS_GET_CLASSES 0x4005
#endif /* OPID_CUPS_GET_CLASSES */
papi_status_t
papiPrintersList(papi_service_t handle, char **requested_attrs,
papi_filter_t *filter, papi_printer_t **printers)
{
papi_status_t status, result = PAPI_INTERNAL_ERROR;
service_t *svc = handle;
papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
void *iter = NULL;
if ((svc == NULL) || (printers == NULL))
return (PAPI_BAD_ARGUMENT);
/* if we are already connected, use that connection. */
if (svc->connection == NULL)
if ((result = service_connect(svc, DEFAULT_DEST)) != PAPI_OK)
return (result);
ipp_initialize_request(svc, &request, OPID_CUPS_GET_PRINTERS);
ipp_initialize_operational_attributes(svc, &op, NULL, -1);
if (requested_attrs != NULL) {
int i;
for (i = 0; requested_attrs[i] != NULL; i++)
papiAttributeListAddString(&op, PAPI_ATTR_APPEND,
"requested-attributes", requested_attrs[i]);
}
papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
"operational-attributes-group", op);
papiAttributeListFree(op);
result = ipp_send_request(svc, request, &response);
papiAttributeListFree(request);
op = NULL;
for (status = papiAttributeListGetCollection(response, &iter,
"printer-attributes-group", &op);
status == PAPI_OK;
status = papiAttributeListGetCollection(response, &iter,
NULL, &op)) {
printer_t *p = NULL;
if ((p = calloc(1, sizeof (*p))) == NULL)
return (PAPI_TEMPORARY_ERROR);
copy_attributes(&p->attributes, op);
op = NULL;
list_append(printers, p);
}
papiAttributeListFree(response);
return (result);
}
papi_status_t
papiPrinterQuery(papi_service_t handle, char *name,
char **requested_attrs,
papi_attribute_t **job_attributes,
papi_printer_t *printer)
{
papi_status_t result = PAPI_INTERNAL_ERROR;
service_t *svc = handle;
printer_t *p = NULL;
papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
if ((svc == NULL) || (name == NULL) || (printer == NULL))
return (PAPI_BAD_ARGUMENT);
/* if we are already connected, use that connection. */
if (svc->connection == NULL)
if ((result = service_connect(svc, name)) != PAPI_OK)
return (result);
if ((*printer = p = calloc(1, sizeof (*p))) == NULL)
return (PAPI_TEMPORARY_ERROR);
ipp_initialize_request(svc, &request, OPID_GET_PRINTER_ATTRIBUTES);
ipp_initialize_operational_attributes(svc, &op, name, -1);
if (requested_attrs != NULL) {
int i;
for (i = 0; requested_attrs[i] != NULL; i++)
papiAttributeListAddString(&op, PAPI_ATTR_APPEND,
"requested-attributes", requested_attrs[i]);
}
papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
"operational-attributes-group", op);
papiAttributeListFree(op);
result = ipp_send_request(svc, request, &response);
papiAttributeListFree(request);
op = NULL;
papiAttributeListGetCollection(response, NULL,
"printer-attributes-group", &op);
copy_attributes(&p->attributes, op);
papiAttributeListFree(response);
return (result);
}
static papi_status_t
_printer_enable_disable_pause_resume_delete(papi_service_t handle, char *name,
char *message, uint16_t type)
{
papi_status_t result = PAPI_INTERNAL_ERROR;
service_t *svc = handle;
papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
if ((svc == NULL) || (name == NULL))
return (PAPI_BAD_ARGUMENT);
/* if we are already connected, use that connection. */
if (svc->connection == NULL)
if ((result = service_connect(svc, name)) != PAPI_OK)
return (result);
ipp_initialize_request(svc, &request, type);
ipp_initialize_operational_attributes(svc, &op, name, -1);
switch (type) {
case OPID_DISABLE_PRINTER:
papiAttributeListAddString(&op, PAPI_ATTR_REPLACE,
"printer-message-from-operator", message);
break;
case OPID_PAUSE_PRINTER:
papiAttributeListAddString(&op, PAPI_ATTR_REPLACE,
"printer-state-message", message);
break;
default: /* a message value is of no use */
break;
}
papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
"operational-attributes-group", op);
papiAttributeListFree(op);
result = ipp_send_request(svc, request, &response);
papiAttributeListFree(request);
papiAttributeListFree(response);
return (result);
}
papi_status_t
papiPrinterEnable(papi_service_t handle, char *name)
{
return (_printer_enable_disable_pause_resume_delete(handle, name,
NULL, OPID_ENABLE_PRINTER));
}
papi_status_t
papiPrinterResume(papi_service_t handle, char *name)
{
return (_printer_enable_disable_pause_resume_delete(handle, name,
NULL, OPID_RESUME_PRINTER));
}
papi_status_t
papiPrinterPause(papi_service_t handle, char *name, char *message)
{
return (_printer_enable_disable_pause_resume_delete(handle, name,
message, OPID_PAUSE_PRINTER));
}
papi_status_t
papiPrinterDisable(papi_service_t handle, char *name, char *message)
{
return (_printer_enable_disable_pause_resume_delete(handle, name,
message, OPID_PAUSE_PRINTER));
}
/*
* there is no IPP create operation, the set-printer-attibutes operation
* is the closest we have, so we will assume that the server will create
* a printer and set attributes if there is none.
*/
papi_status_t
papiPrinterAdd(papi_service_t handle, char *name,
papi_attribute_t **attributes, papi_printer_t *printer)
{
return (papiPrinterModify(handle, name, attributes, printer));
}
papi_status_t
papiPrinterModify(papi_service_t handle, char *name,
papi_attribute_t **attributes, papi_printer_t *printer)
{
papi_status_t result = PAPI_INTERNAL_ERROR;
service_t *svc = handle;
printer_t *p = NULL;
papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
if ((svc == NULL) || (name == NULL) || (printer == NULL))
return (PAPI_BAD_ARGUMENT);
/* if we are already connected, use that connection. */
if (svc->connection == NULL)
if ((result = service_connect(svc, name)) != PAPI_OK)
return (result);
if ((*printer = p = calloc(1, sizeof (*p))) == NULL)
return (PAPI_TEMPORARY_ERROR);
ipp_initialize_request(svc, &request, OPID_SET_PRINTER_ATTRIBUTES);
ipp_initialize_operational_attributes(svc, &op, name, -1);
papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
"operational-attributes-group", op);
papiAttributeListFree(op);
papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
"printer-attributes-group", attributes);
result = ipp_send_request(svc, request, &response);
papiAttributeListFree(request);
op = NULL;
papiAttributeListGetCollection(response, NULL,
"printer-attributes-group", &op);
copy_attributes(&p->attributes, op);
papiAttributeListFree(response);
return (result);
}
papi_status_t
papiPrinterRemove(papi_service_t handle, char *name)
{
return (_printer_enable_disable_pause_resume_delete(handle, name,
NULL, OPID_CUPS_DELETE_PRINTER));
}
papi_status_t
papiPrinterPurgeJobs(papi_service_t handle, char *name,
papi_job_t **jobs)
{
papi_status_t status, result = PAPI_INTERNAL_ERROR;
service_t *svc = handle;
papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
void *iter = NULL;
if ((svc == NULL) || (name == NULL))
return (PAPI_BAD_ARGUMENT);
/* if we are already connected, use that connection. */
if (svc->connection == NULL)
if ((result = service_connect(svc, name)) != PAPI_OK)
return (result);
ipp_initialize_request(svc, &request, OPID_PURGE_JOBS);
ipp_initialize_operational_attributes(svc, &op, name, -1);
papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
"operational-attributes-group", op);
papiAttributeListFree(op);
result = ipp_send_request(svc, request, &response);
papiAttributeListFree(request);
op = NULL;
for (status = papiAttributeListGetCollection(response, &iter,
"job-attributes-group", &op);
status == PAPI_OK;
status = papiAttributeListGetCollection(response, &iter,
NULL, &op)) {
job_t *j = NULL;
if ((j = calloc(1, sizeof (*j))) == NULL)
return (PAPI_TEMPORARY_ERROR);
copy_attributes(&j->attributes, op);
op = NULL;
list_append(jobs, j);
}
papiAttributeListFree(response);
return (result);
}
papi_status_t
papiPrinterListJobs(papi_service_t handle, char *name,
char **requested_attrs, int type_mask,
int max_num_jobs, papi_job_t **jobs)
{
papi_status_t status, result = PAPI_INTERNAL_ERROR;
service_t *svc = handle;
papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
void *iter = NULL;
if ((svc == NULL) || (name == NULL))
return (PAPI_BAD_ARGUMENT);
/* if we are already connected, use that connection. */
if (svc->connection == NULL)
if ((result = service_connect(svc, name)) != PAPI_OK)
return (result);
ipp_initialize_request(svc, &request, OPID_GET_JOBS);
ipp_initialize_operational_attributes(svc, &op, name, -1);
if (requested_attrs != NULL) {
int i;
for (i = 0; requested_attrs[i] != NULL; i++)
papiAttributeListAddString(&op, PAPI_ATTR_APPEND,
"requested-attributes", requested_attrs[i]);
}
papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
"operational-attributes-group", op);
papiAttributeListFree(op);
result = ipp_send_request(svc, request, &response);
papiAttributeListFree(request);
op = NULL;
for (status = papiAttributeListGetCollection(response, &iter,
"job-attributes-group", &op);
status == PAPI_OK;
status = papiAttributeListGetCollection(response, &iter,
NULL, &op)) {
job_t *j = NULL;
if ((j = calloc(1, sizeof (*j))) == NULL)
return (PAPI_TEMPORARY_ERROR);
copy_attributes(&j->attributes, op);
op = NULL;
list_append(jobs, j);
}
papiAttributeListFree(response);
return (result);
}
papi_attribute_t **
papiPrinterGetAttributeList(papi_printer_t printer)
{
papi_attribute_t **result = NULL;
printer_t *p = printer;
if (p != NULL)
result = p->attributes;
return (result);
}