10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52264Sjacobs  * Common Development and Distribution License (the "License").
62264Sjacobs  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*3125Sjacobs 
220Sstevel@tonic-gate /*
232264Sjacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*LINTLIBRARY*/
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <stdarg.h>
330Sstevel@tonic-gate #include <libintl.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <stdlib.h>
362264Sjacobs #include <errno.h>
370Sstevel@tonic-gate 
380Sstevel@tonic-gate 
390Sstevel@tonic-gate /* lpsched include files */
400Sstevel@tonic-gate #include "lp.h"
410Sstevel@tonic-gate #include "msgs.h"
420Sstevel@tonic-gate #include "printers.h"
432264Sjacobs #include "class.h"
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #include <papi_impl.h>
460Sstevel@tonic-gate 
470Sstevel@tonic-gate 
480Sstevel@tonic-gate /*
490Sstevel@tonic-gate  * Format and send message to lpsched (die if any errors occur)
500Sstevel@tonic-gate  */
510Sstevel@tonic-gate /*VARARGS1*/
520Sstevel@tonic-gate int
530Sstevel@tonic-gate snd_msg(service_t *svc, int type, ...)
540Sstevel@tonic-gate {
550Sstevel@tonic-gate 	int rc = -1;
560Sstevel@tonic-gate 	va_list	ap;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 	if (svc == NULL)
590Sstevel@tonic-gate 		return (-1);
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	/* fill the message buffer */
620Sstevel@tonic-gate 	va_start(ap, type);
630Sstevel@tonic-gate 	rc = _putmessage(svc->msgbuf, type, ap);
640Sstevel@tonic-gate 	va_end(ap);
650Sstevel@tonic-gate 	if (rc < 0) {
660Sstevel@tonic-gate 		detailed_error(svc,
670Sstevel@tonic-gate 			gettext("unable to build message for scheduler: %s"),
680Sstevel@tonic-gate 				strerror(errno));
690Sstevel@tonic-gate 		return (rc);
700Sstevel@tonic-gate 	}
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	/* write the message */
730Sstevel@tonic-gate 	while (((rc = mwrite(svc->md, svc->msgbuf)) < 0) && (errno == EINTR));
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	if (rc < 0)
760Sstevel@tonic-gate 		detailed_error(svc,
770Sstevel@tonic-gate 			gettext("unable to send message to scheduler: %s"),
780Sstevel@tonic-gate 				strerror(errno));
790Sstevel@tonic-gate 	return (rc);
800Sstevel@tonic-gate }
810Sstevel@tonic-gate 
820Sstevel@tonic-gate /*
830Sstevel@tonic-gate  * Receive message from lpsched (die if any errors occur)
840Sstevel@tonic-gate  */
850Sstevel@tonic-gate int
860Sstevel@tonic-gate rcv_msg(service_t *svc, int type, ...)
870Sstevel@tonic-gate {
880Sstevel@tonic-gate 	int rc = -1;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	if (svc == NULL)
910Sstevel@tonic-gate 		return (-1);
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	/* read the message */
940Sstevel@tonic-gate 	while (((rc = mread(svc->md, svc->msgbuf, svc->msgbuf_size)) < 0) &&
950Sstevel@tonic-gate 		(errno == EINTR));
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	if (rc < 0)
980Sstevel@tonic-gate 		detailed_error(svc,
990Sstevel@tonic-gate 			gettext("unable to read message from scheduler: %s"),
1000Sstevel@tonic-gate 				strerror(errno));
1010Sstevel@tonic-gate 	else {
1020Sstevel@tonic-gate 		va_list ap;
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 		va_start(ap, type);
1050Sstevel@tonic-gate 		rc = _getmessage(svc->msgbuf, type, ap);
1060Sstevel@tonic-gate 		va_end(ap);
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 		if (rc < 0)
1090Sstevel@tonic-gate 			detailed_error(svc,
1100Sstevel@tonic-gate 			gettext("unable to parse message from scheduler: %s"),
1110Sstevel@tonic-gate 				strerror(errno));
1120Sstevel@tonic-gate 	}
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	return (rc);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate papi_status_t
1180Sstevel@tonic-gate lpsched_status_to_papi_status(int status)
1190Sstevel@tonic-gate {
1200Sstevel@tonic-gate 	switch (status) {
1210Sstevel@tonic-gate 	case MNOMEM:
1220Sstevel@tonic-gate 		return (PAPI_TEMPORARY_ERROR);
1230Sstevel@tonic-gate 	case MNOFILTER:
1240Sstevel@tonic-gate 		return (PAPI_DOCUMENT_FORMAT_ERROR);
1250Sstevel@tonic-gate 	case MNOOPEN:
1260Sstevel@tonic-gate 		return (PAPI_DOCUMENT_ACCESS_ERROR);
1270Sstevel@tonic-gate 	case MERRDEST:
1280Sstevel@tonic-gate 	case MDENYDEST:
1290Sstevel@tonic-gate 		return (PAPI_NOT_ACCEPTING);
1300Sstevel@tonic-gate 	case MNOMEDIA:
1310Sstevel@tonic-gate 		return (PAPI_PRINT_SUPPORT_FILE_NOT_FOUND);
1320Sstevel@tonic-gate 	case MDENYMEDIA:
1330Sstevel@tonic-gate 	case MNOPERM:
1340Sstevel@tonic-gate 		return (PAPI_NOT_AUTHORIZED);
1350Sstevel@tonic-gate 	case MUNKNOWN:
1360Sstevel@tonic-gate 	case MNODEST:
1370Sstevel@tonic-gate 	case MNOINFO:
1380Sstevel@tonic-gate 		return (PAPI_NOT_FOUND);
1390Sstevel@tonic-gate 	case MTRANSMITERR:
1400Sstevel@tonic-gate 		return (PAPI_SERVICE_UNAVAILABLE);
1410Sstevel@tonic-gate 	case M2LATE:
1420Sstevel@tonic-gate 		return (PAPI_GONE);
1432264Sjacobs 	case MBUSY:
1442264Sjacobs 		return (PAPI_PRINTER_BUSY);
1450Sstevel@tonic-gate 	case MOK:
1460Sstevel@tonic-gate 	case MOKMORE:
1470Sstevel@tonic-gate 		return (PAPI_OK);
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	return (PAPI_INTERNAL_ERROR);
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate char *
1540Sstevel@tonic-gate lpsched_status_string(short status)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate 		switch (status) {
1570Sstevel@tonic-gate 	case MNOMEM:
1580Sstevel@tonic-gate 		return (gettext("lpsched: out of memory"));
1590Sstevel@tonic-gate 	case MNOFILTER:
1600Sstevel@tonic-gate 		return (gettext("No filter available to convert job"));
1610Sstevel@tonic-gate 	case MNOOPEN:
1620Sstevel@tonic-gate 		return (gettext("lpsched: could not open request"));
1630Sstevel@tonic-gate 	case MERRDEST:
164*3125Sjacobs 		return (gettext("queue disabled"));
1650Sstevel@tonic-gate 	case MDENYDEST:
1660Sstevel@tonic-gate 		return (gettext("destination denied request"));
1670Sstevel@tonic-gate 	case MNOMEDIA:
1680Sstevel@tonic-gate 		return (gettext("unknown form specified in job"));
1690Sstevel@tonic-gate 	case MDENYMEDIA:
1700Sstevel@tonic-gate 		return (gettext("access denied to form specified in job"));
1710Sstevel@tonic-gate 	case MUNKNOWN:
1720Sstevel@tonic-gate 		return (gettext("no such resource"));
1730Sstevel@tonic-gate 	case MNODEST:
1740Sstevel@tonic-gate 		return (gettext("unknown destination"));
1750Sstevel@tonic-gate 	case MNOPERM:
1760Sstevel@tonic-gate 		return (gettext("permission denied"));
1770Sstevel@tonic-gate 	case MNOINFO:
1780Sstevel@tonic-gate 		return (gettext("no information available"));
1790Sstevel@tonic-gate 	case MTRANSMITERR:
1800Sstevel@tonic-gate 		return (gettext("failure to communicate with lpsched"));
1810Sstevel@tonic-gate 	default: {
1820Sstevel@tonic-gate 		static char result[16];
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 		snprintf(result, sizeof (result), gettext("status: %d"),
1850Sstevel@tonic-gate 								status);
1860Sstevel@tonic-gate 		return (result);
1870Sstevel@tonic-gate 		}
1880Sstevel@tonic-gate 	}
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate papi_status_t
1920Sstevel@tonic-gate lpsched_alloc_files(papi_service_t svc, int number, char **prefix)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate 	papi_status_t result = PAPI_OK;
1950Sstevel@tonic-gate 	short status = MOK;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	if ((svc == NULL) || (prefix == NULL))
1980Sstevel@tonic-gate 		return (PAPI_BAD_ARGUMENT);
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	if ((snd_msg(svc, S_ALLOC_FILES, number) < 0) ||
2010Sstevel@tonic-gate 	    (rcv_msg(svc, R_ALLOC_FILES, &status, prefix) < 0))
2020Sstevel@tonic-gate 		status = MTRANSMITERR;
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	if (status != MOK) {
2050Sstevel@tonic-gate 		detailed_error(svc,
2060Sstevel@tonic-gate 		gettext("failed to allocate %d file(s) for request: %s"),
2070Sstevel@tonic-gate 			number, lpsched_status_string(status));
2080Sstevel@tonic-gate 		result = lpsched_status_to_papi_status(status);
2090Sstevel@tonic-gate 	}
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	return (result);
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate papi_status_t
2150Sstevel@tonic-gate lpsched_commit_job(papi_service_t svc, char *job, char **tmp)
2160Sstevel@tonic-gate /* job is host/req-id */
2170Sstevel@tonic-gate {
2180Sstevel@tonic-gate 	papi_status_t result = PAPI_OK;
2190Sstevel@tonic-gate 	short status = MOK;
2200Sstevel@tonic-gate 	long bits;
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	if ((svc == NULL) || (job == NULL) || (tmp == NULL))
2230Sstevel@tonic-gate 		return (PAPI_BAD_ARGUMENT);
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	if ((snd_msg(svc, S_PRINT_REQUEST, job) < 0) ||
2260Sstevel@tonic-gate 	    (rcv_msg(svc, R_PRINT_REQUEST, &status, tmp, &bits) < 0))
2270Sstevel@tonic-gate 		status = MTRANSMITERR;
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	if (status != MOK) {
2300Sstevel@tonic-gate 		detailed_error(svc, gettext("failed to commit job (%s): %s"),
2310Sstevel@tonic-gate 			job, lpsched_status_string(status));
2320Sstevel@tonic-gate 		result = lpsched_status_to_papi_status(status);
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	return (result);
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate papi_status_t
2392264Sjacobs lpsched_start_change(papi_service_t svc, char *printer, int32_t job_id,
2400Sstevel@tonic-gate 		char **tmp)
2410Sstevel@tonic-gate {
2420Sstevel@tonic-gate 	papi_status_t result = PAPI_OK;
2430Sstevel@tonic-gate 	short status = MOK;
2440Sstevel@tonic-gate 	char req[BUFSIZ];
2450Sstevel@tonic-gate 	char *dest;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	if ((svc == NULL) || (printer == NULL) || (job_id < 0))
2480Sstevel@tonic-gate 		return (PAPI_BAD_ARGUMENT);
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	dest = printer_name_from_uri_id(printer, job_id);
2510Sstevel@tonic-gate 	snprintf(req, sizeof (req), "%s-%d", dest, job_id);
2520Sstevel@tonic-gate 	free(dest);
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	if ((snd_msg(svc, S_START_CHANGE_REQUEST, req) < 0) ||
2550Sstevel@tonic-gate 	    (rcv_msg(svc, R_START_CHANGE_REQUEST, &status, tmp) < 0))
2560Sstevel@tonic-gate 		status = MTRANSMITERR;
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	if (status != MOK) {
2590Sstevel@tonic-gate 		detailed_error(svc,
2600Sstevel@tonic-gate 		gettext("failed to initiate change for job (%s-%d): %s"),
2610Sstevel@tonic-gate 			printer,
2620Sstevel@tonic-gate 			job_id, lpsched_status_string(status));
2630Sstevel@tonic-gate 		result = lpsched_status_to_papi_status(status);
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	return (result);
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate papi_status_t
2702264Sjacobs lpsched_end_change(papi_service_t svc, char *printer, int32_t job_id)
2710Sstevel@tonic-gate {
2720Sstevel@tonic-gate 	papi_status_t result = PAPI_OK;
2730Sstevel@tonic-gate 	short status = MOK;
2740Sstevel@tonic-gate 	long bits;
2750Sstevel@tonic-gate 	char req[BUFSIZ];
2760Sstevel@tonic-gate 	char *dest;
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	if ((svc == NULL) || (printer == NULL) || (job_id < 0))
2790Sstevel@tonic-gate 		return (PAPI_BAD_ARGUMENT);
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	dest = printer_name_from_uri_id(printer, job_id);
2820Sstevel@tonic-gate 	snprintf(req, sizeof (req), "%s-%d", dest, job_id);
2830Sstevel@tonic-gate 	free(dest);
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	if ((snd_msg(svc, S_END_CHANGE_REQUEST, req) < 0) ||
2860Sstevel@tonic-gate 	    (rcv_msg(svc, R_END_CHANGE_REQUEST, &status, &bits) < 0))
2870Sstevel@tonic-gate 		status = MTRANSMITERR;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	if (status != MOK) {
2900Sstevel@tonic-gate 		detailed_error(svc,
2910Sstevel@tonic-gate 		gettext("failed to commit change for job (%s-%d): %s"), printer,
2920Sstevel@tonic-gate 			job_id, lpsched_status_string(status));
2930Sstevel@tonic-gate 		result = lpsched_status_to_papi_status(status);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	return (result);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate papi_status_t
3002264Sjacobs lpsched_accept_printer(papi_service_t svc, char *printer)
3012264Sjacobs {
3022264Sjacobs 	papi_status_t result = PAPI_OK;
3032264Sjacobs 	short	 status;
3042264Sjacobs 	char	*req_id;
3052264Sjacobs 	char *dest;
3062264Sjacobs 
3072264Sjacobs 	if ((svc == NULL) || (printer == NULL))
3082264Sjacobs 		return (PAPI_BAD_ARGUMENT);
3092264Sjacobs 
3102264Sjacobs 	dest = printer_name_from_uri_id(printer, -1);
3112264Sjacobs 	if ((snd_msg(svc, S_ACCEPT_DEST, dest) < 0) ||
3122264Sjacobs 	    (rcv_msg(svc, R_ACCEPT_DEST, &status, &req_id) < 0))
3132264Sjacobs 		status = MTRANSMITERR;
3142264Sjacobs 	free(dest);
3152264Sjacobs 
3162264Sjacobs 	if ((status != MOK) && (status != MERRDEST)) {
3172264Sjacobs 		detailed_error(svc, "%s: %s", printer,
3182264Sjacobs 			lpsched_status_string(status));
3192264Sjacobs 		result = lpsched_status_to_papi_status(status);
3202264Sjacobs 	}
3212264Sjacobs 
3222264Sjacobs 	return (result);
3232264Sjacobs }
3242264Sjacobs 
3252264Sjacobs papi_status_t
3262264Sjacobs lpsched_reject_printer(papi_service_t svc, char *printer, char *message)
3272264Sjacobs {
3282264Sjacobs 	papi_status_t result = PAPI_OK;
3292264Sjacobs 	short	 status;
3302264Sjacobs 	char	*req_id;
3312264Sjacobs 	char *dest;
3322264Sjacobs 
3332264Sjacobs 	if ((svc == NULL) || (printer == NULL))
3342264Sjacobs 		return (PAPI_BAD_ARGUMENT);
3352264Sjacobs 
3362264Sjacobs 	if (message == NULL)
3372264Sjacobs 		message = "stopped by user";
3382264Sjacobs 
3392264Sjacobs 	dest = printer_name_from_uri_id(printer, -1);
3402264Sjacobs 	if ((snd_msg(svc, S_REJECT_DEST, dest, message, 0) < 0) ||
3412264Sjacobs 	    (rcv_msg(svc, R_REJECT_DEST, &status, &req_id) < 0))
3422264Sjacobs 		status = MTRANSMITERR;
3432264Sjacobs 	free(dest);
3442264Sjacobs 
3452264Sjacobs 	if ((status != MOK) && (status != MERRDEST)) {
3462264Sjacobs 		detailed_error(svc, "%s: %s", printer,
3472264Sjacobs 			lpsched_status_string(status));
3482264Sjacobs 		result = lpsched_status_to_papi_status(status);
3492264Sjacobs 	}
3502264Sjacobs 
3512264Sjacobs 	return (result);
3522264Sjacobs }
3532264Sjacobs 
3542264Sjacobs papi_status_t
3552264Sjacobs lpsched_enable_printer(papi_service_t svc, char *printer)
3560Sstevel@tonic-gate {
3570Sstevel@tonic-gate 	papi_status_t result = PAPI_OK;
3580Sstevel@tonic-gate 	short	 status;
3590Sstevel@tonic-gate 	char	*req_id;
3600Sstevel@tonic-gate 	char *dest;
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	if ((svc == NULL) || (printer == NULL))
3630Sstevel@tonic-gate 		return (PAPI_BAD_ARGUMENT);
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	dest = printer_name_from_uri_id(printer, -1);
3660Sstevel@tonic-gate 	if ((snd_msg(svc, S_ENABLE_DEST, dest) < 0) ||
3670Sstevel@tonic-gate 	    (rcv_msg(svc, R_ENABLE_DEST, &status, &req_id) < 0))
3680Sstevel@tonic-gate 		status = MTRANSMITERR;
3690Sstevel@tonic-gate 	free(dest);
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	if ((status != MOK) && (status != MERRDEST)) {
3720Sstevel@tonic-gate 		detailed_error(svc, "%s: %s", printer,
3730Sstevel@tonic-gate 			lpsched_status_string(status));
3740Sstevel@tonic-gate 		result = lpsched_status_to_papi_status(status);
3750Sstevel@tonic-gate 	}
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	return (result);
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate papi_status_t
3812264Sjacobs lpsched_disable_printer(papi_service_t svc, char *printer, char *message)
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate 	papi_status_t result = PAPI_OK;
3840Sstevel@tonic-gate 	short	 status;
3850Sstevel@tonic-gate 	char	*req_id;
3860Sstevel@tonic-gate 	char *dest;
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	if ((svc == NULL) || (printer == NULL))
3890Sstevel@tonic-gate 		return (PAPI_BAD_ARGUMENT);
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	if (message == NULL)
3920Sstevel@tonic-gate 		message = "stopped by user";
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 	dest = printer_name_from_uri_id(printer, -1);
3950Sstevel@tonic-gate 	if ((snd_msg(svc, S_DISABLE_DEST, dest, message, 0) < 0) ||
3960Sstevel@tonic-gate 	    (rcv_msg(svc, R_DISABLE_DEST, &status, &req_id) < 0))
3970Sstevel@tonic-gate 		status = MTRANSMITERR;
3980Sstevel@tonic-gate 	free(dest);
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	if ((status != MOK) && (status != MERRDEST)) {
4010Sstevel@tonic-gate 		detailed_error(svc, "%s: %s", printer,
4020Sstevel@tonic-gate 			lpsched_status_string(status));
4030Sstevel@tonic-gate 		result = lpsched_status_to_papi_status(status);
4040Sstevel@tonic-gate 	}
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	return (result);
4070Sstevel@tonic-gate }
4082264Sjacobs 
4092264Sjacobs papi_status_t
4102264Sjacobs lpsched_load_unload_dest(papi_service_t handle, char *dest, int type)
4112264Sjacobs {
4122264Sjacobs 	service_t *svc = handle;
4132264Sjacobs 	papi_status_t result;
4142264Sjacobs 	short status = MOK;
4152264Sjacobs 
4162264Sjacobs 	/* tell the scheduler it's going */
4172264Sjacobs 	if (snd_msg(svc, type, dest, "", "") < 0)
4182264Sjacobs 		return (PAPI_SERVICE_UNAVAILABLE);
4192264Sjacobs 
4202264Sjacobs 	switch (type) {
4212264Sjacobs 	case S_LOAD_PRINTER:
4222264Sjacobs 		type = R_LOAD_PRINTER;
4232264Sjacobs 		break;
4242264Sjacobs 	case S_UNLOAD_PRINTER:
4252264Sjacobs 		type = R_UNLOAD_PRINTER;
4262264Sjacobs 		break;
4272264Sjacobs 	case S_LOAD_CLASS:
4282264Sjacobs 		type = R_LOAD_CLASS;
4292264Sjacobs 		break;
4302264Sjacobs 	case S_UNLOAD_CLASS:
4312264Sjacobs 		type = R_UNLOAD_CLASS;
4322264Sjacobs 	}
4332264Sjacobs 
4342264Sjacobs 	if (rcv_msg(svc, type, &status) < 0)
4352264Sjacobs 		return (PAPI_SERVICE_UNAVAILABLE);
4362264Sjacobs 
4372264Sjacobs 	result = lpsched_status_to_papi_status(status);
4382264Sjacobs 
4392264Sjacobs 	return (result);
4402264Sjacobs }
4412264Sjacobs 
4422264Sjacobs papi_status_t
4432264Sjacobs lpsched_remove_class(papi_service_t handle, char *dest)
4442264Sjacobs {
4452264Sjacobs 	papi_status_t result;
4462264Sjacobs 
4472264Sjacobs 	/* tell the scheduler it's going */
4482264Sjacobs 	result = lpsched_load_unload_dest(handle, dest, S_UNLOAD_CLASS);
4492264Sjacobs 
4502264Sjacobs 	if (result == PAPI_OK) {
4512264Sjacobs 		/* remove the scheduler config files */
4522264Sjacobs 		if (delclass(dest) == -1)
4532264Sjacobs 			result = PAPI_SERVICE_UNAVAILABLE;
4542264Sjacobs 	}
4552264Sjacobs 
4562264Sjacobs 	return (result);
4572264Sjacobs }
4582264Sjacobs 
4592264Sjacobs static void
4602264Sjacobs remove_from_class(papi_service_t handle, char *dest, CLASS *cls)
4612264Sjacobs {
4622264Sjacobs 	if (dellist(&cls->members, dest) == 0) {
4632264Sjacobs 		if (cls->members != NULL) {
4642264Sjacobs 			if (putclass(cls->name, cls) == 0)
4652264Sjacobs 				(void) lpsched_load_unload_dest(handle,
4662264Sjacobs 						cls->name, S_LOAD_CLASS);
4672264Sjacobs 		} else
4682264Sjacobs 			(void) lpsched_remove_class(handle, cls->name);
4692264Sjacobs 	}
4702264Sjacobs }
4712264Sjacobs 
4722264Sjacobs papi_status_t
4732264Sjacobs lpsched_remove_printer(papi_service_t handle, char *dest)
4742264Sjacobs {
4752264Sjacobs 
4762264Sjacobs 	papi_status_t result;
4772264Sjacobs 
4782264Sjacobs 	/* tell the scheduler it's going */
4792264Sjacobs 	result = lpsched_load_unload_dest(handle, dest, S_UNLOAD_PRINTER);
4802264Sjacobs 
4812264Sjacobs 	if (result == PAPI_OK) {
4822264Sjacobs 		CLASS *cls;
4832264Sjacobs 		char *dflt;
4842264Sjacobs 
4852264Sjacobs 		/* remove the scheduler config files */
4862264Sjacobs 		if (delprinter(dest) == -1)
4872264Sjacobs 			return (PAPI_SERVICE_UNAVAILABLE);
4882264Sjacobs 
4892264Sjacobs 		/* remove from any classes */
490*3125Sjacobs 		while ((cls = getclass(NAME_ALL)) != NULL) {
4912264Sjacobs 			if (searchlist(dest, cls->members) != 0)
4922264Sjacobs 				remove_from_class(handle, dest, cls);
493*3125Sjacobs 			freeclass(cls);
494*3125Sjacobs 		}
4952264Sjacobs 
4962264Sjacobs 		/* reset the default if it needs to be done */
4972264Sjacobs 		if (((dflt = getdefault()) != NULL) &&
4982264Sjacobs 		    (strcmp(dflt, dest) == 0))
4992264Sjacobs 			putdefault(NAME_NONE);
5002264Sjacobs 	}
5012264Sjacobs 
5022264Sjacobs 	return (result);
5032264Sjacobs }
5042264Sjacobs 
5052264Sjacobs papi_status_t
5062264Sjacobs lpsched_add_modify_class(papi_service_t handle, char *dest,
5072264Sjacobs 		papi_attribute_t **attributes)
5082264Sjacobs {
5092264Sjacobs 	papi_status_t result;
5102264Sjacobs 	void *iter = NULL;
5112264Sjacobs 	char **members = NULL;
5122264Sjacobs 	char *member;
5132264Sjacobs 
5142264Sjacobs 	/*
5152264Sjacobs 	 * The only attribute that we can modify for a class is the set of
5162264Sjacobs 	 * members.  Anything else will be ignored.
5172264Sjacobs 	 */
5182264Sjacobs 	for (result = papiAttributeListGetString(attributes, &iter,
5192264Sjacobs 					"member-names", &member);
5202264Sjacobs 	    result == PAPI_OK;
5212264Sjacobs 	    result = papiAttributeListGetString(attributes, &iter,
5222264Sjacobs 					NULL, &member))
5232264Sjacobs 		addlist(&members, member);
5242264Sjacobs 
5252264Sjacobs 	if (members != NULL) {
5262264Sjacobs 		/* modify the configuration file */
5272264Sjacobs 		CLASS class;
5282264Sjacobs 
5292264Sjacobs 		memset(&class, 0, sizeof (class));
5302264Sjacobs 		class.name = dest;
5312264Sjacobs 		class.members = members;
5322264Sjacobs 
5332264Sjacobs 		if (putclass(dest, &class) == -1) {
5342264Sjacobs 			if ((errno == EPERM) || (errno == EACCES))
5352264Sjacobs 				result = PAPI_NOT_AUTHORIZED;
5362264Sjacobs 			else
5372264Sjacobs 				result = PAPI_NOT_POSSIBLE;
5382264Sjacobs 		} else
5392264Sjacobs 			result = PAPI_OK;
5402264Sjacobs 
5412264Sjacobs 		freelist(members);
5422264Sjacobs 	} else
5432264Sjacobs 		result = PAPI_ATTRIBUTES;
5442264Sjacobs 
5452264Sjacobs 	/* tell the scheduler about the changes */
5462264Sjacobs 	if (result == PAPI_OK)
5472264Sjacobs 		result = lpsched_load_unload_dest(handle, dest, S_LOAD_CLASS);
5482264Sjacobs 
5492264Sjacobs 	return (result);
5502264Sjacobs }
5512264Sjacobs 
5522264Sjacobs papi_status_t
5532264Sjacobs lpsched_add_printer(papi_service_t handle, char *dest,
5542264Sjacobs 		papi_attribute_t **attributes)
5552264Sjacobs {
5562264Sjacobs 	PRINTER *p;
5572264Sjacobs 	papi_status_t result = PAPI_TEMPORARY_ERROR;
5582264Sjacobs 
5592264Sjacobs 	if ((p = calloc(1, sizeof (*p))) != NULL) {
5602264Sjacobs 		p->name = strdup(dest);
5612264Sjacobs 		p->banner = BAN_ALWAYS;
5622264Sjacobs 		p->interface = strdup("/usr/lib/lp/model/uri");
5632264Sjacobs 		p->fault_alert.shcmd = strdup("mail");
5642264Sjacobs 
5652264Sjacobs 		attributes_to_printer(attributes, p);
5662264Sjacobs 
5672264Sjacobs 		if (putprinter(dest, p) == -1) {
5682264Sjacobs 			if ((errno == EPERM) || (errno == EACCES))
5692264Sjacobs 				result = PAPI_NOT_AUTHORIZED;
5702264Sjacobs 			else
5712264Sjacobs 				result = PAPI_NOT_POSSIBLE;
5722264Sjacobs 		} else
5732264Sjacobs 			result = PAPI_OK;
5742264Sjacobs 
5752264Sjacobs 		freeprinter(p);
5762264Sjacobs 	}
5772264Sjacobs 
5782264Sjacobs 	/* tell the scheduler about the changes */
5792264Sjacobs 	if (result == PAPI_OK)
5802264Sjacobs 		result = lpsched_load_unload_dest(handle, dest, S_LOAD_PRINTER);
5812264Sjacobs 
5822264Sjacobs 	return (result);
5832264Sjacobs }
5842264Sjacobs 
5852264Sjacobs papi_status_t
5862264Sjacobs lpsched_add_modify_printer(papi_service_t handle, char *dest,
5872264Sjacobs 		papi_attribute_t **attributes, int type)
5882264Sjacobs {
5892264Sjacobs 	PRINTER *p;
5902264Sjacobs 	papi_status_t result;
5912264Sjacobs 
5922264Sjacobs 	if (type == 0) {
5932264Sjacobs 		if ((p = calloc(1, sizeof (*p))) != NULL) {
5942264Sjacobs 			p->name = strdup(dest);
5952264Sjacobs 			p->banner = BAN_ALWAYS;
5962264Sjacobs 			p->interface = strdup("/usr/lib/lp/model/uri");
5972264Sjacobs 			p->fault_alert.shcmd = strdup("mail");
5982264Sjacobs 		}
5992264Sjacobs 	} else
6002264Sjacobs 		p = getprinter(dest);
6012264Sjacobs 
6022264Sjacobs 	if (p != NULL) {
6032264Sjacobs 		attributes_to_printer(attributes, p);
6042264Sjacobs 
6052264Sjacobs 		if (putprinter(dest, p) == -1) {
6062264Sjacobs 			if ((errno == EPERM) || (errno == EACCES))
6072264Sjacobs 				result = PAPI_NOT_AUTHORIZED;
6082264Sjacobs 			else
6092264Sjacobs 				result = PAPI_NOT_POSSIBLE;
6102264Sjacobs 		} else
6112264Sjacobs 			result = PAPI_OK;
6122264Sjacobs 
6132264Sjacobs 		freeprinter(p);
6142264Sjacobs 	} else
6152264Sjacobs 		result = PAPI_NOT_POSSIBLE;
6162264Sjacobs 
6172264Sjacobs 	/* tell the scheduler about the changes */
6182264Sjacobs 	if (result == PAPI_OK)
6192264Sjacobs 		result = lpsched_load_unload_dest(handle, dest, S_LOAD_PRINTER);
6202264Sjacobs 
6212264Sjacobs 	return (result);
6222264Sjacobs }
623