From: root Date: Thu, 19 Jan 2006 09:47:15 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=f23f116b36ebd592ad914de453c1ce25c8948830;p=dana%2Furxvt.git *** empty log message *** --- diff --git a/Changes b/Changes index ee60a95d..2596d87a 100644 --- a/Changes +++ b/Changes @@ -14,7 +14,6 @@ WISH: support tex fonts 9.0 TODO: distributed clipboard example -TODO: use correct %ENV for perl exec'ed processes. - setuid/setgid operation is now _encouraged_: security has been improved by moving privileged operations into a separate process and permanently dropping privileges within the terminal. This @@ -54,6 +53,7 @@ TODO: use correct %ENV for perl exec'ed processes. - made some fixes to xpm offset and scaling code. - perl-overlays and refresh hooks were not applied in correct order. - changed coordinate-system of view_start/nsaved to be top to bottom. + - iom extended to support listening for child exits. 7.0 Fri Jan 13 14:02:18 CET 2006 - added sections for DISTRIBUTION MAINTAINERS and about diff --git a/src/hookinc.h b/src/hookinc.h index d0814249..108ad66b 100644 --- a/src/hookinc.h +++ b/src/hookinc.h @@ -4,6 +4,8 @@ def (DESTROY) def (RESET) def (START) + def (CHILD_START) + def (CHILD_EXIT) def (SEL_BEGIN) def (SEL_EXTEND) diff --git a/src/init.C b/src/init.C index 08c110b8..a2e58d07 100644 --- a/src/init.C +++ b/src/init.C @@ -1443,6 +1443,10 @@ rxvt_term::run_command (const char *const *argv) #endif pty->close_tty (); + + child_ev.start (cmd_pid); + + HOOK_INVOKE ((this, HOOK_CHILD_START, DT_INT, cmd_pid, DT_END)); break; } } diff --git a/src/iom.C b/src/iom.C index 3ec1ab83..e42dee86 100644 --- a/src/iom.C +++ b/src/iom.C @@ -24,18 +24,20 @@ #include #include #include +#include +#include #include -#include - #if 1 // older unices need these includes for select (2) # include -# include # include #endif -// for IOM_SIG +#if IOM_CHILD +# include +#endif + #if IOM_SIG # include # include @@ -72,28 +74,63 @@ struct sig_vec : io_manager_vec { }; static vector sw; #endif +#if IOM_CHILD +static io_manager_vec pw; +#endif // this is a dummy time watcher to ensure that the first // time watcher is _always_ valid, this gets rid of a lot // of null-pointer-checks // (must come _before_ iom is being defined) static struct tw0 : time_watcher +{ + void cb (time_watcher &w) { - void cb (time_watcher &w) - { - // should never get called - // reached end-of-time, or tstamp has a bogus definition, - // or compiler initialisation order broken, or something else :) - abort (); - } + // should never get called + // reached end-of-time, or tstamp has a bogus definition, + // or compiler initialisation order broken, or something else :) + abort (); + } - tw0 () - : time_watcher (this, &tw0::cb) - { } - } tw0; + tw0 () + : time_watcher (this, &tw0::cb) + { } +} tw0; tstamp NOW; +#if IOM_CHILD +// sig_watcher for child signal(s) +static struct sw0 : sig_watcher +{ + void cb (sig_watcher &w) + { + // SIGCHLD, call corresponding watchera + pid_t pid; + int status; + + while ((pid = waitpid (-1, &status, WNOHANG)) > 0) + for (int i = pw.size (); i--; ) + { + child_watcher *w = pw[i]; + + if (!w) + pw.erase_unordered (i); + else if (w->pid == pid) + { + w->stop (); + w->call (*w, status); + } + } + + } + + sw0 () + : sig_watcher (this, &sw0::cb) + { } +} sw0; +#endif + #if IOM_TIME tstamp io_manager::now () { @@ -115,6 +152,8 @@ static bool iom_valid; static struct init { init () { + iom_valid = true; + #if IOM_SIG sigemptyset (&sigs); @@ -128,7 +167,9 @@ static struct init { fcntl (sigpipe[1], F_SETFL, O_NONBLOCK); fcntl (sigpipe[1], F_SETFD, FD_CLOEXEC); #endif - iom_valid = true; +#if IOM_CHILD + sw0.start (SIGCHLD); +#endif #if IOM_TIME io_manager::set_now (); @@ -273,6 +314,11 @@ void sig_watcher::start (int signum) } #endif +#if IOM_CHILD +void io_manager::reg (child_watcher &w) { io_manager::reg (w, pw); } +void io_manager::unreg (child_watcher &w) { io_manager::unreg (w, pw); } +#endif + void io_manager::loop () { init::required (); diff --git a/src/iom.h b/src/iom.h index 7cfbe751..42c76318 100644 --- a/src/iom.h +++ b/src/iom.h @@ -28,24 +28,13 @@ // edit iom_conf.h as appropriate. #include "iom_conf.h" -#include "callback.h" - -#ifndef IOM_IO -# define IOM_IO 0 -#endif -#ifndef IOM_TIME -# define IOM_TIME 0 -#endif -#ifndef IOM_CHECK -# define IOM_CHECK 0 -#endif -#ifndef IOM_IDLE -# define IOM_IDLE 0 -#endif -#ifndef IOM_SIG -# define IOM_SIG 0 +#if IOM_CHILD +# undef IOM_SIG +# define IOM_SIG 1 #endif +#include "callback.h" + typedef double tstamp; extern tstamp NOW; @@ -68,6 +57,9 @@ struct idle_watcher; #if IOM_SIG struct sig_watcher; #endif +#if IOM_CHILD +struct child_watcher; +#endif template struct io_manager_vec : vector { @@ -115,6 +107,9 @@ public: #if IOM_SIG static void reg (sig_watcher &w); static void unreg (sig_watcher &w); #endif +#if IOM_CHILD + static void reg (child_watcher &w); static void unreg (child_watcher &w); +#endif static void loop (); }; @@ -141,7 +136,7 @@ struct io_watcher : watcher, callback2 { template io_watcher (O1 *object, void (O2::*method) (io_watcher &, short)) - : callback2 (object,method) + : callback2 (object, method) { } ~io_watcher () { stop (); } }; @@ -161,7 +156,7 @@ struct time_watcher : watcher, callback1 { template time_watcher (O1 *object, void (O2::*method) (time_watcher &)) - : callback1 (object,method), at (0) + : callback1 (object, method), at (0) { } ~time_watcher () { stop (); } }; @@ -175,7 +170,7 @@ struct check_watcher : watcher, callback1 { template check_watcher (O1 *object, void (O2::*method) (check_watcher &)) - : callback1 (object,method) + : callback1 (object, method) { } ~check_watcher () { stop (); } }; @@ -189,7 +184,7 @@ struct idle_watcher : watcher, callback1 { template idle_watcher (O1 *object, void (O2::*method) (idle_watcher &)) - : callback1 (object,method) + : callback1 (object, method) { } ~idle_watcher () { stop (); } }; @@ -204,11 +199,26 @@ struct sig_watcher : watcher, callback1 { template sig_watcher (O1 *object, void (O2::*method) (sig_watcher &)) - : callback1 (object,method), signum (-1) + : callback1 (object, method), signum (0) { } ~sig_watcher () { stop (); } }; #endif +#if IOM_CHILD +struct child_watcher : watcher, callback2 { + int /*pid_t*/ pid; + + void start (int pid) { this->pid = pid; io_manager::reg (*this); } + void stop () { io_manager::unreg (*this); } + + template + child_watcher (O1 *object, void (O2::*method) (child_watcher &, int status)) + : callback2 (object, method), pid (0) + { } + ~child_watcher () { stop (); } +}; +#endif + #endif diff --git a/src/iom_conf.h b/src/iom_conf.h index c79022fd..be08fc62 100644 --- a/src/iom_conf.h +++ b/src/iom_conf.h @@ -22,10 +22,11 @@ #include -#define IOM_IO 1 -#define IOM_TIME 1 +#define IOM_IO 1 +#define IOM_TIME 1 #define IOM_CHECK 1 -#define IOM_SIG 1 +#define IOM_SIG 1 +#define IOM_CHILD 1 #endif diff --git a/src/main.C b/src/main.C index e08736b7..b98eedb1 100644 --- a/src/main.C +++ b/src/main.C @@ -171,6 +171,7 @@ rxvt_term::rxvt_term () #endif termwin_ev (this, &rxvt_term::x_cb), vt_ev (this, &rxvt_term::x_cb), + child_ev (this, &rxvt_term::child_cb), check_ev (this, &rxvt_term::check_cb), flush_ev (this, &rxvt_term::flush_cb), destroy_ev (this, &rxvt_term::destroy_cb), @@ -287,9 +288,12 @@ rxvt_term::~rxvt_term () #endif } +// child has exited, usually destroys void -rxvt_term::child_exit () +rxvt_term::child_cb (child_watcher &w, int status) { + HOOK_INVOKE ((this, HOOK_CHILD_EXIT, DT_INT, status, DT_END)); + cmd_pid = 0; if (!OPTION (Opt_hold)) @@ -527,22 +531,8 @@ rxvt_term::init (int argc, const char *const *argv) static struct sig_handlers { - sig_watcher sw_chld, sw_term, sw_int; + sig_watcher sw_term, sw_int; - void sig_chld (sig_watcher &w) - { - // we are being called for every SIGCHLD, find the corresponding term - int pid; - - while ((pid = waitpid (-1, NULL, WNOHANG)) > 0) - for (rxvt_term **t = rxvt_term::termlist.begin (); t < rxvt_term::termlist.end (); t++) - if (pid == (*t)->cmd_pid) - { - (*t)->child_exit (); - break; - } - } - /* * Catch a fatal signal and tidy up before quitting */ @@ -558,8 +548,7 @@ static struct sig_handlers } sig_handlers () - : sw_chld (this, &sig_handlers::sig_chld), - sw_term (this, &sig_handlers::sig_term), + : sw_term (this, &sig_handlers::sig_term), sw_int (this, &sig_handlers::sig_term) { } @@ -606,7 +595,6 @@ rxvt_init () signal (SIGHUP, SIG_IGN); signal (SIGPIPE, SIG_IGN); - sig_handlers.sw_chld.start (SIGCHLD); sig_handlers.sw_term.start (SIGTERM); sig_handlers.sw_int.start (SIGINT); diff --git a/src/perl/mark-urls b/src/perl/mark-urls index d1245903..bfd47f14 100644 --- a/src/perl/mark-urls +++ b/src/perl/mark-urls @@ -51,7 +51,7 @@ sub on_button_release { if ($event->{button} == 2 && ($event->{state} & $mask) == 0) { while ($text =~ /$url/g) { if ($-[1] <= $col && $+[1] >= $col) { - urxvt::exec_async $self->{browser}, $1; + $self->exec_async ($self->{browser}, $1); return 1; } } diff --git a/src/perl/selection b/src/perl/selection index ca71f9c3..10e40011 100644 --- a/src/perl/selection +++ b/src/perl/selection @@ -14,7 +14,8 @@ sub on_init { for (my $idx = 0; defined (my $res = $self->x_resource ("selection.pattern-$idx")); $idx++) { no re 'eval'; # just to be sure - $res = utf8::encode $self->locale_decode ($res); + $res = $self->locale_decode ($res); + utf8::encode $res; push @{ $self->{patterns} }, qr/$res/; } diff --git a/src/perl/selection-popup b/src/perl/selection-popup index bcb0b4e7..82e87d11 100644 --- a/src/perl/selection-popup +++ b/src/perl/selection-popup @@ -71,7 +71,7 @@ sub on_button_press { and $add_button->("shell quote" => sub { $_ = "\Q$_" }); /^(http|ftp|telnet|irc|news):\// - and $add_button->("run $self->{browser}" => sub { urxvt::exec_async $self->{browser}, $_ }); + and $add_button->("run $self->{browser}" => sub { $self->exec_async ($self->{browser}, $_) }); for my $hook (@hook) { if (my ($title, $cb) = $hook->($popup)) { diff --git a/src/rxvt.h b/src/rxvt.h index cac5d4ba..4640b511 100644 --- a/src/rxvt.h +++ b/src/rxvt.h @@ -1189,6 +1189,7 @@ struct rxvt_term : zero_initialized, rxvt_vars { xevent_watcher scrollbar_ev; #endif + void child_cb (child_watcher &w, int status); child_watcher child_ev; void check_cb (check_watcher &w); check_watcher check_ev; void destroy_cb (time_watcher &w); time_watcher destroy_ev; void flush_cb (time_watcher &w); time_watcher flush_ev; @@ -1228,7 +1229,6 @@ struct rxvt_term : zero_initialized, rxvt_vars { rxvt_term (); ~rxvt_term (); - void child_exit (); // child has exited, usually destroys void destroy (); void emergency_cleanup (); diff --git a/src/urxvt.pm b/src/urxvt.pm index e016145d..6b403c50 100644 --- a/src/urxvt.pm +++ b/src/urxvt.pm @@ -145,15 +145,15 @@ $word>: And this example matches the same,but replaces it with vi-commands you can paste directly into your (vi :) editor: - URxvt.selection-autotransform.0: s/^([^:[:space:]]+(\\d+):?$/\\x1b:e \\Q$1\\E\\x0d:$2\\x0d/ + URxvt.selection-autotransform.0: s/^([^:[:space:]]+(\\d+):?$/:e \\Q$1\\E\\x0d:$2\\x0d/ Of course, this can be modified to suit your needs and your editor :) To expand the example above to typical perl error messages ("XXX at FILENAME line YYY."), you need a slightly more elaborate solution: - URxvt.selection.pattern-0: ( at .*? line \\d+\\.) - URxvt.selection-autotransform.0: s/^ at (.*?) line (\\d+)\\.$/\x1b:e \\Q$1\E\\x0d:$2\\x0d/ + URxvt.selection.pattern-0: ( at .*? line \\d+[,.]) + URxvt.selection-autotransform.0: s/^ at (.*?) line (\\d+)[,.]$/:e \\Q$1\E\\x0d:$2\\x0d/ The first line tells the selection code to treat the unchanging part of every error message as a selection pattern, and the second line transforms @@ -327,6 +327,15 @@ variables. Called at the very end of initialisation of a new terminal, just before returning to the mainloop. +=item on_child_start $term, $pid + +Called just after the child process has been Ced. + +=item on_child_exit $term, $status + +Called just after the child process has exited. C<$status> is the status +from C. + =item on_sel_make $term, $eventtime Called whenever a selection has been made by the user, but before the @@ -746,18 +755,6 @@ sub invoke { $retval } -sub exec_async(@) { - my $pid = fork; - - return - if !defined $pid or $pid; - - %ENV = %{ $TERM->env }; - - exec @_; - _exit 255; -} - # urxvt::term::extension package urxvt::term::extension; @@ -944,6 +941,31 @@ Destroy the terminal object (close the window, free resources etc.). Please note that @@RXVT_NAME@@ will not exit as long as any event watchers (timers, io watchers) are still active. +=item $term->exec_async ($cmd[, @args]) + +Works like the combination of the C/C builtins, which executes +("starts") programs in the background. This function takes care of setting +the user environment before exec'ing the command (e.g. C) and should +be preferred over explicit calls to C or C. + +Returns the pid of the subprocess or C on error. + +=cut + +sub exec_async { + my $self = shift; + + my $pid = fork; + + return $pid + if !defined $pid or $pid; + + %ENV = %{ $self->env }; + + exec @_; + urxvt::_exit 255; +} + =item $isset = $term->option ($optval[, $set]) Returns true if the option specified by C<$optval> is enabled, and