xref: /titanic_44/usr/src/lib/libc/port/gen/deflt.c (revision b9175c69691c8949bec97fb8f689b7d1efdb05bb)
106e1a714Sraf /*
206e1a714Sraf  * CDDL HEADER START
306e1a714Sraf  *
406e1a714Sraf  * The contents of this file are subject to the terms of the
506e1a714Sraf  * Common Development and Distribution License (the "License").
606e1a714Sraf  * You may not use this file except in compliance with the License.
706e1a714Sraf  *
806e1a714Sraf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
906e1a714Sraf  * or http://www.opensolaris.org/os/licensing.
1006e1a714Sraf  * See the License for the specific language governing permissions
1106e1a714Sraf  * and limitations under the License.
1206e1a714Sraf  *
1306e1a714Sraf  * When distributing Covered Code, include this CDDL HEADER in each
1406e1a714Sraf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1506e1a714Sraf  * If applicable, add the following below this CDDL HEADER, with the
1606e1a714Sraf  * fields enclosed by brackets "[]" replaced with your own identifying
1706e1a714Sraf  * information: Portions Copyright [yyyy] [name of copyright owner]
1806e1a714Sraf  *
1906e1a714Sraf  * CDDL HEADER END
2006e1a714Sraf  */
2106e1a714Sraf 
2206e1a714Sraf /*
23*b9175c69SKenjiro Tsuji  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2406e1a714Sraf  * Use is subject to license terms.
2506e1a714Sraf  */
2606e1a714Sraf 
2706e1a714Sraf /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
2806e1a714Sraf /*	  All Rights Reserved  	*/
2906e1a714Sraf 
3006e1a714Sraf /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
3106e1a714Sraf /*	  All Rights Reserved	*/
3206e1a714Sraf 
337257d1b4Sraf #include "lint.h"
3406e1a714Sraf #include "libc.h"
3506e1a714Sraf #include <stdio.h>
3606e1a714Sraf #include <stdlib.h>
3706e1a714Sraf #include <deflt.h>
3806e1a714Sraf #include <sys/types.h>
3906e1a714Sraf #include <string.h>
4006e1a714Sraf #include <ctype.h>
4106e1a714Sraf #include <unistd.h>
4206e1a714Sraf #include "tsd.h"
4306e1a714Sraf 
4406e1a714Sraf #define	TSTBITS(flags, mask)	(((flags) & (mask)) == (mask))
4506e1a714Sraf 
4606e1a714Sraf struct thr_data {
4706e1a714Sraf 	int  Dcflags;	/* [re-]initialized on each call to defopen() */
4806e1a714Sraf 	FILE *fp;
4906e1a714Sraf 	char *buf;
5006e1a714Sraf };
5106e1a714Sraf 
52*b9175c69SKenjiro Tsuji static int	defopen_common(const char *, struct thr_data *);
53*b9175c69SKenjiro Tsuji static void strip_quotes(char *);
54*b9175c69SKenjiro Tsuji 
5506e1a714Sraf #define	BUFFERSIZE	1024
5606e1a714Sraf 
5706e1a714Sraf /*
5806e1a714Sraf  * destructor for per-thread data, registered with tsdalloc()
5906e1a714Sraf  */
6006e1a714Sraf static void
free_thr_data(void * arg)6106e1a714Sraf free_thr_data(void *arg)
6206e1a714Sraf {
6306e1a714Sraf 	struct thr_data *thr_data = (struct thr_data *)arg;
6406e1a714Sraf 
6506e1a714Sraf 	if (thr_data->fp) {
6606e1a714Sraf 		(void) fclose(thr_data->fp);
6706e1a714Sraf 		thr_data->fp = NULL;
6806e1a714Sraf 	}
6906e1a714Sraf 	if (thr_data->buf) {
7006e1a714Sraf 		lfree(thr_data->buf, BUFFERSIZE);
7106e1a714Sraf 		thr_data->buf = NULL;
7206e1a714Sraf 	}
7306e1a714Sraf }
7406e1a714Sraf 
7506e1a714Sraf /*
7606e1a714Sraf  * get the per-thread-data-item for the calling thread
7706e1a714Sraf  */
7806e1a714Sraf static struct thr_data *
get_thr_data(void)7906e1a714Sraf get_thr_data(void)
8006e1a714Sraf {
8106e1a714Sraf 	struct thr_data *thr_data =
8206e1a714Sraf 	    tsdalloc(_T_DEFREAD, sizeof (*thr_data), free_thr_data);
8306e1a714Sraf 
8406e1a714Sraf 	return (thr_data);
8506e1a714Sraf }
8606e1a714Sraf 
8706e1a714Sraf /*
8806e1a714Sraf  *	defopen() - declare defopen filename
8906e1a714Sraf  *
9006e1a714Sraf  *	defopen(fn)
9106e1a714Sraf  *		char *fn
9206e1a714Sraf  *
9306e1a714Sraf  *	If 'fn' is non-null; it is a full pathname of a file
9406e1a714Sraf  *	which becomes the one read by subsequent defread() calls.
9506e1a714Sraf  *	If 'fn' is null the defopen file is closed.
9606e1a714Sraf  *
9706e1a714Sraf  *	see defread() for more details.
9806e1a714Sraf  *
9906e1a714Sraf  *	EXIT    returns 0 if ok
10006e1a714Sraf  *		returns -1 if error
10106e1a714Sraf  */
10206e1a714Sraf int
defopen(char * fn)10306e1a714Sraf defopen(char *fn)
10406e1a714Sraf {
10506e1a714Sraf 	struct thr_data *thr_data = get_thr_data();
10606e1a714Sraf 
107*b9175c69SKenjiro Tsuji 	return (defopen_common(fn, thr_data));
108*b9175c69SKenjiro Tsuji }
109*b9175c69SKenjiro Tsuji 
110*b9175c69SKenjiro Tsuji /*
111*b9175c69SKenjiro Tsuji  *	defopen_r() - declare defopen filename (reentrant)
112*b9175c69SKenjiro Tsuji  *
113*b9175c69SKenjiro Tsuji  *	defopen_r(const char *fn)
114*b9175c69SKenjiro Tsuji  *
115*b9175c69SKenjiro Tsuji  *	'fn' is a full pathname of a file which becomes the one read
116*b9175c69SKenjiro Tsuji  *	by subsequent defread_r() calls.  defopen_r returns a pointer
117*b9175c69SKenjiro Tsuji  *	to the internally allocated buffer containing the file descriptor.
118*b9175c69SKenjiro Tsuji  *	The pointer should be specified to the following defread_r and
119*b9175c69SKenjiro Tsuji  *	defcntl_r functions.  As the pointer to be returned points to
120*b9175c69SKenjiro Tsuji  *	the libc lmalloc'd memory, defclose_r must be used to close
121*b9175c69SKenjiro Tsuji  *	the defopen file and to release the allocated memory.  Caller
122*b9175c69SKenjiro Tsuji  *	must not try to release the memory by free().
123*b9175c69SKenjiro Tsuji  *
124*b9175c69SKenjiro Tsuji  *	see defread_r() for more details.
125*b9175c69SKenjiro Tsuji  *
126*b9175c69SKenjiro Tsuji  *	EXIT    returns non-NULL pointer if success
127*b9175c69SKenjiro Tsuji  *		returns NULL if error
128*b9175c69SKenjiro Tsuji  */
129*b9175c69SKenjiro Tsuji void *
defopen_r(const char * fn)130*b9175c69SKenjiro Tsuji defopen_r(const char *fn)
131*b9175c69SKenjiro Tsuji {
132*b9175c69SKenjiro Tsuji 	/* memory allocated by lmalloc gets initialized to zeros */
133*b9175c69SKenjiro Tsuji 	struct thr_data	*thr_data = lmalloc(sizeof (struct thr_data));
134*b9175c69SKenjiro Tsuji 
135*b9175c69SKenjiro Tsuji 	if (defopen_common(fn, thr_data) < 0) {
136*b9175c69SKenjiro Tsuji 		if (thr_data != NULL)
137*b9175c69SKenjiro Tsuji 			lfree(thr_data, sizeof (struct thr_data));
138*b9175c69SKenjiro Tsuji 		return (NULL);
139*b9175c69SKenjiro Tsuji 	}
140*b9175c69SKenjiro Tsuji 
141*b9175c69SKenjiro Tsuji 	return ((void *)thr_data);
142*b9175c69SKenjiro Tsuji }
143*b9175c69SKenjiro Tsuji 
144*b9175c69SKenjiro Tsuji static int
defopen_common(const char * fn,struct thr_data * thr_data)145*b9175c69SKenjiro Tsuji defopen_common(const char *fn, struct thr_data *thr_data)
146*b9175c69SKenjiro Tsuji {
14706e1a714Sraf 	if (thr_data == NULL)
14806e1a714Sraf 		return (-1);
14906e1a714Sraf 
15006e1a714Sraf 	if (thr_data->fp != NULL) {
15106e1a714Sraf 		(void) fclose(thr_data->fp);
15206e1a714Sraf 		thr_data->fp = NULL;
15306e1a714Sraf 	}
15406e1a714Sraf 
15506e1a714Sraf 	if (fn == NULL)
15606e1a714Sraf 		return (0);
15706e1a714Sraf 
15806e1a714Sraf 	if ((thr_data->fp = fopen(fn, "rF")) == NULL)
15906e1a714Sraf 		return (-1);
16006e1a714Sraf 
16106e1a714Sraf 	/*
16206e1a714Sraf 	 * We allocate the big buffer only if the fopen() succeeds.
163*b9175c69SKenjiro Tsuji 	 * Notice that we deallocate the buffer only when the thread exits
164*b9175c69SKenjiro Tsuji 	 * for defopen().
16506e1a714Sraf 	 * There are misguided applications that assume that data returned
16606e1a714Sraf 	 * by defread() continues to exist after defopen(NULL) is called.
16706e1a714Sraf 	 */
16806e1a714Sraf 	if (thr_data->buf == NULL &&
16906e1a714Sraf 	    (thr_data->buf = lmalloc(BUFFERSIZE)) == NULL) {
17006e1a714Sraf 		(void) fclose(thr_data->fp);
17106e1a714Sraf 		thr_data->fp = NULL;
17206e1a714Sraf 		return (-1);
17306e1a714Sraf 	}
17406e1a714Sraf 
17506e1a714Sraf 	thr_data->Dcflags = DC_STD;
17606e1a714Sraf 
17706e1a714Sraf 	return (0);
17806e1a714Sraf }
17906e1a714Sraf 
18006e1a714Sraf /*
18106e1a714Sraf  *	defread() - read an entry from the defopen file
18206e1a714Sraf  *
18306e1a714Sraf  *	defread(cp)
18406e1a714Sraf  *		char *cp
18506e1a714Sraf  *
18606e1a714Sraf  *	The defopen data file must have been previously opened by
18706e1a714Sraf  *	defopen().  defread scans the data file looking for a line
18806e1a714Sraf  *	which begins with the string '*cp'.  If such a line is found,
18906e1a714Sraf  *	defread returns a pointer to the first character following
19006e1a714Sraf  *	the matched string (*cp).  If no line is found or no file
19106e1a714Sraf  *	is open, defread() returns NULL.
19206e1a714Sraf  *
193*b9175c69SKenjiro Tsuji  *	Note that there is no way to simultaneously peruse multiple
19406e1a714Sraf  *	defopen files; since there is no way of indicating 'which one'
19506e1a714Sraf  *	to defread().  If you want to peruse a secondary file you must
19606e1a714Sraf  *	recall defopen().  If you need to go back to the first file,
19706e1a714Sraf  *	you must call defopen() again.
19806e1a714Sraf  */
19906e1a714Sraf char *
defread(char * cp)20006e1a714Sraf defread(char *cp)
20106e1a714Sraf {
20206e1a714Sraf 	struct thr_data *thr_data = get_thr_data();
203*b9175c69SKenjiro Tsuji 
204*b9175c69SKenjiro Tsuji 	return (defread_r(cp, thr_data));
205*b9175c69SKenjiro Tsuji }
206*b9175c69SKenjiro Tsuji 
207*b9175c69SKenjiro Tsuji /*
208*b9175c69SKenjiro Tsuji  *	defread_r() - read an entry from the defopen file
209*b9175c69SKenjiro Tsuji  *
210*b9175c69SKenjiro Tsuji  *	defread_r(const char *cp, void *defp)
211*b9175c69SKenjiro Tsuji  *
212*b9175c69SKenjiro Tsuji  *	defread_r scans the data file associated with the pointer
213*b9175c69SKenjiro Tsuji  *	specified by 'defp' that was returned by defopen_r(), and
214*b9175c69SKenjiro Tsuji  *	looks for a line which begins with the string '*cp'.
215*b9175c69SKenjiro Tsuji  *	If such a line is found, defread_r returns a pointer to
216*b9175c69SKenjiro Tsuji  *	the first character following the matched string (*cp).
217*b9175c69SKenjiro Tsuji  *	If no line is found or no file is open, defread_r() returns NULL.
218*b9175c69SKenjiro Tsuji  */
219*b9175c69SKenjiro Tsuji char *
defread_r(const char * cp,void * ptr)220*b9175c69SKenjiro Tsuji defread_r(const char *cp, void *ptr)
221*b9175c69SKenjiro Tsuji {
222*b9175c69SKenjiro Tsuji 	struct thr_data *thr_data = (struct thr_data *)ptr;
22306e1a714Sraf 	int (*compare)(const char *, const char *, size_t);
224*b9175c69SKenjiro Tsuji 	char *buf_tmp;
225*b9175c69SKenjiro Tsuji 	char *ret_ptr = NULL;
22606e1a714Sraf 	size_t off, patlen;
22706e1a714Sraf 
22806e1a714Sraf 	if (thr_data == NULL || thr_data->fp == NULL)
22906e1a714Sraf 		return (NULL);
23006e1a714Sraf 
23106e1a714Sraf 	compare = TSTBITS(thr_data->Dcflags, DC_CASE) ? strncmp : strncasecmp;
23206e1a714Sraf 	patlen = strlen(cp);
23306e1a714Sraf 
23406e1a714Sraf 	if (!TSTBITS(thr_data->Dcflags, DC_NOREWIND))
23506e1a714Sraf 		rewind(thr_data->fp);
23606e1a714Sraf 
23706e1a714Sraf 	while (fgets(thr_data->buf, BUFFERSIZE, thr_data->fp)) {
23806e1a714Sraf 		for (buf_tmp = thr_data->buf; *buf_tmp == ' '; buf_tmp++)
23906e1a714Sraf 			;
24006e1a714Sraf 		off = strlen(buf_tmp) - 1;
24106e1a714Sraf 		if (buf_tmp[off] == '\n')
24206e1a714Sraf 			buf_tmp[off] = 0;
24306e1a714Sraf 		else
24406e1a714Sraf 			break;	/* line too long */
24506e1a714Sraf 		if ((*compare)(cp, buf_tmp, patlen) == 0) {
24606e1a714Sraf 			/* found it */
24706e1a714Sraf 			/* strip quotes if requested */
24806e1a714Sraf 			if (TSTBITS(thr_data->Dcflags, DC_STRIP_QUOTES)) {
24906e1a714Sraf 				strip_quotes(buf_tmp);
25006e1a714Sraf 			}
25106e1a714Sraf 			ret_ptr = &buf_tmp[patlen];
25206e1a714Sraf 			break;
25306e1a714Sraf 		}
25406e1a714Sraf 	}
25506e1a714Sraf 
25606e1a714Sraf 	return (ret_ptr);
25706e1a714Sraf }
25806e1a714Sraf 
25906e1a714Sraf /*
26006e1a714Sraf  *	defcntl -- default control
26106e1a714Sraf  *
26206e1a714Sraf  *	SYNOPSIS
26306e1a714Sraf  *	  oldflags = defcntl(cmd, arg);
26406e1a714Sraf  *
26506e1a714Sraf  *	ENTRY
26606e1a714Sraf  *	  cmd		Command.  One of DC_GET, DC_SET.
267*b9175c69SKenjiro Tsuji  *	  arg		Depends on command.  If DC_GET, ignored.
268*b9175c69SKenjiro Tsuji  *			If DC_SET, new flags value, created by ORing
269*b9175c69SKenjiro Tsuji  *			the DC_* bits.
27006e1a714Sraf  *	RETURN
27106e1a714Sraf  *	  oldflags	Old value of flags.  -1 on error.
27206e1a714Sraf  *	NOTES
273*b9175c69SKenjiro Tsuji  *	  The following commands are implemented:
274*b9175c69SKenjiro Tsuji  *
275*b9175c69SKenjiro Tsuji  *	  DC_CASE:		respect(on)/ignore(off) case
276*b9175c69SKenjiro Tsuji  *	  DC_NOREWIND:		don't(on)/do(off) reqind in defread
277*b9175c69SKenjiro Tsuji  *	  DC_STRIP_QUOTES:	strip(on)/leave(off) qoates
27806e1a714Sraf  */
27906e1a714Sraf int
defcntl(int cmd,int newflags)28006e1a714Sraf defcntl(int cmd, int newflags)
28106e1a714Sraf {
28206e1a714Sraf 	struct thr_data *thr_data = get_thr_data();
283*b9175c69SKenjiro Tsuji 
284*b9175c69SKenjiro Tsuji 	return (defcntl_r(cmd, newflags, thr_data));
285*b9175c69SKenjiro Tsuji }
286*b9175c69SKenjiro Tsuji 
287*b9175c69SKenjiro Tsuji /*
288*b9175c69SKenjiro Tsuji  *	defcntl_r -- default control
289*b9175c69SKenjiro Tsuji  *
290*b9175c69SKenjiro Tsuji  *	SYNOPSIS
291*b9175c69SKenjiro Tsuji  *	  oldflags = defcntl_r(int cmd, int arg, void *defp);
292*b9175c69SKenjiro Tsuji  *
293*b9175c69SKenjiro Tsuji  *	ENTRY
294*b9175c69SKenjiro Tsuji  *	  cmd		Command.  One of DC_GET, DC_SET.
295*b9175c69SKenjiro Tsuji  *	  arg		Depends on command.  If DC_GET, ignored.
296*b9175c69SKenjiro Tsuji  *			If DC_SET, new flags value, created by ORing
297*b9175c69SKenjiro Tsuji  *			the DC_* bits.
298*b9175c69SKenjiro Tsuji  *	  defp		pointer to the defopen'd descriptor
299*b9175c69SKenjiro Tsuji  *
300*b9175c69SKenjiro Tsuji  *	RETURN
301*b9175c69SKenjiro Tsuji  *	  oldflags	Old value of flags.  -1 on error.
302*b9175c69SKenjiro Tsuji  *	NOTES
303*b9175c69SKenjiro Tsuji  *	  The following commands are implemented:
304*b9175c69SKenjiro Tsuji  *
305*b9175c69SKenjiro Tsuji  *	  DC_CASE:		respect(on)/ignore(off) case
306*b9175c69SKenjiro Tsuji  *	  DC_NOREWIND:		don't(on)/do(off) reqind in defread
307*b9175c69SKenjiro Tsuji  *	  DC_STRIP_QUOTES:	strip(on)/leave(off) qoates
308*b9175c69SKenjiro Tsuji  */
309*b9175c69SKenjiro Tsuji int
defcntl_r(int cmd,int newflags,void * ptr)310*b9175c69SKenjiro Tsuji defcntl_r(int cmd, int newflags, void *ptr)
311*b9175c69SKenjiro Tsuji {
312*b9175c69SKenjiro Tsuji 	struct thr_data *thr_data = (struct thr_data *)ptr;
31306e1a714Sraf 	int  oldflags;
31406e1a714Sraf 
31506e1a714Sraf 	if (thr_data == NULL)
31606e1a714Sraf 		return (-1);
31706e1a714Sraf 
31806e1a714Sraf 	switch (cmd) {
31906e1a714Sraf 	case DC_GETFLAGS:		/* query */
32006e1a714Sraf 		oldflags = thr_data->Dcflags;
32106e1a714Sraf 		break;
32206e1a714Sraf 	case DC_SETFLAGS:		/* set */
32306e1a714Sraf 		oldflags = thr_data->Dcflags;
32406e1a714Sraf 		thr_data->Dcflags = newflags;
32506e1a714Sraf 		break;
32606e1a714Sraf 	default:			/* error */
32706e1a714Sraf 		oldflags = -1;
32806e1a714Sraf 		break;
32906e1a714Sraf 	}
33006e1a714Sraf 
33106e1a714Sraf 	return (oldflags);
33206e1a714Sraf }
33306e1a714Sraf 
33406e1a714Sraf /*
335*b9175c69SKenjiro Tsuji  *	defclose_r() - close defopen file
336*b9175c69SKenjiro Tsuji  *
337*b9175c69SKenjiro Tsuji  *	defclose_r(void *defp)
338*b9175c69SKenjiro Tsuji  *
339*b9175c69SKenjiro Tsuji  *	defclose_r closes the defopen file associated with the specified
340*b9175c69SKenjiro Tsuji  *	pointer and releases the allocated resources.
341*b9175c69SKenjiro Tsuji  */
342*b9175c69SKenjiro Tsuji void
defclose_r(void * ptr)343*b9175c69SKenjiro Tsuji defclose_r(void *ptr)
344*b9175c69SKenjiro Tsuji {
345*b9175c69SKenjiro Tsuji 	struct thr_data *thr_data = (struct thr_data *)ptr;
346*b9175c69SKenjiro Tsuji 
347*b9175c69SKenjiro Tsuji 	(void) fclose(thr_data->fp);
348*b9175c69SKenjiro Tsuji 	lfree(thr_data->buf, BUFFERSIZE);
349*b9175c69SKenjiro Tsuji 	lfree(thr_data, sizeof (struct thr_data));
350*b9175c69SKenjiro Tsuji }
351*b9175c69SKenjiro Tsuji 
352*b9175c69SKenjiro Tsuji /*
35306e1a714Sraf  *	strip_quotes -- strip double (") or single (') quotes from a buffer
35406e1a714Sraf  *
35506e1a714Sraf  *	ENTRY
35606e1a714Sraf  *	  ptr		initial string
35706e1a714Sraf  *
35806e1a714Sraf  *	EXIT
35906e1a714Sraf  *	  ptr		string with quotes (if any) removed
36006e1a714Sraf  */
36106e1a714Sraf static void
strip_quotes(char * ptr)36206e1a714Sraf strip_quotes(char *ptr)
36306e1a714Sraf {
36406e1a714Sraf 	char *strip_ptr = NULL;
36506e1a714Sraf 
36606e1a714Sraf 	while (*ptr != '\0') {
36706e1a714Sraf 		if ((*ptr == '"') || (*ptr == '\'')) {
36806e1a714Sraf 			if (strip_ptr == NULL)
36906e1a714Sraf 				strip_ptr = ptr;	/* skip over quote */
37006e1a714Sraf 		} else {
37106e1a714Sraf 			if (strip_ptr != NULL) {
37206e1a714Sraf 				*strip_ptr = *ptr;
37306e1a714Sraf 				strip_ptr++;
37406e1a714Sraf 			}
37506e1a714Sraf 		}
37606e1a714Sraf 		ptr++;
37706e1a714Sraf 	}
37806e1a714Sraf 	if (strip_ptr != NULL) {
37906e1a714Sraf 		*strip_ptr = '\0';
38006e1a714Sraf 	}
38106e1a714Sraf }
382