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