1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include "cfga_usb.h" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #define MAXLINESIZE 512 33*7c478bd9Sstevel@tonic-gate #define FE_BUFLEN 256 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #define isunary(ch) ((ch) == '~' || (ch) == '-') 36*7c478bd9Sstevel@tonic-gate #define iswhite(ch) ((ch) == ' ' || (ch) == '\t') 37*7c478bd9Sstevel@tonic-gate #define isnewline(ch) ((ch) == '\n' || (ch) == '\r' || (ch) == '\f') 38*7c478bd9Sstevel@tonic-gate #define isalphanum(ch) (isalpha(ch) || isdigit(ch)) 39*7c478bd9Sstevel@tonic-gate #define isnamechar(ch) (isalphanum(ch) || (ch) == '_' || (ch) == '-') 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #define MAX(a, b) ((a) < (b) ? (b) : (a)) 42*7c478bd9Sstevel@tonic-gate #define GETC(a, cntr) a[cntr++] 43*7c478bd9Sstevel@tonic-gate #define UNGETC(cntr) cntr-- 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate typedef struct usb_configrec { 47*7c478bd9Sstevel@tonic-gate char *selection; 48*7c478bd9Sstevel@tonic-gate int idVendor, idProduct, cfgndx; 49*7c478bd9Sstevel@tonic-gate char *serialno; 50*7c478bd9Sstevel@tonic-gate char *pathname; 51*7c478bd9Sstevel@tonic-gate char *driver; 52*7c478bd9Sstevel@tonic-gate } usb_configrec_t; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate typedef enum { 55*7c478bd9Sstevel@tonic-gate USB_SELECTION, USB_VENDOR, USB_PRODUCT, USB_CFGNDX, USB_SRNO, 56*7c478bd9Sstevel@tonic-gate USB_PATH, USB_DRIVER, USB_NONE 57*7c478bd9Sstevel@tonic-gate } config_field_t; 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate typedef struct usbcfg_var { 60*7c478bd9Sstevel@tonic-gate const char *name; 61*7c478bd9Sstevel@tonic-gate config_field_t field; 62*7c478bd9Sstevel@tonic-gate } usbcfg_var_t; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static usbcfg_var_t usbcfg_varlist[] = { 65*7c478bd9Sstevel@tonic-gate { "selection", USB_SELECTION }, 66*7c478bd9Sstevel@tonic-gate { "idVendor", USB_VENDOR }, 67*7c478bd9Sstevel@tonic-gate { "idProduct", USB_PRODUCT }, 68*7c478bd9Sstevel@tonic-gate { "cfgndx", USB_CFGNDX }, 69*7c478bd9Sstevel@tonic-gate { "srno", USB_SRNO }, 70*7c478bd9Sstevel@tonic-gate { "pathname", USB_PATH }, 71*7c478bd9Sstevel@tonic-gate { "driver", USB_DRIVER }, 72*7c478bd9Sstevel@tonic-gate { NULL, USB_NONE } 73*7c478bd9Sstevel@tonic-gate }; 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate typedef enum { 76*7c478bd9Sstevel@tonic-gate EQUALS, 77*7c478bd9Sstevel@tonic-gate AMPERSAND, 78*7c478bd9Sstevel@tonic-gate BIT_OR, 79*7c478bd9Sstevel@tonic-gate STAR, 80*7c478bd9Sstevel@tonic-gate POUND, 81*7c478bd9Sstevel@tonic-gate COLON, 82*7c478bd9Sstevel@tonic-gate SEMICOLON, 83*7c478bd9Sstevel@tonic-gate COMMA, 84*7c478bd9Sstevel@tonic-gate SLASH, 85*7c478bd9Sstevel@tonic-gate WHITE_SPACE, 86*7c478bd9Sstevel@tonic-gate NEWLINE, 87*7c478bd9Sstevel@tonic-gate E_O_F, 88*7c478bd9Sstevel@tonic-gate STRING, 89*7c478bd9Sstevel@tonic-gate HEXVAL, 90*7c478bd9Sstevel@tonic-gate DECVAL, 91*7c478bd9Sstevel@tonic-gate NAME 92*7c478bd9Sstevel@tonic-gate } token_t; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate static char usbconf_file[] = USBCONF_FILE; 96*7c478bd9Sstevel@tonic-gate static int linenum = 1; 97*7c478bd9Sstevel@tonic-gate static int cntr = 0; 98*7c478bd9Sstevel@tonic-gate static int frec = 0; 99*7c478bd9Sstevel@tonic-gate static int brec = 0; 100*7c478bd9Sstevel@tonic-gate static int btoken = 0; 101*7c478bd9Sstevel@tonic-gate mutex_t file_lock = DEFAULTMUTEX; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * prototypes 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate static int get_string(u_longlong_t *llptr, char *tchar); 108*7c478bd9Sstevel@tonic-gate static int getvalue(char *token, u_longlong_t *valuep); 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* 112*7c478bd9Sstevel@tonic-gate * The next item on the line is a string value. Allocate memory for 113*7c478bd9Sstevel@tonic-gate * it and copy the string. Return 1, and set arg ptr to newly allocated 114*7c478bd9Sstevel@tonic-gate * and initialized buffer, or NULL if an error occurs. 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate static int 117*7c478bd9Sstevel@tonic-gate get_string(u_longlong_t *llptr, char *tchar) 118*7c478bd9Sstevel@tonic-gate { 119*7c478bd9Sstevel@tonic-gate register char *cp; 120*7c478bd9Sstevel@tonic-gate register char *start = (char *)0; 121*7c478bd9Sstevel@tonic-gate register int len = 0; 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate len = strlen(tchar); 124*7c478bd9Sstevel@tonic-gate start = tchar; 125*7c478bd9Sstevel@tonic-gate /* copy string */ 126*7c478bd9Sstevel@tonic-gate cp = (char *)calloc(len + 1, sizeof (char)); 127*7c478bd9Sstevel@tonic-gate if (cp == (char *)NULL) { 128*7c478bd9Sstevel@tonic-gate *llptr = NULL; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate return (0); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate *llptr = (u_longlong_t)(uintptr_t)cp; 134*7c478bd9Sstevel@tonic-gate for (; len > 0; len--) { 135*7c478bd9Sstevel@tonic-gate /* convert some common escape sequences */ 136*7c478bd9Sstevel@tonic-gate if (*start == '\\') { 137*7c478bd9Sstevel@tonic-gate switch (*(start + 1)) { 138*7c478bd9Sstevel@tonic-gate case 't': 139*7c478bd9Sstevel@tonic-gate /* tab */ 140*7c478bd9Sstevel@tonic-gate *cp++ = '\t'; 141*7c478bd9Sstevel@tonic-gate len--; 142*7c478bd9Sstevel@tonic-gate start += 2; 143*7c478bd9Sstevel@tonic-gate break; 144*7c478bd9Sstevel@tonic-gate case 'n': 145*7c478bd9Sstevel@tonic-gate /* new line */ 146*7c478bd9Sstevel@tonic-gate *cp++ = '\n'; 147*7c478bd9Sstevel@tonic-gate len--; 148*7c478bd9Sstevel@tonic-gate start += 2; 149*7c478bd9Sstevel@tonic-gate break; 150*7c478bd9Sstevel@tonic-gate case 'b': 151*7c478bd9Sstevel@tonic-gate /* back space */ 152*7c478bd9Sstevel@tonic-gate *cp++ = '\b'; 153*7c478bd9Sstevel@tonic-gate len--; 154*7c478bd9Sstevel@tonic-gate start += 2; 155*7c478bd9Sstevel@tonic-gate break; 156*7c478bd9Sstevel@tonic-gate default: 157*7c478bd9Sstevel@tonic-gate /* simply copy it */ 158*7c478bd9Sstevel@tonic-gate *cp++ = *start++; 159*7c478bd9Sstevel@tonic-gate break; 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate } else { 162*7c478bd9Sstevel@tonic-gate *cp++ = *start++; 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate *cp = '\0'; 166*7c478bd9Sstevel@tonic-gate return (1); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate /* 171*7c478bd9Sstevel@tonic-gate * get a decimal octal or hex number. Handle '~' for one's complement. 172*7c478bd9Sstevel@tonic-gate */ 173*7c478bd9Sstevel@tonic-gate static int 174*7c478bd9Sstevel@tonic-gate getvalue(char *token, u_longlong_t *valuep) 175*7c478bd9Sstevel@tonic-gate { 176*7c478bd9Sstevel@tonic-gate register int radix; 177*7c478bd9Sstevel@tonic-gate register u_longlong_t retval = 0; 178*7c478bd9Sstevel@tonic-gate register int onescompl = 0; 179*7c478bd9Sstevel@tonic-gate register int negate = 0; 180*7c478bd9Sstevel@tonic-gate register char c; 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate if (*token == '~') { 183*7c478bd9Sstevel@tonic-gate onescompl++; /* perform one's complement on result */ 184*7c478bd9Sstevel@tonic-gate token++; 185*7c478bd9Sstevel@tonic-gate } else if (*token == '-') { 186*7c478bd9Sstevel@tonic-gate negate++; 187*7c478bd9Sstevel@tonic-gate token++; 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate if (*token == '0') { 190*7c478bd9Sstevel@tonic-gate token++; 191*7c478bd9Sstevel@tonic-gate c = *token; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate if (c == '\0') { 194*7c478bd9Sstevel@tonic-gate *valuep = 0; /* value is 0 */ 195*7c478bd9Sstevel@tonic-gate return (0); 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate if (c == 'x' || c == 'X') { 199*7c478bd9Sstevel@tonic-gate radix = 16; 200*7c478bd9Sstevel@tonic-gate token++; 201*7c478bd9Sstevel@tonic-gate } else { 202*7c478bd9Sstevel@tonic-gate radix = 8; 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate } else { 205*7c478bd9Sstevel@tonic-gate radix = 10; 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate while ((c = *token++)) { 209*7c478bd9Sstevel@tonic-gate switch (radix) { 210*7c478bd9Sstevel@tonic-gate case 8: 211*7c478bd9Sstevel@tonic-gate if (c >= '0' && c <= '7') { 212*7c478bd9Sstevel@tonic-gate c -= '0'; 213*7c478bd9Sstevel@tonic-gate } else { 214*7c478bd9Sstevel@tonic-gate return (-1); /* invalid number */ 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate retval = (retval << 3) + c; 217*7c478bd9Sstevel@tonic-gate break; 218*7c478bd9Sstevel@tonic-gate case 10: 219*7c478bd9Sstevel@tonic-gate if (c >= '0' && c <= '9') { 220*7c478bd9Sstevel@tonic-gate c -= '0'; 221*7c478bd9Sstevel@tonic-gate } else { 222*7c478bd9Sstevel@tonic-gate return (-1); /* invalid number */ 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate retval = (retval * 10) + c; 225*7c478bd9Sstevel@tonic-gate break; 226*7c478bd9Sstevel@tonic-gate case 16: 227*7c478bd9Sstevel@tonic-gate if (c >= 'a' && c <= 'f') { 228*7c478bd9Sstevel@tonic-gate c = c - 'a' + 10; 229*7c478bd9Sstevel@tonic-gate } else if (c >= 'A' && c <= 'F') { 230*7c478bd9Sstevel@tonic-gate c = c - 'A' + 10; 231*7c478bd9Sstevel@tonic-gate } else if (c >= '0' && c <= '9') { 232*7c478bd9Sstevel@tonic-gate c -= '0'; 233*7c478bd9Sstevel@tonic-gate } else { 234*7c478bd9Sstevel@tonic-gate return (-1); /* invalid number */ 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate retval = (retval << 4) + c; 237*7c478bd9Sstevel@tonic-gate break; 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate if (onescompl) 241*7c478bd9Sstevel@tonic-gate retval = ~retval; 242*7c478bd9Sstevel@tonic-gate if (negate) 243*7c478bd9Sstevel@tonic-gate retval = -retval; 244*7c478bd9Sstevel@tonic-gate *valuep = retval; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate return (0); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate /* 250*7c478bd9Sstevel@tonic-gate * returns the field from the token 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate static config_field_t 253*7c478bd9Sstevel@tonic-gate usb_get_var_type(char *str) 254*7c478bd9Sstevel@tonic-gate { 255*7c478bd9Sstevel@tonic-gate usbcfg_var_t *cfgvar; 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate cfgvar = &usbcfg_varlist[0]; 258*7c478bd9Sstevel@tonic-gate while (cfgvar->field != USB_NONE) { 259*7c478bd9Sstevel@tonic-gate if (strcasecmp(cfgvar->name, str) == NULL) { 260*7c478bd9Sstevel@tonic-gate break; 261*7c478bd9Sstevel@tonic-gate } else { 262*7c478bd9Sstevel@tonic-gate cfgvar++; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate return (cfgvar->field); 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 271*7c478bd9Sstevel@tonic-gate static token_t 272*7c478bd9Sstevel@tonic-gate lex(char *buf, char *val, char **errmsg) 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate int ch, oval, badquote; 275*7c478bd9Sstevel@tonic-gate char *cp; 276*7c478bd9Sstevel@tonic-gate token_t token; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate cp = val; 279*7c478bd9Sstevel@tonic-gate while ((ch = GETC(buf, cntr)) == ' ' || ch == '\t'); 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * Note the beginning of a token 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate btoken = cntr - 1; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 287*7c478bd9Sstevel@tonic-gate switch (ch) { 288*7c478bd9Sstevel@tonic-gate case '=': 289*7c478bd9Sstevel@tonic-gate token = EQUALS; 290*7c478bd9Sstevel@tonic-gate break; 291*7c478bd9Sstevel@tonic-gate case '&': 292*7c478bd9Sstevel@tonic-gate token = AMPERSAND; 293*7c478bd9Sstevel@tonic-gate break; 294*7c478bd9Sstevel@tonic-gate case '|': 295*7c478bd9Sstevel@tonic-gate token = BIT_OR; 296*7c478bd9Sstevel@tonic-gate break; 297*7c478bd9Sstevel@tonic-gate case '*': 298*7c478bd9Sstevel@tonic-gate token = STAR; 299*7c478bd9Sstevel@tonic-gate break; 300*7c478bd9Sstevel@tonic-gate case '#': 301*7c478bd9Sstevel@tonic-gate token = POUND; 302*7c478bd9Sstevel@tonic-gate break; 303*7c478bd9Sstevel@tonic-gate case ':': 304*7c478bd9Sstevel@tonic-gate token = COLON; 305*7c478bd9Sstevel@tonic-gate break; 306*7c478bd9Sstevel@tonic-gate case ';': 307*7c478bd9Sstevel@tonic-gate token = SEMICOLON; 308*7c478bd9Sstevel@tonic-gate break; 309*7c478bd9Sstevel@tonic-gate case ',': 310*7c478bd9Sstevel@tonic-gate token = COMMA; 311*7c478bd9Sstevel@tonic-gate break; 312*7c478bd9Sstevel@tonic-gate case '/': 313*7c478bd9Sstevel@tonic-gate token = SLASH; 314*7c478bd9Sstevel@tonic-gate break; 315*7c478bd9Sstevel@tonic-gate case ' ': 316*7c478bd9Sstevel@tonic-gate case '\t': 317*7c478bd9Sstevel@tonic-gate case '\f': 318*7c478bd9Sstevel@tonic-gate while ((ch = GETC(buf, cntr)) == ' ' || 319*7c478bd9Sstevel@tonic-gate ch == '\t' || ch == '\f') 320*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 321*7c478bd9Sstevel@tonic-gate (void) UNGETC(cntr); 322*7c478bd9Sstevel@tonic-gate token = WHITE_SPACE; 323*7c478bd9Sstevel@tonic-gate break; 324*7c478bd9Sstevel@tonic-gate case '\n': 325*7c478bd9Sstevel@tonic-gate case '\r': 326*7c478bd9Sstevel@tonic-gate token = NEWLINE; 327*7c478bd9Sstevel@tonic-gate break; 328*7c478bd9Sstevel@tonic-gate case '"': 329*7c478bd9Sstevel@tonic-gate cp--; 330*7c478bd9Sstevel@tonic-gate badquote = 0; 331*7c478bd9Sstevel@tonic-gate while (!badquote && (ch = GETC(buf, cntr)) != '"') { 332*7c478bd9Sstevel@tonic-gate switch (ch) { 333*7c478bd9Sstevel@tonic-gate case '\n': 334*7c478bd9Sstevel@tonic-gate case -1: 335*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 336*7c478bd9Sstevel@tonic-gate "Missing \""); 337*7c478bd9Sstevel@tonic-gate cp = val; 338*7c478bd9Sstevel@tonic-gate *cp++ = '\n'; 339*7c478bd9Sstevel@tonic-gate badquote = 1; 340*7c478bd9Sstevel@tonic-gate /* since we consumed the newline/EOF */ 341*7c478bd9Sstevel@tonic-gate (void) UNGETC(cntr); 342*7c478bd9Sstevel@tonic-gate break; 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate case '\\': 345*7c478bd9Sstevel@tonic-gate ch = (char)GETC(buf, cntr); 346*7c478bd9Sstevel@tonic-gate if (!isdigit(ch)) { 347*7c478bd9Sstevel@tonic-gate /* escape the character */ 348*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 349*7c478bd9Sstevel@tonic-gate break; 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate oval = 0; 352*7c478bd9Sstevel@tonic-gate while (ch >= '0' && ch <= '7') { 353*7c478bd9Sstevel@tonic-gate ch -= '0'; 354*7c478bd9Sstevel@tonic-gate oval = (oval << 3) + ch; 355*7c478bd9Sstevel@tonic-gate ch = (char)GETC(buf, cntr); 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate (void) UNGETC(cntr); 358*7c478bd9Sstevel@tonic-gate /* check for character overflow? */ 359*7c478bd9Sstevel@tonic-gate if (oval > 127) { 360*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 361*7c478bd9Sstevel@tonic-gate "Character overflow detected.\n"); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate *cp++ = (char)oval; 364*7c478bd9Sstevel@tonic-gate break; 365*7c478bd9Sstevel@tonic-gate default: 366*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 367*7c478bd9Sstevel@tonic-gate break; 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate token = STRING; 371*7c478bd9Sstevel@tonic-gate break; 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate default: 374*7c478bd9Sstevel@tonic-gate if (ch == -1) { 375*7c478bd9Sstevel@tonic-gate token = EOF; 376*7c478bd9Sstevel@tonic-gate break; 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate /* 379*7c478bd9Sstevel@tonic-gate * detect a lone '-' (including at the end of a line), and 380*7c478bd9Sstevel@tonic-gate * identify it as a 'name' 381*7c478bd9Sstevel@tonic-gate */ 382*7c478bd9Sstevel@tonic-gate if (ch == '-') { 383*7c478bd9Sstevel@tonic-gate *cp++ = (char)(ch = GETC(buf, cntr)); 384*7c478bd9Sstevel@tonic-gate if (iswhite(ch) || (ch == '\n')) { 385*7c478bd9Sstevel@tonic-gate (void) UNGETC(cntr); 386*7c478bd9Sstevel@tonic-gate cp--; 387*7c478bd9Sstevel@tonic-gate token = NAME; 388*7c478bd9Sstevel@tonic-gate break; 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate } else if (isunary(ch)) { 391*7c478bd9Sstevel@tonic-gate *cp++ = (char)(ch = GETC(buf, cntr)); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate if (isdigit(ch)) { 395*7c478bd9Sstevel@tonic-gate if (ch == '0') { 396*7c478bd9Sstevel@tonic-gate if ((ch = GETC(buf, cntr)) == 'x') { 397*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 398*7c478bd9Sstevel@tonic-gate ch = GETC(buf, cntr); 399*7c478bd9Sstevel@tonic-gate while (isxdigit(ch)) { 400*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 401*7c478bd9Sstevel@tonic-gate ch = GETC(buf, cntr); 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate (void) UNGETC(cntr); 404*7c478bd9Sstevel@tonic-gate token = HEXVAL; 405*7c478bd9Sstevel@tonic-gate } else { 406*7c478bd9Sstevel@tonic-gate goto digit; 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate } else { 409*7c478bd9Sstevel@tonic-gate ch = GETC(buf, cntr); 410*7c478bd9Sstevel@tonic-gate digit: 411*7c478bd9Sstevel@tonic-gate while (isdigit(ch)) { 412*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 413*7c478bd9Sstevel@tonic-gate ch = GETC(buf, cntr); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate (void) UNGETC(cntr); 416*7c478bd9Sstevel@tonic-gate token = DECVAL; 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate } else if (isalpha(ch) || ch == '\\') { 419*7c478bd9Sstevel@tonic-gate if (ch != '\\') { 420*7c478bd9Sstevel@tonic-gate ch = GETC(buf, cntr); 421*7c478bd9Sstevel@tonic-gate } else { 422*7c478bd9Sstevel@tonic-gate /* 423*7c478bd9Sstevel@tonic-gate * if the character was a backslash, 424*7c478bd9Sstevel@tonic-gate * back up so we can overwrite it with 425*7c478bd9Sstevel@tonic-gate * the next (i.e. escaped) character. 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate cp--; 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate while (isnamechar(ch) || ch == '\\') { 431*7c478bd9Sstevel@tonic-gate if (ch == '\\') 432*7c478bd9Sstevel@tonic-gate ch = GETC(buf, cntr); 433*7c478bd9Sstevel@tonic-gate *cp++ = (char)ch; 434*7c478bd9Sstevel@tonic-gate ch = GETC(buf, cntr); 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate (void) UNGETC(cntr); 437*7c478bd9Sstevel@tonic-gate token = NAME; 438*7c478bd9Sstevel@tonic-gate } else { 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate return (-1); 441*7c478bd9Sstevel@tonic-gate } 442*7c478bd9Sstevel@tonic-gate break; 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate *cp = '\0'; 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate return (token); 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate /* 451*7c478bd9Sstevel@tonic-gate * Leave NEWLINE as the next character. 452*7c478bd9Sstevel@tonic-gate */ 453*7c478bd9Sstevel@tonic-gate static void 454*7c478bd9Sstevel@tonic-gate find_eol(char *buf) 455*7c478bd9Sstevel@tonic-gate { 456*7c478bd9Sstevel@tonic-gate register int ch; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate while ((ch = GETC(buf, cntr)) != -1) { 459*7c478bd9Sstevel@tonic-gate if (isnewline(ch)) { 460*7c478bd9Sstevel@tonic-gate (void) UNGETC(cntr); 461*7c478bd9Sstevel@tonic-gate break; 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate /* 468*7c478bd9Sstevel@tonic-gate * Fetch one record from the USBCONF_FILE 469*7c478bd9Sstevel@tonic-gate */ 470*7c478bd9Sstevel@tonic-gate static token_t 471*7c478bd9Sstevel@tonic-gate usb_get_conf_rec(char *buf, usb_configrec_t **rec, char **errmsg) 472*7c478bd9Sstevel@tonic-gate { 473*7c478bd9Sstevel@tonic-gate token_t token; 474*7c478bd9Sstevel@tonic-gate char tokval[MAXLINESIZE]; 475*7c478bd9Sstevel@tonic-gate usb_configrec_t *user_rec; 476*7c478bd9Sstevel@tonic-gate config_field_t cfgvar; 477*7c478bd9Sstevel@tonic-gate u_longlong_t llptr; 478*7c478bd9Sstevel@tonic-gate u_longlong_t value; 479*7c478bd9Sstevel@tonic-gate boolean_t sor = B_TRUE; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate enum { 482*7c478bd9Sstevel@tonic-gate USB_NEWVAR, USB_CONFIG_VAR, USB_VAR_EQUAL, USB_VAR_VALUE, 483*7c478bd9Sstevel@tonic-gate USB_ERROR 484*7c478bd9Sstevel@tonic-gate } parse_state = USB_NEWVAR; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate DPRINTF("usb_get_conf_rec:\n"); 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate user_rec = (usb_configrec_t *)calloc(1, sizeof (usb_configrec_t)); 489*7c478bd9Sstevel@tonic-gate if (user_rec == (usb_configrec_t *)NULL) { 490*7c478bd9Sstevel@tonic-gate return (0); 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate user_rec->idVendor = user_rec->idProduct = user_rec->cfgndx = -1; 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate token = lex(buf, tokval, errmsg); 496*7c478bd9Sstevel@tonic-gate while ((token != EOF) && (token != SEMICOLON)) { 497*7c478bd9Sstevel@tonic-gate switch (token) { 498*7c478bd9Sstevel@tonic-gate case STAR: 499*7c478bd9Sstevel@tonic-gate case POUND: 500*7c478bd9Sstevel@tonic-gate /* skip comments */ 501*7c478bd9Sstevel@tonic-gate find_eol(buf); 502*7c478bd9Sstevel@tonic-gate break; 503*7c478bd9Sstevel@tonic-gate case NEWLINE: 504*7c478bd9Sstevel@tonic-gate linenum++; 505*7c478bd9Sstevel@tonic-gate break; 506*7c478bd9Sstevel@tonic-gate case NAME: 507*7c478bd9Sstevel@tonic-gate case STRING: 508*7c478bd9Sstevel@tonic-gate switch (parse_state) { 509*7c478bd9Sstevel@tonic-gate case USB_NEWVAR: 510*7c478bd9Sstevel@tonic-gate cfgvar = usb_get_var_type(tokval); 511*7c478bd9Sstevel@tonic-gate if (cfgvar == USB_NONE) { 512*7c478bd9Sstevel@tonic-gate parse_state = USB_ERROR; 513*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 514*7c478bd9Sstevel@tonic-gate "Syntax Error: Invalid field %s", 515*7c478bd9Sstevel@tonic-gate tokval); 516*7c478bd9Sstevel@tonic-gate } else { 517*7c478bd9Sstevel@tonic-gate /* 518*7c478bd9Sstevel@tonic-gate * Note the beginning of a record 519*7c478bd9Sstevel@tonic-gate */ 520*7c478bd9Sstevel@tonic-gate if (sor) { 521*7c478bd9Sstevel@tonic-gate brec = btoken; 522*7c478bd9Sstevel@tonic-gate if (frec == 0) frec = brec; 523*7c478bd9Sstevel@tonic-gate sor = B_FALSE; 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate parse_state = USB_CONFIG_VAR; 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate break; 528*7c478bd9Sstevel@tonic-gate case USB_VAR_VALUE: 529*7c478bd9Sstevel@tonic-gate if ((cfgvar == USB_VENDOR) || 530*7c478bd9Sstevel@tonic-gate (cfgvar == USB_PRODUCT) || 531*7c478bd9Sstevel@tonic-gate (cfgvar == USB_CFGNDX)) { 532*7c478bd9Sstevel@tonic-gate parse_state = USB_ERROR; 533*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 534*7c478bd9Sstevel@tonic-gate "Syntax Error: Invalid value %s " 535*7c478bd9Sstevel@tonic-gate "for field: %s\n", tokval, 536*7c478bd9Sstevel@tonic-gate usbcfg_varlist[cfgvar].name); 537*7c478bd9Sstevel@tonic-gate } else if (get_string(&llptr, tokval)) { 538*7c478bd9Sstevel@tonic-gate switch (cfgvar) { 539*7c478bd9Sstevel@tonic-gate case USB_SELECTION: 540*7c478bd9Sstevel@tonic-gate user_rec->selection = 541*7c478bd9Sstevel@tonic-gate (char *)llptr; 542*7c478bd9Sstevel@tonic-gate parse_state = USB_NEWVAR; 543*7c478bd9Sstevel@tonic-gate break; 544*7c478bd9Sstevel@tonic-gate case USB_SRNO: 545*7c478bd9Sstevel@tonic-gate user_rec->serialno = 546*7c478bd9Sstevel@tonic-gate (char *)llptr; 547*7c478bd9Sstevel@tonic-gate parse_state = USB_NEWVAR; 548*7c478bd9Sstevel@tonic-gate break; 549*7c478bd9Sstevel@tonic-gate case USB_PATH: 550*7c478bd9Sstevel@tonic-gate user_rec->pathname = 551*7c478bd9Sstevel@tonic-gate (char *)llptr; 552*7c478bd9Sstevel@tonic-gate parse_state = USB_NEWVAR; 553*7c478bd9Sstevel@tonic-gate break; 554*7c478bd9Sstevel@tonic-gate case USB_DRIVER: 555*7c478bd9Sstevel@tonic-gate user_rec->driver = 556*7c478bd9Sstevel@tonic-gate (char *)llptr; 557*7c478bd9Sstevel@tonic-gate parse_state = USB_NEWVAR; 558*7c478bd9Sstevel@tonic-gate break; 559*7c478bd9Sstevel@tonic-gate default: 560*7c478bd9Sstevel@tonic-gate parse_state = USB_ERROR; 561*7c478bd9Sstevel@tonic-gate free((char *)llptr); 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate } else { 564*7c478bd9Sstevel@tonic-gate parse_state = USB_ERROR; 565*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 566*7c478bd9Sstevel@tonic-gate "Syntax Error: Invalid value %s " 567*7c478bd9Sstevel@tonic-gate "for field: %s\n", tokval, 568*7c478bd9Sstevel@tonic-gate usbcfg_varlist[cfgvar].name); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate break; 571*7c478bd9Sstevel@tonic-gate case USB_ERROR: 572*7c478bd9Sstevel@tonic-gate /* just skip */ 573*7c478bd9Sstevel@tonic-gate break; 574*7c478bd9Sstevel@tonic-gate default: 575*7c478bd9Sstevel@tonic-gate parse_state = USB_ERROR; 576*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 577*7c478bd9Sstevel@tonic-gate "Syntax Error: at %s", tokval); 578*7c478bd9Sstevel@tonic-gate break; 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate break; 581*7c478bd9Sstevel@tonic-gate case EQUALS: 582*7c478bd9Sstevel@tonic-gate if (parse_state == USB_CONFIG_VAR) { 583*7c478bd9Sstevel@tonic-gate if (cfgvar == USB_NONE) { 584*7c478bd9Sstevel@tonic-gate parse_state = USB_ERROR; 585*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 586*7c478bd9Sstevel@tonic-gate "Syntax Error: unexpected '='"); 587*7c478bd9Sstevel@tonic-gate } else { 588*7c478bd9Sstevel@tonic-gate parse_state = USB_VAR_VALUE; 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate } else if (parse_state != USB_ERROR) { 591*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 592*7c478bd9Sstevel@tonic-gate "Syntax Error: unexpected '='"); 593*7c478bd9Sstevel@tonic-gate parse_state = USB_ERROR; 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate break; 596*7c478bd9Sstevel@tonic-gate case HEXVAL: 597*7c478bd9Sstevel@tonic-gate case DECVAL: 598*7c478bd9Sstevel@tonic-gate if ((parse_state == USB_VAR_VALUE) && (cfgvar != 599*7c478bd9Sstevel@tonic-gate USB_NONE)) { 600*7c478bd9Sstevel@tonic-gate (void) getvalue(tokval, &value); 601*7c478bd9Sstevel@tonic-gate switch (cfgvar) { 602*7c478bd9Sstevel@tonic-gate case USB_VENDOR: 603*7c478bd9Sstevel@tonic-gate user_rec->idVendor = (int)value; 604*7c478bd9Sstevel@tonic-gate parse_state = USB_NEWVAR; 605*7c478bd9Sstevel@tonic-gate break; 606*7c478bd9Sstevel@tonic-gate case USB_PRODUCT: 607*7c478bd9Sstevel@tonic-gate user_rec->idProduct = (int)value; 608*7c478bd9Sstevel@tonic-gate parse_state = USB_NEWVAR; 609*7c478bd9Sstevel@tonic-gate break; 610*7c478bd9Sstevel@tonic-gate case USB_CFGNDX: 611*7c478bd9Sstevel@tonic-gate user_rec->cfgndx = (int)value; 612*7c478bd9Sstevel@tonic-gate parse_state = USB_NEWVAR; 613*7c478bd9Sstevel@tonic-gate break; 614*7c478bd9Sstevel@tonic-gate default: 615*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 616*7c478bd9Sstevel@tonic-gate "Syntax Error: Invalid value for " 617*7c478bd9Sstevel@tonic-gate "%s", usbcfg_varlist[cfgvar].name); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate } else if (parse_state != USB_ERROR) { 620*7c478bd9Sstevel@tonic-gate parse_state = USB_ERROR; 621*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 622*7c478bd9Sstevel@tonic-gate "Syntax Error: unexpected hex/decimal: %s", 623*7c478bd9Sstevel@tonic-gate tokval); 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate break; 626*7c478bd9Sstevel@tonic-gate default: 627*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 628*7c478bd9Sstevel@tonic-gate "Syntax Error: at: %s", tokval); 629*7c478bd9Sstevel@tonic-gate parse_state = USB_ERROR; 630*7c478bd9Sstevel@tonic-gate break; 631*7c478bd9Sstevel@tonic-gate } 632*7c478bd9Sstevel@tonic-gate token = lex(buf, tokval, errmsg); 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate *rec = user_rec; 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate return (token); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* 641*7c478bd9Sstevel@tonic-gate * Here we compare the two records and determine if they are the same 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate static boolean_t 644*7c478bd9Sstevel@tonic-gate usb_cmp_rec(usb_configrec_t *cfg_rec, usb_configrec_t *user_rec) 645*7c478bd9Sstevel@tonic-gate { 646*7c478bd9Sstevel@tonic-gate char *ustr, *cstr; 647*7c478bd9Sstevel@tonic-gate boolean_t srno = B_FALSE, path = B_FALSE; 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate DPRINTF("usb_cmp_rec:\n"); 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate if ((cfg_rec->idVendor == user_rec->idVendor) && 652*7c478bd9Sstevel@tonic-gate (cfg_rec->idProduct == user_rec->idProduct)) { 653*7c478bd9Sstevel@tonic-gate if (user_rec->serialno) { 654*7c478bd9Sstevel@tonic-gate if (cfg_rec->serialno) { 655*7c478bd9Sstevel@tonic-gate srno = (strcmp(cfg_rec->serialno, 656*7c478bd9Sstevel@tonic-gate user_rec->serialno) == 0); 657*7c478bd9Sstevel@tonic-gate } else { 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate return (B_FALSE); 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate } else if (user_rec->pathname) { 663*7c478bd9Sstevel@tonic-gate if (cfg_rec->pathname) { 664*7c478bd9Sstevel@tonic-gate /* 665*7c478bd9Sstevel@tonic-gate * Comparing on this is tricky. At this point 666*7c478bd9Sstevel@tonic-gate * hubd knows: ../hubd@P/device@P while user 667*7c478bd9Sstevel@tonic-gate * will specify ..../hubd@P/keyboard@P 668*7c478bd9Sstevel@tonic-gate * First compare till .../hubd@P 669*7c478bd9Sstevel@tonic-gate * Second compare is just P in "device@P" 670*7c478bd9Sstevel@tonic-gate * 671*7c478bd9Sstevel@tonic-gate * XXX: note that we assume P as one character 672*7c478bd9Sstevel@tonic-gate * as there are no 2 digit hubs in the market. 673*7c478bd9Sstevel@tonic-gate */ 674*7c478bd9Sstevel@tonic-gate ustr = strrchr(user_rec->pathname, '/'); 675*7c478bd9Sstevel@tonic-gate cstr = strrchr(cfg_rec->pathname, '/'); 676*7c478bd9Sstevel@tonic-gate path = (strncmp(cfg_rec->pathname, 677*7c478bd9Sstevel@tonic-gate user_rec->pathname, 678*7c478bd9Sstevel@tonic-gate MAX(ustr - user_rec->pathname, 679*7c478bd9Sstevel@tonic-gate cstr - cfg_rec->pathname)) == 0); 680*7c478bd9Sstevel@tonic-gate path = path && (*(user_rec->pathname + 681*7c478bd9Sstevel@tonic-gate strlen(user_rec->pathname) -1) == 682*7c478bd9Sstevel@tonic-gate *(cfg_rec->pathname + 683*7c478bd9Sstevel@tonic-gate strlen(cfg_rec->pathname) - 1)); 684*7c478bd9Sstevel@tonic-gate } else { 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate return (B_FALSE); 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate } else if (cfg_rec->serialno || cfg_rec->pathname) { 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate return (B_FALSE); 692*7c478bd9Sstevel@tonic-gate } else { 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate return (B_TRUE); 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate return (srno || path); 698*7c478bd9Sstevel@tonic-gate } else { 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate return (B_FALSE); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate /* 706*7c478bd9Sstevel@tonic-gate * free the record allocated in usb_get_conf_rec 707*7c478bd9Sstevel@tonic-gate */ 708*7c478bd9Sstevel@tonic-gate static void 709*7c478bd9Sstevel@tonic-gate usb_free_rec(usb_configrec_t *rec) 710*7c478bd9Sstevel@tonic-gate { 711*7c478bd9Sstevel@tonic-gate if (rec == (usb_configrec_t *)NULL) { 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate return; 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate free(rec->selection); 717*7c478bd9Sstevel@tonic-gate free(rec->serialno); 718*7c478bd9Sstevel@tonic-gate free(rec->pathname); 719*7c478bd9Sstevel@tonic-gate free(rec->driver); 720*7c478bd9Sstevel@tonic-gate free(rec); 721*7c478bd9Sstevel@tonic-gate } 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate int 725*7c478bd9Sstevel@tonic-gate add_entry(char *selection, int vid, int pid, int cfgndx, char *srno, 726*7c478bd9Sstevel@tonic-gate char *path, char *driver, char **errmsg) 727*7c478bd9Sstevel@tonic-gate { 728*7c478bd9Sstevel@tonic-gate int file; 729*7c478bd9Sstevel@tonic-gate int rval = CFGA_USB_OK; 730*7c478bd9Sstevel@tonic-gate char *buf = (char *)NULL; 731*7c478bd9Sstevel@tonic-gate char str[MAXLINESIZE]; 732*7c478bd9Sstevel@tonic-gate token_t token = NEWLINE; 733*7c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 734*7c478bd9Sstevel@tonic-gate struct stat st; 735*7c478bd9Sstevel@tonic-gate usb_configrec_t cfgrec, *user_rec = NULL; 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: driver=%s, path=%s\n", 738*7c478bd9Sstevel@tonic-gate driver ? driver : "", path ? path : ""); 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate if (*errmsg == (char *)NULL) { 741*7c478bd9Sstevel@tonic-gate if ((*errmsg = calloc(MAXPATHLEN, 1)) == (char *)NULL) { 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate return (CFGA_USB_CONFIG_FILE); 744*7c478bd9Sstevel@tonic-gate } 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&file_lock); 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate /* Initialize the cfgrec */ 750*7c478bd9Sstevel@tonic-gate cfgrec.selection = selection; 751*7c478bd9Sstevel@tonic-gate cfgrec.idVendor = vid; 752*7c478bd9Sstevel@tonic-gate cfgrec.idProduct = pid; 753*7c478bd9Sstevel@tonic-gate cfgrec.cfgndx = cfgndx; 754*7c478bd9Sstevel@tonic-gate cfgrec.serialno = srno; 755*7c478bd9Sstevel@tonic-gate cfgrec.pathname = path; 756*7c478bd9Sstevel@tonic-gate cfgrec.driver = driver; 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate /* open config_map.conf file */ 759*7c478bd9Sstevel@tonic-gate file = open(usbconf_file, O_RDWR, 0666); 760*7c478bd9Sstevel@tonic-gate if (file == -1) { 761*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 762*7c478bd9Sstevel@tonic-gate "failed to open config file\n"); 763*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&file_lock); 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate return (CFGA_USB_CONFIG_FILE); 766*7c478bd9Sstevel@tonic-gate } 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate if (lockf(file, F_TLOCK, 0) == -1) { 769*7c478bd9Sstevel@tonic-gate (void) snprintf(*errmsg, MAXPATHLEN, 770*7c478bd9Sstevel@tonic-gate "failed to lock config file\n"); 771*7c478bd9Sstevel@tonic-gate close(file); 772*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&file_lock); 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate return (CFGA_USB_LOCK_FILE); 775*7c478bd9Sstevel@tonic-gate } 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate /* 778*7c478bd9Sstevel@tonic-gate * These variables need to be reinitialized here as they may 779*7c478bd9Sstevel@tonic-gate * have been modified by a previous thread that called this 780*7c478bd9Sstevel@tonic-gate * function 781*7c478bd9Sstevel@tonic-gate */ 782*7c478bd9Sstevel@tonic-gate linenum = 1; 783*7c478bd9Sstevel@tonic-gate cntr = 0; 784*7c478bd9Sstevel@tonic-gate frec = 0; 785*7c478bd9Sstevel@tonic-gate brec = 0; 786*7c478bd9Sstevel@tonic-gate btoken = 0; 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate if (fstat(file, &st) != 0) { 789*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to fstat config file\n"); 790*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_CONFIG_FILE; 791*7c478bd9Sstevel@tonic-gate goto exit; 792*7c478bd9Sstevel@tonic-gate } 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate if ((buf = (char *)malloc(st.st_size)) == NULL) { 795*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to fstat config file\n"); 796*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_ALLOC_FAIL; 797*7c478bd9Sstevel@tonic-gate goto exit; 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate if (st.st_size != read(file, buf, st.st_size)) { 801*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to read config file\n"); 802*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_CONFIG_FILE; 803*7c478bd9Sstevel@tonic-gate goto exit; 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate /* set up for reading the file */ 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate while ((token != EOF) && !found) { 809*7c478bd9Sstevel@tonic-gate if (user_rec) { 810*7c478bd9Sstevel@tonic-gate usb_free_rec(user_rec); 811*7c478bd9Sstevel@tonic-gate user_rec = NULL; 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate token = usb_get_conf_rec(buf, &user_rec, errmsg); 814*7c478bd9Sstevel@tonic-gate found = usb_cmp_rec(&cfgrec, user_rec); 815*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: token=%x, found=%x\n", token, found); 816*7c478bd9Sstevel@tonic-gate } 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate bzero(str, MAXLINESIZE); 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate if (found) { 821*7c478bd9Sstevel@tonic-gate DPRINTF("FOUND\n"); 822*7c478bd9Sstevel@tonic-gate (void) snprintf(str, MAXLINESIZE, "selection=%s idVendor=0x%x " 823*7c478bd9Sstevel@tonic-gate "idProduct=0x%x ", 824*7c478bd9Sstevel@tonic-gate (cfgrec.selection) ? cfgrec.selection : user_rec->selection, 825*7c478bd9Sstevel@tonic-gate user_rec->idVendor, user_rec->idProduct); 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate if ((user_rec->cfgndx != -1) || (cfgrec.cfgndx != -1)) { 828*7c478bd9Sstevel@tonic-gate (void) snprintf(&str[strlen(str)], MAXLINESIZE, 829*7c478bd9Sstevel@tonic-gate "cfgndx=0x%x ", (cfgrec.cfgndx != -1) ? 830*7c478bd9Sstevel@tonic-gate cfgrec.cfgndx : user_rec->cfgndx); 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate if (user_rec->serialno) { 834*7c478bd9Sstevel@tonic-gate (void) snprintf(&str[strlen(str)], MAXLINESIZE, 835*7c478bd9Sstevel@tonic-gate "srno=\"%s\" ", user_rec->serialno); 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate if (user_rec->pathname) { 839*7c478bd9Sstevel@tonic-gate (void) snprintf(&str[strlen(str)], MAXLINESIZE, 840*7c478bd9Sstevel@tonic-gate "pathname=\"%s\" ", user_rec->pathname); 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate if (user_rec->driver) { 844*7c478bd9Sstevel@tonic-gate (void) snprintf(&str[strlen(str)], MAXLINESIZE, 845*7c478bd9Sstevel@tonic-gate "driver=\"%s\" ", user_rec->driver); 846*7c478bd9Sstevel@tonic-gate } else if (cfgrec.driver != NULL) { 847*7c478bd9Sstevel@tonic-gate if (strlen(cfgrec.driver)) { 848*7c478bd9Sstevel@tonic-gate (void) snprintf(&str[strlen(str)], MAXLINESIZE, 849*7c478bd9Sstevel@tonic-gate "driver=\"%s\" ", cfgrec.driver); 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate } 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate (void) strlcat(str, ";", sizeof (str)); 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate /* 856*7c478bd9Sstevel@tonic-gate * Seek to the beginning of the record 857*7c478bd9Sstevel@tonic-gate */ 858*7c478bd9Sstevel@tonic-gate if (lseek(file, brec, SEEK_SET) == -1) { 859*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to lseek config file\n"); 860*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_CONFIG_FILE; 861*7c478bd9Sstevel@tonic-gate goto exit; 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate /* 865*7c478bd9Sstevel@tonic-gate * Write the modified record 866*7c478bd9Sstevel@tonic-gate */ 867*7c478bd9Sstevel@tonic-gate if (write(file, str, strlen(str)) == -1) { 868*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to write config file\n"); 869*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_CONFIG_FILE; 870*7c478bd9Sstevel@tonic-gate goto exit; 871*7c478bd9Sstevel@tonic-gate } 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate /* 874*7c478bd9Sstevel@tonic-gate * Write the rest of the file as it was 875*7c478bd9Sstevel@tonic-gate */ 876*7c478bd9Sstevel@tonic-gate if (write(file, buf+cntr, st.st_size - cntr) == -1) { 877*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to write config file\n"); 878*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_CONFIG_FILE; 879*7c478bd9Sstevel@tonic-gate goto exit; 880*7c478bd9Sstevel@tonic-gate } 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate } else { 883*7c478bd9Sstevel@tonic-gate DPRINTF("!FOUND\n"); 884*7c478bd9Sstevel@tonic-gate (void) snprintf(str, MAXLINESIZE, 885*7c478bd9Sstevel@tonic-gate "selection=%s idVendor=0x%x idProduct=0x%x ", 886*7c478bd9Sstevel@tonic-gate (cfgrec.selection) ? cfgrec.selection : "enable", 887*7c478bd9Sstevel@tonic-gate cfgrec.idVendor, cfgrec.idProduct); 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate if (cfgrec.cfgndx != -1) { 890*7c478bd9Sstevel@tonic-gate (void) snprintf(&str[strlen(str)], MAXLINESIZE, 891*7c478bd9Sstevel@tonic-gate "cfgndx=0x%x ", cfgrec.cfgndx); 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate if (cfgrec.serialno) { 895*7c478bd9Sstevel@tonic-gate (void) snprintf(&str[strlen(str)], MAXLINESIZE, 896*7c478bd9Sstevel@tonic-gate "srno=\"%s\" ", cfgrec.serialno); 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate if (cfgrec.pathname != NULL) { 900*7c478bd9Sstevel@tonic-gate (void) snprintf(&str[strlen(str)], MAXLINESIZE, 901*7c478bd9Sstevel@tonic-gate "pathname=\"%s\" ", cfgrec.pathname); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate if (cfgrec.driver != NULL) { 905*7c478bd9Sstevel@tonic-gate if (strlen(cfgrec.driver)) { 906*7c478bd9Sstevel@tonic-gate (void) snprintf(&str[strlen(str)], MAXLINESIZE, 907*7c478bd9Sstevel@tonic-gate "driver=\"%s\" ", cfgrec.driver); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate (void) strlcat(str, ";\n", sizeof (str)); 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate /* 914*7c478bd9Sstevel@tonic-gate * Incase this is the first entry, add it after the comments 915*7c478bd9Sstevel@tonic-gate */ 916*7c478bd9Sstevel@tonic-gate if (frec == 0) { 917*7c478bd9Sstevel@tonic-gate frec = st.st_size; 918*7c478bd9Sstevel@tonic-gate } 919*7c478bd9Sstevel@tonic-gate 920*7c478bd9Sstevel@tonic-gate /* 921*7c478bd9Sstevel@tonic-gate * Go to the beginning of the records 922*7c478bd9Sstevel@tonic-gate */ 923*7c478bd9Sstevel@tonic-gate if (lseek(file, frec, SEEK_SET) == -1) { 924*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to lseek config file\n"); 925*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_CONFIG_FILE; 926*7c478bd9Sstevel@tonic-gate goto exit; 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate /* 930*7c478bd9Sstevel@tonic-gate * Add the entry 931*7c478bd9Sstevel@tonic-gate */ 932*7c478bd9Sstevel@tonic-gate if (write(file, str, strlen(str)) == -1) { 933*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to write config file\n"); 934*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_CONFIG_FILE; 935*7c478bd9Sstevel@tonic-gate goto exit; 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate /* 939*7c478bd9Sstevel@tonic-gate * write the remaining file as it was 940*7c478bd9Sstevel@tonic-gate */ 941*7c478bd9Sstevel@tonic-gate if (write(file, buf+frec, st.st_size - frec) == -1) { 942*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to write config file\n"); 943*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_CONFIG_FILE; 944*7c478bd9Sstevel@tonic-gate goto exit; 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate } 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate /* no error encountered */ 949*7c478bd9Sstevel@tonic-gate if (rval == CFGA_USB_OK) { 950*7c478bd9Sstevel@tonic-gate free(errmsg); 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate exit: 954*7c478bd9Sstevel@tonic-gate if (buf != NULL) { 955*7c478bd9Sstevel@tonic-gate free(buf); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate if (lockf(file, F_ULOCK, 0) == -1) { 959*7c478bd9Sstevel@tonic-gate DPRINTF("add_entry: failed to unlock config file\n"); 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate rval = CFGA_USB_LOCK_FILE; 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate close(file); 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&file_lock); 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate return (rval); 969*7c478bd9Sstevel@tonic-gate } 970