summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actions.c30
-rw-r--r--src/data.h12
-rw-r--r--src/events.c7
-rw-r--r--src/main.c31
4 files changed, 64 insertions, 16 deletions
diff --git a/src/actions.c b/src/actions.c
index 2779101..d02a983 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -973,29 +973,27 @@ void
spawn(void *data)
{
char *cmd = data;
- /* Ugly dance to avoid leaving zombies. Could use SIGCHLD, but it's
- not very portable. */
- if (fork() == 0)
+ int pid;
+
+ pid = fork();
+ if (pid == 0)
{
- if (fork() == 0)
- {
- /* Some process setup to make sure the spawned process runs
- in its own session. */
- putenv(current_screen()->display_string);
+ /* Some process setup to make sure the spawned process runs
+ in its own session. */
+ putenv(current_screen()->display_string);
#ifdef HAVE_SETSID
- setsid();
+ setsid();
#endif
#if defined (HAVE_SETPGID)
- setpgid (0, 0);
+ setpgid (0, 0);
#elif defined (HAVE_SETPGRP)
- setpgrp (0, 0);
+ setpgrp (0, 0);
#endif
- execl("/bin/sh", "sh", "-c", cmd, 0);
- _exit(EXIT_FAILURE);
- }
- _exit(EXIT_SUCCESS);
+ execl("/bin/sh", "sh", "-c", cmd, 0);
+ _exit(EXIT_FAILURE);
}
- wait((int *) 0);
+
+/* wait((int *) 0); */
PRINT_DEBUG ("spawned %s\n", cmd);
}
diff --git a/src/data.h b/src/data.h
index eae7df7..d81918d 100644
--- a/src/data.h
+++ b/src/data.h
@@ -165,6 +165,17 @@ struct rp_defaults
int warp;
};
+/* Information about a child process. */
+struct rp_child_info
+{
+ int pid;
+ int status;
+};
+
+/* When a child process exits this structure holds the information
+ about it to be used to report back to the user. */
+extern struct rp_child_info child_info;
+
extern struct rp_defaults defaults;
/* The prefix key also known as the command character under screen. */
@@ -250,6 +261,7 @@ extern struct modifier_info rp_modifier_info;
extern int alarm_signalled;
extern int kill_signalled;
extern int hup_signalled;
+extern int chld_signalled;
/* rudeness levels */
extern int rp_honour_transient_raise;
diff --git a/src/events.c b/src/events.c
index 4004c61..54270c3 100644
--- a/src/events.c
+++ b/src/events.c
@@ -33,6 +33,7 @@
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
+#include <sys/wait.h>
#include "ratpoison.h"
@@ -782,6 +783,12 @@ handle_signals ()
alarm_signalled = 0;
}
+ if (chld_signalled > 0)
+ {
+ marked_message_printf (0,0, " Command not found ");
+ chld_signalled = 0;
+ }
+
if (hup_signalled > 0)
{
clean_up ();
diff --git a/src/main.c b/src/main.c
index d5d5417..4f4e9af 100644
--- a/src/main.c
+++ b/src/main.c
@@ -33,6 +33,7 @@
#include <unistd.h>
#include <getopt.h>
#include <string.h>
+#include <sys/wait.h>
#include "ratpoison.h"
@@ -41,6 +42,7 @@ static void init_screen (screen_info *s, int screen_num);
int alarm_signalled = 0;
int kill_signalled = 0;
int hup_signalled = 0;
+int chld_signalled = 0;
int rat_x;
int rat_y;
int rat_visible = 1; /* rat is visible by default */
@@ -61,6 +63,7 @@ screen_info *screens;
int num_screens;
Display *dpy;
+struct rp_child_info child_info;
struct rp_defaults defaults;
int ignore_badwindow = 0;
@@ -201,6 +204,33 @@ alrm_handler (int signum)
alarm_signalled++;
}
+void
+chld_handler (int signum)
+{
+ int pid, status, serrno;
+ serrno = errno;
+
+ while (1)
+ {
+ pid = waitpid (WAIT_ANY, &status, WNOHANG);
+ if (pid <= 0)
+ break;
+
+ PRINT_DEBUG("Child status: %d\n", WEXITSTATUS (status));
+
+ /* Tell ratpoison about the CHLD signal. We are only interested
+ in reporting commands that failed to execute. These processes
+ have a return value of 127 (according to the sh manual). */
+ if (WEXITSTATUS (status) == 127)
+ {
+ chld_signalled = 1;
+ child_info.pid = pid;
+ child_info.status = status;
+ }
+ }
+ errno = serrno;
+}
+
int
handler (Display *d, XErrorEvent *e)
{
@@ -537,6 +567,7 @@ main (int argc, char *argv[])
set_sig_handler (SIGTERM, sighandler);
set_sig_handler (SIGINT, sighandler);
set_sig_handler (SIGHUP, hup_handler);
+ set_sig_handler (SIGCHLD, chld_handler);
/* Setup ratpoison's internal structures */
init_defaults();