fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / um / os-Linux / main.c
index 2878e89..685feaa 100644 (file)
@@ -23,6 +23,7 @@
 #include "choose-mode.h"
 #include "uml-config.h"
 #include "os.h"
+#include "um_malloc.h"
 
 /* Set in set_stklim, which is called from main and __wrap_malloc.
  * __wrap_malloc only calls it if main hasn't started.
@@ -59,7 +60,7 @@ static __init void do_uml_initcalls(void)
        initcall_t *call;
 
        call = &__uml_initcall_start;
-       while (call < &__uml_initcall_end){;
+       while (call < &__uml_initcall_end){
                (*call)();
                call++;
        }
@@ -67,13 +68,60 @@ static __init void do_uml_initcalls(void)
 
 static void last_ditch_exit(int sig)
 {
-       signal(SIGINT, SIG_DFL);
-       signal(SIGTERM, SIG_DFL);
-       signal(SIGHUP, SIG_DFL);
        uml_cleanup();
        exit(1);
 }
 
+static void install_fatal_handler(int sig)
+{
+       struct sigaction action;
+
+       /* All signals are enabled in this handler ... */
+       sigemptyset(&action.sa_mask);
+
+       /* ... including the signal being handled, plus we want the
+        * handler reset to the default behavior, so that if an exit
+        * handler is hanging for some reason, the UML will just die
+        * after this signal is sent a second time.
+        */
+       action.sa_flags = SA_RESETHAND | SA_NODEFER;
+       action.sa_restorer = NULL;
+       action.sa_handler = last_ditch_exit;
+       if(sigaction(sig, &action, NULL) < 0){
+               printf("failed to install handler for signal %d - errno = %d\n",
+                      errno);
+               exit(1);
+       }
+}
+
+#define UML_LIB_PATH   ":/usr/lib/uml"
+
+static void setup_env_path(void)
+{
+       char *new_path = NULL;
+       char *old_path = NULL;
+       int path_len = 0;
+
+       old_path = getenv("PATH");
+       /* if no PATH variable is set or it has an empty value
+        * just use the default + /usr/lib/uml
+        */
+       if (!old_path || (path_len = strlen(old_path)) == 0) {
+               putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH);
+               return;
+       }
+
+       /* append /usr/lib/uml to the existing path */
+       path_len += strlen("PATH=" UML_LIB_PATH) + 1;
+       new_path = malloc(path_len);
+       if (!new_path) {
+               perror("coudn't malloc to set a new PATH");
+               return;
+       }
+       snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path);
+       putenv(new_path);
+}
+
 extern int uml_exitcode;
 
 extern void scan_elf_aux( char **envp);
@@ -114,6 +162,8 @@ int main(int argc, char **argv, char **envp)
 
        set_stklim();
 
+       setup_env_path();
+
        new_argv = malloc((argc + 1) * sizeof(char *));
        if(new_argv == NULL){
                perror("Mallocing argv");
@@ -128,9 +178,12 @@ int main(int argc, char **argv, char **envp)
        }
        new_argv[argc] = NULL;
 
-       set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-       set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
-       set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+       /* Allow these signals to bring down a UML if all other
+        * methods of control fail.
+        */
+       install_fatal_handler(SIGINT);
+       install_fatal_handler(SIGTERM);
+       install_fatal_handler(SIGHUP);
 
        scan_elf_aux( envp);