xref: /illumos-gate/usr/src/lib/print/libpapi-ipp/common/printer.c (revision 60a3f738d56f92ae8b80e4b62a2331c6e1f2311f)
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: printer.c 146 2006-03-24 00:26:54Z njacobs $ */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*LINTLIBRARY*/
33 
34 #include <stdlib.h>
35 #include <papi_impl.h>
36 
37 #include <config-site.h>
38 
39 void
40 papiPrinterFree(papi_printer_t printer)
41 {
42 	printer_t *tmp = printer;
43 
44 	if (tmp != NULL) {
45 		if (tmp->attributes != NULL)
46 			papiAttributeListFree(tmp->attributes);
47 		free(tmp);
48 	}
49 }
50 
51 void
52 papiPrinterListFree(papi_printer_t *printers)
53 {
54 	if (printers != NULL) {
55 		int i;
56 
57 		for (i = 0; printers[i] != NULL; i++)
58 			papiPrinterFree(printers[i]);
59 		free(printers);
60 	}
61 }
62 
63 /*
64  * Enumeration of printers is not part of the IPP specification, so many
65  * servers will probably not respond back with a list of printers, but
66  * CUPS has implemented an extension to IPP to enumerate printers and
67  * classes. the Apache/mod_ipp IPP listener module available in Solaris
68  * implements this IPP extension, so CUPS and Solaris can provide this
69  * to IPP clients.
70  */
71 #ifndef	OPID_CUPS_GET_PRINTERS		/* for servers that will enumerate */
72 #define	OPID_CUPS_GET_PRINTERS		0x4002
73 #endif	/* OPID_CUPS_GET_PRINTERS */
74 #ifndef	OPID_CUPS_DELETE_PRINTER	/* for servers that can delete */
75 #define	OPID_CUPS_DELETE_PRINTER	0x4004
76 #endif	/* OPID_CUPS_DELETE_PRINTER */
77 #ifndef	OPID_CUPS_GET_CLASSES		/* for servers that will enumerate */
78 #define	OPID_CUPS_GET_CLASSES		0x4005
79 #endif	/* OPID_CUPS_GET_CLASSES */
80 
81 papi_status_t
82 papiPrintersList(papi_service_t handle, char **requested_attrs,
83 		papi_filter_t *filter, papi_printer_t **printers)
84 {
85 	papi_status_t status, result = PAPI_INTERNAL_ERROR;
86 	service_t *svc = handle;
87 	papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
88 	void *iter = NULL;
89 
90 	if ((svc == NULL) || (printers == NULL))
91 		return (PAPI_BAD_ARGUMENT);
92 
93 	/* if we are already connected, use that connection. */
94 	if (svc->connection == NULL)
95 		if ((result = service_connect(svc, DEFAULT_DEST)) != PAPI_OK)
96 			return (result);
97 	ipp_initialize_request(svc, &request, OPID_CUPS_GET_PRINTERS);
98 
99 	ipp_initialize_operational_attributes(svc, &op, NULL);
100 
101 	if (requested_attrs != NULL) {
102 		int i;
103 
104 		for (i = 0; requested_attrs[i] != NULL; i++)
105 			papiAttributeListAddString(&op, PAPI_ATTR_APPEND,
106 				"requested-attributes", requested_attrs[i]);
107 	}
108 
109 	papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
110 			"operational-attributes-group", op);
111 	papiAttributeListFree(op);
112 	result = ipp_send_request(svc, request, &response);
113 	papiAttributeListFree(request);
114 
115 	op = NULL;
116 	for (status = papiAttributeListGetCollection(response, &iter,
117 				"printer-attributes-group", &op);
118 	     status == PAPI_OK;
119 	     status = papiAttributeListGetCollection(response, &iter,
120 				NULL, &op)) {
121 		printer_t *p = NULL;
122 
123 		if ((p = calloc(1, sizeof (*p))) == NULL)
124 			return (PAPI_TEMPORARY_ERROR);
125 
126 		copy_attributes(&p->attributes, op);
127 		op = NULL;
128 		list_append(printers, p);
129 	}
130 	papiAttributeListFree(response);
131 
132 	return (result);
133 }
134 
135 papi_status_t
136 papiPrinterQuery(papi_service_t handle, char *name,
137 		char **requested_attrs,
138 		papi_attribute_t **job_attributes,
139 		papi_printer_t *printer)
140 {
141 	papi_status_t result = PAPI_INTERNAL_ERROR;
142 	service_t *svc = handle;
143 	printer_t *p = NULL;
144 	papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
145 
146 	if ((svc == NULL) || (name == NULL) || (printer == NULL))
147 		return (PAPI_BAD_ARGUMENT);
148 
149 	/* if we are already connected, use that connection. */
150 	if (svc->connection == NULL)
151 		if ((result = service_connect(svc, name)) != PAPI_OK)
152 			return (result);
153 
154 	if ((*printer = p = calloc(1, sizeof (*p))) == NULL)
155 		return (PAPI_TEMPORARY_ERROR);
156 
157 	ipp_initialize_request(svc, &request, OPID_GET_PRINTER_ATTRIBUTES);
158 
159 	ipp_initialize_operational_attributes(svc, &op, NULL);
160 	ipp_add_printer_uri(svc, name, &op);
161 
162 	if (requested_attrs != NULL) {
163 		int i;
164 
165 		for (i = 0; requested_attrs[i] != NULL; i++)
166 			papiAttributeListAddString(&op, PAPI_ATTR_APPEND,
167 				"requested-attributes", requested_attrs[i]);
168 	}
169 
170 	papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
171 			"operational-attributes-group", op);
172 	papiAttributeListFree(op);
173 	result = ipp_send_request(svc, request, &response);
174 	papiAttributeListFree(request);
175 
176 	op = NULL;
177 	papiAttributeListGetCollection(response, NULL,
178 			"printer-attributes-group", &op);
179 	copy_attributes(&p->attributes, op);
180 	papiAttributeListFree(response);
181 
182 	return (result);
183 }
184 
185 static papi_status_t
186 _printer_enable_disable_pause_resume_delete(papi_service_t handle, char *name,
187 		char *message, uint16_t type)
188 {
189 	papi_status_t result = PAPI_INTERNAL_ERROR;
190 	service_t *svc = handle;
191 	papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
192 
193 	if ((svc == NULL) || (name == NULL))
194 		return (PAPI_BAD_ARGUMENT);
195 
196 	/* if we are already connected, use that connection. */
197 	if (svc->connection == NULL)
198 		if ((result = service_connect(svc, name)) != PAPI_OK)
199 			return (result);
200 
201 	ipp_initialize_request(svc, &request, type);
202 
203 	ipp_initialize_operational_attributes(svc, &op, NULL);
204 	ipp_add_printer_uri(svc, name, &op);
205 
206 	switch (type) {
207 	case OPID_DISABLE_PRINTER:
208 		papiAttributeListAddString(&op, PAPI_ATTR_REPLACE,
209 				"printer-message-from-operator", message);
210 		break;
211 	case OPID_PAUSE_PRINTER:
212 		papiAttributeListAddString(&op, PAPI_ATTR_REPLACE,
213 				"printer-state-message", message);
214 		break;
215 	default: /* a message value is of no use */
216 		break;
217 	}
218 
219 	papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
220 			"operational-attributes-group", op);
221 	papiAttributeListFree(op);
222 	result = ipp_send_request(svc, request, &response);
223 	papiAttributeListFree(request);
224 	papiAttributeListFree(response);
225 
226 	return (result);
227 }
228 
229 papi_status_t
230 papiPrinterEnable(papi_service_t handle, char *name)
231 {
232 	return (_printer_enable_disable_pause_resume_delete(handle, name,
233 				NULL, OPID_ENABLE_PRINTER));
234 }
235 
236 papi_status_t
237 papiPrinterResume(papi_service_t handle, char *name)
238 {
239 	return (_printer_enable_disable_pause_resume_delete(handle, name,
240 				NULL, OPID_RESUME_PRINTER));
241 }
242 
243 papi_status_t
244 papiPrinterPause(papi_service_t handle, char *name, char *message)
245 {
246 	return (_printer_enable_disable_pause_resume_delete(handle, name,
247 				message, OPID_PAUSE_PRINTER));
248 }
249 
250 papi_status_t
251 papiPrinterDisable(papi_service_t handle, char *name, char *message)
252 {
253 	return (_printer_enable_disable_pause_resume_delete(handle, name,
254 				message, OPID_PAUSE_PRINTER));
255 }
256 
257 /*
258  * there is no IPP create operation, the set-printer-attibutes operation
259  * is the closest we have, so we will assume that the server will create
260  * a printer and set attributes if there is none.
261  */
262 papi_status_t
263 papiPrinterAdd(papi_service_t handle, char *name,
264 		papi_attribute_t **attributes, papi_printer_t *printer)
265 {
266 	return (papiPrinterModify(handle, name, attributes, printer));
267 }
268 
269 papi_status_t
270 papiPrinterModify(papi_service_t handle, char *name,
271 		papi_attribute_t **attributes, papi_printer_t *printer)
272 {
273 	papi_status_t result = PAPI_INTERNAL_ERROR;
274 	service_t *svc = handle;
275 	printer_t *p = NULL;
276 	papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
277 
278 	if ((svc == NULL) || (name == NULL) || (printer == NULL))
279 		return (PAPI_BAD_ARGUMENT);
280 
281 	/* if we are already connected, use that connection. */
282 	if (svc->connection == NULL)
283 		if ((result = service_connect(svc, name)) != PAPI_OK)
284 			return (result);
285 
286 	if ((*printer = p = calloc(1, sizeof (*p))) == NULL)
287 		return (PAPI_TEMPORARY_ERROR);
288 
289 	ipp_initialize_request(svc, &request, OPID_SET_PRINTER_ATTRIBUTES);
290 
291 	ipp_initialize_operational_attributes(svc, &op, NULL);
292 	ipp_add_printer_uri(svc, name, &op);
293 
294 	papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
295 			"operational-attributes-group", op);
296 	papiAttributeListFree(op);
297 
298 	papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
299 			"printer-attributes-group", attributes);
300 	result = ipp_send_request(svc, request, &response);
301 	papiAttributeListFree(request);
302 
303 	op = NULL;
304 	papiAttributeListGetCollection(response, NULL,
305 			"printer-attributes-group", &op);
306 	copy_attributes(&p->attributes, op);
307 	papiAttributeListFree(response);
308 
309 	return (result);
310 }
311 
312 papi_status_t
313 papiPrinterRemove(papi_service_t handle, char *name)
314 {
315 	return (_printer_enable_disable_pause_resume_delete(handle, name,
316 				NULL, OPID_CUPS_DELETE_PRINTER));
317 }
318 
319 papi_status_t
320 papiPrinterPurgeJobs(papi_service_t handle, char *name,
321 		papi_job_t **jobs)
322 {
323 	papi_status_t status, result = PAPI_INTERNAL_ERROR;
324 	service_t *svc = handle;
325 	papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
326 	void *iter = NULL;
327 
328 
329 	if ((svc == NULL) || (name == NULL))
330 		return (PAPI_BAD_ARGUMENT);
331 
332 	/* if we are already connected, use that connection. */
333 	if (svc->connection == NULL)
334 		if ((result = service_connect(svc, name)) != PAPI_OK)
335 			return (result);
336 
337 	ipp_initialize_request(svc, &request, OPID_PURGE_JOBS);
338 
339 	ipp_initialize_operational_attributes(svc, &op, NULL);
340 	ipp_add_printer_uri(svc, name, &op);
341 
342 	papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
343 			"operational-attributes-group", op);
344 	papiAttributeListFree(op);
345 	result = ipp_send_request(svc, request, &response);
346 	papiAttributeListFree(request);
347 
348 	op = NULL;
349 	for (status = papiAttributeListGetCollection(response, &iter,
350 				"job-attributes-group", &op);
351 	     status == PAPI_OK;
352 	     status = papiAttributeListGetCollection(response, &iter,
353 				NULL, &op)) {
354 		job_t *j = NULL;
355 
356 		if ((j = calloc(1, sizeof (*j))) == NULL)
357 			return (PAPI_TEMPORARY_ERROR);
358 
359 		copy_attributes(&j->attributes, op);
360 		op = NULL;
361 		list_append(jobs, j);
362 	}
363 	papiAttributeListFree(response);
364 
365 	return (result);
366 }
367 
368 papi_status_t
369 papiPrinterListJobs(papi_service_t handle, char *name,
370 		char **requested_attrs, int type_mask,
371 		int max_num_jobs, papi_job_t **jobs)
372 {
373 	papi_status_t status, result = PAPI_INTERNAL_ERROR;
374 	service_t *svc = handle;
375 	papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
376 	void *iter = NULL;
377 
378 	if ((svc == NULL) || (name == NULL))
379 		return (PAPI_BAD_ARGUMENT);
380 
381 	/* if we are already connected, use that connection. */
382 	if (svc->connection == NULL)
383 		if ((result = service_connect(svc, name)) != PAPI_OK)
384 			return (result);
385 
386 	ipp_initialize_request(svc, &request, OPID_GET_JOBS);
387 
388 	ipp_initialize_operational_attributes(svc, &op, NULL);
389 	ipp_add_printer_uri(svc, name, &op);
390 
391 	if (requested_attrs != NULL) {
392 		int i;
393 
394 		for (i = 0; requested_attrs[i] != NULL; i++)
395 			papiAttributeListAddString(&op, PAPI_ATTR_APPEND,
396 				"requested-attributes", requested_attrs[i]);
397 	}
398 
399 	papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
400 			"operational-attributes-group", op);
401 	papiAttributeListFree(op);
402 	result = ipp_send_request(svc, request, &response);
403 	papiAttributeListFree(request);
404 
405 	op = NULL;
406 	for (status = papiAttributeListGetCollection(response, &iter,
407 				"job-attributes-group", &op);
408 	     status == PAPI_OK;
409 	     status = papiAttributeListGetCollection(response, &iter,
410 				NULL, &op)) {
411 		job_t *j = NULL;
412 
413 		if ((j = calloc(1, sizeof (*j))) == NULL)
414 			return (PAPI_TEMPORARY_ERROR);
415 
416 		copy_attributes(&j->attributes, op);
417 		op = NULL;
418 		list_append(jobs, j);
419 	}
420 	papiAttributeListFree(response);
421 
422 	return (result);
423 }
424 
425 papi_attribute_t **
426 papiPrinterGetAttributeList(papi_printer_t printer)
427 {
428 	papi_attribute_t **result = NULL;
429 	printer_t *p = printer;
430 
431 	if (p != NULL)
432 		result = p->attributes;
433 
434 	return (result);
435 }
436