xref: /illumos-gate/usr/src/cmd/lp/lib/papi/lpsched-msgs.c (revision f808c858fa61e7769218966759510a8b1190dfcf)
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 <stdio.h>
31 #include <stdarg.h>
32 #include <libintl.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <errno.h>
36 
37 
38 /* lpsched include files */
39 #include "lp.h"
40 #include "msgs.h"
41 #include "printers.h"
42 #include "class.h"
43 
44 #include <papi_impl.h>
45 
46 
47 /*
48  * Format and send message to lpsched (die if any errors occur)
49  */
50 /*VARARGS1*/
51 int
52 snd_msg(service_t *svc, int type, ...)
53 {
54 	int rc = -1;
55 	va_list	ap;
56 
57 	if (svc == NULL)
58 		return (-1);
59 
60 	/* fill the message buffer */
61 	va_start(ap, type);
62 	rc = _putmessage(svc->msgbuf, type, ap);
63 	va_end(ap);
64 	if (rc < 0) {
65 		detailed_error(svc,
66 			gettext("unable to build message for scheduler: %s"),
67 				strerror(errno));
68 		return (rc);
69 	}
70 
71 	/* write the message */
72 	while (((rc = mwrite(svc->md, svc->msgbuf)) < 0) && (errno == EINTR));
73 
74 	if (rc < 0)
75 		detailed_error(svc,
76 			gettext("unable to send message to scheduler: %s"),
77 				strerror(errno));
78 	return (rc);
79 }
80 
81 /*
82  * Receive message from lpsched (die if any errors occur)
83  */
84 int
85 rcv_msg(service_t *svc, int type, ...)
86 {
87 	int rc = -1;
88 
89 	if (svc == NULL)
90 		return (-1);
91 
92 	/* read the message */
93 	while (((rc = mread(svc->md, svc->msgbuf, svc->msgbuf_size)) < 0) &&
94 		(errno == EINTR));
95 
96 	if (rc < 0)
97 		detailed_error(svc,
98 			gettext("unable to read message from scheduler: %s"),
99 				strerror(errno));
100 	else {
101 		va_list ap;
102 
103 		va_start(ap, type);
104 		rc = _getmessage(svc->msgbuf, type, ap);
105 		va_end(ap);
106 
107 		if (rc < 0)
108 			detailed_error(svc,
109 			gettext("unable to parse message from scheduler: %s"),
110 				strerror(errno));
111 	}
112 
113 	return (rc);
114 }
115 
116 papi_status_t
117 lpsched_status_to_papi_status(int status)
118 {
119 	switch (status) {
120 	case MNOMEM:
121 		return (PAPI_TEMPORARY_ERROR);
122 	case MNOFILTER:
123 		return (PAPI_DOCUMENT_FORMAT_ERROR);
124 	case MNOOPEN:
125 		return (PAPI_DOCUMENT_ACCESS_ERROR);
126 	case MERRDEST:
127 		return (PAPI_DEVICE_ERROR);
128 	case MDENYDEST:
129 		return (PAPI_NOT_ACCEPTING);
130 	case MNOMEDIA:
131 		return (PAPI_PRINT_SUPPORT_FILE_NOT_FOUND);
132 	case MDENYMEDIA:
133 	case MNOPERM:
134 		return (PAPI_NOT_AUTHORIZED);
135 	case MUNKNOWN:
136 	case MNODEST:
137 	case MNOINFO:
138 		return (PAPI_NOT_FOUND);
139 	case MTRANSMITERR:
140 		return (PAPI_SERVICE_UNAVAILABLE);
141 	case M2LATE:
142 		return (PAPI_GONE);
143 	case MBUSY:
144 		return (PAPI_PRINTER_BUSY);
145 	case MOK:
146 	case MOKMORE:
147 		return (PAPI_OK);
148 	}
149 
150 	return (PAPI_INTERNAL_ERROR);
151 }
152 
153 char *
154 lpsched_status_string(short status)
155 {
156 		switch (status) {
157 	case MNOMEM:
158 		return (gettext("lpsched: out of memory"));
159 	case MNOFILTER:
160 		return (gettext("No filter available to convert job"));
161 	case MNOOPEN:
162 		return (gettext("lpsched: could not open request"));
163 	case MERRDEST:
164 		return (gettext("An error occured in submission"));
165 	case MDENYDEST:
166 		return (gettext("destination denied request"));
167 	case MNOMEDIA:
168 		return (gettext("unknown form specified in job"));
169 	case MDENYMEDIA:
170 		return (gettext("access denied to form specified in job"));
171 	case MUNKNOWN:
172 		return (gettext("no such resource"));
173 	case MNODEST:
174 		return (gettext("unknown destination"));
175 	case MNOPERM:
176 		return (gettext("permission denied"));
177 	case MNOINFO:
178 		return (gettext("no information available"));
179 	case MTRANSMITERR:
180 		return (gettext("failure to communicate with lpsched"));
181 	default: {
182 		static char result[16];
183 
184 		snprintf(result, sizeof (result), gettext("status: %d"),
185 								status);
186 		return (result);
187 		}
188 	}
189 }
190 
191 papi_status_t
192 lpsched_alloc_files(papi_service_t svc, int number, char **prefix)
193 {
194 	papi_status_t result = PAPI_OK;
195 	short status = MOK;
196 
197 	if ((svc == NULL) || (prefix == NULL))
198 		return (PAPI_BAD_ARGUMENT);
199 
200 	if ((snd_msg(svc, S_ALLOC_FILES, number) < 0) ||
201 	    (rcv_msg(svc, R_ALLOC_FILES, &status, prefix) < 0))
202 		status = MTRANSMITERR;
203 
204 	if (status != MOK) {
205 		detailed_error(svc,
206 		gettext("failed to allocate %d file(s) for request: %s"),
207 			number, lpsched_status_string(status));
208 		result = lpsched_status_to_papi_status(status);
209 	}
210 
211 	return (result);
212 }
213 
214 papi_status_t
215 lpsched_commit_job(papi_service_t svc, char *job, char **tmp)
216 /* job is host/req-id */
217 {
218 	papi_status_t result = PAPI_OK;
219 	short status = MOK;
220 	long bits;
221 
222 	if ((svc == NULL) || (job == NULL) || (tmp == NULL))
223 		return (PAPI_BAD_ARGUMENT);
224 
225 	if ((snd_msg(svc, S_PRINT_REQUEST, job) < 0) ||
226 	    (rcv_msg(svc, R_PRINT_REQUEST, &status, tmp, &bits) < 0))
227 		status = MTRANSMITERR;
228 
229 	if (status != MOK) {
230 		detailed_error(svc, gettext("failed to commit job (%s): %s"),
231 			job, lpsched_status_string(status));
232 		result = lpsched_status_to_papi_status(status);
233 	}
234 
235 	return (result);
236 }
237 
238 papi_status_t
239 lpsched_start_change(papi_service_t svc, char *printer, int32_t job_id,
240 		char **tmp)
241 {
242 	papi_status_t result = PAPI_OK;
243 	short status = MOK;
244 	char req[BUFSIZ];
245 	char *dest;
246 
247 	if ((svc == NULL) || (printer == NULL) || (job_id < 0))
248 		return (PAPI_BAD_ARGUMENT);
249 
250 	dest = printer_name_from_uri_id(printer, job_id);
251 	snprintf(req, sizeof (req), "%s-%d", dest, job_id);
252 	free(dest);
253 
254 	if ((snd_msg(svc, S_START_CHANGE_REQUEST, req) < 0) ||
255 	    (rcv_msg(svc, R_START_CHANGE_REQUEST, &status, tmp) < 0))
256 		status = MTRANSMITERR;
257 
258 	if (status != MOK) {
259 		detailed_error(svc,
260 		gettext("failed to initiate change for job (%s-%d): %s"),
261 			printer,
262 			job_id, lpsched_status_string(status));
263 		result = lpsched_status_to_papi_status(status);
264 	}
265 
266 	return (result);
267 }
268 
269 papi_status_t
270 lpsched_end_change(papi_service_t svc, char *printer, int32_t job_id)
271 {
272 	papi_status_t result = PAPI_OK;
273 	short status = MOK;
274 	long bits;
275 	char req[BUFSIZ];
276 	char *dest;
277 
278 	if ((svc == NULL) || (printer == NULL) || (job_id < 0))
279 		return (PAPI_BAD_ARGUMENT);
280 
281 	dest = printer_name_from_uri_id(printer, job_id);
282 	snprintf(req, sizeof (req), "%s-%d", dest, job_id);
283 	free(dest);
284 
285 	if ((snd_msg(svc, S_END_CHANGE_REQUEST, req) < 0) ||
286 	    (rcv_msg(svc, R_END_CHANGE_REQUEST, &status, &bits) < 0))
287 		status = MTRANSMITERR;
288 
289 	if (status != MOK) {
290 		detailed_error(svc,
291 		gettext("failed to commit change for job (%s-%d): %s"), printer,
292 			job_id, lpsched_status_string(status));
293 		result = lpsched_status_to_papi_status(status);
294 	}
295 
296 	return (result);
297 }
298 
299 papi_status_t
300 lpsched_accept_printer(papi_service_t svc, char *printer)
301 {
302 	papi_status_t result = PAPI_OK;
303 	short	 status;
304 	char	*req_id;
305 	char *dest;
306 
307 	if ((svc == NULL) || (printer == NULL))
308 		return (PAPI_BAD_ARGUMENT);
309 
310 	dest = printer_name_from_uri_id(printer, -1);
311 	if ((snd_msg(svc, S_ACCEPT_DEST, dest) < 0) ||
312 	    (rcv_msg(svc, R_ACCEPT_DEST, &status, &req_id) < 0))
313 		status = MTRANSMITERR;
314 	free(dest);
315 
316 	if ((status != MOK) && (status != MERRDEST)) {
317 		detailed_error(svc, "%s: %s", printer,
318 			lpsched_status_string(status));
319 		result = lpsched_status_to_papi_status(status);
320 	}
321 
322 	return (result);
323 }
324 
325 papi_status_t
326 lpsched_reject_printer(papi_service_t svc, char *printer, char *message)
327 {
328 	papi_status_t result = PAPI_OK;
329 	short	 status;
330 	char	*req_id;
331 	char *dest;
332 
333 	if ((svc == NULL) || (printer == NULL))
334 		return (PAPI_BAD_ARGUMENT);
335 
336 	if (message == NULL)
337 		message = "stopped by user";
338 
339 	dest = printer_name_from_uri_id(printer, -1);
340 	if ((snd_msg(svc, S_REJECT_DEST, dest, message, 0) < 0) ||
341 	    (rcv_msg(svc, R_REJECT_DEST, &status, &req_id) < 0))
342 		status = MTRANSMITERR;
343 	free(dest);
344 
345 	if ((status != MOK) && (status != MERRDEST)) {
346 		detailed_error(svc, "%s: %s", printer,
347 			lpsched_status_string(status));
348 		result = lpsched_status_to_papi_status(status);
349 	}
350 
351 	return (result);
352 }
353 
354 papi_status_t
355 lpsched_enable_printer(papi_service_t svc, char *printer)
356 {
357 	papi_status_t result = PAPI_OK;
358 	short	 status;
359 	char	*req_id;
360 	char *dest;
361 
362 	if ((svc == NULL) || (printer == NULL))
363 		return (PAPI_BAD_ARGUMENT);
364 
365 	dest = printer_name_from_uri_id(printer, -1);
366 	if ((snd_msg(svc, S_ENABLE_DEST, dest) < 0) ||
367 	    (rcv_msg(svc, R_ENABLE_DEST, &status, &req_id) < 0))
368 		status = MTRANSMITERR;
369 	free(dest);
370 
371 	if ((status != MOK) && (status != MERRDEST)) {
372 		detailed_error(svc, "%s: %s", printer,
373 			lpsched_status_string(status));
374 		result = lpsched_status_to_papi_status(status);
375 	}
376 
377 	return (result);
378 }
379 
380 papi_status_t
381 lpsched_disable_printer(papi_service_t svc, char *printer, char *message)
382 {
383 	papi_status_t result = PAPI_OK;
384 	short	 status;
385 	char	*req_id;
386 	char *dest;
387 
388 	if ((svc == NULL) || (printer == NULL))
389 		return (PAPI_BAD_ARGUMENT);
390 
391 	if (message == NULL)
392 		message = "stopped by user";
393 
394 	dest = printer_name_from_uri_id(printer, -1);
395 	if ((snd_msg(svc, S_DISABLE_DEST, dest, message, 0) < 0) ||
396 	    (rcv_msg(svc, R_DISABLE_DEST, &status, &req_id) < 0))
397 		status = MTRANSMITERR;
398 	free(dest);
399 
400 	if ((status != MOK) && (status != MERRDEST)) {
401 		detailed_error(svc, "%s: %s", printer,
402 			lpsched_status_string(status));
403 		result = lpsched_status_to_papi_status(status);
404 	}
405 
406 	return (result);
407 }
408 
409 papi_status_t
410 lpsched_load_unload_dest(papi_service_t handle, char *dest, int type)
411 {
412 	service_t *svc = handle;
413 	papi_status_t result;
414 	short status = MOK;
415 
416 	/* tell the scheduler it's going */
417 	if (snd_msg(svc, type, dest, "", "") < 0)
418 		return (PAPI_SERVICE_UNAVAILABLE);
419 
420 	switch (type) {
421 	case S_LOAD_PRINTER:
422 		type = R_LOAD_PRINTER;
423 		break;
424 	case S_UNLOAD_PRINTER:
425 		type = R_UNLOAD_PRINTER;
426 		break;
427 	case S_LOAD_CLASS:
428 		type = R_LOAD_CLASS;
429 		break;
430 	case S_UNLOAD_CLASS:
431 		type = R_UNLOAD_CLASS;
432 	}
433 
434 	if (rcv_msg(svc, type, &status) < 0)
435 		return (PAPI_SERVICE_UNAVAILABLE);
436 
437 	result = lpsched_status_to_papi_status(status);
438 
439 	return (result);
440 }
441 
442 papi_status_t
443 lpsched_remove_class(papi_service_t handle, char *dest)
444 {
445 	papi_status_t result;
446 
447 	/* tell the scheduler it's going */
448 	result = lpsched_load_unload_dest(handle, dest, S_UNLOAD_CLASS);
449 
450 	if (result == PAPI_OK) {
451 		/* remove the scheduler config files */
452 		if (delclass(dest) == -1)
453 			result = PAPI_SERVICE_UNAVAILABLE;
454 	}
455 
456 	return (result);
457 }
458 
459 static void
460 remove_from_class(papi_service_t handle, char *dest, CLASS *cls)
461 {
462 	if (dellist(&cls->members, dest) == 0) {
463 		if (cls->members != NULL) {
464 			if (putclass(cls->name, cls) == 0)
465 				(void) lpsched_load_unload_dest(handle,
466 						cls->name, S_LOAD_CLASS);
467 		} else
468 			(void) lpsched_remove_class(handle, cls->name);
469 	}
470 }
471 
472 papi_status_t
473 lpsched_remove_printer(papi_service_t handle, char *dest)
474 {
475 
476 	papi_status_t result;
477 
478 	/* tell the scheduler it's going */
479 	result = lpsched_load_unload_dest(handle, dest, S_UNLOAD_PRINTER);
480 
481 	if (result == PAPI_OK) {
482 		CLASS *cls;
483 		char *dflt;
484 
485 		/* remove the scheduler config files */
486 		if (delprinter(dest) == -1)
487 			return (PAPI_SERVICE_UNAVAILABLE);
488 
489 		/* remove from any classes */
490 		while ((cls = getclass(NAME_ALL)) != NULL)
491 			if (searchlist(dest, cls->members) != 0)
492 				remove_from_class(handle, dest, cls);
493 
494 		/* reset the default if it needs to be done */
495 		if (((dflt = getdefault()) != NULL) &&
496 		    (strcmp(dflt, dest) == 0))
497 			putdefault(NAME_NONE);
498 	}
499 
500 	return (result);
501 }
502 
503 papi_status_t
504 lpsched_add_modify_class(papi_service_t handle, char *dest,
505 		papi_attribute_t **attributes)
506 {
507 	papi_status_t result;
508 	void *iter = NULL;
509 	char **members = NULL;
510 	char *member;
511 
512 	/*
513 	 * The only attribute that we can modify for a class is the set of
514 	 * members.  Anything else will be ignored.
515 	 */
516 	for (result = papiAttributeListGetString(attributes, &iter,
517 					"member-names", &member);
518 	    result == PAPI_OK;
519 	    result = papiAttributeListGetString(attributes, &iter,
520 					NULL, &member))
521 		addlist(&members, member);
522 
523 	if (members != NULL) {
524 		/* modify the configuration file */
525 		CLASS class;
526 
527 		memset(&class, 0, sizeof (class));
528 		class.name = dest;
529 		class.members = members;
530 
531 		if (putclass(dest, &class) == -1) {
532 			if ((errno == EPERM) || (errno == EACCES))
533 				result = PAPI_NOT_AUTHORIZED;
534 			else
535 				result = PAPI_NOT_POSSIBLE;
536 		} else
537 			result = PAPI_OK;
538 
539 		freelist(members);
540 	} else
541 		result = PAPI_ATTRIBUTES;
542 
543 	/* tell the scheduler about the changes */
544 	if (result == PAPI_OK)
545 		result = lpsched_load_unload_dest(handle, dest, S_LOAD_CLASS);
546 
547 	return (result);
548 }
549 
550 papi_status_t
551 lpsched_add_printer(papi_service_t handle, char *dest,
552 		papi_attribute_t **attributes)
553 {
554 	PRINTER *p;
555 	papi_status_t result = PAPI_TEMPORARY_ERROR;
556 
557 	if ((p = calloc(1, sizeof (*p))) != NULL) {
558 		p->name = strdup(dest);
559 		p->banner = BAN_ALWAYS;
560 		p->interface = strdup("/usr/lib/lp/model/uri");
561 		p->fault_alert.shcmd = strdup("mail");
562 
563 		attributes_to_printer(attributes, p);
564 
565 		if (putprinter(dest, p) == -1) {
566 			if ((errno == EPERM) || (errno == EACCES))
567 				result = PAPI_NOT_AUTHORIZED;
568 			else
569 				result = PAPI_NOT_POSSIBLE;
570 		} else
571 			result = PAPI_OK;
572 
573 		freeprinter(p);
574 	}
575 
576 	/* tell the scheduler about the changes */
577 	if (result == PAPI_OK)
578 		result = lpsched_load_unload_dest(handle, dest, S_LOAD_PRINTER);
579 
580 	return (result);
581 }
582 
583 papi_status_t
584 lpsched_add_modify_printer(papi_service_t handle, char *dest,
585 		papi_attribute_t **attributes, int type)
586 {
587 	PRINTER *p;
588 	papi_status_t result;
589 
590 	if (type == 0) {
591 		if ((p = calloc(1, sizeof (*p))) != NULL) {
592 			p->name = strdup(dest);
593 			p->banner = BAN_ALWAYS;
594 			p->interface = strdup("/usr/lib/lp/model/uri");
595 			p->fault_alert.shcmd = strdup("mail");
596 		}
597 	} else
598 		p = getprinter(dest);
599 
600 	if (p != NULL) {
601 		attributes_to_printer(attributes, p);
602 
603 		if (putprinter(dest, p) == -1) {
604 			if ((errno == EPERM) || (errno == EACCES))
605 				result = PAPI_NOT_AUTHORIZED;
606 			else
607 				result = PAPI_NOT_POSSIBLE;
608 		} else
609 			result = PAPI_OK;
610 
611 		freeprinter(p);
612 	} else
613 		result = PAPI_NOT_POSSIBLE;
614 
615 	/* tell the scheduler about the changes */
616 	if (result == PAPI_OK)
617 		result = lpsched_load_unload_dest(handle, dest, S_LOAD_PRINTER);
618 
619 	return (result);
620 }
621