xref: /illumos-gate/usr/src/cmd/lp/lib/papi/printer.c (revision 3db86aab)
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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*LINTLIBRARY*/
29 
30 #include <stdlib.h>
31 #include <string.h>
32 #include <libintl.h>
33 #include <papi_impl.h>
34 #include <lp.h>
35 
36 extern int isclass(char *);
37 
38 void
39 papiPrinterFree(papi_printer_t printer)
40 {
41 	printer_t *tmp = printer;
42 
43 	if (tmp != NULL) {
44 		papiAttributeListFree(tmp->attributes);
45 		free(tmp);
46 	}
47 }
48 
49 void
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 papi_status_t
62 papiPrintersList(papi_service_t handle, char **requested_attrs,
63 		papi_filter_t *filter, papi_printer_t **printers)
64 {
65 	service_t *svc = handle;
66 	printer_t *p = NULL;
67 	short status = MOK;
68 	char *printer = NULL,
69 		*form = NULL,
70 		*request_id = NULL,
71 		*character_set = NULL,
72 		*reject_reason = NULL,
73 		*disable_reason = NULL;
74 	short printer_status = 0;
75 	long enable_date = 0, reject_date = 0;
76 
77 	if ((handle == NULL) || (printers == NULL))
78 		return (PAPI_BAD_ARGUMENT);
79 
80 	if ((filter == NULL) ||
81 	    ((filter->filter.bitmask.mask & PAPI_PRINTER_LOCAL) ==
82 	    (filter->filter.bitmask.value & PAPI_PRINTER_LOCAL))) {
83 		/* ask the spooler for the printer(s) and state */
84 		if (snd_msg(svc, S_INQUIRE_PRINTER_STATUS, NAME_ALL) < 0)
85 			return (PAPI_SERVICE_UNAVAILABLE);
86 
87 		do {
88 			if (rcv_msg(svc, R_INQUIRE_PRINTER_STATUS, &status,
89 					&printer, &form, &character_set,
90 					&disable_reason, &reject_reason,
91 					&printer_status, &request_id,
92 					&enable_date, &reject_date) < 0)
93 				return (PAPI_SERVICE_UNAVAILABLE);
94 
95 			if ((p = calloc(1, sizeof (*p))) == NULL)
96 				return (PAPI_TEMPORARY_ERROR);
97 
98 			lpsched_printer_configuration_to_attributes(svc, p,
99 					printer);
100 
101 			printer_status_to_attributes(p, printer, form,
102 					character_set, disable_reason,
103 					reject_reason, printer_status,
104 					request_id, enable_date, reject_date);
105 
106 			list_append(printers, p);
107 
108 		} while (status == MOKMORE);
109 	}
110 
111 	if ((filter == NULL) ||
112 	    ((filter->filter.bitmask.mask & PAPI_PRINTER_CLASS) ==
113 	    (filter->filter.bitmask.value & PAPI_PRINTER_CLASS))) {
114 		/* ask the spooler for the class(es) and state */
115 		if (snd_msg(svc, S_INQUIRE_CLASS, NAME_ALL) < 0)
116 			return (PAPI_SERVICE_UNAVAILABLE);
117 
118 		do {
119 			if (rcv_msg(svc, R_INQUIRE_CLASS, &status, &printer,
120 					&printer_status, &reject_reason,
121 					&reject_date) < 0)
122 				return (PAPI_SERVICE_UNAVAILABLE);
123 
124 			if ((p = calloc(1, sizeof (*p))) == NULL)
125 				return (PAPI_TEMPORARY_ERROR);
126 
127 			lpsched_class_configuration_to_attributes(svc, p,
128 					printer);
129 
130 			class_status_to_attributes(p, printer, printer_status,
131 					reject_reason, reject_date);
132 
133 			list_append(printers, p);
134 
135 		} while (status == MOKMORE);
136 	}
137 
138 	return (PAPI_OK);
139 }
140 
141 papi_status_t
142 papiPrinterQuery(papi_service_t handle, char *name,
143 		char **requested_attrs,
144 		papi_attribute_t **job_attrs,
145 		papi_printer_t *printer)
146 {
147 	papi_status_t pst;
148 	service_t *svc = handle;
149 	printer_t *p = NULL;
150 	char *dest;
151 	short status = MOK;
152 	char *pname = NULL,
153 		*form = NULL,
154 		*request_id = NULL,
155 		*character_set = NULL,
156 		*reject_reason = NULL,
157 		*disable_reason = NULL;
158 	short printer_status = 0;
159 	long enable_date = 0, reject_date = 0;
160 
161 	if ((handle == NULL) || (name == NULL) || (printer == NULL))
162 		return (PAPI_BAD_ARGUMENT);
163 
164 	if ((*printer = p = calloc(1, sizeof (*p))) == NULL)
165 		return (PAPI_TEMPORARY_ERROR);
166 
167 	dest = printer_name_from_uri_id(name, -1);
168 
169 	if (strcmp(dest, "_default") == 0) {
170 		static char *_default;
171 
172 		if (_default == NULL) {
173 			int fd;
174 			static char buf[128];
175 
176 			if ((fd = open("/etc/lp/default", O_RDONLY)) >= 0) {
177 				read(fd, buf, sizeof (buf));
178 				close(fd);
179 				_default = strtok(buf, " \t\n");
180 			}
181 		}
182 		dest = _default;
183 	}
184 
185 	if (isprinter(dest) != 0) {
186 		pst = lpsched_printer_configuration_to_attributes(svc, p, dest);
187 		if (pst != PAPI_OK)
188 			return (pst);
189 
190 		/* get the spooler status data now */
191 		if (snd_msg(svc, S_INQUIRE_PRINTER_STATUS, dest) < 0)
192 			return (PAPI_SERVICE_UNAVAILABLE);
193 
194 		if (rcv_msg(svc, R_INQUIRE_PRINTER_STATUS, &status, &pname,
195 				&form, &character_set, &disable_reason,
196 				&reject_reason, &printer_status, &request_id,
197 				&enable_date, &reject_date) < 0)
198 			return (PAPI_SERVICE_UNAVAILABLE);
199 
200 		printer_status_to_attributes(p, pname, form, character_set,
201 				disable_reason, reject_reason, printer_status,
202 				request_id, enable_date, reject_date);
203 	} else if (isclass(dest) != 0) {
204 		pst = lpsched_class_configuration_to_attributes(svc, p, dest);
205 		if (pst != PAPI_OK)
206 			return (pst);
207 
208 		/* get the spooler status data now */
209 		if (snd_msg(svc, S_INQUIRE_CLASS, dest) < 0)
210 			return (PAPI_SERVICE_UNAVAILABLE);
211 
212 		if (rcv_msg(svc, R_INQUIRE_CLASS, &status, &pname,
213 				&printer_status, &reject_reason,
214 				&reject_date) < 0)
215 			return (PAPI_SERVICE_UNAVAILABLE);
216 
217 		class_status_to_attributes(p, pname, printer_status,
218 				reject_reason, reject_date);
219 	} else if (strcmp(dest, "PrintService") == 0) {
220 		/* fill the printer object with service information */
221 		lpsched_service_information(&p->attributes);
222 	} else
223 		return (PAPI_NOT_FOUND);
224 
225 	free(dest);
226 
227 	return (PAPI_OK);
228 }
229 
230 papi_status_t
231 papiPrinterAdd(papi_service_t handle, char *name,
232 		papi_attribute_t **attributes, papi_printer_t *result)
233 {
234 	papi_status_t status;
235 	printer_t *p = NULL;
236 	char *dest;
237 
238 	if ((handle == NULL) || (name == NULL) || (attributes == NULL))
239 		return (PAPI_BAD_ARGUMENT);
240 
241 	dest = printer_name_from_uri_id(name, -1);
242 
243 	if (isprinter(dest) != 0) {
244 		status = lpsched_add_modify_printer(handle, dest,
245 							attributes, 0);
246 
247 		if ((*result = p = calloc(1, sizeof (*p))) != NULL)
248 			lpsched_printer_configuration_to_attributes(handle, p,
249 									dest);
250 		else
251 			status = PAPI_TEMPORARY_ERROR;
252 
253 	} else if (isclass(dest) != 0) {
254 		status = lpsched_add_modify_class(handle, dest, attributes);
255 
256 		if ((*result = p = calloc(1, sizeof (*p))) != NULL)
257 			lpsched_class_configuration_to_attributes(handle, p,
258 									dest);
259 		else
260 			status = PAPI_TEMPORARY_ERROR;
261 
262 	} else
263 		status = PAPI_NOT_FOUND;
264 
265 	free(dest);
266 
267 	return (status);
268 }
269 
270 papi_status_t
271 papiPrinterModify(papi_service_t handle, char *name,
272 		papi_attribute_t **attributes, papi_printer_t *result)
273 {
274 	papi_status_t status;
275 	printer_t *p = NULL;
276 	char *dest;
277 
278 	if ((handle == NULL) || (name == NULL) || (attributes == NULL))
279 		return (PAPI_BAD_ARGUMENT);
280 
281 	dest = printer_name_from_uri_id(name, -1);
282 
283 	if (isprinter(dest) != 0) {
284 		status = lpsched_add_modify_printer(handle, dest,
285 							attributes, 1);
286 
287 		if ((*result = p = calloc(1, sizeof (*p))) != NULL)
288 			lpsched_printer_configuration_to_attributes(handle, p,
289 									dest);
290 		else
291 			status = PAPI_TEMPORARY_ERROR;
292 	} else if (isclass(dest) != 0) {
293 		status = lpsched_add_modify_class(handle, dest, attributes);
294 
295 		if ((*result = p = calloc(1, sizeof (*p))) != NULL)
296 			lpsched_class_configuration_to_attributes(handle, p,
297 									dest);
298 		else
299 			status = PAPI_TEMPORARY_ERROR;
300 	} else
301 		status = PAPI_NOT_FOUND;
302 
303 	free(dest);
304 
305 	return (status);
306 }
307 
308 papi_status_t
309 papiPrinterRemove(papi_service_t handle, char *name)
310 {
311 	papi_status_t result;
312 	char *dest;
313 
314 	if ((handle == NULL) || (name == NULL))
315 		return (PAPI_BAD_ARGUMENT);
316 
317 	dest = printer_name_from_uri_id(name, -1);
318 
319 	if (isprinter(dest) != 0) {
320 		result = lpsched_remove_printer(handle, dest);
321 	} else if (isclass(dest) != 0) {
322 		result = lpsched_remove_class(handle, dest);
323 	} else
324 		result = PAPI_NOT_FOUND;
325 
326 	free(dest);
327 
328 	return (result);
329 }
330 
331 papi_status_t
332 papiPrinterDisable(papi_service_t handle, char *name, char *message)
333 {
334 	papi_status_t result;
335 
336 	if ((handle == NULL) || (name == NULL))
337 		return (PAPI_BAD_ARGUMENT);
338 
339 	result = lpsched_disable_printer(handle, name, message);
340 
341 	return (result);
342 }
343 
344 papi_status_t
345 papiPrinterEnable(papi_service_t handle, char *name)
346 {
347 	papi_status_t result;
348 
349 	if ((handle == NULL) || (name == NULL))
350 		return (PAPI_BAD_ARGUMENT);
351 
352 	result = lpsched_enable_printer(handle, name);
353 
354 	return (result);
355 }
356 
357 papi_status_t
358 papiPrinterPause(papi_service_t handle, char *name, char *message)
359 {
360 	papi_status_t result;
361 
362 	if ((handle == NULL) || (name == NULL))
363 		return (PAPI_BAD_ARGUMENT);
364 
365 	result = lpsched_reject_printer(handle, name, message);
366 
367 	return (result);
368 }
369 
370 papi_status_t
371 papiPrinterResume(papi_service_t handle, char *name)
372 {
373 	papi_status_t result;
374 
375 	if ((handle == NULL) || (name == NULL))
376 		return (PAPI_BAD_ARGUMENT);
377 
378 	result = lpsched_accept_printer(handle, name);
379 
380 	return (result);
381 }
382 
383 papi_status_t
384 papiPrinterPurgeJobs(papi_service_t handle, char *name, papi_job_t **jobs)
385 {
386 	service_t *svc = handle;
387 	papi_status_t result = PAPI_OK_SUBST;
388 	short more;
389 	long status;
390 	char *dest;
391 	char *req_id;
392 
393 	if ((handle == NULL) || (name == NULL))
394 		return (PAPI_BAD_ARGUMENT);
395 
396 	dest = printer_name_from_uri_id(name, -1);
397 	more = snd_msg(svc, S_CANCEL, dest, "", "");
398 	free(dest);
399 	if (more < 0)
400 		return (PAPI_SERVICE_UNAVAILABLE);
401 
402 	do {
403 		if (rcv_msg(svc, R_CANCEL, &more, &status, &req_id) < 0)
404 			return (PAPI_SERVICE_UNAVAILABLE);
405 
406 	switch (status) {
407 	case MOK:
408 		papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND,
409 				"canceled-jobs", req_id);
410 		break;
411 	case M2LATE:
412 	case MUNKNOWN:
413 	case MNOINFO:
414 		papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND,
415 				"cancel-failed", req_id);
416 		result = PAPI_DEVICE_ERROR;
417 		break;
418 	case MNOPERM:
419 		papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND,
420 				"cancel-failed", req_id);
421 		result = PAPI_NOT_AUTHORIZED;
422 		break;
423 	default:
424 		detailed_error(svc, gettext("cancel failed, bad status (%d)\n"),
425 			status);
426 		return (PAPI_DEVICE_ERROR);
427 	}
428 	} while (more == MOKMORE);
429 
430 	return (result);
431 }
432 
433 papi_status_t
434 papiPrinterListJobs(papi_service_t handle, char *name,
435 		char **requested_attrs, int type_mask,
436 		int max_num_jobs, papi_job_t **jobs)
437 {
438 	service_t *svc = handle;
439 	char *dest;
440 	short rc;
441 	int count = 1;
442 
443 	if ((handle == NULL) || (name == NULL) || (jobs == NULL))
444 		return (PAPI_BAD_ARGUMENT);
445 
446 	dest = printer_name_from_uri_id(name, -1);
447 
448 	rc = snd_msg(svc, S_INQUIRE_REQUEST_RANK, 0, "", dest, "", "", "");
449 	free(dest);
450 	if (rc < 0)
451 		return (PAPI_SERVICE_UNAVAILABLE);
452 
453 	do {
454 		job_t *job = NULL;
455 		char *dest = NULL,
456 			*ptr,
457 			*form = NULL,
458 			*req_id = NULL,
459 			*charset = NULL,
460 			*owner = NULL,
461 			*slabel = NULL,
462 			*file = NULL;
463 		time_t date = 0;
464 		size_t size = 0;
465 		short  rank = 0, state = 0;
466 
467 		if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &req_id,
468 				&owner, &slabel, &size, &date, &state, &dest,
469 				&form, &charset, &rank, &file) < 0)
470 			return (PAPI_SERVICE_UNAVAILABLE);
471 
472 		if ((rc != MOK) && (rc != MOKMORE))
473 			continue;
474 		/*
475 		 * at this point, we should check to see if the job matches the
476 		 * selection criterion defined in "type_mask".
477 		 */
478 
479 		/* too many yet? */
480 		if ((max_num_jobs != 0) && (count++ > max_num_jobs))
481 			continue;
482 
483 		if ((job = calloc(1, sizeof (*job))) == NULL)
484 			continue;
485 
486 		job_status_to_attributes(job, req_id, owner, slabel, size,
487 				date, state, dest, form, charset, rank, file);
488 
489 		if ((ptr = strrchr(file, '-')) != NULL) {
490 			*++ptr = '0';
491 			*++ptr = NULL;
492 		}
493 
494 		lpsched_read_job_configuration(svc, job, file);
495 
496 		list_append(jobs, job);
497 
498 	} while (rc == MOKMORE);
499 
500 	if (rc == MNOINFO)	/* If no jobs are found, it's still ok */
501 		rc = MOK;
502 
503 	return (lpsched_status_to_papi_status(rc));
504 }
505 
506 papi_attribute_t **
507 papiPrinterGetAttributeList(papi_printer_t printer)
508 {
509 	printer_t *tmp = printer;
510 
511 	if (tmp == NULL)
512 		return (NULL);
513 
514 	return (tmp->attributes);
515 }
516