backport: grep: support for -x, match whole line
[busybox-power] / debian / patches / 0001-appletlib-parse-etc-environment-prior-to-applet-laun.patch
1 From 92c63984fc28ea1bb0939acfcb551f65d7bfddf7 Mon Sep 17 00:00:00 2001
2 From: Dennis Groenen <tj.groenen@gmail.com>
3 Date: Fri, 23 Dec 2011 20:34:22 +0100
4 Subject: [PATCH] appletlib: parse /etc/environment prior to applet launch
5
6 ---
7  libbb/appletlib.c |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++
8  1 files changed, 117 insertions(+), 0 deletions(-)
9
10 diff --git a/libbb/appletlib.c b/libbb/appletlib.c
11 index 8157b4f..d13aee5 100644
12 --- a/libbb/appletlib.c
13 +++ b/libbb/appletlib.c
14 @@ -474,6 +474,121 @@ static inline void parse_config_file(void)
15  }
16  # endif /* FEATURE_SUID_CONFIG */
17  
18 +/* We do not want to allow all characters in environment variables.
19 + * Function based on patch by Tito.
20 + * http://lists.busybox.net/pipermail/busybox/2011-August/076364.html */
21 +static bool bad_env_var(const char *name)
22 +{
23 +       const char *s = name;
24 +
25 +       do {
26 +               /* We don't use isalnum  as it will allow locale-specific non-ASCII */
27 +               /* letters in legacy 8-bit locales. */
28 +               if (((*name >= 48 && *name <= 57) && name != s) /* no numeric values as first char */
29 +                || *name == '_' /* allow underscores */
30 +                || (*name >= 65 && *name <= 90)  /* allow A-Z */
31 +                || (*name >= 97 && *name <= 122) /* allow a-z */
32 +               ) {
33 +                       continue;
34 +               }
35 +               return true;
36 +       } while (*++name);
37 +       return false;
38 +}
39 +
40 +static void load_env_vars(void)
41 +{
42 +       /* Don't depend on the tools to combine strings. */
43 +       static const char config_file[] ALIGN1 = "/etc/environment";
44 +
45 +       FILE *f;
46 +       const char *errmsg;
47 +       unsigned lc;
48 +       struct stat st;
49 +
50 +       if ((stat(config_file, &st) != 0)       /* No config file? */
51 +        || !S_ISREG(st.st_mode)                /* Not a regular file? */
52 +        || (st.st_uid != 0)                    /* Not owned by root? */
53 +        || (st.st_mode & (S_IWGRP | S_IWOTH))  /* Writable by non-root? */
54 +        || !(f = fopen_for_read(config_file))  /* Cannot open? */
55 +       ) {
56 +               return;
57 +       }
58 +
59 +       lc = 0;
60 +
61 +       while (1) {
62 +               char buffer[256];
63 +               char *key;
64 +               char *val;
65 +               char *e;
66 +
67 +               if (!fgets(buffer, sizeof(buffer), f)) { /* Are we done? */
68 +                       fclose(f);
69 +                       return;
70 +               }
71 +
72 +               key = buffer;
73 +               lc++;                                   /* Got a (partial) line. */
74 +
75 +               /* If a line is too long for our buffer, we consider it an error.
76 +                * The following test does mistreat one corner case though.
77 +                * If the final line of the file does not end with a newline and
78 +                * yet exactly fills the buffer, it will be treated as too long
79 +                * even though there isn't really a problem.  But it isn't really
80 +                * worth adding code to deal with such an unlikely situation, and
81 +                * we do err on the side of caution.  Besides, the line would be
82 +                * too long if it did end with a newline. */
83 +               if (!strchr(key, '\n') && !feof(f)) {
84 +                       errmsg = "line too long";
85 +                       goto pe_label;
86 +               }
87 +
88 +               /* Trim leading and trailing whitespace, ignoring comments, and
89 +                * check if the resulting string is empty. */
90 +               key = get_trimmed_slice(key, strchrnul(key, '#'));
91 +               if (!*key) {
92 +                       continue;
93 +               }
94 +
95 +               /* Get the key */
96 +               e = strchr(key, '=');
97 +
98 +               if (e) {
99 +                       key = get_trimmed_slice(key, e);
100 +               }
101 +
102 +               if (!e || !*key) {      /* Missing '=' or empty key. */
103 +                       errmsg = "keyword";
104 +                       goto pe_label;
105 +               }
106 +               if (bad_env_var(key)) { /* Check for illegal characters */
107 +                       errmsg = "illegal character";
108 +                       goto pe_label;
109 +               }
110 +
111 +               /* Get the value */
112 +               val = skip_whitespace(e+1); /* What's after the equal sign? */
113 +
114 +               if (!*val) { /* Empty value */
115 +                       errmsg = "value";
116 +                       goto pe_label;
117 +               }
118 +               if (*val == '"' && val[(strlen(val)-1)] == '"') {
119 +                       /* We do not want to pass quoted strings to setenv. */
120 +                       val++; 
121 +                       val[strlen(val)-1] = 0;
122 +               }
123 +
124 +               if (!getenv(key)) /* User vars > config vars */
125 +                       xsetenv(key, val);
126 +               continue;
127 +       } /* while (1) */
128 +
129 + pe_label:
130 +       fclose(f);
131 +       bb_error_msg("parse error in %s, line %u: %s", config_file, lc, errmsg);
132 +}
133  
134  # if ENABLE_FEATURE_SUID
135  static void check_suid(int applet_no)
136 @@ -802,9 +917,11 @@ int main(int argc UNUSED_PARAM, char **argv)
137         }
138         /* applet_names in this case is just "applet\0\0" */
139         lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv));
140 +       load_env_vars();
141         return SINGLE_APPLET_MAIN(argc, argv);
142  #else
143         lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
144 +       load_env_vars();
145  
146         applet_name = argv[0];
147         if (applet_name[0] == '-')
148 -- 
149 1.7.8
150