1*2923Sraf /* 2*2923Sraf * CDDL HEADER START 3*2923Sraf * 4*2923Sraf * The contents of this file are subject to the terms of the 5*2923Sraf * Common Development and Distribution License (the "License"). 6*2923Sraf * You may not use this file except in compliance with the License. 7*2923Sraf * 8*2923Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*2923Sraf * or http://www.opensolaris.org/os/licensing. 10*2923Sraf * See the License for the specific language governing permissions 11*2923Sraf * and limitations under the License. 12*2923Sraf * 13*2923Sraf * When distributing Covered Code, include this CDDL HEADER in each 14*2923Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*2923Sraf * If applicable, add the following below this CDDL HEADER, with the 16*2923Sraf * fields enclosed by brackets "[]" replaced with your own identifying 17*2923Sraf * information: Portions Copyright [yyyy] [name of copyright owner] 18*2923Sraf * 19*2923Sraf * CDDL HEADER END 20*2923Sraf */ 21*2923Sraf 22*2923Sraf /* 23*2923Sraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*2923Sraf * Use is subject to license terms. 25*2923Sraf */ 26*2923Sraf 27*2923Sraf /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*2923Sraf /* All Rights Reserved */ 29*2923Sraf 30*2923Sraf /* Copyright (c) 1987, 1988 Microsoft Corporation */ 31*2923Sraf /* All Rights Reserved */ 32*2923Sraf 33*2923Sraf #pragma ident "%Z%%M% %I% %E% SMI" 34*2923Sraf 35*2923Sraf #pragma weak defopen = _defopen 36*2923Sraf #pragma weak defread = _defread 37*2923Sraf #pragma weak defcntl = _defcntl 38*2923Sraf 39*2923Sraf #include "synonyms.h" 40*2923Sraf #include "libc.h" 41*2923Sraf #include <stdio.h> 42*2923Sraf #include <stdlib.h> 43*2923Sraf #include <deflt.h> 44*2923Sraf #include <sys/types.h> 45*2923Sraf #include <string.h> 46*2923Sraf #include <ctype.h> 47*2923Sraf #include <unistd.h> 48*2923Sraf #include "tsd.h" 49*2923Sraf 50*2923Sraf #define TSTBITS(flags, mask) (((flags) & (mask)) == (mask)) 51*2923Sraf 52*2923Sraf static void strip_quotes(char *); 53*2923Sraf 54*2923Sraf struct thr_data { 55*2923Sraf int Dcflags; /* [re-]initialized on each call to defopen() */ 56*2923Sraf FILE *fp; 57*2923Sraf char *buf; 58*2923Sraf }; 59*2923Sraf 60*2923Sraf #define BUFFERSIZE 1024 61*2923Sraf 62*2923Sraf /* 63*2923Sraf * destructor for per-thread data, registered with tsdalloc() 64*2923Sraf */ 65*2923Sraf static void 66*2923Sraf free_thr_data(void *arg) 67*2923Sraf { 68*2923Sraf struct thr_data *thr_data = (struct thr_data *)arg; 69*2923Sraf 70*2923Sraf if (thr_data->fp) { 71*2923Sraf (void) fclose(thr_data->fp); 72*2923Sraf thr_data->fp = NULL; 73*2923Sraf } 74*2923Sraf if (thr_data->buf) { 75*2923Sraf lfree(thr_data->buf, BUFFERSIZE); 76*2923Sraf thr_data->buf = NULL; 77*2923Sraf } 78*2923Sraf } 79*2923Sraf 80*2923Sraf /* 81*2923Sraf * get the per-thread-data-item for the calling thread 82*2923Sraf */ 83*2923Sraf static struct thr_data * 84*2923Sraf get_thr_data(void) 85*2923Sraf { 86*2923Sraf struct thr_data *thr_data = 87*2923Sraf tsdalloc(_T_DEFREAD, sizeof (*thr_data), free_thr_data); 88*2923Sraf 89*2923Sraf return (thr_data); 90*2923Sraf } 91*2923Sraf 92*2923Sraf /* 93*2923Sraf * defopen() - declare defopen filename 94*2923Sraf * 95*2923Sraf * defopen(fn) 96*2923Sraf * char *fn 97*2923Sraf * 98*2923Sraf * If 'fn' is non-null; it is a full pathname of a file 99*2923Sraf * which becomes the one read by subsequent defread() calls. 100*2923Sraf * If 'fn' is null the defopen file is closed. 101*2923Sraf * 102*2923Sraf * see defread() for more details. 103*2923Sraf * 104*2923Sraf * EXIT returns 0 if ok 105*2923Sraf * returns -1 if error 106*2923Sraf */ 107*2923Sraf int 108*2923Sraf defopen(char *fn) 109*2923Sraf { 110*2923Sraf struct thr_data *thr_data = get_thr_data(); 111*2923Sraf 112*2923Sraf if (thr_data == NULL) 113*2923Sraf return (-1); 114*2923Sraf 115*2923Sraf if (thr_data->fp != NULL) { 116*2923Sraf (void) fclose(thr_data->fp); 117*2923Sraf thr_data->fp = NULL; 118*2923Sraf } 119*2923Sraf 120*2923Sraf if (fn == NULL) 121*2923Sraf return (0); 122*2923Sraf 123*2923Sraf if ((thr_data->fp = fopen(fn, "rF")) == NULL) 124*2923Sraf return (-1); 125*2923Sraf 126*2923Sraf /* 127*2923Sraf * We allocate the big buffer only if the fopen() succeeds. 128*2923Sraf * Notice that we deallocate the buffer only when the thread exits. 129*2923Sraf * There are misguided applications that assume that data returned 130*2923Sraf * by defread() continues to exist after defopen(NULL) is called. 131*2923Sraf */ 132*2923Sraf if (thr_data->buf == NULL && 133*2923Sraf (thr_data->buf = lmalloc(BUFFERSIZE)) == NULL) { 134*2923Sraf (void) fclose(thr_data->fp); 135*2923Sraf thr_data->fp = NULL; 136*2923Sraf return (-1); 137*2923Sraf } 138*2923Sraf 139*2923Sraf thr_data->Dcflags = DC_STD; 140*2923Sraf 141*2923Sraf return (0); 142*2923Sraf } 143*2923Sraf 144*2923Sraf /* 145*2923Sraf * defread() - read an entry from the defopen file 146*2923Sraf * 147*2923Sraf * defread(cp) 148*2923Sraf * char *cp 149*2923Sraf * 150*2923Sraf * The defopen data file must have been previously opened by 151*2923Sraf * defopen(). defread scans the data file looking for a line 152*2923Sraf * which begins with the string '*cp'. If such a line is found, 153*2923Sraf * defread returns a pointer to the first character following 154*2923Sraf * the matched string (*cp). If no line is found or no file 155*2923Sraf * is open, defread() returns NULL. 156*2923Sraf * 157*2923Sraf * Note that there is no way to simulatniously peruse multiple 158*2923Sraf * defopen files; since there is no way of indicating 'which one' 159*2923Sraf * to defread(). If you want to peruse a secondary file you must 160*2923Sraf * recall defopen(). If you need to go back to the first file, 161*2923Sraf * you must call defopen() again. 162*2923Sraf */ 163*2923Sraf char * 164*2923Sraf defread(char *cp) 165*2923Sraf { 166*2923Sraf struct thr_data *thr_data = get_thr_data(); 167*2923Sraf int (*compare)(const char *, const char *, size_t); 168*2923Sraf char *buf_tmp, *ret_ptr = NULL; 169*2923Sraf size_t off, patlen; 170*2923Sraf 171*2923Sraf if (thr_data == NULL || thr_data->fp == NULL) 172*2923Sraf return (NULL); 173*2923Sraf 174*2923Sraf compare = TSTBITS(thr_data->Dcflags, DC_CASE) ? strncmp : strncasecmp; 175*2923Sraf patlen = strlen(cp); 176*2923Sraf 177*2923Sraf if (!TSTBITS(thr_data->Dcflags, DC_NOREWIND)) 178*2923Sraf rewind(thr_data->fp); 179*2923Sraf 180*2923Sraf while (fgets(thr_data->buf, BUFFERSIZE, thr_data->fp)) { 181*2923Sraf for (buf_tmp = thr_data->buf; *buf_tmp == ' '; buf_tmp++) 182*2923Sraf ; 183*2923Sraf off = strlen(buf_tmp) - 1; 184*2923Sraf if (buf_tmp[off] == '\n') 185*2923Sraf buf_tmp[off] = 0; 186*2923Sraf else 187*2923Sraf break; /* line too long */ 188*2923Sraf if ((*compare)(cp, buf_tmp, patlen) == 0) { 189*2923Sraf /* found it */ 190*2923Sraf /* strip quotes if requested */ 191*2923Sraf if (TSTBITS(thr_data->Dcflags, DC_STRIP_QUOTES)) { 192*2923Sraf strip_quotes(buf_tmp); 193*2923Sraf } 194*2923Sraf ret_ptr = &buf_tmp[patlen]; 195*2923Sraf break; 196*2923Sraf } 197*2923Sraf } 198*2923Sraf 199*2923Sraf return (ret_ptr); 200*2923Sraf } 201*2923Sraf 202*2923Sraf /* 203*2923Sraf * defcntl -- default control 204*2923Sraf * 205*2923Sraf * SYNOPSIS 206*2923Sraf * oldflags = defcntl(cmd, arg); 207*2923Sraf * 208*2923Sraf * ENTRY 209*2923Sraf * cmd Command. One of DC_GET, DC_SET. 210*2923Sraf * arg Depends on command. If DC_GET, ignored. If 211*2923Sraf * DC_GET, new flags value, created by ORing the DC_* bits. 212*2923Sraf * RETURN 213*2923Sraf * oldflags Old value of flags. -1 on error. 214*2923Sraf * NOTES 215*2923Sraf * Currently only one bit of flags implemented, namely respect/ 216*2923Sraf * ignore case. The routine is as general as it is so that we 217*2923Sraf * leave our options open. E.g. we might want to specify rewind/ 218*2923Sraf * norewind before each defread. 219*2923Sraf */ 220*2923Sraf 221*2923Sraf int 222*2923Sraf defcntl(int cmd, int newflags) 223*2923Sraf { 224*2923Sraf struct thr_data *thr_data = get_thr_data(); 225*2923Sraf int oldflags; 226*2923Sraf 227*2923Sraf if (thr_data == NULL) 228*2923Sraf return (-1); 229*2923Sraf 230*2923Sraf switch (cmd) { 231*2923Sraf case DC_GETFLAGS: /* query */ 232*2923Sraf oldflags = thr_data->Dcflags; 233*2923Sraf break; 234*2923Sraf case DC_SETFLAGS: /* set */ 235*2923Sraf oldflags = thr_data->Dcflags; 236*2923Sraf thr_data->Dcflags = newflags; 237*2923Sraf break; 238*2923Sraf default: /* error */ 239*2923Sraf oldflags = -1; 240*2923Sraf break; 241*2923Sraf } 242*2923Sraf 243*2923Sraf return (oldflags); 244*2923Sraf } 245*2923Sraf 246*2923Sraf /* 247*2923Sraf * strip_quotes -- strip double (") or single (') quotes from a buffer 248*2923Sraf * 249*2923Sraf * ENTRY 250*2923Sraf * ptr initial string 251*2923Sraf * 252*2923Sraf * EXIT 253*2923Sraf * ptr string with quotes (if any) removed 254*2923Sraf */ 255*2923Sraf static void 256*2923Sraf strip_quotes(char *ptr) 257*2923Sraf { 258*2923Sraf char *strip_ptr = NULL; 259*2923Sraf 260*2923Sraf while (*ptr != '\0') { 261*2923Sraf if ((*ptr == '"') || (*ptr == '\'')) { 262*2923Sraf if (strip_ptr == NULL) 263*2923Sraf strip_ptr = ptr; /* skip over quote */ 264*2923Sraf } else { 265*2923Sraf if (strip_ptr != NULL) { 266*2923Sraf *strip_ptr = *ptr; 267*2923Sraf strip_ptr++; 268*2923Sraf } 269*2923Sraf } 270*2923Sraf ptr++; 271*2923Sraf } 272*2923Sraf if (strip_ptr != NULL) { 273*2923Sraf *strip_ptr = '\0'; 274*2923Sraf } 275*2923Sraf } 276