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