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