* Allow init to delte extra environment variables (was local bug
authorDr. Werner Fink <werner@suse.de>
Fri, 16 Mar 2012 15:58:21 +0000 (15:58 +0000)
committerDr. Werner Fink <werner@suse.de>
Fri, 16 Mar 2012 15:58:21 +0000 (15:58 +0000)
  #35858)
* Avoid that init double environment variables for its childs
  (was local bug #35855)

git-svn-id: svn://svn.sv.gnu.org/sysvinit/sysvinit/trunk@114 456724a4-4300-0410-8514-c89748c515a2

doc/Changelog
src/init.c

index 0cb2ca09819b5e8b838d42d0f4a4d5d13ffcf42c..d50f39d0e47d603ff0bde19a2f88d5e2a3ecb5fc 100644 (file)
@@ -1,6 +1,10 @@
 sysvinit (2.89dsf) UNRELEASED; urgency=low
 
   [ Werner Fink ]
+  * Allow init to delte extra environment variables (was local bug
+    #35858)
+  * Avoid that init double environment variables for its childs
+    (was local bug #35855)
   * Remove man-db tag for encoding for canonical man
   * Sulogin: try to detect the real device(s) used for the system console
     /dev/console if but only if /dev/console is used.  On Linux this can
index 5ab3459bb33e2e5e449ebdddef8ce577b516d33f..ad97d2762f2712d1bf072f66da652c846e377ac1 100644 (file)
@@ -248,7 +248,7 @@ void *imalloc(size_t size)
 }
 
 static
-char *istrdup(char *s)
+char *istrdup(const char *s)
 {
        char    *m;
        int     l;
@@ -880,6 +880,27 @@ void initlog(int loglevel, char *s, ...)
        }
 }
 
+/*
+ *     Add or replace specific environment value
+ */
+int addnewenv(const char *new, char **curr, int n)
+{
+       size_t nlen = strcspn(new, "=");
+       int i;
+       for (i = 0; i < n; i++) {
+               if (nlen != strcspn(curr[i], "="))
+                       continue;
+               if (strncmp (new, curr[i], nlen) == 0)
+                       break;
+       }
+       if (i >= n)
+               curr[n++] = istrdup(new);
+       else {
+               free(curr[i]);
+               curr[i] = istrdup(new);
+       }
+       return n;
+}
 
 /*
  *     Build a new environment for execve().
@@ -888,7 +909,7 @@ char **init_buildenv(int child)
 {
        char            i_lvl[] = "RUNLEVEL=x";
        char            i_prev[] = "PREVLEVEL=x";
-       char            i_cons[32];
+       char            i_cons[128];
        char            i_shell[] = "SHELL=" SHELL;
        char            **e;
        int             n, i;
@@ -898,25 +919,30 @@ char **init_buildenv(int child)
        n += NR_EXTRA_ENV;
        if (child)
                n += 8;
-       e = calloc(n, sizeof(char *));
+
+       while ((e = (char**)calloc(n, sizeof(char *))) == NULL) {
+               initlog(L_VB, "out of memory");
+               do_sleep(5);
+       }
 
        for (n = 0; environ[n]; n++)
                e[n] = istrdup(environ[n]);
 
        for (i = 0; i < NR_EXTRA_ENV; i++) {
-               if (extra_env[i])
-                       e[n++] = istrdup(extra_env[i]);
+               if (extra_env[i] == NULL || *extra_env[i] == '\0')
+                       continue;
+               n = addnewenv(extra_env[i], e, n);
        }
 
        if (child) {
                snprintf(i_cons, sizeof(i_cons), "CONSOLE=%s", console_dev);
                i_lvl[9]   = thislevel;
                i_prev[10] = prevlevel;
-               e[n++] = istrdup(i_shell);
-               e[n++] = istrdup(i_lvl);
-               e[n++] = istrdup(i_prev);
-               e[n++] = istrdup(i_cons);
-               e[n++] = istrdup(E_VERSION);
+               n = addnewenv(i_shell, e, n);
+               n = addnewenv(i_lvl, e, n);
+               n = addnewenv(i_prev, e, n);
+               n = addnewenv(i_cons, e, n);
+               n = addnewenv(E_VERSION, e, n);
        }
 
        e[n++] = NULL;
@@ -2133,41 +2159,46 @@ void fifo_new_level(int level)
 static
 void initcmd_setenv(char *data, int size)
 {
-       char            *env, *p, *e, *eq;
-       int             i, sz;
+       char            *env, *p, *e;
+       size_t          sz;
+       int             i, eq;
 
        e = data + size;
 
        while (*data && data < e) {
-               eq = NULL;
                for (p = data; *p && p < e; p++)
-                       if (*p == '=') eq = p;
+                       ;
                if (*p) break;
                env = data;
                data = ++p;
 
-               sz = eq ? (eq - env) : (p - env);
-
-               /*initlog(L_SY, "init_setenv: %s, %s, %d", env, eq, sz);*/
-
                /*
                 *      We only allow INIT_* to be set.
                 */
                if (strncmp(env, "INIT_", 5) != 0)
                        continue;
 
+               sz = strcspn(env, "=");
+               eq = (env[sz] == '=');
+
+               /*initlog(L_SY, "init_setenv: %s, %d, %d", env, eq, sz);*/
+
                /* Free existing vars. */
                for (i = 0; i < NR_EXTRA_ENV; i++) {
-                       if (extra_env[i] == NULL) continue;
-                       if (!strncmp(extra_env[i], env, sz) &&
-                           extra_env[i][sz] == '=') {
+                       if (extra_env[i] == NULL)
+                               continue;
+                       if (sz != strcspn(extra_env[i], "="))
+                               continue;
+                       if (strncmp(extra_env[i], env, sz) == 0) {
                                free(extra_env[i]);
                                extra_env[i] = NULL;
                        }
                }
 
+               if (eq == 0)
+                       continue;
+
                /* Set new vars if needed. */
-               if (eq == NULL) continue;
                for (i = 0; i < NR_EXTRA_ENV; i++) {
                        if (extra_env[i] == NULL) {
                                extra_env[i] = istrdup(env);