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 
83 static char **xenv = 0;
84 static char *(xenvptrs[MAXVARS]);
85 static char xbuf[MAXENV];
86 
87 static void reduce(char *);
88 
89 /*
90  *	set up an environment buffer
91  *	and the pointers into it
92  */
93 int
94 xsetenv(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  */
142 char *
143 xgetenv(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  */
158 char *
159 Xgetenv(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 
175 static void
176 reduce(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