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 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 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 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 * 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 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 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 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