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