xgetenv.c revision 1219:f89f56c2d9ac
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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
24/*	  All Rights Reserved  	*/
25
26/*
27 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
28 * Use is subject to license terms.
29 */
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"
32/*LINTLIBRARY*/
33
34/*
35 *  NAME
36 *	xsetenv, xgetenv, Xgetenv - manage an alternate environment space
37 *
38 *  SYNOPSIS
39 *	int ret = xsetenv(file)
40 *	char *x = xgetenv("FOO");
41 *	char *x = Xgetenv("FOO");
42 *
43 *  DESCRIPTION
44 *	xsetenv() reads the given file into an internal buffer
45 *	and sets up an alternate environment.
46 *
47 *	Return values:	1 - OKAY
48 *			0 - troubles reading the file
49 *			-1 - troubles opening the file
50 *
51 *	xgetenv() returns the environment value from the
52 *	alternate environment.
53 *
54 *	Return values:	(char *)0 - no value for that variable
55 *			pointer  - the value
56 *
57 *	Xgetenv() returns the environment value from the
58 *	alternate environment.
59 *
60 *	Return values:	"" - no value for that variable
61 *			pointer  - the value
62 *
63 *  LIMITATIONS
64 *	Assumes the environment is < 5120 bytes, as in the UNIX
65 *	System environment. Assumes < 512 lines in the file.
66 *	These values may be adjusted below.
67 */
68
69#include "c_synonyms.h"
70#include <sys/types.h>
71#include "libmail.h"
72#include <stdio.h>
73#include <string.h>
74#include <fcntl.h>
75#include <ctype.h>
76
77#include <stdlib.h>
78#include <unistd.h>
79
80#define	MAXVARS  512
81#define	MAXENV  5120
82
83static char **xenv = 0;
84static char *(xenvptrs[MAXVARS]);
85static char xbuf[MAXENV];
86
87static void reduce(char *);
88
89/*
90 *	set up an environment buffer
91 *	and the pointers into it
92 */
93int
94xsetenv(char *xfile)
95{
96	int envctr, infd;
97	ssize_t i, nread;
98
99	/* Open the file */
100	infd = open(xfile, O_RDONLY);
101	if (infd == -1) {
102		return (-1);
103	}
104
105	/* Read in the entire file. */
106	nread = read(infd, xbuf, sizeof (xbuf));
107	if (nread < 0) {
108		(void) close(infd);
109		return (0);
110	}
111
112	/*
113	 * Set up pointers into the buffer.
114	 * Replace \n with \0.
115	 * Collapse white space around the = sign and at the
116	 * beginning and end of the line.
117	 */
118	xenv = xenvptrs;
119	xenv[0] = &xbuf[0];
120	for (i = 0, envctr = 0; i < nread; i++) {
121		if (xbuf[i] == '\n') {
122			xbuf[i] = '\0';
123			reduce(xenv[envctr]);
124			xenv[++envctr] = &xbuf[i+1];
125			if (envctr == MAXVARS) {
126				break;
127			}
128		}
129	}
130
131	xenv[envctr] = 0;
132	(void) close(infd);
133	return (1);
134}
135
136/*
137 *	Let getenv() do the dirty work
138 *	of looking up the variable. We
139 *	do this by temporarily resetting
140 *	environ to point to the local area.
141 */
142char *
143xgetenv(char *env)
144{
145	extern char **environ;
146	char *ret, **svenviron = environ;
147
148	environ = xenv;
149	ret = getenv(env);
150	environ = svenviron;
151	return (ret);
152}
153
154/*
155 *	Let xgetenv() do the dirty work
156 *	of looking up the variable.
157 */
158char *
159Xgetenv(char *env)
160{
161	char *ret = xgetenv(env);
162	return (ret ? ret : "");
163}
164
165/*
166 * Remove the spaces within the environment variable.
167 * The variable can look like this:
168 *
169 * <sp1> variable <sp2> = <sp3> value <sp4> \0
170 *
171 * All spaces can be removed, except within
172 * the variable name and the value.
173 */
174
175static void
176reduce(char *from)
177{
178	char *to = from;
179	char *svfrom = from;
180
181	/* <sp1> */
182	while (*from &&isspace((int)*from))
183		from++;
184
185	/* variable */
186	while (*from && (*from != '=') && !isspace((int)*from))
187		*to++ = *from++;
188
189	/* <sp2> */
190	while (*from && isspace((int)*from))
191		from++;
192
193	/* = */
194	if (*from == '=')
195		*to++ = *from++;
196
197	/* <sp3> */
198	while (*from && isspace((int)*from))
199		from++;
200
201	/* value */
202	while (*from)
203		*to++ = *from++;
204
205	/* <sp4> */
206	while ((to > svfrom) && isspace((int)to[-1]))
207		to--;
208	*to = '\0';
209}
210