xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/faults.c (revision 18c2aff776a775d34a4c9893a4c72e0434d68e36)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
33 
34 #include "lpsched.h"
35 #include <syslog.h>
36 
37 static char *
38 shortenReason(char *reason)
39 {
40 	register char	*ptr, *pe;
41 	int		peLen;
42 
43 	if (strncmp(reason,"%%[",3) == 0)
44 		reason += 3;
45 
46 	while (*reason == ' ')
47 		reason++;
48 
49 	pe = "PrinterError:";
50 	peLen = strlen(pe);
51 	if (strncmp(reason,pe,peLen) == 0)
52 		reason += peLen;
53 
54 	if (((ptr = strchr(reason,']')) != NULL) && (strncmp(ptr,"]%%",3) == 0))
55 		*ptr = 0;
56 
57 	pe = reason + strlen(reason) -1;
58 	pe = reason;
59 	while (pe = strchr(pe,'\n'))
60 		*pe = ' ';
61 
62 	pe = reason + strlen(reason) -1;
63 	while ((pe > reason) && (*pe == ' ')) {
64 		*pe = 0;
65 		pe--;
66 	}
67 	return(reason);
68 }
69 
70 /**
71  ** printer_fault() - RECOGNIZE PRINTER FAULT
72  **/
73 
74 void
75 printer_fault(register PSTATUS *pps, register RSTATUS *prs, char *alert_text,
76 	 int err)
77 {
78 	register char		*why,*shortWhy;
79 
80 	pps->status |= PS_FAULTED;
81 
82 	/*  -F wait  */
83 	if (STREQU(pps->printer->fault_rec, NAME_WAIT))
84 		disable (pps, CUZ_FAULT, DISABLE_STOP);
85 
86 	/*  -F beginning  */
87 	else if (STREQU(pps->printer->fault_rec, NAME_BEGINNING))
88 		terminate (pps->exec);
89 
90 	/*  -F continue  AND  the interface program died  */
91 	else if (!(pps->status & PS_LATER) && !pps->request) {
92 		load_str (&pps->dis_reason, CUZ_STOPPED);
93 		schedule (EV_LATER, WHEN_PRINTER, EV_ENABLE, pps);
94 	}
95 
96 	if (err) {
97 		errno = err;
98 		why = makestr(alert_text, "(", PERROR, ")\n", (char *)0);
99 	} else if (! alert_text)
100 		why = makestr("exec exit fault", (char *) 0);
101 	else
102 		why = makestr(alert_text, (char *) 0);
103 
104 	if (!why)
105 		why = alert_text;
106 
107 	shortWhy = (why != alert_text ? shortenReason(why) : why);
108 
109 	load_str (&pps->fault_reason, shortWhy);
110 	dump_fault_status (pps);
111 	if (STREQU(pps->printer->fault_alert.shcmd,"show fault"))
112 		pps->status |= PS_SHOW_FAULT;
113 	else
114 		pps->status &= ~PS_SHOW_FAULT;
115 
116 	note("printer fault. type: %s, status: %x\nmsg: (%s)\n",
117 		(pps->printer->fault_alert.shcmd ?
118 		    pps->printer->fault_alert.shcmd : "??"),
119 		pps->status, shortWhy);
120 	syslog(LOG_INFO, "fault (%s), type (%s), status(%x): %s",
121 		(pps->printer->name ? pps->printer->name : "NULL"),
122 		(pps->printer->fault_alert.shcmd ?
123 			pps->printer->fault_alert.shcmd : "NULL"),
124 		pps->status, (shortWhy ? shortWhy : "NULL"));
125 
126 	if (pps->status & PS_SHOW_FAULT)
127 		schedule (EV_MESSAGE, pps);
128 	else {
129 		alert(A_PRINTER, pps, prs, shortWhy);
130 	}
131 	if (why != alert_text)
132 		Free (why);
133 }
134 
135 /**
136  ** clear_printer_fault() - RECOGNIZE PRINTER FAULT
137  **/
138 
139 void
140 clear_printer_fault(register PSTATUS *pps, char *alert_text)
141 {
142 	register char	*why, *shortWhy;
143 
144 	pps->status &= ~PS_FAULTED;
145 
146 	why = makestr(alert_text, (char *) 0);
147 
148 	shortWhy = (why ? shortenReason(why) : alert_text);
149 
150 	load_str (&pps->fault_reason, shortWhy);
151 	dump_fault_status (pps);
152 	if (STREQU(pps->printer->fault_alert.shcmd,"show fault"))
153 		pps->status |= PS_SHOW_FAULT;
154 	else
155 		pps->status &= ~PS_SHOW_FAULT;
156 
157 	if (pps->status & PS_SHOW_FAULT)
158 		schedule (EV_MESSAGE, pps);
159 	if (why != alert_text)
160 		Free(why);
161 	schedule(EV_ENABLE, pps);
162 }
163 
164 /**
165  ** dial_problem() - ADDRESS DIAL-OUT PROBLEM
166  **/
167 
168 void
169 dial_problem(register PSTATUS *pps, RSTATUS *prs, int rc)
170 {
171 	static struct problem {
172 		char			*reason;
173 		int			retry_max,
174 					dial_error;
175 	}			problems[] = {
176 		"DIAL FAILED",			10,	 2, /* D_HUNG  */
177 		"CALLER SCRIPT FAILED",		10,	 3, /* NO_ANS  */
178 		"CAN'T ACCESS DEVICE",		 0,	 6, /* L_PROB  */
179 		"DEVICE LOCKED",		20,	 8, /* DV_NT_A */
180 		"NO DEVICES AVAILABLE",		 0,	10, /* NO_BD_A */
181 		"SYSTEM NOT IN Systems FILE",	 0,	13, /* BAD_SYS */
182 		"UNKNOWN dial() FAILURE",	 0,	0
183 	};
184 
185 	register struct problem	*p;
186 
187 	register char		*msg;
188 
189 #define PREFIX	"Connect problem: "
190 #define SUFFIX	"This problem has occurred several times.\nPlease check the dialing instructions for this printer.\n"
191 
192 
193 	for (p = problems; p->dial_error; p++)
194 		if (p->dial_error == rc)
195 			break;
196 
197 	if (!p->retry_max) {
198 		msg = Malloc(strlen(PREFIX) + strlen(p->reason) + 2);
199 		sprintf (msg, "%s%s\n", PREFIX, p->reason);
200 		printer_fault (pps, prs, msg, 0);
201 		Free (msg);
202 
203 	} else if (pps->last_dial_rc != rc) {
204 		pps->nretry = 1;
205 		pps->last_dial_rc = (short)rc;
206 
207 	} else if (pps->nretry++ > p->retry_max) {
208 		pps->nretry = 0;
209 		pps->last_dial_rc = (short)rc;
210 		msg = Malloc(
211 		strlen(PREFIX) + strlen(p->reason) + strlen(SUFFIX) + 2
212 		);
213 		sprintf (msg, "%s%s%s\n", PREFIX, p->reason, SUFFIX);
214 		printer_fault (pps, prs, msg, 0);
215 		Free (msg);
216 	}
217 
218 	if (!(pps->status & PS_FAULTED)) {
219 		load_str (&pps->dis_reason, p->reason);
220 		schedule (EV_LATER, WHEN_PRINTER, EV_ENABLE, pps);
221 	}
222 
223 	return;
224 }
225