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

Diff of /trunk/src/librc-misc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 3006 Revision 3007
3 rc misc functions 3 rc misc functions
4 Copyright 2007 Gentoo Foundation 4 Copyright 2007 Gentoo Foundation
5 */ 5 */
6 6
7#include "librc.h" 7#include "librc.h"
8
9
10#define PROFILE_ENV "/etc/profile.env"
11#define SYS_WHITELIST RC_LIBDIR "/conf.d/env_whitelist"
12#define USR_WHITELIST "/etc/conf.d/env_whitelist"
13#define RC_CONFIG "/etc/conf.d/rc"
14
15#define PATH_PREFIX RC_LIBDIR "/bin:/bin:/sbin:/usr/bin:/usr/sbin"
16
17 8
18bool rc_env_bool (const char *var) 9bool rc_env_bool (const char *var)
19{ 10{
20 char *v; 11 char *v;
21 12
226 fclose (fp); 217 fclose (fp);
227 218
228 return (list); 219 return (list);
229} 220}
230librc_hidden_def(rc_config_list) 221librc_hidden_def(rc_config_list)
231
232char **rc_env_filter (void)
233{
234 char **env = NULL;
235 char **whitelist = NULL;
236 char *env_name = NULL;
237 char **profile = NULL;
238 int count = 0;
239 bool got_path = false;
240 char *env_var;
241 int env_len;
242 char *p;
243 char *token;
244 char *sep;
245 char *e;
246 int pplen = strlen (PATH_PREFIX);
247
248 whitelist = rc_config_list (SYS_WHITELIST);
249 if (! whitelist)
250 fprintf (stderr, "system environment whitelist (" SYS_WHITELIST ") missing\n");
251
252 env = rc_config_list (USR_WHITELIST);
253 rc_strlist_join (&whitelist, env);
254 rc_strlist_free (env);
255 env = NULL;
256
257 if (! whitelist)
258 return (NULL);
259
260 if (rc_exists (PROFILE_ENV))
261 profile = rc_config_load (PROFILE_ENV);
262
263 STRLIST_FOREACH (whitelist, env_name, count) {
264 char *space = strchr (env_name, ' ');
265 if (space)
266 *space = 0;
267
268 env_var = getenv (env_name);
269
270 if (! env_var && profile) {
271 env_len = strlen (env_name) + strlen ("export ") + 1;
272 p = rc_xmalloc (sizeof (char *) * env_len);
273 snprintf (p, env_len, "export %s", env_name);
274 env_var = rc_config_value (profile, p);
275 free (p);
276 }
277
278 if (! env_var)
279 continue;
280
281 /* Ensure our PATH is prefixed with the system locations first
282 for a little extra security */
283 if (strcmp (env_name, "PATH") == 0 &&
284 strncmp (PATH_PREFIX, env_var, pplen) != 0)
285 {
286 got_path = true;
287 env_len = strlen (env_name) + strlen (env_var) + pplen + 2;
288 e = p = rc_xmalloc (sizeof (char *) * env_len);
289 p += snprintf (e, env_len, "%s=%s", env_name, PATH_PREFIX);
290
291 /* Now go through the env var and only add bits not in our PREFIX */
292 sep = env_var;
293 while ((token = strsep (&sep, ":"))) {
294 char *np = rc_xstrdup (PATH_PREFIX);
295 char *npp = np;
296 char *tok = NULL;
297 while ((tok = strsep (&npp, ":")))
298 if (strcmp (tok, token) == 0)
299 break;
300 if (! tok)
301 p += snprintf (p, env_len - (p - e), ":%s", token);
302 free (np);
303 }
304 *p++ = 0;
305 } else {
306 env_len = strlen (env_name) + strlen (env_var) + 2;
307 e = rc_xmalloc (sizeof (char *) * env_len);
308 snprintf (e, env_len, "%s=%s", env_name, env_var);
309 }
310
311 rc_strlist_add (&env, e);
312 free (e);
313 }
314
315 /* We filtered the env but didn't get a PATH? Very odd.
316 However, we do need a path, so use a default. */
317 if (! got_path) {
318 env_len = strlen ("PATH=") + strlen (PATH_PREFIX) + 2;
319 p = rc_xmalloc (sizeof (char *) * env_len);
320 snprintf (p, env_len, "PATH=%s", PATH_PREFIX);
321 rc_strlist_add (&env, p);
322 free (p);
323 }
324
325 rc_strlist_free (whitelist);
326 rc_strlist_free (profile);
327
328 return (env);
329}
330librc_hidden_def(rc_env_filter)
331
332/* Other systems may need this at some point, but for now it's Linux only */
333#ifdef __linux__
334static bool file_regex (const char *file, const char *regex)
335{
336 FILE *fp;
337 char buffer[RC_LINEBUFFER];
338 regex_t re;
339 bool retval = false;
340 int result;
341
342 if (! (fp = fopen (file, "r")))
343 return (false);
344
345 if ((result = regcomp (&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) {
346 fclose (fp);
347 regerror (result, &re, buffer, sizeof (buffer));
348 fprintf (stderr, "file_regex: %s", buffer);
349 return (false);
350 }
351
352 while (fgets (buffer, RC_LINEBUFFER, fp)) {
353 if (regexec (&re, buffer, 0, NULL, 0) == 0)
354 {
355 retval = true;
356 break;
357 }
358 }
359 fclose (fp);
360 regfree (&re);
361
362 return (retval);
363}
364#endif
365
366char **rc_env_config (void)
367{
368 char **env = NULL;
369 char *line;
370 int i;
371 char *p;
372 char **config;
373 char *e;
374#ifdef __linux__
375 char sys[6];
376#endif
377 struct utsname uts;
378 bool has_net_fs_list = false;
379 FILE *fp;
380 char buffer[PATH_MAX];
381 char *runlevel = rc_runlevel_get ();
382
383 /* Don't trust environ for softlevel yet */
384 snprintf (buffer, PATH_MAX, "%s.%s", RC_CONFIG, runlevel);
385 if (rc_exists (buffer))
386 config = rc_config_load (buffer);
387 else
388 config = rc_config_load (RC_CONFIG);
389
390 STRLIST_FOREACH (config, line, i) {
391 p = strchr (line, '=');
392 if (! p)
393 continue;
394
395 *p = 0;
396 e = getenv (line);
397 if (! e) {
398 *p = '=';
399 rc_strlist_add (&env, line);
400 } else {
401 int len = strlen (line) + strlen (e) + 2;
402 char *new = rc_xmalloc (sizeof (char *) * len);
403 snprintf (new, len, "%s=%s", line, e);
404 rc_strlist_add (&env, new);
405 free (new);
406 }
407 }
408 rc_strlist_free (config);
409
410 /* One char less to drop the trailing / */
411 i = strlen ("RC_LIBDIR=") + strlen (RC_LIBDIR) + 1;
412 line = rc_xmalloc (sizeof (char *) * i);
413 snprintf (line, i, "RC_LIBDIR=" RC_LIBDIR);
414 rc_strlist_add (&env, line);
415 free (line);
416
417 /* One char less to drop the trailing / */
418 i = strlen ("RC_SVCDIR=") + strlen (RC_SVCDIR) + 1;
419 line = rc_xmalloc (sizeof (char *) * i);
420 snprintf (line, i, "RC_SVCDIR=" RC_SVCDIR);
421 rc_strlist_add (&env, line);
422 free (line);
423
424 rc_strlist_add (&env, "RC_BOOTLEVEL=" RC_LEVEL_BOOT);
425
426 i = strlen ("RC_SOFTLEVEL=") + strlen (runlevel) + 1;
427 line = rc_xmalloc (sizeof (char *) * i);
428 snprintf (line, i, "RC_SOFTLEVEL=%s", runlevel);
429 rc_strlist_add (&env, line);
430 free (line);
431
432 if ((fp = fopen (RC_KSOFTLEVEL, "r"))) {
433 memset (buffer, 0, sizeof (buffer));
434 if (fgets (buffer, sizeof (buffer), fp)) {
435 i = strlen (buffer) - 1;
436 if (buffer[i] == '\n')
437 buffer[i] = 0;
438 i += strlen ("RC_DEFAULTLEVEL=") + 2;
439 line = rc_xmalloc (sizeof (char *) * i);
440 snprintf (line, i, "RC_DEFAULTLEVEL=%s", buffer);
441 rc_strlist_add (&env, line);
442 free (line);
443 }
444 fclose (fp);
445 } else
446 rc_strlist_add (&env, "RC_DEFAULTLEVEL=" RC_LEVEL_DEFAULT);
447
448
449#ifdef __linux__
450 /* Linux can run some funky stuff like Xen, VServer, UML, etc
451 We store this special system in RC_SYS so our scripts run fast */
452 memset (sys, 0, sizeof (sys));
453
454 if (rc_exists ("/proc/xen")) {
455 if ((fp = fopen ("/proc/xen/capabilities", "r"))) {
456 fclose (fp);
457 if (file_regex ("/proc/xen/capabilities", "control_d"))
458 snprintf (sys, sizeof (sys), "XENU");
459 }
460 if (! sys[0])
461 snprintf (sys, sizeof (sys), "XEN0");
462 } else if (file_regex ("/proc/cpuinfo", "UML")) {
463 snprintf (sys, sizeof (sys), "UML");
464 } else if (file_regex ("/proc/self/status",
465 "(s_context|VxID|envID):[[:space:]]*[1-9]"))
466 {
467 snprintf (sys, sizeof (sys), "VPS");
468 }
469
470 if (sys[0]) {
471 i = strlen ("RC_SYS=") + strlen (sys) + 2;
472 line = rc_xmalloc (sizeof (char *) * i);
473 snprintf (line, i, "RC_SYS=%s", sys);
474 rc_strlist_add (&env, line);
475 free (line);
476 }
477
478#endif
479
480 /* Only add a NET_FS list if not defined */
481 STRLIST_FOREACH (env, line, i)
482 if (strncmp (line, "RC_NET_FS_LIST=", strlen ("RC_NET_FS_LIST=")) == 0) {
483 has_net_fs_list = true;
484 break;
485 }
486
487 if (! has_net_fs_list) {
488 i = strlen ("RC_NET_FS_LIST=") + strlen (RC_NET_FS_LIST_DEFAULT) + 1;
489 line = rc_xmalloc (sizeof (char *) * i);
490 snprintf (line, i, "RC_NET_FS_LIST=%s", RC_NET_FS_LIST_DEFAULT);
491 rc_strlist_add (&env, line);
492 free (line);
493 }
494
495 /* Some scripts may need to take a different code path if Linux/FreeBSD, etc
496 To save on calling uname, we store it in an environment variable */
497 if (uname (&uts) == 0) {
498 i = strlen ("RC_UNAME=") + strlen (uts.sysname) + 2;
499 line = rc_xmalloc (sizeof (char *) * i);
500 snprintf (line, i, "RC_UNAME=%s", uts.sysname);
501 rc_strlist_add (&env, line);
502 free (line);
503 }
504
505 free (runlevel);
506 return (env);
507}
508librc_hidden_def(rc_env_config)

Legend:
Removed from v.3006  
changed lines
  Added in v.3007

  ViewVC Help
Powered by ViewVC 1.1.20