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
5*2264Sjacobs  * Common Development and Distribution License (the "License").
6*2264Sjacobs  * 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  */
210Sstevel@tonic-gate /*
22*2264Sjacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*LINTLIBRARY*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #include <stdarg.h>
320Sstevel@tonic-gate #include <libintl.h>
330Sstevel@tonic-gate #include <string.h>
340Sstevel@tonic-gate #include <stdlib.h>
35*2264Sjacobs #include <errno.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /* lpsched include files */
390Sstevel@tonic-gate #include "lp.h"
400Sstevel@tonic-gate #include "msgs.h"
410Sstevel@tonic-gate #include "printers.h"
42*2264Sjacobs #include "class.h"
430Sstevel@tonic-gate 
440Sstevel@tonic-gate #include <papi_impl.h>
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate  * Format and send message to lpsched (die if any errors occur)
490Sstevel@tonic-gate  */
500Sstevel@tonic-gate /*VARARGS1*/
510Sstevel@tonic-gate int
520Sstevel@tonic-gate snd_msg(service_t *svc, int type, ...)
530Sstevel@tonic-gate {
540Sstevel@tonic-gate 	int rc = -1;
550Sstevel@tonic-gate 	va_list	ap;
560Sstevel@tonic-gate 
570Sstevel@tonic-gate 	if (svc == NULL)
580Sstevel@tonic-gate 		return (-1);
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 	/* fill the message buffer */
610Sstevel@tonic-gate 	va_start(ap, type);
620Sstevel@tonic-gate 	rc = _putmessage(svc->msgbuf, type, ap);
630Sstevel@tonic-gate 	va_end(ap);
640Sstevel@tonic-gate 	if (rc < 0) {
650Sstevel@tonic-gate 		detailed_error(svc,
660Sstevel@tonic-gate 			gettext("unable to build message for scheduler: %s"),
670Sstevel@tonic-gate 				strerror(errno));
680Sstevel@tonic-gate 		return (rc);
690Sstevel@tonic-gate 	}
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 	/* write the message */
720Sstevel@tonic-gate 	while (((rc = mwrite(svc->md, svc->msgbuf)) < 0) && (errno == EINTR));
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	if (rc < 0)
750Sstevel@tonic-gate 		detailed_error(svc,
760Sstevel@tonic-gate 			gettext("unable to send message to scheduler: %s"),
770Sstevel@tonic-gate 				strerror(errno));
780Sstevel@tonic-gate 	return (rc);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate 
810Sstevel@tonic-gate /*
820Sstevel@tonic-gate  * Receive message from lpsched (die if any errors occur)
830Sstevel@tonic-gate  */
840Sstevel@tonic-gate int
850Sstevel@tonic-gate rcv_msg(service_t *svc, int type, ...)
860Sstevel@tonic-gate {
870Sstevel@tonic-gate 	int rc = -1;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	if (svc == NULL)
900Sstevel@tonic-gate 		return (-1);
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 	/* read the message */
930Sstevel@tonic-gate 	while (((rc = mread(svc->md, svc->msgbuf, svc->msgbuf_size)) < 0) &&
940Sstevel@tonic-gate 		(errno == EINTR));
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	if (rc < 0)
970Sstevel@tonic-gate 		detailed_error(svc,
980Sstevel@tonic-gate 			gettext("unable to read message from scheduler: %s"),
990Sstevel@tonic-gate 				strerror(errno));
1000Sstevel@tonic-gate 	else {
1010Sstevel@tonic-gate 		va_list ap;
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 		va_start(ap, type);
1040Sstevel@tonic-gate 		rc = _getmessage(svc->msgbuf, type, ap);
1050Sstevel@tonic-gate 		va_end(ap);
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 		if (rc < 0)
1080Sstevel@tonic-gate 			detailed_error(svc,
1090Sstevel@tonic-gate 			gettext("unable to parse message from scheduler: %s"),
1100Sstevel@tonic-gate 				strerror(errno));
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	return (rc);
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate papi_status_t
1170Sstevel@tonic-gate lpsched_status_to_papi_status(int status)
1180Sstevel@tonic-gate {
1190Sstevel@tonic-gate 	switch (status) {
1200Sstevel@tonic-gate 	case MNOMEM:
1210Sstevel@tonic-gate 		return (PAPI_TEMPORARY_ERROR);
1220Sstevel@tonic-gate 	case MNOFILTER:
1230Sstevel@tonic-gate 		return (PAPI_DOCUMENT_FORMAT_ERROR);
1240Sstevel@tonic-gate 	case MNOOPEN:
1250Sstevel@tonic-gate 		return (PAPI_DOCUMENT_ACCESS_ERROR);
1260Sstevel@tonic-gate 	case MERRDEST:
1270Sstevel@tonic-gate 		return (PAPI_DEVICE_ERROR);
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);
143*2264Sjacobs 	case MBUSY:
144*2264Sjacobs 		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:
1640Sstevel@tonic-gate 		return (gettext("An error occured in submission"));
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
239*2264Sjacobs 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
270*2264Sjacobs 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
300*2264Sjacobs lpsched_accept_printer(papi_service_t svc, char *printer)
301*2264Sjacobs {
302*2264Sjacobs 	papi_status_t result = PAPI_OK;
303*2264Sjacobs 	short	 status;
304*2264Sjacobs 	char	*req_id;
305*2264Sjacobs 	char *dest;
306*2264Sjacobs 
307*2264Sjacobs 	if ((svc == NULL) || (printer == NULL))
308*2264Sjacobs 		return (PAPI_BAD_ARGUMENT);
309*2264Sjacobs 
310*2264Sjacobs 	dest = printer_name_from_uri_id(printer, -1);
311*2264Sjacobs 	if ((snd_msg(svc, S_ACCEPT_DEST, dest) < 0) ||
312*2264Sjacobs 	    (rcv_msg(svc, R_ACCEPT_DEST, &status, &req_id) < 0))
313*2264Sjacobs 		status = MTRANSMITERR;
314*2264Sjacobs 	free(dest);
315*2264Sjacobs 
316*2264Sjacobs 	if ((status != MOK) && (status != MERRDEST)) {
317*2264Sjacobs 		detailed_error(svc, "%s: %s", printer,
318*2264Sjacobs 			lpsched_status_string(status));
319*2264Sjacobs 		result = lpsched_status_to_papi_status(status);
320*2264Sjacobs 	}
321*2264Sjacobs 
322*2264Sjacobs 	return (result);
323*2264Sjacobs }
324*2264Sjacobs 
325*2264Sjacobs papi_status_t
326*2264Sjacobs lpsched_reject_printer(papi_service_t svc, char *printer, char *message)
327*2264Sjacobs {
328*2264Sjacobs 	papi_status_t result = PAPI_OK;
329*2264Sjacobs 	short	 status;
330*2264Sjacobs 	char	*req_id;
331*2264Sjacobs 	char *dest;
332*2264Sjacobs 
333*2264Sjacobs 	if ((svc == NULL) || (printer == NULL))
334*2264Sjacobs 		return (PAPI_BAD_ARGUMENT);
335*2264Sjacobs 
336*2264Sjacobs 	if (message == NULL)
337*2264Sjacobs 		message = "stopped by user";
338*2264Sjacobs 
339*2264Sjacobs 	dest = printer_name_from_uri_id(printer, -1);
340*2264Sjacobs 	if ((snd_msg(svc, S_REJECT_DEST, dest, message, 0) < 0) ||
341*2264Sjacobs 	    (rcv_msg(svc, R_REJECT_DEST, &status, &req_id) < 0))
342*2264Sjacobs 		status = MTRANSMITERR;
343*2264Sjacobs 	free(dest);
344*2264Sjacobs 
345*2264Sjacobs 	if ((status != MOK) && (status != MERRDEST)) {
346*2264Sjacobs 		detailed_error(svc, "%s: %s", printer,
347*2264Sjacobs 			lpsched_status_string(status));
348*2264Sjacobs 		result = lpsched_status_to_papi_status(status);
349*2264Sjacobs 	}
350*2264Sjacobs 
351*2264Sjacobs 	return (result);
352*2264Sjacobs }
353*2264Sjacobs 
354*2264Sjacobs papi_status_t
355*2264Sjacobs 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
381*2264Sjacobs 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 }
408*2264Sjacobs 
409*2264Sjacobs papi_status_t
410*2264Sjacobs lpsched_load_unload_dest(papi_service_t handle, char *dest, int type)
411*2264Sjacobs {
412*2264Sjacobs 	service_t *svc = handle;
413*2264Sjacobs 	papi_status_t result;
414*2264Sjacobs 	short status = MOK;
415*2264Sjacobs 
416*2264Sjacobs 	/* tell the scheduler it's going */
417*2264Sjacobs 	if (snd_msg(svc, type, dest, "", "") < 0)
418*2264Sjacobs 		return (PAPI_SERVICE_UNAVAILABLE);
419*2264Sjacobs 
420*2264Sjacobs 	switch (type) {
421*2264Sjacobs 	case S_LOAD_PRINTER:
422*2264Sjacobs 		type = R_LOAD_PRINTER;
423*2264Sjacobs 		break;
424*2264Sjacobs 	case S_UNLOAD_PRINTER:
425*2264Sjacobs 		type = R_UNLOAD_PRINTER;
426*2264Sjacobs 		break;
427*2264Sjacobs 	case S_LOAD_CLASS:
428*2264Sjacobs 		type = R_LOAD_CLASS;
429*2264Sjacobs 		break;
430*2264Sjacobs 	case S_UNLOAD_CLASS:
431*2264Sjacobs 		type = R_UNLOAD_CLASS;
432*2264Sjacobs 	}
433*2264Sjacobs 
434*2264Sjacobs 	if (rcv_msg(svc, type, &status) < 0)
435*2264Sjacobs 		return (PAPI_SERVICE_UNAVAILABLE);
436*2264Sjacobs 
437*2264Sjacobs 	result = lpsched_status_to_papi_status(status);
438*2264Sjacobs 
439*2264Sjacobs 	return (result);
440*2264Sjacobs }
441*2264Sjacobs 
442*2264Sjacobs papi_status_t
443*2264Sjacobs lpsched_remove_class(papi_service_t handle, char *dest)
444*2264Sjacobs {
445*2264Sjacobs 	papi_status_t result;
446*2264Sjacobs 
447*2264Sjacobs 	/* tell the scheduler it's going */
448*2264Sjacobs 	result = lpsched_load_unload_dest(handle, dest, S_UNLOAD_CLASS);
449*2264Sjacobs 
450*2264Sjacobs 	if (result == PAPI_OK) {
451*2264Sjacobs 		/* remove the scheduler config files */
452*2264Sjacobs 		if (delclass(dest) == -1)
453*2264Sjacobs 			result = PAPI_SERVICE_UNAVAILABLE;
454*2264Sjacobs 	}
455*2264Sjacobs 
456*2264Sjacobs 	return (result);
457*2264Sjacobs }
458*2264Sjacobs 
459*2264Sjacobs static void
460*2264Sjacobs remove_from_class(papi_service_t handle, char *dest, CLASS *cls)
461*2264Sjacobs {
462*2264Sjacobs 	if (dellist(&cls->members, dest) == 0) {
463*2264Sjacobs 		if (cls->members != NULL) {
464*2264Sjacobs 			if (putclass(cls->name, cls) == 0)
465*2264Sjacobs 				(void) lpsched_load_unload_dest(handle,
466*2264Sjacobs 						cls->name, S_LOAD_CLASS);
467*2264Sjacobs 		} else
468*2264Sjacobs 			(void) lpsched_remove_class(handle, cls->name);
469*2264Sjacobs 	}
470*2264Sjacobs }
471*2264Sjacobs 
472*2264Sjacobs papi_status_t
473*2264Sjacobs lpsched_remove_printer(papi_service_t handle, char *dest)
474*2264Sjacobs {
475*2264Sjacobs 
476*2264Sjacobs 	papi_status_t result;
477*2264Sjacobs 
478*2264Sjacobs 	/* tell the scheduler it's going */
479*2264Sjacobs 	result = lpsched_load_unload_dest(handle, dest, S_UNLOAD_PRINTER);
480*2264Sjacobs 
481*2264Sjacobs 	if (result == PAPI_OK) {
482*2264Sjacobs 		CLASS *cls;
483*2264Sjacobs 		char *dflt;
484*2264Sjacobs 
485*2264Sjacobs 		/* remove the scheduler config files */
486*2264Sjacobs 		if (delprinter(dest) == -1)
487*2264Sjacobs 			return (PAPI_SERVICE_UNAVAILABLE);
488*2264Sjacobs 
489*2264Sjacobs 		/* remove from any classes */
490*2264Sjacobs 		while ((cls = getclass(NAME_ALL)) != NULL)
491*2264Sjacobs 			if (searchlist(dest, cls->members) != 0)
492*2264Sjacobs 				remove_from_class(handle, dest, cls);
493*2264Sjacobs 
494*2264Sjacobs 		/* reset the default if it needs to be done */
495*2264Sjacobs 		if (((dflt = getdefault()) != NULL) &&
496*2264Sjacobs 		    (strcmp(dflt, dest) == 0))
497*2264Sjacobs 			putdefault(NAME_NONE);
498*2264Sjacobs 	}
499*2264Sjacobs 
500*2264Sjacobs 	return (result);
501*2264Sjacobs }
502*2264Sjacobs 
503*2264Sjacobs papi_status_t
504*2264Sjacobs lpsched_add_modify_class(papi_service_t handle, char *dest,
505*2264Sjacobs 		papi_attribute_t **attributes)
506*2264Sjacobs {
507*2264Sjacobs 	papi_status_t result;
508*2264Sjacobs 	void *iter = NULL;
509*2264Sjacobs 	char **members = NULL;
510*2264Sjacobs 	char *member;
511*2264Sjacobs 
512*2264Sjacobs 	/*
513*2264Sjacobs 	 * The only attribute that we can modify for a class is the set of
514*2264Sjacobs 	 * members.  Anything else will be ignored.
515*2264Sjacobs 	 */
516*2264Sjacobs 	for (result = papiAttributeListGetString(attributes, &iter,
517*2264Sjacobs 					"member-names", &member);
518*2264Sjacobs 	    result == PAPI_OK;
519*2264Sjacobs 	    result = papiAttributeListGetString(attributes, &iter,
520*2264Sjacobs 					NULL, &member))
521*2264Sjacobs 		addlist(&members, member);
522*2264Sjacobs 
523*2264Sjacobs 	if (members != NULL) {
524*2264Sjacobs 		/* modify the configuration file */
525*2264Sjacobs 		CLASS class;
526*2264Sjacobs 
527*2264Sjacobs 		memset(&class, 0, sizeof (class));
528*2264Sjacobs 		class.name = dest;
529*2264Sjacobs 		class.members = members;
530*2264Sjacobs 
531*2264Sjacobs 		if (putclass(dest, &class) == -1) {
532*2264Sjacobs 			if ((errno == EPERM) || (errno == EACCES))
533*2264Sjacobs 				result = PAPI_NOT_AUTHORIZED;
534*2264Sjacobs 			else
535*2264Sjacobs 				result = PAPI_NOT_POSSIBLE;
536*2264Sjacobs 		} else
537*2264Sjacobs 			result = PAPI_OK;
538*2264Sjacobs 
539*2264Sjacobs 		freelist(members);
540*2264Sjacobs 	} else
541*2264Sjacobs 		result = PAPI_ATTRIBUTES;
542*2264Sjacobs 
543*2264Sjacobs 	/* tell the scheduler about the changes */
544*2264Sjacobs 	if (result == PAPI_OK)
545*2264Sjacobs 		result = lpsched_load_unload_dest(handle, dest, S_LOAD_CLASS);
546*2264Sjacobs 
547*2264Sjacobs 	return (result);
548*2264Sjacobs }
549*2264Sjacobs 
550*2264Sjacobs papi_status_t
551*2264Sjacobs lpsched_add_printer(papi_service_t handle, char *dest,
552*2264Sjacobs 		papi_attribute_t **attributes)
553*2264Sjacobs {
554*2264Sjacobs 	PRINTER *p;
555*2264Sjacobs 	papi_status_t result = PAPI_TEMPORARY_ERROR;
556*2264Sjacobs 
557*2264Sjacobs 	if ((p = calloc(1, sizeof (*p))) != NULL) {
558*2264Sjacobs 		p->name = strdup(dest);
559*2264Sjacobs 		p->banner = BAN_ALWAYS;
560*2264Sjacobs 		p->interface = strdup("/usr/lib/lp/model/uri");
561*2264Sjacobs 		p->fault_alert.shcmd = strdup("mail");
562*2264Sjacobs 
563*2264Sjacobs 		attributes_to_printer(attributes, p);
564*2264Sjacobs 
565*2264Sjacobs 		if (putprinter(dest, p) == -1) {
566*2264Sjacobs 			if ((errno == EPERM) || (errno == EACCES))
567*2264Sjacobs 				result = PAPI_NOT_AUTHORIZED;
568*2264Sjacobs 			else
569*2264Sjacobs 				result = PAPI_NOT_POSSIBLE;
570*2264Sjacobs 		} else
571*2264Sjacobs 			result = PAPI_OK;
572*2264Sjacobs 
573*2264Sjacobs 		freeprinter(p);
574*2264Sjacobs 	}
575*2264Sjacobs 
576*2264Sjacobs 	/* tell the scheduler about the changes */
577*2264Sjacobs 	if (result == PAPI_OK)
578*2264Sjacobs 		result = lpsched_load_unload_dest(handle, dest, S_LOAD_PRINTER);
579*2264Sjacobs 
580*2264Sjacobs 	return (result);
581*2264Sjacobs }
582*2264Sjacobs 
583*2264Sjacobs papi_status_t
584*2264Sjacobs lpsched_add_modify_printer(papi_service_t handle, char *dest,
585*2264Sjacobs 		papi_attribute_t **attributes, int type)
586*2264Sjacobs {
587*2264Sjacobs 	PRINTER *p;
588*2264Sjacobs 	papi_status_t result;
589*2264Sjacobs 
590*2264Sjacobs 	if (type == 0) {
591*2264Sjacobs 		if ((p = calloc(1, sizeof (*p))) != NULL) {
592*2264Sjacobs 			p->name = strdup(dest);
593*2264Sjacobs 			p->banner = BAN_ALWAYS;
594*2264Sjacobs 			p->interface = strdup("/usr/lib/lp/model/uri");
595*2264Sjacobs 			p->fault_alert.shcmd = strdup("mail");
596*2264Sjacobs 		}
597*2264Sjacobs 	} else
598*2264Sjacobs 		p = getprinter(dest);
599*2264Sjacobs 
600*2264Sjacobs 	if (p != NULL) {
601*2264Sjacobs 		attributes_to_printer(attributes, p);
602*2264Sjacobs 
603*2264Sjacobs 		if (putprinter(dest, p) == -1) {
604*2264Sjacobs 			if ((errno == EPERM) || (errno == EACCES))
605*2264Sjacobs 				result = PAPI_NOT_AUTHORIZED;
606*2264Sjacobs 			else
607*2264Sjacobs 				result = PAPI_NOT_POSSIBLE;
608*2264Sjacobs 		} else
609*2264Sjacobs 			result = PAPI_OK;
610*2264Sjacobs 
611*2264Sjacobs 		freeprinter(p);
612*2264Sjacobs 	} else
613*2264Sjacobs 		result = PAPI_NOT_POSSIBLE;
614*2264Sjacobs 
615*2264Sjacobs 	/* tell the scheduler about the changes */
616*2264Sjacobs 	if (result == PAPI_OK)
617*2264Sjacobs 		result = lpsched_load_unload_dest(handle, dest, S_LOAD_PRINTER);
618*2264Sjacobs 
619*2264Sjacobs 	return (result);
620*2264Sjacobs }
621