/[baselayout]/trunk/src/rc-misc.c
Gentoo

Contents of /trunk/src/rc-misc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3007 - (show annotations) (download) (as text)
Mon Oct 8 11:07:39 2007 UTC (7 years, 3 months ago) by uberlord
File MIME type: text/x-csrc
File size: 7570 byte(s)
Move rc_env_filter and rc_env_config out of librc and into rc
1 /*
2 librc-misc.c
3 rc misc functions
4 Copyright 2007 Gentoo Foundation
5 */
6
7 #ifdef __linux__
8 #include <sys/sysinfo.h>
9 #endif
10
11 #include <sys/utsname.h>
12 #include <limits.h>
13 #include <regex.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "rc.h"
19 #include "rc-misc.h"
20 #include "strlist.h"
21
22 #define PROFILE_ENV "/etc/profile.env"
23 #define SYS_WHITELIST RC_LIBDIR "/conf.d/env_whitelist"
24 #define USR_WHITELIST "/etc/conf.d/env_whitelist"
25 #define RC_CONFIG "/etc/conf.d/rc"
26
27 #define PATH_PREFIX RC_LIBDIR "/bin:/bin:/sbin:/usr/bin:/usr/sbin"
28
29 char **env_filter (void)
30 {
31 char **env = NULL;
32 char **whitelist = NULL;
33 char *env_name = NULL;
34 char **profile = NULL;
35 int count = 0;
36 bool got_path = false;
37 char *env_var;
38 int env_len;
39 char *p;
40 char *token;
41 char *sep;
42 char *e;
43 int pplen = strlen (PATH_PREFIX);
44
45 whitelist = rc_config_list (SYS_WHITELIST);
46 if (! whitelist)
47 fprintf (stderr, "system environment whitelist (" SYS_WHITELIST ") missing\n");
48
49 env = rc_config_list (USR_WHITELIST);
50 rc_strlist_join (&whitelist, env);
51 rc_strlist_free (env);
52 env = NULL;
53
54 if (! whitelist)
55 return (NULL);
56
57 if (rc_exists (PROFILE_ENV))
58 profile = rc_config_load (PROFILE_ENV);
59
60 STRLIST_FOREACH (whitelist, env_name, count) {
61 char *space = strchr (env_name, ' ');
62 if (space)
63 *space = 0;
64
65 env_var = getenv (env_name);
66
67 if (! env_var && profile) {
68 env_len = strlen (env_name) + strlen ("export ") + 1;
69 p = rc_xmalloc (sizeof (char *) * env_len);
70 snprintf (p, env_len, "export %s", env_name);
71 env_var = rc_config_value (profile, p);
72 free (p);
73 }
74
75 if (! env_var)
76 continue;
77
78 /* Ensure our PATH is prefixed with the system locations first
79 for a little extra security */
80 if (strcmp (env_name, "PATH") == 0 &&
81 strncmp (PATH_PREFIX, env_var, pplen) != 0)
82 {
83 got_path = true;
84 env_len = strlen (env_name) + strlen (env_var) + pplen + 2;
85 e = p = rc_xmalloc (sizeof (char *) * env_len);
86 p += snprintf (e, env_len, "%s=%s", env_name, PATH_PREFIX);
87
88 /* Now go through the env var and only add bits not in our PREFIX */
89 sep = env_var;
90 while ((token = strsep (&sep, ":"))) {
91 char *np = rc_xstrdup (PATH_PREFIX);
92 char *npp = np;
93 char *tok = NULL;
94 while ((tok = strsep (&npp, ":")))
95 if (strcmp (tok, token) == 0)
96 break;
97 if (! tok)
98 p += snprintf (p, env_len - (p - e), ":%s", token);
99 free (np);
100 }
101 *p++ = 0;
102 } else {
103 env_len = strlen (env_name) + strlen (env_var) + 2;
104 e = rc_xmalloc (sizeof (char *) * env_len);
105 snprintf (e, env_len, "%s=%s", env_name, env_var);
106 }
107
108 rc_strlist_add (&env, e);
109 free (e);
110 }
111
112 /* We filtered the env but didn't get a PATH? Very odd.
113 However, we do need a path, so use a default. */
114 if (! got_path) {
115 env_len = strlen ("PATH=") + strlen (PATH_PREFIX) + 2;
116 p = rc_xmalloc (sizeof (char *) * env_len);
117 snprintf (p, env_len, "PATH=%s", PATH_PREFIX);
118 rc_strlist_add (&env, p);
119 free (p);
120 }
121
122 rc_strlist_free (whitelist);
123 rc_strlist_free (profile);
124
125 return (env);
126 }
127
128 /* Other systems may need this at some point, but for now it's Linux only */
129 #ifdef __linux__
130 static bool file_regex (const char *file, const char *regex)
131 {
132 FILE *fp;
133 char buffer[RC_LINEBUFFER];
134 regex_t re;
135 bool retval = false;
136 int result;
137
138 if (! (fp = fopen (file, "r")))
139 return (false);
140
141 if ((result = regcomp (&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) {
142 fclose (fp);
143 regerror (result, &re, buffer, sizeof (buffer));
144 fprintf (stderr, "file_regex: %s", buffer);
145 return (false);
146 }
147
148 while (fgets (buffer, RC_LINEBUFFER, fp)) {
149 if (regexec (&re, buffer, 0, NULL, 0) == 0)
150 {
151 retval = true;
152 break;
153 }
154 }
155 fclose (fp);
156 regfree (&re);
157
158 return (retval);
159 }
160 #endif
161
162 char **env_config (void)
163 {
164 char **env = NULL;
165 char *line;
166 int i;
167 char *p;
168 char **config;
169 char *e;
170 #ifdef __linux__
171 char sys[6];
172 #endif
173 struct utsname uts;
174 bool has_net_fs_list = false;
175 FILE *fp;
176 char buffer[PATH_MAX];
177 char *runlevel = rc_runlevel_get ();
178
179 /* Don't trust environ for softlevel yet */
180 snprintf (buffer, PATH_MAX, "%s.%s", RC_CONFIG, runlevel);
181 if (rc_exists (buffer))
182 config = rc_config_load (buffer);
183 else
184 config = rc_config_load (RC_CONFIG);
185
186 STRLIST_FOREACH (config, line, i) {
187 p = strchr (line, '=');
188 if (! p)
189 continue;
190
191 *p = 0;
192 e = getenv (line);
193 if (! e) {
194 *p = '=';
195 rc_strlist_add (&env, line);
196 } else {
197 int len = strlen (line) + strlen (e) + 2;
198 char *new = rc_xmalloc (sizeof (char *) * len);
199 snprintf (new, len, "%s=%s", line, e);
200 rc_strlist_add (&env, new);
201 free (new);
202 }
203 }
204 rc_strlist_free (config);
205
206 /* One char less to drop the trailing / */
207 i = strlen ("RC_LIBDIR=") + strlen (RC_LIBDIR) + 1;
208 line = rc_xmalloc (sizeof (char *) * i);
209 snprintf (line, i, "RC_LIBDIR=" RC_LIBDIR);
210 rc_strlist_add (&env, line);
211 free (line);
212
213 /* One char less to drop the trailing / */
214 i = strlen ("RC_SVCDIR=") + strlen (RC_SVCDIR) + 1;
215 line = rc_xmalloc (sizeof (char *) * i);
216 snprintf (line, i, "RC_SVCDIR=" RC_SVCDIR);
217 rc_strlist_add (&env, line);
218 free (line);
219
220 rc_strlist_add (&env, "RC_BOOTLEVEL=" RC_LEVEL_BOOT);
221
222 i = strlen ("RC_SOFTLEVEL=") + strlen (runlevel) + 1;
223 line = rc_xmalloc (sizeof (char *) * i);
224 snprintf (line, i, "RC_SOFTLEVEL=%s", runlevel);
225 rc_strlist_add (&env, line);
226 free (line);
227
228 if ((fp = fopen (RC_KSOFTLEVEL, "r"))) {
229 memset (buffer, 0, sizeof (buffer));
230 if (fgets (buffer, sizeof (buffer), fp)) {
231 i = strlen (buffer) - 1;
232 if (buffer[i] == '\n')
233 buffer[i] = 0;
234 i += strlen ("RC_DEFAULTLEVEL=") + 2;
235 line = rc_xmalloc (sizeof (char *) * i);
236 snprintf (line, i, "RC_DEFAULTLEVEL=%s", buffer);
237 rc_strlist_add (&env, line);
238 free (line);
239 }
240 fclose (fp);
241 } else
242 rc_strlist_add (&env, "RC_DEFAULTLEVEL=" RC_LEVEL_DEFAULT);
243
244
245 #ifdef __linux__
246 /* Linux can run some funky stuff like Xen, VServer, UML, etc
247 We store this special system in RC_SYS so our scripts run fast */
248 memset (sys, 0, sizeof (sys));
249
250 if (rc_exists ("/proc/xen")) {
251 if ((fp = fopen ("/proc/xen/capabilities", "r"))) {
252 fclose (fp);
253 if (file_regex ("/proc/xen/capabilities", "control_d"))
254 snprintf (sys, sizeof (sys), "XENU");
255 }
256 if (! sys[0])
257 snprintf (sys, sizeof (sys), "XEN0");
258 } else if (file_regex ("/proc/cpuinfo", "UML")) {
259 snprintf (sys, sizeof (sys), "UML");
260 } else if (file_regex ("/proc/self/status",
261 "(s_context|VxID|envID):[[:space:]]*[1-9]"))
262 {
263 snprintf (sys, sizeof (sys), "VPS");
264 }
265
266 if (sys[0]) {
267 i = strlen ("RC_SYS=") + strlen (sys) + 2;
268 line = rc_xmalloc (sizeof (char *) * i);
269 snprintf (line, i, "RC_SYS=%s", sys);
270 rc_strlist_add (&env, line);
271 free (line);
272 }
273
274 #endif
275
276 /* Only add a NET_FS list if not defined */
277 STRLIST_FOREACH (env, line, i)
278 if (strncmp (line, "RC_NET_FS_LIST=", strlen ("RC_NET_FS_LIST=")) == 0) {
279 has_net_fs_list = true;
280 break;
281 }
282
283 if (! has_net_fs_list) {
284 i = strlen ("RC_NET_FS_LIST=") + strlen (RC_NET_FS_LIST_DEFAULT) + 1;
285 line = rc_xmalloc (sizeof (char *) * i);
286 snprintf (line, i, "RC_NET_FS_LIST=%s", RC_NET_FS_LIST_DEFAULT);
287 rc_strlist_add (&env, line);
288 free (line);
289 }
290
291 /* Some scripts may need to take a different code path if Linux/FreeBSD, etc
292 To save on calling uname, we store it in an environment variable */
293 if (uname (&uts) == 0) {
294 i = strlen ("RC_UNAME=") + strlen (uts.sysname) + 2;
295 line = rc_xmalloc (sizeof (char *) * i);
296 snprintf (line, i, "RC_UNAME=%s", uts.sysname);
297 rc_strlist_add (&env, line);
298 free (line);
299 }
300
301 free (runlevel);
302 return (env);
303 }

  ViewVC Help
Powered by ViewVC 1.1.20