xref: /onnv-gate/usr/src/lib/libc/port/gen/deflt.c (revision 8563:3cefe121bbd2)
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*8563SKenjiro.Tsuji@Sun.COM  * Copyright 2009 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 
336812Sraf #include "lint.h"
342923Sraf #include "libc.h"
352923Sraf #include <stdio.h>
362923Sraf #include <stdlib.h>
372923Sraf #include <deflt.h>
382923Sraf #include <sys/types.h>
392923Sraf #include <string.h>
402923Sraf #include <ctype.h>
412923Sraf #include <unistd.h>
422923Sraf #include "tsd.h"
432923Sraf 
442923Sraf #define	TSTBITS(flags, mask)	(((flags) & (mask)) == (mask))
452923Sraf 
462923Sraf struct thr_data {
472923Sraf 	int  Dcflags;	/* [re-]initialized on each call to defopen() */
482923Sraf 	FILE *fp;
492923Sraf 	char *buf;
502923Sraf };
512923Sraf 
52*8563SKenjiro.Tsuji@Sun.COM static int	defopen_common(const char *, struct thr_data *);
53*8563SKenjiro.Tsuji@Sun.COM static void strip_quotes(char *);
54*8563SKenjiro.Tsuji@Sun.COM 
552923Sraf #define	BUFFERSIZE	1024
562923Sraf 
572923Sraf /*
582923Sraf  * destructor for per-thread data, registered with tsdalloc()
592923Sraf  */
602923Sraf static void
free_thr_data(void * arg)612923Sraf free_thr_data(void *arg)
622923Sraf {
632923Sraf 	struct thr_data *thr_data = (struct thr_data *)arg;
642923Sraf 
652923Sraf 	if (thr_data->fp) {
662923Sraf 		(void) fclose(thr_data->fp);
672923Sraf 		thr_data->fp = NULL;
682923Sraf 	}
692923Sraf 	if (thr_data->buf) {
702923Sraf 		lfree(thr_data->buf, BUFFERSIZE);
712923Sraf 		thr_data->buf = NULL;
722923Sraf 	}
732923Sraf }
742923Sraf 
752923Sraf /*
762923Sraf  * get the per-thread-data-item for the calling thread
772923Sraf  */
782923Sraf static struct thr_data *
get_thr_data(void)792923Sraf get_thr_data(void)
802923Sraf {
812923Sraf 	struct thr_data *thr_data =
822923Sraf 	    tsdalloc(_T_DEFREAD, sizeof (*thr_data), free_thr_data);
832923Sraf 
842923Sraf 	return (thr_data);
852923Sraf }
862923Sraf 
872923Sraf /*
882923Sraf  *	defopen() - declare defopen filename
892923Sraf  *
902923Sraf  *	defopen(fn)
912923Sraf  *		char *fn
922923Sraf  *
932923Sraf  *	If 'fn' is non-null; it is a full pathname of a file
942923Sraf  *	which becomes the one read by subsequent defread() calls.
952923Sraf  *	If 'fn' is null the defopen file is closed.
962923Sraf  *
972923Sraf  *	see defread() for more details.
982923Sraf  *
992923Sraf  *	EXIT    returns 0 if ok
1002923Sraf  *		returns -1 if error
1012923Sraf  */
1022923Sraf int
defopen(char * fn)1032923Sraf defopen(char *fn)
1042923Sraf {
1052923Sraf 	struct thr_data *thr_data = get_thr_data();
1062923Sraf 
107*8563SKenjiro.Tsuji@Sun.COM 	return (defopen_common(fn, thr_data));
108*8563SKenjiro.Tsuji@Sun.COM }
109*8563SKenjiro.Tsuji@Sun.COM 
110*8563SKenjiro.Tsuji@Sun.COM /*
111*8563SKenjiro.Tsuji@Sun.COM  *	defopen_r() - declare defopen filename (reentrant)
112*8563SKenjiro.Tsuji@Sun.COM  *
113*8563SKenjiro.Tsuji@Sun.COM  *	defopen_r(const char *fn)
114*8563SKenjiro.Tsuji@Sun.COM  *
115*8563SKenjiro.Tsuji@Sun.COM  *	'fn' is a full pathname of a file which becomes the one read
116*8563SKenjiro.Tsuji@Sun.COM  *	by subsequent defread_r() calls.  defopen_r returns a pointer
117*8563SKenjiro.Tsuji@Sun.COM  *	to the internally allocated buffer containing the file descriptor.
118*8563SKenjiro.Tsuji@Sun.COM  *	The pointer should be specified to the following defread_r and
119*8563SKenjiro.Tsuji@Sun.COM  *	defcntl_r functions.  As the pointer to be returned points to
120*8563SKenjiro.Tsuji@Sun.COM  *	the libc lmalloc'd memory, defclose_r must be used to close
121*8563SKenjiro.Tsuji@Sun.COM  *	the defopen file and to release the allocated memory.  Caller
122*8563SKenjiro.Tsuji@Sun.COM  *	must not try to release the memory by free().
123*8563SKenjiro.Tsuji@Sun.COM  *
124*8563SKenjiro.Tsuji@Sun.COM  *	see defread_r() for more details.
125*8563SKenjiro.Tsuji@Sun.COM  *
126*8563SKenjiro.Tsuji@Sun.COM  *	EXIT    returns non-NULL pointer if success
127*8563SKenjiro.Tsuji@Sun.COM  *		returns NULL if error
128*8563SKenjiro.Tsuji@Sun.COM  */
129*8563SKenjiro.Tsuji@Sun.COM void *
defopen_r(const char * fn)130*8563SKenjiro.Tsuji@Sun.COM defopen_r(const char *fn)
131*8563SKenjiro.Tsuji@Sun.COM {
132*8563SKenjiro.Tsuji@Sun.COM 	/* memory allocated by lmalloc gets initialized to zeros */
133*8563SKenjiro.Tsuji@Sun.COM 	struct thr_data	*thr_data = lmalloc(sizeof (struct thr_data));
134*8563SKenjiro.Tsuji@Sun.COM 
135*8563SKenjiro.Tsuji@Sun.COM 	if (defopen_common(fn, thr_data) < 0) {
136*8563SKenjiro.Tsuji@Sun.COM 		if (thr_data != NULL)
137*8563SKenjiro.Tsuji@Sun.COM 			lfree(thr_data, sizeof (struct thr_data));
138*8563SKenjiro.Tsuji@Sun.COM 		return (NULL);
139*8563SKenjiro.Tsuji@Sun.COM 	}
140*8563SKenjiro.Tsuji@Sun.COM 
141*8563SKenjiro.Tsuji@Sun.COM 	return ((void *)thr_data);
142*8563SKenjiro.Tsuji@Sun.COM }
143*8563SKenjiro.Tsuji@Sun.COM 
144*8563SKenjiro.Tsuji@Sun.COM static int
defopen_common(const char * fn,struct thr_data * thr_data)145*8563SKenjiro.Tsuji@Sun.COM defopen_common(const char *fn, struct thr_data *thr_data)
146*8563SKenjiro.Tsuji@Sun.COM {
1472923Sraf 	if (thr_data == NULL)
1482923Sraf 		return (-1);
1492923Sraf 
1502923Sraf 	if (thr_data->fp != NULL) {
1512923Sraf 		(void) fclose(thr_data->fp);
1522923Sraf 		thr_data->fp = NULL;
1532923Sraf 	}
1542923Sraf 
1552923Sraf 	if (fn == NULL)
1562923Sraf 		return (0);
1572923Sraf 
1582923Sraf 	if ((thr_data->fp = fopen(fn, "rF")) == NULL)
1592923Sraf 		return (-1);
1602923Sraf 
1612923Sraf 	/*
1622923Sraf 	 * We allocate the big buffer only if the fopen() succeeds.
163*8563SKenjiro.Tsuji@Sun.COM 	 * Notice that we deallocate the buffer only when the thread exits
164*8563SKenjiro.Tsuji@Sun.COM 	 * for defopen().
1652923Sraf 	 * There are misguided applications that assume that data returned
1662923Sraf 	 * by defread() continues to exist after defopen(NULL) is called.
1672923Sraf 	 */
1682923Sraf 	if (thr_data->buf == NULL &&
1692923Sraf 	    (thr_data->buf = lmalloc(BUFFERSIZE)) == NULL) {
1702923Sraf 		(void) fclose(thr_data->fp);
1712923Sraf 		thr_data->fp = NULL;
1722923Sraf 		return (-1);
1732923Sraf 	}
1742923Sraf 
1752923Sraf 	thr_data->Dcflags = DC_STD;
1762923Sraf 
1772923Sraf 	return (0);
1782923Sraf }
1792923Sraf 
1802923Sraf /*
1812923Sraf  *	defread() - read an entry from the defopen file
1822923Sraf  *
1832923Sraf  *	defread(cp)
1842923Sraf  *		char *cp
1852923Sraf  *
1862923Sraf  *	The defopen data file must have been previously opened by
1872923Sraf  *	defopen().  defread scans the data file looking for a line
1882923Sraf  *	which begins with the string '*cp'.  If such a line is found,
1892923Sraf  *	defread returns a pointer to the first character following
1902923Sraf  *	the matched string (*cp).  If no line is found or no file
1912923Sraf  *	is open, defread() returns NULL.
1922923Sraf  *
193*8563SKenjiro.Tsuji@Sun.COM  *	Note that there is no way to simultaneously peruse multiple
1942923Sraf  *	defopen files; since there is no way of indicating 'which one'
1952923Sraf  *	to defread().  If you want to peruse a secondary file you must
1962923Sraf  *	recall defopen().  If you need to go back to the first file,
1972923Sraf  *	you must call defopen() again.
1982923Sraf  */
1992923Sraf char *
defread(char * cp)2002923Sraf defread(char *cp)
2012923Sraf {
2022923Sraf 	struct thr_data *thr_data = get_thr_data();
203*8563SKenjiro.Tsuji@Sun.COM 
204*8563SKenjiro.Tsuji@Sun.COM 	return (defread_r(cp, thr_data));
205*8563SKenjiro.Tsuji@Sun.COM }
206*8563SKenjiro.Tsuji@Sun.COM 
207*8563SKenjiro.Tsuji@Sun.COM /*
208*8563SKenjiro.Tsuji@Sun.COM  *	defread_r() - read an entry from the defopen file
209*8563SKenjiro.Tsuji@Sun.COM  *
210*8563SKenjiro.Tsuji@Sun.COM  *	defread_r(const char *cp, void *defp)
211*8563SKenjiro.Tsuji@Sun.COM  *
212*8563SKenjiro.Tsuji@Sun.COM  *	defread_r scans the data file associated with the pointer
213*8563SKenjiro.Tsuji@Sun.COM  *	specified by 'defp' that was returned by defopen_r(), and
214*8563SKenjiro.Tsuji@Sun.COM  *	looks for a line which begins with the string '*cp'.
215*8563SKenjiro.Tsuji@Sun.COM  *	If such a line is found, defread_r returns a pointer to
216*8563SKenjiro.Tsuji@Sun.COM  *	the first character following the matched string (*cp).
217*8563SKenjiro.Tsuji@Sun.COM  *	If no line is found or no file is open, defread_r() returns NULL.
218*8563SKenjiro.Tsuji@Sun.COM  */
219*8563SKenjiro.Tsuji@Sun.COM char *
defread_r(const char * cp,void * ptr)220*8563SKenjiro.Tsuji@Sun.COM defread_r(const char *cp, void *ptr)
221*8563SKenjiro.Tsuji@Sun.COM {
222*8563SKenjiro.Tsuji@Sun.COM 	struct thr_data *thr_data = (struct thr_data *)ptr;
2232923Sraf 	int (*compare)(const char *, const char *, size_t);
224*8563SKenjiro.Tsuji@Sun.COM 	char *buf_tmp;
225*8563SKenjiro.Tsuji@Sun.COM 	char *ret_ptr = NULL;
2262923Sraf 	size_t off, patlen;
2272923Sraf 
2282923Sraf 	if (thr_data == NULL || thr_data->fp == NULL)
2292923Sraf 		return (NULL);
2302923Sraf 
2312923Sraf 	compare = TSTBITS(thr_data->Dcflags, DC_CASE) ? strncmp : strncasecmp;
2322923Sraf 	patlen = strlen(cp);
2332923Sraf 
2342923Sraf 	if (!TSTBITS(thr_data->Dcflags, DC_NOREWIND))
2352923Sraf 		rewind(thr_data->fp);
2362923Sraf 
2372923Sraf 	while (fgets(thr_data->buf, BUFFERSIZE, thr_data->fp)) {
2382923Sraf 		for (buf_tmp = thr_data->buf; *buf_tmp == ' '; buf_tmp++)
2392923Sraf 			;
2402923Sraf 		off = strlen(buf_tmp) - 1;
2412923Sraf 		if (buf_tmp[off] == '\n')
2422923Sraf 			buf_tmp[off] = 0;
2432923Sraf 		else
2442923Sraf 			break;	/* line too long */
2452923Sraf 		if ((*compare)(cp, buf_tmp, patlen) == 0) {
2462923Sraf 			/* found it */
2472923Sraf 			/* strip quotes if requested */
2482923Sraf 			if (TSTBITS(thr_data->Dcflags, DC_STRIP_QUOTES)) {
2492923Sraf 				strip_quotes(buf_tmp);
2502923Sraf 			}
2512923Sraf 			ret_ptr = &buf_tmp[patlen];
2522923Sraf 			break;
2532923Sraf 		}
2542923Sraf 	}
2552923Sraf 
2562923Sraf 	return (ret_ptr);
2572923Sraf }
2582923Sraf 
2592923Sraf /*
2602923Sraf  *	defcntl -- default control
2612923Sraf  *
2622923Sraf  *	SYNOPSIS
2632923Sraf  *	  oldflags = defcntl(cmd, arg);
2642923Sraf  *
2652923Sraf  *	ENTRY
2662923Sraf  *	  cmd		Command.  One of DC_GET, DC_SET.
267*8563SKenjiro.Tsuji@Sun.COM  *	  arg		Depends on command.  If DC_GET, ignored.
268*8563SKenjiro.Tsuji@Sun.COM  *			If DC_SET, new flags value, created by ORing
269*8563SKenjiro.Tsuji@Sun.COM  *			the DC_* bits.
2702923Sraf  *	RETURN
2712923Sraf  *	  oldflags	Old value of flags.  -1 on error.
2722923Sraf  *	NOTES
273*8563SKenjiro.Tsuji@Sun.COM  *	  The following commands are implemented:
274*8563SKenjiro.Tsuji@Sun.COM  *
275*8563SKenjiro.Tsuji@Sun.COM  *	  DC_CASE:		respect(on)/ignore(off) case
276*8563SKenjiro.Tsuji@Sun.COM  *	  DC_NOREWIND:		don't(on)/do(off) reqind in defread
277*8563SKenjiro.Tsuji@Sun.COM  *	  DC_STRIP_QUOTES:	strip(on)/leave(off) qoates
2782923Sraf  */
2792923Sraf int
defcntl(int cmd,int newflags)2802923Sraf defcntl(int cmd, int newflags)
2812923Sraf {
2822923Sraf 	struct thr_data *thr_data = get_thr_data();
283*8563SKenjiro.Tsuji@Sun.COM 
284*8563SKenjiro.Tsuji@Sun.COM 	return (defcntl_r(cmd, newflags, thr_data));
285*8563SKenjiro.Tsuji@Sun.COM }
286*8563SKenjiro.Tsuji@Sun.COM 
287*8563SKenjiro.Tsuji@Sun.COM /*
288*8563SKenjiro.Tsuji@Sun.COM  *	defcntl_r -- default control
289*8563SKenjiro.Tsuji@Sun.COM  *
290*8563SKenjiro.Tsuji@Sun.COM  *	SYNOPSIS
291*8563SKenjiro.Tsuji@Sun.COM  *	  oldflags = defcntl_r(int cmd, int arg, void *defp);
292*8563SKenjiro.Tsuji@Sun.COM  *
293*8563SKenjiro.Tsuji@Sun.COM  *	ENTRY
294*8563SKenjiro.Tsuji@Sun.COM  *	  cmd		Command.  One of DC_GET, DC_SET.
295*8563SKenjiro.Tsuji@Sun.COM  *	  arg		Depends on command.  If DC_GET, ignored.
296*8563SKenjiro.Tsuji@Sun.COM  *			If DC_SET, new flags value, created by ORing
297*8563SKenjiro.Tsuji@Sun.COM  *			the DC_* bits.
298*8563SKenjiro.Tsuji@Sun.COM  *	  defp		pointer to the defopen'd descriptor
299*8563SKenjiro.Tsuji@Sun.COM  *
300*8563SKenjiro.Tsuji@Sun.COM  *	RETURN
301*8563SKenjiro.Tsuji@Sun.COM  *	  oldflags	Old value of flags.  -1 on error.
302*8563SKenjiro.Tsuji@Sun.COM  *	NOTES
303*8563SKenjiro.Tsuji@Sun.COM  *	  The following commands are implemented:
304*8563SKenjiro.Tsuji@Sun.COM  *
305*8563SKenjiro.Tsuji@Sun.COM  *	  DC_CASE:		respect(on)/ignore(off) case
306*8563SKenjiro.Tsuji@Sun.COM  *	  DC_NOREWIND:		don't(on)/do(off) reqind in defread
307*8563SKenjiro.Tsuji@Sun.COM  *	  DC_STRIP_QUOTES:	strip(on)/leave(off) qoates
308*8563SKenjiro.Tsuji@Sun.COM  */
309*8563SKenjiro.Tsuji@Sun.COM int
defcntl_r(int cmd,int newflags,void * ptr)310*8563SKenjiro.Tsuji@Sun.COM defcntl_r(int cmd, int newflags, void *ptr)
311*8563SKenjiro.Tsuji@Sun.COM {
312*8563SKenjiro.Tsuji@Sun.COM 	struct thr_data *thr_data = (struct thr_data *)ptr;
3132923Sraf 	int  oldflags;
3142923Sraf 
3152923Sraf 	if (thr_data == NULL)
3162923Sraf 		return (-1);
3172923Sraf 
3182923Sraf 	switch (cmd) {
3192923Sraf 	case DC_GETFLAGS:		/* query */
3202923Sraf 		oldflags = thr_data->Dcflags;
3212923Sraf 		break;
3222923Sraf 	case DC_SETFLAGS:		/* set */
3232923Sraf 		oldflags = thr_data->Dcflags;
3242923Sraf 		thr_data->Dcflags = newflags;
3252923Sraf 		break;
3262923Sraf 	default:			/* error */
3272923Sraf 		oldflags = -1;
3282923Sraf 		break;
3292923Sraf 	}
3302923Sraf 
3312923Sraf 	return (oldflags);
3322923Sraf }
3332923Sraf 
3342923Sraf /*
335*8563SKenjiro.Tsuji@Sun.COM  *	defclose_r() - close defopen file
336*8563SKenjiro.Tsuji@Sun.COM  *
337*8563SKenjiro.Tsuji@Sun.COM  *	defclose_r(void *defp)
338*8563SKenjiro.Tsuji@Sun.COM  *
339*8563SKenjiro.Tsuji@Sun.COM  *	defclose_r closes the defopen file associated with the specified
340*8563SKenjiro.Tsuji@Sun.COM  *	pointer and releases the allocated resources.
341*8563SKenjiro.Tsuji@Sun.COM  */
342*8563SKenjiro.Tsuji@Sun.COM void
defclose_r(void * ptr)343*8563SKenjiro.Tsuji@Sun.COM defclose_r(void *ptr)
344*8563SKenjiro.Tsuji@Sun.COM {
345*8563SKenjiro.Tsuji@Sun.COM 	struct thr_data *thr_data = (struct thr_data *)ptr;
346*8563SKenjiro.Tsuji@Sun.COM 
347*8563SKenjiro.Tsuji@Sun.COM 	(void) fclose(thr_data->fp);
348*8563SKenjiro.Tsuji@Sun.COM 	lfree(thr_data->buf, BUFFERSIZE);
349*8563SKenjiro.Tsuji@Sun.COM 	lfree(thr_data, sizeof (struct thr_data));
350*8563SKenjiro.Tsuji@Sun.COM }
351*8563SKenjiro.Tsuji@Sun.COM 
352*8563SKenjiro.Tsuji@Sun.COM /*
3532923Sraf  *	strip_quotes -- strip double (") or single (') quotes from a buffer
3542923Sraf  *
3552923Sraf  *	ENTRY
3562923Sraf  *	  ptr		initial string
3572923Sraf  *
3582923Sraf  *	EXIT
3592923Sraf  *	  ptr		string with quotes (if any) removed
3602923Sraf  */
3612923Sraf static void
strip_quotes(char * ptr)3622923Sraf strip_quotes(char *ptr)
3632923Sraf {
3642923Sraf 	char *strip_ptr = NULL;
3652923Sraf 
3662923Sraf 	while (*ptr != '\0') {
3672923Sraf 		if ((*ptr == '"') || (*ptr == '\'')) {
3682923Sraf 			if (strip_ptr == NULL)
3692923Sraf 				strip_ptr = ptr;	/* skip over quote */
3702923Sraf 		} else {
3712923Sraf 			if (strip_ptr != NULL) {
3722923Sraf 				*strip_ptr = *ptr;
3732923Sraf 				strip_ptr++;
3742923Sraf 			}
3752923Sraf 		}
3762923Sraf 		ptr++;
3772923Sraf 	}
3782923Sraf 	if (strip_ptr != NULL) {
3792923Sraf 		*strip_ptr = '\0';
3802923Sraf 	}
3812923Sraf }
382