xref: /onnv-gate/usr/src/lib/libc/port/gen/deflt.c (revision 6812:febeba71273d)
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