]> git.sur5r.net Git - i3/i3/blobdiff - src/util.c
Add vim hints, copyright notice to each file, add LICENSE, retab! everything
[i3/i3] / src / util.c
index 1263cdc4939e41bdff989d7b121618a7d0af270e..525fb4342f2110dae1df9207b5b9f0751f2b3a04 100644 (file)
@@ -1,26 +1,49 @@
+/*
+ * vim:ts=8:expandtab
+ *
+ * i3 - an improved dynamic tiling window manager
+ *
+ * (c) 2009 Michael Stapelberg and contributors
+ *
+ * See file LICENSE for license information.
+ *
+ */
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <sys/wait.h>
 
 #include "i3.h"
 
 /*
- * Starts the given application with the given args.
+ * Starts the given application by passing it through a shell. We use double fork
+ * to avoid zombie processes. As the started application’s parent exits (immediately),
+ * the application is reparented to init (process-id 1), which correctly handles
+ * childs, so we don’t have to do it :-).
+ *
+ * The shell is determined by looking for the SHELL environment variable. If it
+ * does not exist, /bin/sh is used.
  *
  */
-void start_application(const char *path, const char *args) {
-       pid_t pid;
-       if ((pid = vfork()) == 0) {
-               /* This is the child */
-               char *argv[2];
-               /* TODO: For now, we ignore args. Later on, they should be parsed
-                  correctly (like in the shell?) */
-               argv[0] = strdup(path);
-               argv[1] = NULL;
-               execve(path, argv, environment);
-               /* not reached */
-       }
+void start_application(const char *command) {
+        if (fork() == 0) {
+                /* Child process */
+                if (fork() == 0) {
+                        /* Stores the path of the shell */
+                        static const char *shell = NULL;
+
+                        if (shell == NULL)
+                                if ((shell = getenv("SHELL")) == NULL)
+                                        shell = "/bin/sh";
+
+                        /* This is the child */
+                        execl(shell, shell, "-c", command, NULL);
+                        /* not reached */
+                }
+                exit(0);
+        }
+        wait(0);
 }
 
 /*
@@ -29,10 +52,10 @@ void start_application(const char *path, const char *args) {
  *
  */
 void check_error(xcb_connection_t *connection, xcb_void_cookie_t cookie, char *err_message) {
-       xcb_generic_error_t *error = xcb_request_check(connection, cookie);
-       if (error != NULL) {
-               fprintf(stderr, "ERROR: %s : %d\n", err_message , error->error_code);
-               xcb_disconnect(connection);
-               exit(-1);
-       }
+        xcb_generic_error_t *error = xcb_request_check(connection, cookie);
+        if (error != NULL) {
+                fprintf(stderr, "ERROR: %s : %d\n", err_message , error->error_code);
+                xcb_disconnect(connection);
+                exit(-1);
+        }
 }