12923Sraf /* 22923Sraf * CDDL HEADER START 32923Sraf * 42923Sraf * The contents of this file are subject to the terms of the 52923Sraf * Common Development and Distribution License (the "License"). 62923Sraf * You may not use this file except in compliance with the License. 72923Sraf * 82923Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92923Sraf * or http://www.opensolaris.org/os/licensing. 102923Sraf * See the License for the specific language governing permissions 112923Sraf * and limitations under the License. 122923Sraf * 132923Sraf * When distributing Covered Code, include this CDDL HEADER in each 142923Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152923Sraf * If applicable, add the following below this CDDL HEADER, with the 162923Sraf * fields enclosed by brackets "[]" replaced with your own identifying 172923Sraf * information: Portions Copyright [yyyy] [name of copyright owner] 182923Sraf * 192923Sraf * CDDL HEADER END 202923Sraf */ 212923Sraf 222923Sraf /* 23*6812Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 242923Sraf * Use is subject to license terms. 252923Sraf */ 262923Sraf 272923Sraf /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 282923Sraf /* All Rights Reserved */ 292923Sraf 302923Sraf /* Copyright (c) 1987, 1988 Microsoft Corporation */ 312923Sraf /* All Rights Reserved */ 322923Sraf 332923Sraf #pragma ident "%Z%%M% %I% %E% SMI" 342923Sraf 35*6812Sraf #include "lint.h" 362923Sraf #include "libc.h" 372923Sraf #include <stdio.h> 382923Sraf #include <stdlib.h> 392923Sraf #include <deflt.h> 402923Sraf #include <sys/types.h> 412923Sraf #include <string.h> 422923Sraf #include <ctype.h> 432923Sraf #include <unistd.h> 442923Sraf #include "tsd.h" 452923Sraf 462923Sraf #define TSTBITS(flags, mask) (((flags) & (mask)) == (mask)) 472923Sraf 482923Sraf static void strip_quotes(char *); 492923Sraf 502923Sraf struct thr_data { 512923Sraf int Dcflags; /* [re-]initialized on each call to defopen() */ 522923Sraf FILE *fp; 532923Sraf char *buf; 542923Sraf }; 552923Sraf 562923Sraf #define BUFFERSIZE 1024 572923Sraf 582923Sraf /* 592923Sraf * destructor for per-thread data, registered with tsdalloc() 602923Sraf */ 612923Sraf static void 622923Sraf free_thr_data(void *arg) 632923Sraf { 642923Sraf struct thr_data *thr_data = (struct thr_data *)arg; 652923Sraf 662923Sraf if (thr_data->fp) { 672923Sraf (void) fclose(thr_data->fp); 682923Sraf thr_data->fp = NULL; 692923Sraf } 702923Sraf if (thr_data->buf) { 712923Sraf lfree(thr_data->buf, BUFFERSIZE); 722923Sraf thr_data->buf = NULL; 732923Sraf } 742923Sraf } 752923Sraf 762923Sraf /* 772923Sraf * get the per-thread-data-item for the calling thread 782923Sraf */ 792923Sraf static struct thr_data * 802923Sraf get_thr_data(void) 812923Sraf { 822923Sraf struct thr_data *thr_data = 832923Sraf tsdalloc(_T_DEFREAD, sizeof (*thr_data), free_thr_data); 842923Sraf 852923Sraf return (thr_data); 862923Sraf } 872923Sraf 882923Sraf /* 892923Sraf * defopen() - declare defopen filename 902923Sraf * 912923Sraf * defopen(fn) 922923Sraf * char *fn 932923Sraf * 942923Sraf * If 'fn' is non-null; it is a full pathname of a file 952923Sraf * which becomes the one read by subsequent defread() calls. 962923Sraf * If 'fn' is null the defopen file is closed. 972923Sraf * 982923Sraf * see defread() for more details. 992923Sraf * 1002923Sraf * EXIT returns 0 if ok 1012923Sraf * returns -1 if error 1022923Sraf */ 1032923Sraf int 1042923Sraf defopen(char *fn) 1052923Sraf { 1062923Sraf struct thr_data *thr_data = get_thr_data(); 1072923Sraf 1082923Sraf if (thr_data == NULL) 1092923Sraf return (-1); 1102923Sraf 1112923Sraf if (thr_data->fp != NULL) { 1122923Sraf (void) fclose(thr_data->fp); 1132923Sraf thr_data->fp = NULL; 1142923Sraf } 1152923Sraf 1162923Sraf if (fn == NULL) 1172923Sraf return (0); 1182923Sraf 1192923Sraf if ((thr_data->fp = fopen(fn, "rF")) == NULL) 1202923Sraf return (-1); 1212923Sraf 1222923Sraf /* 1232923Sraf * We allocate the big buffer only if the fopen() succeeds. 1242923Sraf * Notice that we deallocate the buffer only when the thread exits. 1252923Sraf * There are misguided applications that assume that data returned 1262923Sraf * by defread() continues to exist after defopen(NULL) is called. 1272923Sraf */ 1282923Sraf if (thr_data->buf == NULL && 1292923Sraf (thr_data->buf = lmalloc(BUFFERSIZE)) == NULL) { 1302923Sraf (void) fclose(thr_data->fp); 1312923Sraf thr_data->fp = NULL; 1322923Sraf return (-1); 1332923Sraf } 1342923Sraf 1352923Sraf thr_data->Dcflags = DC_STD; 1362923Sraf 1372923Sraf return (0); 1382923Sraf } 1392923Sraf 1402923Sraf /* 1412923Sraf * defread() - read an entry from the defopen file 1422923Sraf * 1432923Sraf * defread(cp) 1442923Sraf * char *cp 1452923Sraf * 1462923Sraf * The defopen data file must have been previously opened by 1472923Sraf * defopen(). defread scans the data file looking for a line 1482923Sraf * which begins with the string '*cp'. If such a line is found, 1492923Sraf * defread returns a pointer to the first character following 1502923Sraf * the matched string (*cp). If no line is found or no file 1512923Sraf * is open, defread() returns NULL. 1522923Sraf * 1532923Sraf * Note that there is no way to simulatniously peruse multiple 1542923Sraf * defopen files; since there is no way of indicating 'which one' 1552923Sraf * to defread(). If you want to peruse a secondary file you must 1562923Sraf * recall defopen(). If you need to go back to the first file, 1572923Sraf * you must call defopen() again. 1582923Sraf */ 1592923Sraf char * 1602923Sraf defread(char *cp) 1612923Sraf { 1622923Sraf struct thr_data *thr_data = get_thr_data(); 1632923Sraf int (*compare)(const char *, const char *, size_t); 1642923Sraf char *buf_tmp, *ret_ptr = NULL; 1652923Sraf size_t off, patlen; 1662923Sraf 1672923Sraf if (thr_data == NULL || thr_data->fp == NULL) 1682923Sraf return (NULL); 1692923Sraf 1702923Sraf compare = TSTBITS(thr_data->Dcflags, DC_CASE) ? strncmp : strncasecmp; 1712923Sraf patlen = strlen(cp); 1722923Sraf 1732923Sraf if (!TSTBITS(thr_data->Dcflags, DC_NOREWIND)) 1742923Sraf rewind(thr_data->fp); 1752923Sraf 1762923Sraf while (fgets(thr_data->buf, BUFFERSIZE, thr_data->fp)) { 1772923Sraf for (buf_tmp = thr_data->buf; *buf_tmp == ' '; buf_tmp++) 1782923Sraf ; 1792923Sraf off = strlen(buf_tmp) - 1; 1802923Sraf if (buf_tmp[off] == '\n') 1812923Sraf buf_tmp[off] = 0; 1822923Sraf else 1832923Sraf break; /* line too long */ 1842923Sraf if ((*compare)(cp, buf_tmp, patlen) == 0) { 1852923Sraf /* found it */ 1862923Sraf /* strip quotes if requested */ 1872923Sraf if (TSTBITS(thr_data->Dcflags, DC_STRIP_QUOTES)) { 1882923Sraf strip_quotes(buf_tmp); 1892923Sraf } 1902923Sraf ret_ptr = &buf_tmp[patlen]; 1912923Sraf break; 1922923Sraf } 1932923Sraf } 1942923Sraf 1952923Sraf return (ret_ptr); 1962923Sraf } 1972923Sraf 1982923Sraf /* 1992923Sraf * defcntl -- default control 2002923Sraf * 2012923Sraf * SYNOPSIS 2022923Sraf * oldflags = defcntl(cmd, arg); 2032923Sraf * 2042923Sraf * ENTRY 2052923Sraf * cmd Command. One of DC_GET, DC_SET. 2062923Sraf * arg Depends on command. If DC_GET, ignored. If 2072923Sraf * DC_GET, new flags value, created by ORing the DC_* bits. 2082923Sraf * RETURN 2092923Sraf * oldflags Old value of flags. -1 on error. 2102923Sraf * NOTES 2112923Sraf * Currently only one bit of flags implemented, namely respect/ 2122923Sraf * ignore case. The routine is as general as it is so that we 2132923Sraf * leave our options open. E.g. we might want to specify rewind/ 2142923Sraf * norewind before each defread. 2152923Sraf */ 2162923Sraf 2172923Sraf int 2182923Sraf defcntl(int cmd, int newflags) 2192923Sraf { 2202923Sraf struct thr_data *thr_data = get_thr_data(); 2212923Sraf int oldflags; 2222923Sraf 2232923Sraf if (thr_data == NULL) 2242923Sraf return (-1); 2252923Sraf 2262923Sraf switch (cmd) { 2272923Sraf case DC_GETFLAGS: /* query */ 2282923Sraf oldflags = thr_data->Dcflags; 2292923Sraf break; 2302923Sraf case DC_SETFLAGS: /* set */ 2312923Sraf oldflags = thr_data->Dcflags; 2322923Sraf thr_data->Dcflags = newflags; 2332923Sraf break; 2342923Sraf default: /* error */ 2352923Sraf oldflags = -1; 2362923Sraf break; 2372923Sraf } 2382923Sraf 2392923Sraf return (oldflags); 2402923Sraf } 2412923Sraf 2422923Sraf /* 2432923Sraf * strip_quotes -- strip double (") or single (') quotes from a buffer 2442923Sraf * 2452923Sraf * ENTRY 2462923Sraf * ptr initial string 2472923Sraf * 2482923Sraf * EXIT 2492923Sraf * ptr string with quotes (if any) removed 2502923Sraf */ 2512923Sraf static void 2522923Sraf strip_quotes(char *ptr) 2532923Sraf { 2542923Sraf char *strip_ptr = NULL; 2552923Sraf 2562923Sraf while (*ptr != '\0') { 2572923Sraf if ((*ptr == '"') || (*ptr == '\'')) { 2582923Sraf if (strip_ptr == NULL) 2592923Sraf strip_ptr = ptr; /* skip over quote */ 2602923Sraf } else { 2612923Sraf if (strip_ptr != NULL) { 2622923Sraf *strip_ptr = *ptr; 2632923Sraf strip_ptr++; 2642923Sraf } 2652923Sraf } 2662923Sraf ptr++; 2672923Sraf } 2682923Sraf if (strip_ptr != NULL) { 2692923Sraf *strip_ptr = '\0'; 2702923Sraf } 2712923Sraf } 272