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