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 (c) 1996-1998 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All Rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ 31*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * devtab.c 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * Contains functions that deal with the device table and are not for 37*7c478bd9Sstevel@tonic-gate * consumption by the general user population. 38*7c478bd9Sstevel@tonic-gate * 39*7c478bd9Sstevel@tonic-gate * Functions defined: 40*7c478bd9Sstevel@tonic-gate * _opendevtab() Opens the device table for commands 41*7c478bd9Sstevel@tonic-gate * _setdevtab() Rewinds the open device table 42*7c478bd9Sstevel@tonic-gate * _enddevtab() Closes the open device table 43*7c478bd9Sstevel@tonic-gate * _getdevtabent() Gets the next entry in the device table 44*7c478bd9Sstevel@tonic-gate * _freedevtabent() Frees memory allocated to a device-table entry 45*7c478bd9Sstevel@tonic-gate * _getdevrec() Gets a specific record from the device table 46*7c478bd9Sstevel@tonic-gate * _devtabpath() Get the pathname of the device table file 47*7c478bd9Sstevel@tonic-gate * _validalias() Is a value a valid alias? 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate /* 51*7c478bd9Sstevel@tonic-gate * Header files 52*7c478bd9Sstevel@tonic-gate * 53*7c478bd9Sstevel@tonic-gate * <sys/sysmacros.h> System macro definitions 54*7c478bd9Sstevel@tonic-gate * <sys/types.h> System data types 55*7c478bd9Sstevel@tonic-gate * <sys/mkdev.h> Device Macros 56*7c478bd9Sstevel@tonic-gate * <unistd.h> System Symbolic Constants 57*7c478bd9Sstevel@tonic-gate * <stdio.h> Standard I/O definitions 58*7c478bd9Sstevel@tonic-gate * <string.h> String handling definitions 59*7c478bd9Sstevel@tonic-gate * <ctype.h> Character types and macros 60*7c478bd9Sstevel@tonic-gate * <errno.h> Error codes 61*7c478bd9Sstevel@tonic-gate * <sys/stat.h> File status information 62*7c478bd9Sstevel@tonic-gate * <devmgmt.h> Global Device Management definitions 63*7c478bd9Sstevel@tonic-gate * "devtab.h" Local Device Management definitions 64*7c478bd9Sstevel@tonic-gate */ 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 68*7c478bd9Sstevel@tonic-gate #ifndef SUNOS41 69*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 70*7c478bd9Sstevel@tonic-gate #endif 71*7c478bd9Sstevel@tonic-gate #include <unistd.h> 72*7c478bd9Sstevel@tonic-gate #include <stdio.h> 73*7c478bd9Sstevel@tonic-gate #include <string.h> 74*7c478bd9Sstevel@tonic-gate #include <ctype.h> 75*7c478bd9Sstevel@tonic-gate #include <errno.h> 76*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 77*7c478bd9Sstevel@tonic-gate #include <devmgmt.h> 78*7c478bd9Sstevel@tonic-gate #include "devtab.h" 79*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * Static data definitions: 83*7c478bd9Sstevel@tonic-gate * dtabrecnum Record number of the current record (0 to n-1) 84*7c478bd9Sstevel@tonic-gate * leftoff Addr of char to begin next parse using 85*7c478bd9Sstevel@tonic-gate * getfld(), getattrval(), getquoted() 86*7c478bd9Sstevel@tonic-gate * recbufsz The size of the buffer used for reading records 87*7c478bd9Sstevel@tonic-gate * recbuf Addr of malloc() buffer for reading records 88*7c478bd9Sstevel@tonic-gate * xtndcnt Number of malloc()/realloc() calls on record buffer 89*7c478bd9Sstevel@tonic-gate */ 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate static int xtndcnt = 0; 92*7c478bd9Sstevel@tonic-gate static char *recbuf = NULL; 93*7c478bd9Sstevel@tonic-gate static int recbufsz = 0; 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate static char *leftoff = NULL; 96*7c478bd9Sstevel@tonic-gate static int dtabrecnum = 0; 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* 99*7c478bd9Sstevel@tonic-gate * int samedev(x, y) 100*7c478bd9Sstevel@tonic-gate * struct stat x, y 101*7c478bd9Sstevel@tonic-gate * 102*7c478bd9Sstevel@tonic-gate * Compares pertinent information in a stat() structure 103*7c478bd9Sstevel@tonic-gate * to see if the two structures describe the same device. 104*7c478bd9Sstevel@tonic-gate * If the file modes are the same and they have the same 105*7c478bd9Sstevel@tonic-gate * file system and i-node (i.e. they're links) or they 106*7c478bd9Sstevel@tonic-gate * are block or character devices and have the same major 107*7c478bd9Sstevel@tonic-gate * and minor device numbers (i.e. "mknod"s for the same 108*7c478bd9Sstevel@tonic-gate * device), it's the same device. 109*7c478bd9Sstevel@tonic-gate * 110*7c478bd9Sstevel@tonic-gate * Returns: int 111*7c478bd9Sstevel@tonic-gate * TRUE if the two structures describe the same device 112*7c478bd9Sstevel@tonic-gate * FALSE otherwise 113*7c478bd9Sstevel@tonic-gate */ 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate static int 116*7c478bd9Sstevel@tonic-gate samedev(struct stat64 x, struct stat64 y) 117*7c478bd9Sstevel@tonic-gate { 118*7c478bd9Sstevel@tonic-gate int same; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* If the devices are of the same type ... */ 122*7c478bd9Sstevel@tonic-gate if ((x.st_mode & 0170000) == (y.st_mode & 0170000)) { 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate /* 125*7c478bd9Sstevel@tonic-gate * If they are described by the same inode on the same device, 126*7c478bd9Sstevel@tonic-gate * the two devices are the same. Otherwise, if the devices are 127*7c478bd9Sstevel@tonic-gate * character-special or block-special devices, try to match by 128*7c478bd9Sstevel@tonic-gate * device type and major and minor device numbers. 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate if ((x.st_dev == y.st_dev) && (x.st_ino == y.st_ino)) same = TRUE; 132*7c478bd9Sstevel@tonic-gate else 133*7c478bd9Sstevel@tonic-gate if (((x.st_mode & 0170000) == 0020000) || 134*7c478bd9Sstevel@tonic-gate ((x.st_mode & 0170000) == 0060000)) { 135*7c478bd9Sstevel@tonic-gate if ((major(x.st_rdev) == major(y.st_rdev)) && 136*7c478bd9Sstevel@tonic-gate (minor(x.st_rdev) == minor(y.st_rdev))) same = TRUE; 137*7c478bd9Sstevel@tonic-gate else same = FALSE; 138*7c478bd9Sstevel@tonic-gate } else same = FALSE; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate } else same = FALSE; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate return (same); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * void _setdevtab() 147*7c478bd9Sstevel@tonic-gate * 148*7c478bd9Sstevel@tonic-gate * This function rewinds the open device table so that the next 149*7c478bd9Sstevel@tonic-gate * _getdevtabent() returns the first record in the device table. 150*7c478bd9Sstevel@tonic-gate * 151*7c478bd9Sstevel@tonic-gate * Arguments: None 152*7c478bd9Sstevel@tonic-gate * 153*7c478bd9Sstevel@tonic-gate * Returns: Void 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate void 157*7c478bd9Sstevel@tonic-gate _setdevtab(void) 158*7c478bd9Sstevel@tonic-gate { 159*7c478bd9Sstevel@tonic-gate /* If the device table file is open, rewind the file */ 160*7c478bd9Sstevel@tonic-gate if (oam_devtab != NULL) { 161*7c478bd9Sstevel@tonic-gate rewind(oam_devtab); 162*7c478bd9Sstevel@tonic-gate dtabrecnum = 0; 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* 167*7c478bd9Sstevel@tonic-gate * void _enddevtab() 168*7c478bd9Sstevel@tonic-gate * 169*7c478bd9Sstevel@tonic-gate * This function closes the open device table. It resets the 170*7c478bd9Sstevel@tonic-gate * open device table external variable to NULL. 171*7c478bd9Sstevel@tonic-gate * 172*7c478bd9Sstevel@tonic-gate * Arguments: None 173*7c478bd9Sstevel@tonic-gate * 174*7c478bd9Sstevel@tonic-gate * Returns: Void 175*7c478bd9Sstevel@tonic-gate */ 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate void 178*7c478bd9Sstevel@tonic-gate _enddevtab(void) 179*7c478bd9Sstevel@tonic-gate { 180*7c478bd9Sstevel@tonic-gate /* If the device table file is open, close it */ 181*7c478bd9Sstevel@tonic-gate if (oam_devtab != NULL) { 182*7c478bd9Sstevel@tonic-gate (void) fclose(oam_devtab); 183*7c478bd9Sstevel@tonic-gate oam_devtab = NULL; 184*7c478bd9Sstevel@tonic-gate dtabrecnum = 0; 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* 189*7c478bd9Sstevel@tonic-gate * char *getfld(ptr, delims) 190*7c478bd9Sstevel@tonic-gate * char *ptr 191*7c478bd9Sstevel@tonic-gate * char *delims 192*7c478bd9Sstevel@tonic-gate * 193*7c478bd9Sstevel@tonic-gate * Notes: 194*7c478bd9Sstevel@tonic-gate * - Can't use "strtok()" because of its use of static data. The caller 195*7c478bd9Sstevel@tonic-gate * may be using strtok() and we'll really mess them up. 196*7c478bd9Sstevel@tonic-gate * - The function returns NULL if it didn't find any token -- '\0' can't 197*7c478bd9Sstevel@tonic-gate * be a delimiter using this algorithm. 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate static char * 201*7c478bd9Sstevel@tonic-gate getfld( 202*7c478bd9Sstevel@tonic-gate char *ptr, /* String to parse */ 203*7c478bd9Sstevel@tonic-gate char *delims) /* List of delimiters */ 204*7c478bd9Sstevel@tonic-gate { 205*7c478bd9Sstevel@tonic-gate int done; /* TRUE if we're finished */ 206*7c478bd9Sstevel@tonic-gate char *p, *q; /* Temp pointers */ 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate * Figure out where to start. 210*7c478bd9Sstevel@tonic-gate * If given a pointer, use that. 211*7c478bd9Sstevel@tonic-gate * Otherwise, use where we left off. 212*7c478bd9Sstevel@tonic-gate */ 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate p = ptr ? ptr : leftoff; 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* 218*7c478bd9Sstevel@tonic-gate * If there's anything to parse, search the string for the first 219*7c478bd9Sstevel@tonic-gate * occurrence of any of the delimiters. If one is found, change it 220*7c478bd9Sstevel@tonic-gate * to '\0' and remember the place to start for next time. If not 221*7c478bd9Sstevel@tonic-gate * found, forget the restart address and prepare to return NULL. 222*7c478bd9Sstevel@tonic-gate * Don't terminate on "escaped" characters. 223*7c478bd9Sstevel@tonic-gate */ 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate if (p) { /* Anything to do ?? */ 226*7c478bd9Sstevel@tonic-gate q = p; /* Where to begin */ 227*7c478bd9Sstevel@tonic-gate done = FALSE; /* We're not done yet */ 228*7c478bd9Sstevel@tonic-gate while (*q && !done) { /* Any more chars */ 229*7c478bd9Sstevel@tonic-gate if (*q == '\\') { /* Escaped ? */ 230*7c478bd9Sstevel@tonic-gate if (*(++q)) q++; /* Skip escaped char */ 231*7c478bd9Sstevel@tonic-gate } else /* Not escaped */ 232*7c478bd9Sstevel@tonic-gate if (!strchr(delims, *q)) q++; /* Skip non-delim */ 233*7c478bd9Sstevel@tonic-gate else done = TRUE; /* Otherwise, done */ 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate if (*q) { /* Terminator found? */ 236*7c478bd9Sstevel@tonic-gate *q++ = '\0'; /* Null-terminate token */ 237*7c478bd9Sstevel@tonic-gate leftoff = q; /* Remember restart pt. */ 238*7c478bd9Sstevel@tonic-gate } else 239*7c478bd9Sstevel@tonic-gate leftoff = p = NULL; /* Nothin found or left */ 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate /* Finished */ 243*7c478bd9Sstevel@tonic-gate return (p); /* Return ptr to token */ 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * char *getquoted(ptr) 248*7c478bd9Sstevel@tonic-gate * char *ptr; 249*7c478bd9Sstevel@tonic-gate * 250*7c478bd9Sstevel@tonic-gate * This function extracts a quoted string from the string pointed 251*7c478bd9Sstevel@tonic-gate * to by <ptr>, or, if <ptr> is NULL, wherever we left off 252*7c478bd9Sstevel@tonic-gate * last time. 253*7c478bd9Sstevel@tonic-gate * 254*7c478bd9Sstevel@tonic-gate * Arguments: 255*7c478bd9Sstevel@tonic-gate * char *ptr Pointer to the character-string to parse, or 256*7c478bd9Sstevel@tonic-gate * (char *) NULL if we're to pick up where we 257*7c478bd9Sstevel@tonic-gate * [getquoted(), getfld(), and getattrval()] left off. 258*7c478bd9Sstevel@tonic-gate * 259*7c478bd9Sstevel@tonic-gate * Returns: char * 260*7c478bd9Sstevel@tonic-gate * The address of malloc()ed space that contains the possibly quoted 261*7c478bd9Sstevel@tonic-gate * string. 262*7c478bd9Sstevel@tonic-gate * 263*7c478bd9Sstevel@tonic-gate * Notes: 264*7c478bd9Sstevel@tonic-gate * - This code only works if it can assume that the last character in 265*7c478bd9Sstevel@tonic-gate * the string it's parsing is a '\n', something that is guarenteed 266*7c478bd9Sstevel@tonic-gate * by the getnextrec() function. 267*7c478bd9Sstevel@tonic-gate */ 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate static char * 270*7c478bd9Sstevel@tonic-gate getquoted(char *ptr) 271*7c478bd9Sstevel@tonic-gate { 272*7c478bd9Sstevel@tonic-gate /* Automatic data */ 273*7c478bd9Sstevel@tonic-gate char *rtn; /* Value to return */ 274*7c478bd9Sstevel@tonic-gate char *p, *q; /* Temps */ 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate /* Figure out where to start off */ 277*7c478bd9Sstevel@tonic-gate p = ptr ? ptr : leftoff; 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* If there's anything to parse and it's a quoted string ... */ 280*7c478bd9Sstevel@tonic-gate if ((p) && (*p == '"') && (p = getfld(p+1, "\""))) { 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate /* Copy string for the caller */ 283*7c478bd9Sstevel@tonic-gate if (rtn = malloc(strlen(p)+1)) { /* Malloc() space */ 284*7c478bd9Sstevel@tonic-gate q = rtn; /* Set up temp ptr */ 285*7c478bd9Sstevel@tonic-gate do { 286*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++; /* Skip escape */ 287*7c478bd9Sstevel@tonic-gate *q++ = *p; /* Copy char */ 288*7c478bd9Sstevel@tonic-gate } while (*p++); /* While there's chars */ 289*7c478bd9Sstevel@tonic-gate } else leftoff = rtn = NULL; 290*7c478bd9Sstevel@tonic-gate } else leftoff = rtn = NULL; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate /* Fini */ 293*7c478bd9Sstevel@tonic-gate return (rtn); 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate /* 297*7c478bd9Sstevel@tonic-gate * struct attrval *getattrval(ptr) 298*7c478bd9Sstevel@tonic-gate * char *ptr 299*7c478bd9Sstevel@tonic-gate * 300*7c478bd9Sstevel@tonic-gate * This function extracts the next attr=val pair from <ptr> or wherever 301*7c478bd9Sstevel@tonic-gate * getfld() left off... 302*7c478bd9Sstevel@tonic-gate * 303*7c478bd9Sstevel@tonic-gate * Arguments: 304*7c478bd9Sstevel@tonic-gate * char *ptr The string to parse, or (char *) NULL if we're to 305*7c478bd9Sstevel@tonic-gate * begin wherever we left off last time. 306*7c478bd9Sstevel@tonic-gate * 307*7c478bd9Sstevel@tonic-gate * Returns: struct attrval * 308*7c478bd9Sstevel@tonic-gate * The address of a malloc()ed structure containing the attribute and the 309*7c478bd9Sstevel@tonic-gate * value of the attr=val pair extracted. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate static struct attrval * 313*7c478bd9Sstevel@tonic-gate getattrval(char *ptr) 314*7c478bd9Sstevel@tonic-gate { 315*7c478bd9Sstevel@tonic-gate /* Automatic data */ 316*7c478bd9Sstevel@tonic-gate struct attrval *rtn; /* Ptr to struct to return */ 317*7c478bd9Sstevel@tonic-gate char *p, *q; /* Temp pointers */ 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* Use what's given to us or wherever we left off */ 321*7c478bd9Sstevel@tonic-gate p = ptr ? ptr : leftoff; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* If there's anything to parse, extract the next attr=val pair */ 324*7c478bd9Sstevel@tonic-gate if (p) { 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate /* Eat white space */ 327*7c478bd9Sstevel@tonic-gate while (*p && isspace((unsigned char)*p)) p++; 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate /* Extract the attribute name, if any */ 330*7c478bd9Sstevel@tonic-gate if (*p && getfld(p, "=")) { 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* Allocate space for the structure we're building */ 333*7c478bd9Sstevel@tonic-gate if (rtn = malloc(sizeof (struct attrval))) { 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate /* Allocate space for the attribute name */ 336*7c478bd9Sstevel@tonic-gate if (rtn->attr = malloc(strlen(p)+1)) { 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate /* Copy the attribute name into alloc'd space */ 339*7c478bd9Sstevel@tonic-gate q = rtn->attr; /* Set up temp ptr */ 340*7c478bd9Sstevel@tonic-gate do { 341*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++; /* Skip escape */ 342*7c478bd9Sstevel@tonic-gate *q++ = *p; /* Copy char */ 343*7c478bd9Sstevel@tonic-gate } while (*p++); /* While more */ 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate /* Extract the value */ 346*7c478bd9Sstevel@tonic-gate if (!(rtn->val = getquoted(NULL))) { 347*7c478bd9Sstevel@tonic-gate /* Error getting value, free resources */ 348*7c478bd9Sstevel@tonic-gate free(rtn->attr); 349*7c478bd9Sstevel@tonic-gate free(rtn); 350*7c478bd9Sstevel@tonic-gate leftoff = NULL; 351*7c478bd9Sstevel@tonic-gate rtn = NULL; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate } else { 354*7c478bd9Sstevel@tonic-gate /* Error getting space for attribute, free resources */ 355*7c478bd9Sstevel@tonic-gate free(rtn); 356*7c478bd9Sstevel@tonic-gate leftoff = NULL; 357*7c478bd9Sstevel@tonic-gate rtn = NULL; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate } else { 361*7c478bd9Sstevel@tonic-gate /* No space for attr struct */ 362*7c478bd9Sstevel@tonic-gate leftoff = NULL; 363*7c478bd9Sstevel@tonic-gate rtn = NULL; 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate } else { 367*7c478bd9Sstevel@tonic-gate /* No attribute name */ 368*7c478bd9Sstevel@tonic-gate leftoff = NULL; 369*7c478bd9Sstevel@tonic-gate rtn = NULL; 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate } else { 373*7c478bd9Sstevel@tonic-gate /* Nothing to parse */ 374*7c478bd9Sstevel@tonic-gate leftoff = NULL; 375*7c478bd9Sstevel@tonic-gate rtn = NULL; 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate /* Done */ 379*7c478bd9Sstevel@tonic-gate return (rtn); 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate /* 383*7c478bd9Sstevel@tonic-gate * char *getnextrec() 384*7c478bd9Sstevel@tonic-gate * 385*7c478bd9Sstevel@tonic-gate * This function gets the next record from the input stream "oam_devtab" 386*7c478bd9Sstevel@tonic-gate * and puts it in the device-table record buffer (whose address is in 387*7c478bd9Sstevel@tonic-gate * "recbuf"). If the buffer is not allocated or is too small to 388*7c478bd9Sstevel@tonic-gate * accommodate the record, the function allocates more space to the 389*7c478bd9Sstevel@tonic-gate * buffer. 390*7c478bd9Sstevel@tonic-gate * 391*7c478bd9Sstevel@tonic-gate * Arguments: None 392*7c478bd9Sstevel@tonic-gate * 393*7c478bd9Sstevel@tonic-gate * Returns: char * 394*7c478bd9Sstevel@tonic-gate * The address of the buffer containing the record. 395*7c478bd9Sstevel@tonic-gate * 396*7c478bd9Sstevel@tonic-gate * Static Data Referenced: 397*7c478bd9Sstevel@tonic-gate * recbuf Address of the buffer containing records read from the 398*7c478bd9Sstevel@tonic-gate * device table file 399*7c478bd9Sstevel@tonic-gate * recbufsz Current size of the record buffer 400*7c478bd9Sstevel@tonic-gate * xtndcnt Number of times the record buffer has been extended 401*7c478bd9Sstevel@tonic-gate * oam_devtab Device table stream, expected to be open for (at 402*7c478bd9Sstevel@tonic-gate * least) reading 403*7c478bd9Sstevel@tonic-gate * 404*7c478bd9Sstevel@tonic-gate * Notes: 405*7c478bd9Sstevel@tonic-gate * - The string returned in the buffer <buf> ALWAYS end in a '\n' (newline) 406*7c478bd9Sstevel@tonic-gate * character followed by a '\0' (null). 407*7c478bd9Sstevel@tonic-gate */ 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate static char * 410*7c478bd9Sstevel@tonic-gate getnextrec(void) 411*7c478bd9Sstevel@tonic-gate { 412*7c478bd9Sstevel@tonic-gate /* Automatic data */ 413*7c478bd9Sstevel@tonic-gate char *recp; /* Value to return */ 414*7c478bd9Sstevel@tonic-gate char *p; /* Temp pointer */ 415*7c478bd9Sstevel@tonic-gate int done; /* TRUE if we're finished */ 416*7c478bd9Sstevel@tonic-gate int reclen; /* Number of chars in record */ 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* If there's no buffer for records, try to get one */ 420*7c478bd9Sstevel@tonic-gate if (!recbuf) { 421*7c478bd9Sstevel@tonic-gate if (recbuf = malloc(DTAB_BUFSIZ)) { 422*7c478bd9Sstevel@tonic-gate recbufsz = DTAB_BUFSIZ; 423*7c478bd9Sstevel@tonic-gate xtndcnt = 0; 424*7c478bd9Sstevel@tonic-gate } else return (NULL); 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate /* Get the next record */ 429*7c478bd9Sstevel@tonic-gate recp = fgets(recbuf, recbufsz, oam_devtab); 430*7c478bd9Sstevel@tonic-gate done = FALSE; 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate /* While we've something to return and we're not finished ... */ 433*7c478bd9Sstevel@tonic-gate while (recp && !done) { 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate /* If our return string isn't a null-string ... */ 436*7c478bd9Sstevel@tonic-gate if ((reclen = (int)strlen(recp)) != 0) { 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate /* If we have a complete record, we're finished */ 439*7c478bd9Sstevel@tonic-gate if ((*(recp+reclen-1) == '\n') && 440*7c478bd9Sstevel@tonic-gate ((reclen == 1) || (*(recp+reclen-2) != '\\'))) done = TRUE; 441*7c478bd9Sstevel@tonic-gate else while (!done) { 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate /* 444*7c478bd9Sstevel@tonic-gate * Need to complete the record. A complete record is 445*7c478bd9Sstevel@tonic-gate * one which is terminated by an unescaped new-line 446*7c478bd9Sstevel@tonic-gate * character. 447*7c478bd9Sstevel@tonic-gate */ 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* If the buffer is full, expand it and continue reading */ 450*7c478bd9Sstevel@tonic-gate if (reclen == recbufsz-1) { 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate /* Have we reached our maximum extension count? */ 453*7c478bd9Sstevel@tonic-gate if (xtndcnt < XTND_MAXCNT) { 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate /* Expand the record buffer */ 456*7c478bd9Sstevel@tonic-gate if (p = realloc(recbuf, 457*7c478bd9Sstevel@tonic-gate (size_t)recbufsz+DTAB_BUFINC)) { 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate /* Update buffer information */ 460*7c478bd9Sstevel@tonic-gate xtndcnt++; 461*7c478bd9Sstevel@tonic-gate recbuf = p; 462*7c478bd9Sstevel@tonic-gate recbufsz += DTAB_BUFINC; 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate } else { 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate /* Expansion failed */ 467*7c478bd9Sstevel@tonic-gate recp = NULL; 468*7c478bd9Sstevel@tonic-gate done = TRUE; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate } else { 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate /* Maximum extend count exceeded. Insane table */ 474*7c478bd9Sstevel@tonic-gate recp = NULL; 475*7c478bd9Sstevel@tonic-gate done = TRUE; 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate /* Complete the record */ 481*7c478bd9Sstevel@tonic-gate if (!done) { 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate /* Read stuff into the expanded space */ 484*7c478bd9Sstevel@tonic-gate if (fgets(recbuf+reclen, recbufsz-reclen, oam_devtab)) { 485*7c478bd9Sstevel@tonic-gate reclen = (int)strlen(recbuf); 486*7c478bd9Sstevel@tonic-gate recp = recbuf; 487*7c478bd9Sstevel@tonic-gate if ((*(recp+reclen-1) == '\n') && 488*7c478bd9Sstevel@tonic-gate ((reclen == 1) || (*(recp+reclen-2) != '\\'))) 489*7c478bd9Sstevel@tonic-gate done = TRUE; 490*7c478bd9Sstevel@tonic-gate } else { 491*7c478bd9Sstevel@tonic-gate /* Read failed, corrupt record? */ 492*7c478bd9Sstevel@tonic-gate recp = NULL; 493*7c478bd9Sstevel@tonic-gate done = TRUE; 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate } /* End incomplete record handling */ 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate } else { 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate /* Read a null string? (corrupt table) */ 502*7c478bd9Sstevel@tonic-gate recp = NULL; 503*7c478bd9Sstevel@tonic-gate done = TRUE; 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate } /* while (recp && !done) */ 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate /* Return what we've got (if anything) */ 509*7c478bd9Sstevel@tonic-gate return (recp); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* 513*7c478bd9Sstevel@tonic-gate * char *_devtabpath() 514*7c478bd9Sstevel@tonic-gate * 515*7c478bd9Sstevel@tonic-gate * Get the pathname of the device table 516*7c478bd9Sstevel@tonic-gate * 517*7c478bd9Sstevel@tonic-gate * Arguments: None 518*7c478bd9Sstevel@tonic-gate * 519*7c478bd9Sstevel@tonic-gate * Returns: char * 520*7c478bd9Sstevel@tonic-gate * Returns the pathname to the device table of NULL if 521*7c478bd9Sstevel@tonic-gate * there was a problem getting the memory needed to contain the 522*7c478bd9Sstevel@tonic-gate * pathname. 523*7c478bd9Sstevel@tonic-gate * 524*7c478bd9Sstevel@tonic-gate * Algorithm: 525*7c478bd9Sstevel@tonic-gate * 1. If OAM_DEVTAB is defined in the environment and is not 526*7c478bd9Sstevel@tonic-gate * defined as "", it returns the value of that environment 527*7c478bd9Sstevel@tonic-gate * variable. 528*7c478bd9Sstevel@tonic-gate * 2. Otherwise, use the value of the environment variable DTAB_PATH. 529*7c478bd9Sstevel@tonic-gate */ 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate char * 533*7c478bd9Sstevel@tonic-gate _devtabpath(void) 534*7c478bd9Sstevel@tonic-gate { 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate /* Automatic data */ 537*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 538*7c478bd9Sstevel@tonic-gate char *path; /* Ptr to path in environment */ 539*7c478bd9Sstevel@tonic-gate #endif 540*7c478bd9Sstevel@tonic-gate char *rtnval; /* Ptr to value to return */ 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate /* 544*7c478bd9Sstevel@tonic-gate * If compiled with -DDEBUG=1, 545*7c478bd9Sstevel@tonic-gate * look for the pathname in the environment 546*7c478bd9Sstevel@tonic-gate */ 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 549*7c478bd9Sstevel@tonic-gate if (((path = getenv(OAM_DEVTAB)) != NULL) && (*path)) { 550*7c478bd9Sstevel@tonic-gate if (rtnval = malloc(strlen(path)+1)) 551*7c478bd9Sstevel@tonic-gate (void) strcpy(rtnval, path); 552*7c478bd9Sstevel@tonic-gate } else { 553*7c478bd9Sstevel@tonic-gate #endif 554*7c478bd9Sstevel@tonic-gate /* 555*7c478bd9Sstevel@tonic-gate * Use the standard device table. 556*7c478bd9Sstevel@tonic-gate */ 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate if (rtnval = malloc(strlen(DTAB_PATH)+1)) 559*7c478bd9Sstevel@tonic-gate (void) strcpy(rtnval, DTAB_PATH); 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate #endif 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate /* Finished */ 566*7c478bd9Sstevel@tonic-gate return (rtnval); 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate /* 570*7c478bd9Sstevel@tonic-gate * int _opendevtab(mode) 571*7c478bd9Sstevel@tonic-gate * char *mode 572*7c478bd9Sstevel@tonic-gate * 573*7c478bd9Sstevel@tonic-gate * The _opendevtab() function opens a device table for a command. 574*7c478bd9Sstevel@tonic-gate * 575*7c478bd9Sstevel@tonic-gate * Arguments: 576*7c478bd9Sstevel@tonic-gate * mode The open mode to use to open the file. (i.e. "r" for 577*7c478bd9Sstevel@tonic-gate * reading, "w" for writing. See FOPEN(BA_OS) in SVID.) 578*7c478bd9Sstevel@tonic-gate * 579*7c478bd9Sstevel@tonic-gate * Returns: int 580*7c478bd9Sstevel@tonic-gate * TRUE if it successfully opens the device table file, FALSE otherwise 581*7c478bd9Sstevel@tonic-gate */ 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate int 584*7c478bd9Sstevel@tonic-gate _opendevtab(char *mode) 585*7c478bd9Sstevel@tonic-gate { 586*7c478bd9Sstevel@tonic-gate /* 587*7c478bd9Sstevel@tonic-gate * Automatic data 588*7c478bd9Sstevel@tonic-gate */ 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate char *devtabname; /* Ptr to the device table name */ 591*7c478bd9Sstevel@tonic-gate int rtnval; /* Value to return */ 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate rtnval = TRUE; 595*7c478bd9Sstevel@tonic-gate if (devtabname = _devtabpath()) { 596*7c478bd9Sstevel@tonic-gate if (oam_devtab) (void) fclose(oam_devtab); 597*7c478bd9Sstevel@tonic-gate if (oam_devtab = fopen(devtabname, mode)) 598*7c478bd9Sstevel@tonic-gate dtabrecnum = 0; /* :-) */ 599*7c478bd9Sstevel@tonic-gate else rtnval = FALSE; /* :-( */ 600*7c478bd9Sstevel@tonic-gate } else rtnval = FALSE; /* :-( */ 601*7c478bd9Sstevel@tonic-gate return (rtnval); 602*7c478bd9Sstevel@tonic-gate } 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate /* 605*7c478bd9Sstevel@tonic-gate * int _validalias(alias) 606*7c478bd9Sstevel@tonic-gate * char *alias 607*7c478bd9Sstevel@tonic-gate * 608*7c478bd9Sstevel@tonic-gate * Determine if <alias> is a valid alias. Returns TRUE if it is 609*7c478bd9Sstevel@tonic-gate * a valid alias, FALSE otherwise. 610*7c478bd9Sstevel@tonic-gate * 611*7c478bd9Sstevel@tonic-gate * Arguments: 612*7c478bd9Sstevel@tonic-gate * alias Value to check out 613*7c478bd9Sstevel@tonic-gate * 614*7c478bd9Sstevel@tonic-gate * Returns: int 615*7c478bd9Sstevel@tonic-gate * TRUE if <alias> is a valid alias, FALSE otherwise. 616*7c478bd9Sstevel@tonic-gate */ 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate int 619*7c478bd9Sstevel@tonic-gate _validalias(char *alias) /* Alias to validate */ 620*7c478bd9Sstevel@tonic-gate { 621*7c478bd9Sstevel@tonic-gate /* Automatic data */ 622*7c478bd9Sstevel@tonic-gate char *p; /* Temp pointer */ 623*7c478bd9Sstevel@tonic-gate size_t len; /* Length of <alias> */ 624*7c478bd9Sstevel@tonic-gate int rtn; /* Value to return */ 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate /* Assume the worst */ 628*7c478bd9Sstevel@tonic-gate rtn = FALSE; 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate /* 631*7c478bd9Sstevel@tonic-gate * A valid alias contains 0 < i <= 14 characters. The first 632*7c478bd9Sstevel@tonic-gate * must be alphanumeric or "@$_." and the rest must be alphanumeric 633*7c478bd9Sstevel@tonic-gate * or "@#$_+-." 634*7c478bd9Sstevel@tonic-gate */ 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate /* Check length */ 637*7c478bd9Sstevel@tonic-gate if ((alias != NULL) && ((len = strlen(alias)) > 0) && (len <= 14)) { 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate /* Check the first character */ 640*7c478bd9Sstevel@tonic-gate p = alias; 641*7c478bd9Sstevel@tonic-gate if (isalnum((unsigned char)*p) || strchr("@$_.", *p)) { 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate /* Check the rest of the characters */ 644*7c478bd9Sstevel@tonic-gate for (p++; *p && (isalnum((unsigned char)*p) || 645*7c478bd9Sstevel@tonic-gate strchr("@#$_-+.", *p)); p++) 646*7c478bd9Sstevel@tonic-gate ; 647*7c478bd9Sstevel@tonic-gate if (!(*p)) rtn = TRUE; 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate /* Return indicator... */ 652*7c478bd9Sstevel@tonic-gate return (rtn); 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate } /* int _validalias() */ 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate /* 657*7c478bd9Sstevel@tonic-gate * struct devtabent *_getdevtabent() 658*7c478bd9Sstevel@tonic-gate * 659*7c478bd9Sstevel@tonic-gate * This function returns the next entry in the device table. 660*7c478bd9Sstevel@tonic-gate * If no device table is open, it opens the standard device table 661*7c478bd9Sstevel@tonic-gate * and returns the first record in the table. 662*7c478bd9Sstevel@tonic-gate * 663*7c478bd9Sstevel@tonic-gate * Arguments: None. 664*7c478bd9Sstevel@tonic-gate * 665*7c478bd9Sstevel@tonic-gate * Returns: struct devtabent * 666*7c478bd9Sstevel@tonic-gate * Pointer to the next record in the device table, or 667*7c478bd9Sstevel@tonic-gate * (struct devtabent *) NULL if it was unable to open the file or there 668*7c478bd9Sstevel@tonic-gate * are no more records to read. "errno" reflects the situation. If 669*7c478bd9Sstevel@tonic-gate * errno is not changed and the function returns NULL, there are no more 670*7c478bd9Sstevel@tonic-gate * records to read. If errno is set, it indicates the error. 671*7c478bd9Sstevel@tonic-gate * 672*7c478bd9Sstevel@tonic-gate * Notes: 673*7c478bd9Sstevel@tonic-gate * - The caller should set "errno" to 0 before calling this function. 674*7c478bd9Sstevel@tonic-gate */ 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate struct devtabent * 677*7c478bd9Sstevel@tonic-gate _getdevtabent(void) 678*7c478bd9Sstevel@tonic-gate { 679*7c478bd9Sstevel@tonic-gate /* Automatic data */ 680*7c478bd9Sstevel@tonic-gate struct devtabent *ent; /* Ptr to dev table entry structure */ 681*7c478bd9Sstevel@tonic-gate struct attrval *attr; /* Ptr to struct for attr/val pair */ 682*7c478bd9Sstevel@tonic-gate struct attrval *t; /* Tmp ptr to attr/val struct */ 683*7c478bd9Sstevel@tonic-gate char *record; /* Ptr to the record just read */ 684*7c478bd9Sstevel@tonic-gate char *p, *q; /* Tmp char ptrs */ 685*7c478bd9Sstevel@tonic-gate int done; /* TRUE if we've built an entry */ 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate /* Open the device table if it's not already open */ 689*7c478bd9Sstevel@tonic-gate if (oam_devtab == NULL) { 690*7c478bd9Sstevel@tonic-gate if (!_opendevtab("r")) 691*7c478bd9Sstevel@tonic-gate return (NULL); 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate /* Get space for the structure we're returning */ 695*7c478bd9Sstevel@tonic-gate if (!(ent = malloc(sizeof (struct devtabent)))) { 696*7c478bd9Sstevel@tonic-gate return (NULL); 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate done = FALSE; 700*7c478bd9Sstevel@tonic-gate while (!done && (record = getnextrec())) { 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate /* Save record number in structure */ 703*7c478bd9Sstevel@tonic-gate ent->entryno = dtabrecnum++; 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate /* Comment record? If so, just save the value and we're through */ 706*7c478bd9Sstevel@tonic-gate if (strchr("#\n", *record) || isspace((unsigned char)*record)) { 707*7c478bd9Sstevel@tonic-gate ent->comment = TRUE; 708*7c478bd9Sstevel@tonic-gate done = TRUE; 709*7c478bd9Sstevel@tonic-gate if (ent->attrstr = malloc(strlen(record)+1)) { 710*7c478bd9Sstevel@tonic-gate q = ent->attrstr; 711*7c478bd9Sstevel@tonic-gate p = record; 712*7c478bd9Sstevel@tonic-gate do { 713*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++; 714*7c478bd9Sstevel@tonic-gate *q++ = *p; 715*7c478bd9Sstevel@tonic-gate } while (*p++); 716*7c478bd9Sstevel@tonic-gate } else { 717*7c478bd9Sstevel@tonic-gate free(ent); 718*7c478bd9Sstevel@tonic-gate ent = NULL; 719*7c478bd9Sstevel@tonic-gate } 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate else { 723*7c478bd9Sstevel@tonic-gate 724*7c478bd9Sstevel@tonic-gate /* Record is a data record. Parse it. */ 725*7c478bd9Sstevel@tonic-gate ent->comment = FALSE; 726*7c478bd9Sstevel@tonic-gate ent->attrstr = NULL; /* For now */ 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate /* Extract the device alias */ 729*7c478bd9Sstevel@tonic-gate if (p = getfld(record, ":")) { 730*7c478bd9Sstevel@tonic-gate if (*p) { 731*7c478bd9Sstevel@tonic-gate if (ent->alias = malloc(strlen(p)+1)) { 732*7c478bd9Sstevel@tonic-gate q = ent->alias; 733*7c478bd9Sstevel@tonic-gate do { 734*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++; 735*7c478bd9Sstevel@tonic-gate *q++ = *p; 736*7c478bd9Sstevel@tonic-gate } while (*p++); 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate } else ent->alias = NULL; 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate /* Extract the character-device name */ 741*7c478bd9Sstevel@tonic-gate if ((p = getfld(NULL, ":")) == NULL) { 742*7c478bd9Sstevel@tonic-gate if (ent->alias) 743*7c478bd9Sstevel@tonic-gate free(ent->alias); 744*7c478bd9Sstevel@tonic-gate } else { 745*7c478bd9Sstevel@tonic-gate if (*p) { 746*7c478bd9Sstevel@tonic-gate if (ent->cdevice = malloc(strlen(p)+1)) { 747*7c478bd9Sstevel@tonic-gate q = ent->cdevice; 748*7c478bd9Sstevel@tonic-gate do { 749*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++; 750*7c478bd9Sstevel@tonic-gate *q++ = *p; 751*7c478bd9Sstevel@tonic-gate } while (*p++); 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate } else ent->cdevice = NULL; 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate /* Extract the block-device name */ 756*7c478bd9Sstevel@tonic-gate if (!(p = getfld(NULL, ":"))) { 757*7c478bd9Sstevel@tonic-gate if (ent->alias) free(ent->alias); 758*7c478bd9Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice); 759*7c478bd9Sstevel@tonic-gate } else { 760*7c478bd9Sstevel@tonic-gate if (*p) { 761*7c478bd9Sstevel@tonic-gate if (ent->bdevice = malloc(strlen(p)+1)) { 762*7c478bd9Sstevel@tonic-gate q = ent->bdevice; 763*7c478bd9Sstevel@tonic-gate do { 764*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++; 765*7c478bd9Sstevel@tonic-gate *q++ = *p; 766*7c478bd9Sstevel@tonic-gate } while (*p++); 767*7c478bd9Sstevel@tonic-gate } 768*7c478bd9Sstevel@tonic-gate } else 769*7c478bd9Sstevel@tonic-gate ent->bdevice = NULL; 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate /* Extract the pathname */ 772*7c478bd9Sstevel@tonic-gate if ((p = getfld(NULL, ":\n")) == NULL) { 773*7c478bd9Sstevel@tonic-gate if (ent->alias) free(ent->alias); 774*7c478bd9Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice); 775*7c478bd9Sstevel@tonic-gate if (ent->bdevice) free(ent->bdevice); 776*7c478bd9Sstevel@tonic-gate } else { 777*7c478bd9Sstevel@tonic-gate if (*p) { 778*7c478bd9Sstevel@tonic-gate if (ent->pathname = malloc(strlen(p)+1)) { 779*7c478bd9Sstevel@tonic-gate q = ent->pathname; 780*7c478bd9Sstevel@tonic-gate do { 781*7c478bd9Sstevel@tonic-gate if (*p == '\\') p++; 782*7c478bd9Sstevel@tonic-gate *q++ = *p; 783*7c478bd9Sstevel@tonic-gate } while (*p++); 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate } else 786*7c478bd9Sstevel@tonic-gate ent->pathname = NULL; 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate /* Found a valid record */ 789*7c478bd9Sstevel@tonic-gate done = TRUE; 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate /* 792*7c478bd9Sstevel@tonic-gate * Extract attributes, build a linked list of 793*7c478bd9Sstevel@tonic-gate * 'em (may be none) 794*7c478bd9Sstevel@tonic-gate */ 795*7c478bd9Sstevel@tonic-gate if (attr = getattrval(NULL)) { 796*7c478bd9Sstevel@tonic-gate ent->attrlist = attr; 797*7c478bd9Sstevel@tonic-gate t = attr; 798*7c478bd9Sstevel@tonic-gate while (attr = getattrval(NULL)) { 799*7c478bd9Sstevel@tonic-gate t->next = attr; 800*7c478bd9Sstevel@tonic-gate t = attr; 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate t->next = NULL; 803*7c478bd9Sstevel@tonic-gate } else 804*7c478bd9Sstevel@tonic-gate ent->attrlist = NULL; 805*7c478bd9Sstevel@tonic-gate 806*7c478bd9Sstevel@tonic-gate } /* pathname extracted */ 807*7c478bd9Sstevel@tonic-gate } /* bdevice extracted */ 808*7c478bd9Sstevel@tonic-gate } /* cdevice extracted */ 809*7c478bd9Sstevel@tonic-gate } /* alias extracted */ 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate } /* !done && record read */ 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate /* If no entry was read, free space allocated to the structure */ 814*7c478bd9Sstevel@tonic-gate if (!done) { 815*7c478bd9Sstevel@tonic-gate free(ent); 816*7c478bd9Sstevel@tonic-gate ent = NULL; 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate return (ent); 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate 822*7c478bd9Sstevel@tonic-gate /* 823*7c478bd9Sstevel@tonic-gate * void _freedevtabent(devtabent) 824*7c478bd9Sstevel@tonic-gate * struct devtabent *devtabent; 825*7c478bd9Sstevel@tonic-gate * 826*7c478bd9Sstevel@tonic-gate * This function frees space allocated to a device table entry. 827*7c478bd9Sstevel@tonic-gate * 828*7c478bd9Sstevel@tonic-gate * Arguments: 829*7c478bd9Sstevel@tonic-gate * struct devtabent *devtabent The structure whose space is to be 830*7c478bd9Sstevel@tonic-gate * freed. 831*7c478bd9Sstevel@tonic-gate * 832*7c478bd9Sstevel@tonic-gate * Returns: void 833*7c478bd9Sstevel@tonic-gate */ 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate void 836*7c478bd9Sstevel@tonic-gate _freedevtabent(struct devtabent *ent) 837*7c478bd9Sstevel@tonic-gate { 838*7c478bd9Sstevel@tonic-gate /* 839*7c478bd9Sstevel@tonic-gate * Automatic data 840*7c478bd9Sstevel@tonic-gate */ 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate struct attrval *p; /* Structure being freed */ 843*7c478bd9Sstevel@tonic-gate struct attrval *q; /* Next structure to free */ 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate if (!ent->comment) { 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate /* 848*7c478bd9Sstevel@tonic-gate * Free the attribute list. For each item in the attribute 849*7c478bd9Sstevel@tonic-gate * list, 850*7c478bd9Sstevel@tonic-gate * 1. Free the attribute name (always defined), 851*7c478bd9Sstevel@tonic-gate * 2. Free the value (if any -- it's not defined if we're 852*7c478bd9Sstevel@tonic-gate * changing an existing attribute), 853*7c478bd9Sstevel@tonic-gate * 3. Free the space allocated to the structure. 854*7c478bd9Sstevel@tonic-gate */ 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate q = ent->attrlist; 857*7c478bd9Sstevel@tonic-gate if (q) 858*7c478bd9Sstevel@tonic-gate do { 859*7c478bd9Sstevel@tonic-gate p = q; 860*7c478bd9Sstevel@tonic-gate q = p->next; 861*7c478bd9Sstevel@tonic-gate free(p->attr); 862*7c478bd9Sstevel@tonic-gate if (p->val) free(p->val); 863*7c478bd9Sstevel@tonic-gate free(p); 864*7c478bd9Sstevel@tonic-gate } while (q); 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate /* Free the standard fields (alias, cdevice, bdevice, pathname) */ 867*7c478bd9Sstevel@tonic-gate if (ent->alias) free(ent->alias); 868*7c478bd9Sstevel@tonic-gate if (ent->cdevice) free(ent->cdevice); 869*7c478bd9Sstevel@tonic-gate if (ent->bdevice) free(ent->bdevice); 870*7c478bd9Sstevel@tonic-gate if (ent->pathname) free(ent->pathname); 871*7c478bd9Sstevel@tonic-gate } 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate /* Free the attribute string */ 874*7c478bd9Sstevel@tonic-gate if (ent->attrstr) free(ent->attrstr); 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate /* Free the space allocated to the structure */ 877*7c478bd9Sstevel@tonic-gate free(ent); 878*7c478bd9Sstevel@tonic-gate } 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate /* 881*7c478bd9Sstevel@tonic-gate * struct devtabent *_getdevrec(device) 882*7c478bd9Sstevel@tonic-gate * char *device 883*7c478bd9Sstevel@tonic-gate * 884*7c478bd9Sstevel@tonic-gate * Thie _getdevrec() function returns a pointer to a structure that 885*7c478bd9Sstevel@tonic-gate * contains the information in the device-table entry that describes 886*7c478bd9Sstevel@tonic-gate * the device <device>. 887*7c478bd9Sstevel@tonic-gate * 888*7c478bd9Sstevel@tonic-gate * The device <device> can be a device alias, a pathname contained in 889*7c478bd9Sstevel@tonic-gate * the entry as the "cdevice", "bdevice", or "pathname" attribute, 890*7c478bd9Sstevel@tonic-gate * or a pathname to a device described using the "cdevice", "bdevice", 891*7c478bd9Sstevel@tonic-gate * or "pathname" attribute (depending on whether the pathname references 892*7c478bd9Sstevel@tonic-gate * a character-special file, block-special file, or something else, 893*7c478bd9Sstevel@tonic-gate * respectively. 894*7c478bd9Sstevel@tonic-gate * 895*7c478bd9Sstevel@tonic-gate * Arguments: 896*7c478bd9Sstevel@tonic-gate * char *device A character-string describing the device whose record 897*7c478bd9Sstevel@tonic-gate * is to be retrieved from the device table. 898*7c478bd9Sstevel@tonic-gate * 899*7c478bd9Sstevel@tonic-gate * Returns: struct devtabent * 900*7c478bd9Sstevel@tonic-gate * A pointer to a structure describing the device. 901*7c478bd9Sstevel@tonic-gate * 902*7c478bd9Sstevel@tonic-gate * Notes: 903*7c478bd9Sstevel@tonic-gate * - Someday, add a cache so that repeated requests for the same record 904*7c478bd9Sstevel@tonic-gate * don't require going to the filesystem. (Maybe -- this might belong 905*7c478bd9Sstevel@tonic-gate * in devattr()...) 906*7c478bd9Sstevel@tonic-gate */ 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate struct devtabent * 909*7c478bd9Sstevel@tonic-gate _getdevrec(char *device) /* The device to search for */ 910*7c478bd9Sstevel@tonic-gate { 911*7c478bd9Sstevel@tonic-gate /* 912*7c478bd9Sstevel@tonic-gate * Automatic data 913*7c478bd9Sstevel@tonic-gate */ 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate struct stat64 devstatbuf; /* Stat struct, <device> */ 916*7c478bd9Sstevel@tonic-gate struct stat64 tblstatbuf; /* Stat struct, tbl entry */ 917*7c478bd9Sstevel@tonic-gate struct devtabent *devrec; /* Pointer to current record */ 918*7c478bd9Sstevel@tonic-gate int found; /* TRUE if record found */ 919*7c478bd9Sstevel@tonic-gate int olderrno; /* Old value of errno */ 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate /* 923*7c478bd9Sstevel@tonic-gate * Search the device table looking for the requested device 924*7c478bd9Sstevel@tonic-gate */ 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate _setdevtab(); 927*7c478bd9Sstevel@tonic-gate olderrno = errno; 928*7c478bd9Sstevel@tonic-gate found = FALSE; 929*7c478bd9Sstevel@tonic-gate if ((device != NULL) && !_validalias(device)) { 930*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 931*7c478bd9Sstevel@tonic-gate if (!devrec->comment) { 932*7c478bd9Sstevel@tonic-gate if (devrec->cdevice) 933*7c478bd9Sstevel@tonic-gate if (strcmp(device, devrec->cdevice) == 0) found = TRUE; 934*7c478bd9Sstevel@tonic-gate if (devrec->bdevice) 935*7c478bd9Sstevel@tonic-gate if (strcmp(device, devrec->bdevice) == 0) found = TRUE; 936*7c478bd9Sstevel@tonic-gate if (devrec->pathname) 937*7c478bd9Sstevel@tonic-gate if (strcmp(device, devrec->pathname) == 0) found = TRUE; 938*7c478bd9Sstevel@tonic-gate } else _freedevtabent(devrec); 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate /* 942*7c478bd9Sstevel@tonic-gate * If the device <device> wasn't named explicitly in the device 943*7c478bd9Sstevel@tonic-gate * table, compare it against like entries by comparing file- 944*7c478bd9Sstevel@tonic-gate * system, major device number, and minor device number 945*7c478bd9Sstevel@tonic-gate */ 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate if (!found) { 948*7c478bd9Sstevel@tonic-gate _setdevtab(); 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate /* Status the file <device>. If fails, invalid device */ 951*7c478bd9Sstevel@tonic-gate if (stat64(device, &devstatbuf) != 0) errno = ENODEV; 952*7c478bd9Sstevel@tonic-gate else { 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate /* 955*7c478bd9Sstevel@tonic-gate * If <device> is a block-special device. See if it is 956*7c478bd9Sstevel@tonic-gate * in the table by matching its file-system indicator 957*7c478bd9Sstevel@tonic-gate * and major/minor device numbers against the 958*7c478bd9Sstevel@tonic-gate * file-system and major/minor device numbers of the 959*7c478bd9Sstevel@tonic-gate * "bdevice" entries. 960*7c478bd9Sstevel@tonic-gate */ 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate if ((devstatbuf.st_mode & 0170000) == 0020000) { 963*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 964*7c478bd9Sstevel@tonic-gate if (!devrec->comment && 965*7c478bd9Sstevel@tonic-gate (devrec->cdevice != NULL)) 966*7c478bd9Sstevel@tonic-gate if (stat64(devrec->cdevice, &tblstatbuf) == 0) { 967*7c478bd9Sstevel@tonic-gate if (samedev(tblstatbuf, devstatbuf)) 968*7c478bd9Sstevel@tonic-gate found = TRUE; 969*7c478bd9Sstevel@tonic-gate } else { 970*7c478bd9Sstevel@tonic-gate /* Ignore stat() errs */ 971*7c478bd9Sstevel@tonic-gate errno = olderrno; 972*7c478bd9Sstevel@tonic-gate } 973*7c478bd9Sstevel@tonic-gate if (!found) _freedevtabent(devrec); 974*7c478bd9Sstevel@tonic-gate } 975*7c478bd9Sstevel@tonic-gate } 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate /* 978*7c478bd9Sstevel@tonic-gate * If <device> is a block-special device. See if it is 979*7c478bd9Sstevel@tonic-gate * in the table by matching its file-system indicator 980*7c478bd9Sstevel@tonic-gate * and major/minor device numbers against the 981*7c478bd9Sstevel@tonic-gate * file-system and major/minor device numbers of the 982*7c478bd9Sstevel@tonic-gate * "bdevice" entries. 983*7c478bd9Sstevel@tonic-gate */ 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate else if ((devstatbuf.st_mode & 0170000) == 0060000) { 986*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 987*7c478bd9Sstevel@tonic-gate if (!devrec->comment && 988*7c478bd9Sstevel@tonic-gate (devrec->bdevice != NULL)) 989*7c478bd9Sstevel@tonic-gate if (stat64(devrec->bdevice, &tblstatbuf) == 0) { 990*7c478bd9Sstevel@tonic-gate if (samedev(tblstatbuf, devstatbuf)) 991*7c478bd9Sstevel@tonic-gate found = TRUE; 992*7c478bd9Sstevel@tonic-gate } else { 993*7c478bd9Sstevel@tonic-gate /* Ignore stat() errs */ 994*7c478bd9Sstevel@tonic-gate errno = olderrno; 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate if (!found) _freedevtabent(devrec); 997*7c478bd9Sstevel@tonic-gate } 998*7c478bd9Sstevel@tonic-gate } 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate /* 1001*7c478bd9Sstevel@tonic-gate * If <device> is neither a block-special or character- 1002*7c478bd9Sstevel@tonic-gate * special device. See if it is in the table by 1003*7c478bd9Sstevel@tonic-gate * matching its file-system indicator and major/minor 1004*7c478bd9Sstevel@tonic-gate * device numbers against the file-system and 1005*7c478bd9Sstevel@tonic-gate * major/minor device numbers of the "pathname" entries. 1006*7c478bd9Sstevel@tonic-gate */ 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate else { 1009*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 1010*7c478bd9Sstevel@tonic-gate if (!devrec->comment && 1011*7c478bd9Sstevel@tonic-gate (devrec->pathname != NULL)) 1012*7c478bd9Sstevel@tonic-gate if (stat64(devrec->pathname, 1013*7c478bd9Sstevel@tonic-gate &tblstatbuf) == 0) { 1014*7c478bd9Sstevel@tonic-gate if (samedev(tblstatbuf, devstatbuf)) 1015*7c478bd9Sstevel@tonic-gate found = TRUE; 1016*7c478bd9Sstevel@tonic-gate } else { 1017*7c478bd9Sstevel@tonic-gate /* Ignore stat() errs */ 1018*7c478bd9Sstevel@tonic-gate errno = olderrno; 1019*7c478bd9Sstevel@tonic-gate } 1020*7c478bd9Sstevel@tonic-gate if (!found) _freedevtabent(devrec); 1021*7c478bd9Sstevel@tonic-gate } 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate if (!found) { 1025*7c478bd9Sstevel@tonic-gate devrec = NULL; 1026*7c478bd9Sstevel@tonic-gate errno = ENODEV; 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate } /* End case where stat() on the <device> succeeded */ 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate } /* End case handling pathname not explicitly in device table */ 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate } /* End case handling <device> as a fully-qualified pathname */ 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate /* 1037*7c478bd9Sstevel@tonic-gate * Otherwise the device <device> is an alias. 1038*7c478bd9Sstevel@tonic-gate * Search the table for a record that has as the "alias" attribute 1039*7c478bd9Sstevel@tonic-gate * the value <device>. 1040*7c478bd9Sstevel@tonic-gate */ 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate else { 1043*7c478bd9Sstevel@tonic-gate while (!found && (devrec = _getdevtabent())) { 1044*7c478bd9Sstevel@tonic-gate if (!devrec->comment && (device != NULL) && 1045*7c478bd9Sstevel@tonic-gate strcmp(device, devrec->alias) == 0) 1046*7c478bd9Sstevel@tonic-gate found = TRUE; 1047*7c478bd9Sstevel@tonic-gate else _freedevtabent(devrec); 1048*7c478bd9Sstevel@tonic-gate } 1049*7c478bd9Sstevel@tonic-gate if (!found) { 1050*7c478bd9Sstevel@tonic-gate devrec = NULL; 1051*7c478bd9Sstevel@tonic-gate errno = ENODEV; 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate } 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate /* Fini */ 1056*7c478bd9Sstevel@tonic-gate return (devrec); 1057*7c478bd9Sstevel@tonic-gate } 1058