xref: /titanic_41/usr/src/lib/libunistat/common/spcs_s_u.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte /*
26*fcf3ce44SJohn Forte  *	The SPCS status support user utilities
27*fcf3ce44SJohn Forte  *	See spcs_s_u.h and the docs subdirectory for functional spec
28*fcf3ce44SJohn Forte  */
29*fcf3ce44SJohn Forte 
30*fcf3ce44SJohn Forte #include <stdio.h>
31*fcf3ce44SJohn Forte #include <stdlib.h>
32*fcf3ce44SJohn Forte #include <stdarg.h>
33*fcf3ce44SJohn Forte #include <string.h>
34*fcf3ce44SJohn Forte #include <errno.h>
35*fcf3ce44SJohn Forte #include <sys/types.h>
36*fcf3ce44SJohn Forte #include <locale.h>
37*fcf3ce44SJohn Forte #include <libintl.h>
38*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s.h>
39*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s_u.h>
40*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s_impl.h>
41*fcf3ce44SJohn Forte #include <sys/unistat/spcs_errors.h>
42*fcf3ce44SJohn Forte #include <sys/unistat/spcs_etext.h>
43*fcf3ce44SJohn Forte #include <sys/unistat/spcs_etrinkets.h>
44*fcf3ce44SJohn Forte #include <sys/unistat/spcs_dtrinkets.h>
45*fcf3ce44SJohn Forte 
46*fcf3ce44SJohn Forte /*
47*fcf3ce44SJohn Forte  *	Initialize ioctl status storage to "remove" any old status present
48*fcf3ce44SJohn Forte  */
49*fcf3ce44SJohn Forte 
50*fcf3ce44SJohn Forte void
spcs_s_uinit(spcs_s_info_t ustatus)51*fcf3ce44SJohn Forte spcs_s_uinit(spcs_s_info_t ustatus)
52*fcf3ce44SJohn Forte {
53*fcf3ce44SJohn Forte 	spcs_s_pinfo_t *p = (spcs_s_pinfo_t *)ustatus;
54*fcf3ce44SJohn Forte 	p->major = SPCS_S_MAJOR_REV;
55*fcf3ce44SJohn Forte 	p->minor = SPCS_S_MINOR_REV;
56*fcf3ce44SJohn Forte 	p->icount = 0;
57*fcf3ce44SJohn Forte 	p->scount = 0;
58*fcf3ce44SJohn Forte 	p->tcount = 0;
59*fcf3ce44SJohn Forte }
60*fcf3ce44SJohn Forte 
61*fcf3ce44SJohn Forte /*
62*fcf3ce44SJohn Forte  *	Create and initialize local status. Call this prior to invoking
63*fcf3ce44SJohn Forte  * 	an ioctl.
64*fcf3ce44SJohn Forte  */
65*fcf3ce44SJohn Forte 
66*fcf3ce44SJohn Forte spcs_s_info_t
spcs_s_ucreate()67*fcf3ce44SJohn Forte spcs_s_ucreate()
68*fcf3ce44SJohn Forte {
69*fcf3ce44SJohn Forte 	static int need_to_bind = 1;
70*fcf3ce44SJohn Forte 	spcs_s_pinfo_t *ustatus;
71*fcf3ce44SJohn Forte 
72*fcf3ce44SJohn Forte 	if (need_to_bind) {
73*fcf3ce44SJohn Forte 	    (void) setlocale(LC_ALL, "");
74*fcf3ce44SJohn Forte 	    (void) bindtextdomain("unistat", LIBUNISTAT_LOCALE);
75*fcf3ce44SJohn Forte 	    need_to_bind = 0;
76*fcf3ce44SJohn Forte 	};
77*fcf3ce44SJohn Forte 
78*fcf3ce44SJohn Forte 	ustatus = (spcs_s_pinfo_t *)malloc(sizeof (spcs_s_pinfo_t));
79*fcf3ce44SJohn Forte 	spcs_s_uinit((spcs_s_info_t)ustatus);
80*fcf3ce44SJohn Forte 
81*fcf3ce44SJohn Forte 	return ((spcs_s_info_t)ustatus);
82*fcf3ce44SJohn Forte }
83*fcf3ce44SJohn Forte 
84*fcf3ce44SJohn Forte /*
85*fcf3ce44SJohn Forte  *	Return the idata index of the last status code in the array (i.e.
86*fcf3ce44SJohn Forte  *	the "youngest" code present). The assumption is that the caller has
87*fcf3ce44SJohn Forte  *	checked to see that pcount is nonzero.
88*fcf3ce44SJohn Forte  */
89*fcf3ce44SJohn Forte 
90*fcf3ce44SJohn Forte ISSTATIC int
last_code_idx(spcs_s_pinfo_t * p)91*fcf3ce44SJohn Forte last_code_idx(spcs_s_pinfo_t *p)
92*fcf3ce44SJohn Forte {
93*fcf3ce44SJohn Forte 	int last = 0;
94*fcf3ce44SJohn Forte 	int idx = 0;
95*fcf3ce44SJohn Forte 
96*fcf3ce44SJohn Forte 	while (idx < p->icount) {
97*fcf3ce44SJohn Forte 		last = idx;
98*fcf3ce44SJohn Forte 		idx += p->idata[idx].f.sup_count + 1;
99*fcf3ce44SJohn Forte 	}
100*fcf3ce44SJohn Forte 	return (last);
101*fcf3ce44SJohn Forte }
102*fcf3ce44SJohn Forte 
103*fcf3ce44SJohn Forte /*
104*fcf3ce44SJohn Forte  *	Return a string with the module label and error message text or NULL
105*fcf3ce44SJohn Forte  *      if none left
106*fcf3ce44SJohn Forte  */
107*fcf3ce44SJohn Forte 
108*fcf3ce44SJohn Forte char *
spcs_s_string(spcs_s_info_t ustatus,char * msg)109*fcf3ce44SJohn Forte spcs_s_string(spcs_s_info_t ustatus, char *msg)
110*fcf3ce44SJohn Forte {
111*fcf3ce44SJohn Forte 	spcs_s_pinfo_t *p = (spcs_s_pinfo_t *)ustatus;
112*fcf3ce44SJohn Forte 	int idx;
113*fcf3ce44SJohn Forte 	int sup;
114*fcf3ce44SJohn Forte 	int s;
115*fcf3ce44SJohn Forte 	char *format;
116*fcf3ce44SJohn Forte 	char *sp[SPCS_S_MAXSUPP];
117*fcf3ce44SJohn Forte 	char mtemp[SPCS_S_MAXLINE];
118*fcf3ce44SJohn Forte 
119*fcf3ce44SJohn Forte 	if (p->icount > 0) {
120*fcf3ce44SJohn Forte 		idx = last_code_idx(p);
121*fcf3ce44SJohn Forte 		strcpy(msg, module_names[p->idata[idx].f.module]);
122*fcf3ce44SJohn Forte 		strcat(msg, ": ");
123*fcf3ce44SJohn Forte 		sup = p->idata[idx].f.sup_count;
124*fcf3ce44SJohn Forte 
125*fcf3ce44SJohn Forte 		if (p->idata[idx].f.module)
126*fcf3ce44SJohn Forte 			/*
127*fcf3ce44SJohn Forte 			 * The gettext formal parameter is a const char*
128*fcf3ce44SJohn Forte 			 * I guess the gettext creator couldn't imagine
129*fcf3ce44SJohn Forte 			 * needing a variable string. If there is an underlying
130*fcf3ce44SJohn Forte 			 * routine that can be called it should be used.
131*fcf3ce44SJohn Forte 			 * otherwise there will be a compiler warning about this
132*fcf3ce44SJohn Forte 			 * line FOREVER (TS).
133*fcf3ce44SJohn Forte 			 */
134*fcf3ce44SJohn Forte 			format = (char *)dgettext("unistat",
135*fcf3ce44SJohn Forte 				SPCS_S_MSG[p->idata[idx].f.module]
136*fcf3ce44SJohn Forte 				[p->idata[idx].f.code]);
137*fcf3ce44SJohn Forte 
138*fcf3ce44SJohn Forte 		else
139*fcf3ce44SJohn Forte 			format = strerror(p->idata[idx].f.code);
140*fcf3ce44SJohn Forte 
141*fcf3ce44SJohn Forte 		/*
142*fcf3ce44SJohn Forte 		 * step across the status code to the first supplemental data
143*fcf3ce44SJohn Forte 		 * descriptor.
144*fcf3ce44SJohn Forte 		 */
145*fcf3ce44SJohn Forte 
146*fcf3ce44SJohn Forte 		idx += 1;
147*fcf3ce44SJohn Forte 
148*fcf3ce44SJohn Forte 		/*
149*fcf3ce44SJohn Forte 		 * Initialize the array with empty string pointers so we don't
150*fcf3ce44SJohn Forte 		 * seg fault if there are actually fewer values than "%s"
151*fcf3ce44SJohn Forte 		 * format descriptors.
152*fcf3ce44SJohn Forte 		 */
153*fcf3ce44SJohn Forte 		for (s = 0; s < SPCS_S_MAXSUPP; s++)
154*fcf3ce44SJohn Forte 			sp[s] = "";
155*fcf3ce44SJohn Forte 
156*fcf3ce44SJohn Forte 		/*
157*fcf3ce44SJohn Forte 		 * Walk through the supplemental value descriptors and build
158*fcf3ce44SJohn Forte 		 * an array of string pointers.
159*fcf3ce44SJohn Forte 		 */
160*fcf3ce44SJohn Forte 
161*fcf3ce44SJohn Forte 		for (s = 0; s < sup; s++) {
162*fcf3ce44SJohn Forte 			sp[s] = (char *)(p->sdata + p->idata[idx+s].su.offset);
163*fcf3ce44SJohn Forte 		}
164*fcf3ce44SJohn Forte 
165*fcf3ce44SJohn Forte 		/*
166*fcf3ce44SJohn Forte 		 * Now format the message. The unused string pointers will be
167*fcf3ce44SJohn Forte 		 * ignored.
168*fcf3ce44SJohn Forte 		 * NOTE: Any change to SPCS_S_MAXSUPP requires a change to
169*fcf3ce44SJohn Forte 		 * this sprintf.
170*fcf3ce44SJohn Forte 		 */
171*fcf3ce44SJohn Forte 
172*fcf3ce44SJohn Forte 		sprintf(mtemp, format, sp[0], sp[1], sp[2], sp[3], sp[4], sp[5],
173*fcf3ce44SJohn Forte 				    sp[6], sp[7]);
174*fcf3ce44SJohn Forte 
175*fcf3ce44SJohn Forte 		/* remove the code and its supplemental info */
176*fcf3ce44SJohn Forte 
177*fcf3ce44SJohn Forte 		p->icount -= (sup + 1);
178*fcf3ce44SJohn Forte 
179*fcf3ce44SJohn Forte 		return (strcat(msg, mtemp));
180*fcf3ce44SJohn Forte 	} else
181*fcf3ce44SJohn Forte 		return (NULL);
182*fcf3ce44SJohn Forte }
183*fcf3ce44SJohn Forte 
184*fcf3ce44SJohn Forte /*
185*fcf3ce44SJohn Forte  *	Write status info
186*fcf3ce44SJohn Forte  */
187*fcf3ce44SJohn Forte 
188*fcf3ce44SJohn Forte void
spcs_s_report(spcs_s_info_t ustatus,FILE * fd)189*fcf3ce44SJohn Forte spcs_s_report(spcs_s_info_t ustatus, FILE *fd)
190*fcf3ce44SJohn Forte {
191*fcf3ce44SJohn Forte 	spcs_s_pinfo_t *p = (spcs_s_pinfo_t *)ustatus;
192*fcf3ce44SJohn Forte 	short saved_count = p->icount;
193*fcf3ce44SJohn Forte 	char msg[SPCS_S_MAXTEXT];
194*fcf3ce44SJohn Forte 	char *sp;
195*fcf3ce44SJohn Forte 	char *se;
196*fcf3ce44SJohn Forte 	int first_time = 1;
197*fcf3ce44SJohn Forte 
198*fcf3ce44SJohn Forte 	do {
199*fcf3ce44SJohn Forte 		if (sp = spcs_s_string(ustatus, msg))
200*fcf3ce44SJohn Forte 			fprintf(fd, "%s\n", sp);
201*fcf3ce44SJohn Forte 		else if (first_time && (errno > 0)) {
202*fcf3ce44SJohn Forte 			/*
203*fcf3ce44SJohn Forte 			 * This covers the case where Solaris aborted the
204*fcf3ce44SJohn Forte 			 * operation or the ioctl service code got an EFAULT
205*fcf3ce44SJohn Forte 			 * or something from copyin or couldn't allocate the
206*fcf3ce44SJohn Forte 			 * kernel status structure. If errno > 0 but not a
207*fcf3ce44SJohn Forte 			 * valid Solaris error code the extended error is
208*fcf3ce44SJohn Forte 			 * decoded and printed.
209*fcf3ce44SJohn Forte 			 */
210*fcf3ce44SJohn Forte 			se = strerror(errno);
211*fcf3ce44SJohn Forte 			if (se)
212*fcf3ce44SJohn Forte 				fprintf(fd, "%s\n", se);
213*fcf3ce44SJohn Forte 			else {
214*fcf3ce44SJohn Forte 				spcs_s_udata_t spcs_errno;
215*fcf3ce44SJohn Forte 
216*fcf3ce44SJohn Forte 				spcs_errno.i = errno;
217*fcf3ce44SJohn Forte 				fprintf(fd, "%s: %s\n",
218*fcf3ce44SJohn Forte 					module_names[spcs_errno.f.module],
219*fcf3ce44SJohn Forte 					dgettext("unistat",
220*fcf3ce44SJohn Forte 						SPCS_S_MSG[spcs_errno.f.module]
221*fcf3ce44SJohn Forte 						[spcs_errno.f.code]));
222*fcf3ce44SJohn Forte 
223*fcf3ce44SJohn Forte 			}
224*fcf3ce44SJohn Forte 		}
225*fcf3ce44SJohn Forte 		first_time = 0;
226*fcf3ce44SJohn Forte 	} while (sp);
227*fcf3ce44SJohn Forte 
228*fcf3ce44SJohn Forte 	p->icount = saved_count;
229*fcf3ce44SJohn Forte }
230*fcf3ce44SJohn Forte 
231*fcf3ce44SJohn Forte /*ARGSUSED*/
232*fcf3ce44SJohn Forte void
spcs_s_exception(spcs_s_info_t ustatus,void * env)233*fcf3ce44SJohn Forte spcs_s_exception(spcs_s_info_t ustatus, void *env)
234*fcf3ce44SJohn Forte {
235*fcf3ce44SJohn Forte }
236*fcf3ce44SJohn Forte 
237*fcf3ce44SJohn Forte /*
238*fcf3ce44SJohn Forte  *	Release (free) ioctl status storage.
239*fcf3ce44SJohn Forte  */
240*fcf3ce44SJohn Forte 
241*fcf3ce44SJohn Forte void
spcs_s_ufree(spcs_s_info_t * ustatus_a)242*fcf3ce44SJohn Forte spcs_s_ufree(spcs_s_info_t *ustatus_a)
243*fcf3ce44SJohn Forte {
244*fcf3ce44SJohn Forte 	free((void *)*ustatus_a);
245*fcf3ce44SJohn Forte 	*ustatus_a = NULL;
246*fcf3ce44SJohn Forte }
247