Subject: Patch to send signals to process group at exit

From: Rasmus Borup Hansen <[email-masked]>
Date: Wed, 22 Mar 2000 14:53:42 +0100 (MET)

We use FVWM as our window manager here at the Institute for
Mathematical Sciences, University of Copenhagen. Many users have
configured their InitFunction to start up Netscape automatically when
they log in. Sometimes these users log in just to see if they have new
mail (by looking at XBiff), and if they don't have any they log out
even before the Netscape window comes up. Then, the chooser window
reappears and on some X-Terminals (ie. old NCD 19R terminals) a
Netscape window appears too. Since the user may already have left the
X-Terminal, his account may be compromised.

I don't think it's possible to configure the old X-Terminals to
disallow the Netscape window to open, so I wrote a patch for FVWM that
makes the FVWM process send some signals to the entire process group
before the fvwm-process exits. As far as I know, XTerms will always
belong to different process groups, so programs started with "nohup"
will not be "signaled to death". Anyhow, the user can configure which
signals he wants to send by using the "SendSignalsOnExit" directive
like this:

SendSignalsOnExit	"SIGHUP SIGTERM"

(only SIGHUP, SIGINT, SIGQUIT and SIGTERM are supported).

I've attached the patch against version 2.2.2 and some lines for the
Changelog, in case you want to include the patch in the official FVWM.

Thanks for making a nice window manager.

Rasmus

-- 
Rasmus Borup Hansen, email: [email-masked], phone. +45 353 20746, room E206
Institute for Mathematical Sciences, University of Copenhagen, Denmark

M-x praise-be-unto-xemacs
2000-03-22  Rasmus Borup Hansen  <[email-masked]>

	* fvwm/parse.h: Added F_SENDSIGNALSATEXIT to enum.

	* fvwm/misc.h: Added declaration of send_signal_func.

	* fvwm/fvwm.h: Added the global variables SendSIGHUPAtExit,
	SendSIGINTAtExit, SendSIGQUITAtExit and SendSIGTERMAtExit.

	* fvwm/fvwm.c: Added the global variables SendSIGHUPAtExit,
	SendSIGINTAtExit, SendSIGQUITAtExit and SendSIGTERMAtExit.
	Added code to Done so that the configured signals are sent to the
	enire process group at exit.

	* fvwm/functions.c (func_config): Added "SendSignalsAtExit"
	configuration directive.

	* fvwm/builtins.c (send_signals_func): Added the function to parse
	"SendSignalsAtExit".
*** builtins.c.orig	Tue Mar 21 12:46:53 MET 2000
--- builtins.c	Wed Mar 22 13:37:08 MET 2000
***************
*** 4865,4867 ****
--- 4865,4899 ----
      rgpctMovementDefault[i++] = 1.0;
    }
  }
+ 
+ void send_signals_func(XEvent *eventp,Window w,FvwmWindow *tmp_win,
+ 			  unsigned long context, char *action,int* Module)
+ {
+   char *opt, *tok;
+   action = GetNextToken(action, &opt);
+   fprintf(stderr,"send_signals_func: %s\n",opt);
+   SendSIGHUPAtExit = False;
+   SendSIGINTAtExit = False; 
+   SendSIGQUITAtExit = False;
+   SendSIGTERMAtExit = False;
+   tok = strtok(opt," \t");
+   while(tok) {
+     if (!strcasecmp(tok,"sighup")) {
+       fprintf(stderr,"Will send SIGHUP at exit\n");
+       SendSIGHUPAtExit = True;
+     } else if (!strcasecmp(tok,"sigint")) {
+       fprintf(stderr,"Will send SIGINT at exit\n");
+       SendSIGINTAtExit = True;
+     } else if (!strcasecmp(tok,"sigquit")) {
+       fprintf(stderr,"Will send SIGQUIT at exit\n");
+       SendSIGQUITAtExit = True;
+     } else if (!strcasecmp(tok,"sigterm")) {
+       fprintf(stderr,"Will send SIGTERM at exit\n");
+       SendSIGTERMAtExit = True;
+     } else {
+       fvwm_msg(ERR, "SendSignalAtExit", 
+ 	       "Unknown og unsupported signal '%s'", tok);
+     }
+     tok = strtok(NULL," \t");
+   }
+ }
*** functions.c.orig	Tue Mar 21 12:46:50 MET 2000
--- functions.c	Wed Mar 22 12:59:37 MET 2000
***************
*** 148,153 ****
--- 148,154 ----
    {"Scroll",       scroll,           F_SCROLL,              FUNC_NO_WINDOW},
    {"Send_ConfigInfo",SendDataToModule, F_CONFIG_LIST,       FUNC_NO_WINDOW},
    {"Send_WindowList",send_list_func, F_SEND_WINDOW_LIST,    FUNC_NO_WINDOW},
+   {"SendSignalsAtExit",send_signals_func, F_SENDSIGNALSATEXIT, FUNC_NO_WINDOW},
    {"SendToModule", SendStrToModule,  F_SEND_STRING,         FUNC_NO_WINDOW},
    {"set_mask",     set_mask_function,F_SET_MASK,            FUNC_NO_WINDOW},
    {"SetAnimation", set_animation,    F_SET_ANIMATION,	    FUNC_NO_WINDOW},
*** fvwm.c.orig	Tue Mar 21 12:35:22 MET 2000
--- fvwm.c	Wed Mar 22 14:13:15 MET 2000
***************
*** 116,121 ****
--- 116,126 ----
  int fd_width, x_fd;
  char *display_name = NULL;
  
+ Bool SendSIGHUPAtExit = False, 
+   SendSIGINTAtExit = False, 
+   SendSIGQUITAtExit = False, 
+   SendSIGTERMAtExit = False;
+ 
  typedef enum { FVWM_RUNNING=0, FVWM_DONE, FVWM_RESTART } FVWM_STATE;
  
  /*
***************
*** 1505,1510 ****
--- 1510,1559 ----
    else
    {
      XCloseDisplay(dpy);
+   }
+ 
+   /* Ignore SIGHUP, SIGINT, SIGQUIT and SIGTERM while sending these
+    * signals to the entire process group. */
+ #ifdef HAVE_SIGACTION
+   {
+     struct sigaction sigact;
+ #ifdef SA_RESTART
+     sigact.sa_flags = SA_RESTART;
+ #else
+     sigact.sa_flags = 0;
+ #endif
+     sigemptyset(&sigact.sa_mask);
+     sigact.sa_handler = SIG_IGN;
+     sigaction(SIGHUP, &sigact, NULL);
+     sigaction(SIGINT, &sigact, NULL);
+     sigaction(SIGQUIT, &sigact, NULL);
+     sigaction(SIGTERM, &sigact, NULL);
+   }
+ #else
+   signal(SIGHUP,SIG_IGN);
+   signal(SIGINT,SIG_IGN);
+   signal(SIGQUIT,SIG_IGN);
+   signal(SIGTERM,SIG_IGN);
+ #endif
+   /* Now send the signals... */
+   if (SendSIGHUPAtExit) {
+     fprintf(stderr,"Sending SIGHUP\n");
+     kill(-getpgrp(),SIGHUP);
+     sleep(1);
+   }
+   if (SendSIGINTAtExit) {
+     fprintf(stderr,"Sending SIGINT\n");
+     kill(-getpgrp(),SIGINT);
+     sleep(1);
+   }
+   if (SendSIGQUITAtExit) {
+     fprintf(stderr,"Sending SIGQUIT\n");
+     kill(-getpgrp(),SIGQUIT);
+     sleep(1);
+   }
+   if (SendSIGTERMAtExit) {
+     fprintf(stderr,"Sending SIGTERM\n");
+     kill(-getpgrp(),SIGTERM);
    }
    exit(0);
  }
*** fvwm.h.orig	Wed Mar 22 13:22:36 MET 2000
--- fvwm.h	Wed Mar 22 13:23:28 MET 2000
***************
*** 406,411 ****
--- 406,414 ----
  extern Atom _XA_OL_DECOR_HEADER;
  extern Atom _XA_OL_DECOR_ICON_NAME;
  
+ extern Bool SendSIGHUPAtExit, SendSIGINTAtExit, SendSIGQUITAtExit, 
+   SendSIGTERMAtExit;
+ 
  /* include this down here because FvwmWindows must be defined when including
   * this header file. */
  #include "fvwmdebug.h"
*** misc.h.orig	Sun Feb 14 16:48:56 MET 1999
--- misc.h	Wed Mar 22 12:59:34 MET 2000
***************
*** 341,346 ****
--- 341,347 ----
  void UpdateDecor(F_CMD_ARGS);
  void SetColormapFocus(F_CMD_ARGS);
  void SetColorLimit(F_CMD_ARGS);
+ void send_signals_func(F_CMD_ARGS);
  
  #define UP 1
  #define DOWN 0
*** parse.h.orig	Tue Jan 12 22:07:44 MET 1999
--- parse.h	Wed Mar 22 12:56:42 MET 2000
***************
*** 86,91 ****
--- 86,92 ----
      F_DFLT_COLORS,
      F_GLOBAL_OPTS,
      F_EMULATE,
+     F_SENDSIGNALSATEXIT,
  
      F_RESIZE = 100,
      F_RAISE,

---

From: Dan Espen <[email-masked]>
Date: Wed, 22 Mar 2000 09:38:30 -0500

> SendSignalsOnExit	"SIGHUP SIGTERM"

Have you tried doing this   with a shell  or  program added to  fvwm's
ExitFunction?

--
Dan Espen
444 Hoes Lane  Room RRC 1C-214           E-mail: [email-masked]
Piscataway, NJ 08854                     Phone: (732) 699-5570
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Rasmus Borup Hansen <[email-masked]>
Date: Wed, 22 Mar 2000 15:45:47 +0100 (MET)

> Have you tried doing this   with a shell  or  program added to  fvwm's

I considered it, and I agree it can be done in that way. I think it's
more "clean", however, to let FVWM itself clean up. Of course, this is
just a matter of taste.

Rasmus

---

From: Chris Rankin <[email-masked]>
Date: Thu, 23 Mar 2000 08:24:39 +1100 (EST)

> more "clean", however, to let FVWM itself clean up. Of course, this is

Sounds like you could also achieve the same effect by putting

stty +hup

in the start-up shell that launches fvwm2, e.g. in
/etc/X11/xinit/xinitrc. Guys, do other window managers do this sort of
thing? I'd hesitate to implement a feature (particularly since we're
in feature-freeze) that could reasonably be implemented by other means.

Chris.

---

From: Rasmus Borup Hansen <[email-masked]>
Date: Thu, 23 Mar 2000 09:55:24 +0100 (MET)

> in the start-up shell that launches fvwm2, e.g. in

It appears that "stty hup" works on Digital Unix, even though the man
page doesn't say what it's supposed to do. Thanks for the hint.

 > in feature-freeze) that could reasonably be implemented by other means.

I've now stopped using my patched version of FVWM in favour of the
"stty hup" method, because I value using an official version of FVWM,
and because "stty hup" is a simple solution. In my opinion everyone
should use something equivalent to "stty hup" or my patch, because it
gives higher security, and I think people should somehow be encouraged
to do it. Perhaps someone will add a note about it one some web page?

Rasmus

---

From: Mark Rainford <[email-masked]>
Date: Thu, 23 Mar 2000 14:01:23 +0000

Rasmus Borup Hansen wrote:
>  ...

Errm, excuse me, but everyone is overlooking something rather important
here !

This is X windows - not MS windows - your X clients are not constrained
to run on the same CPU as your window manager. Unless there have been
some developments which I've missed, it is not possible for FVWM to send
a SIGHUP from its linux box to a remote xterm process on a neighbouring
host :-0

The most satisfactory solution is unfortunately impossible AFAIK because
X does not incorporate a suitable notion of "session" in its protocol.

The next most satisfactory solution (which my site uses) is to arrange
for your server to close its client's connections after the normal
logout actions have completed (such as  exiting the WM). Each client
which still has a connection then gets an XIO error which always causes
Xlib(3) to exit(2) - these clients can still handle non-X closedown
actions on the way out by using an XSetIOErrorHandler(3X) callback.

This is not completely satisfactory because (a) your Xserver has to
support the "client closedown" on logout, and (b) you still have to
somehow block a vvveeerryyy sluggish Netscape from popping up after the
Xserver has re-opened for business (host chooser or xdm(1) login
banner).

We manage (a) on three different types Xserver:

o   Sun-MS workstation: xdm(1) always sends SIGHUP/TERM to Xsun(1) on
logout

o   NCD X-terminal: set "login-xdm-action-on-disconnect = logout" in
/usr/lib/X11/ncd/configs/ncd_std

o   PC running eXceed : set the checkbox "Exit kills all clients" in the
"XDMCP Startup Modes" dialogue.

We should be managing (b) by setting "DisplayManager*grabServer: True"
in the xdm config. file, but we had problems with the next login when we
did this a long time ago (and have not yet revisited it).

-- 

Regards,  Mark.

---

From: Tim Phipps <[email-masked]>
Date: Thu, 23 Mar 2000 14:18:19 +0000

> did this a long time ago (and have not yet revisited it).
Is it possible to run your X-servers with an xauth file? It's much
better than xhosts in that it will restrict access to the server based
on cookies that can be made private to the user rather than just the
host that the client is run from. It would mean that a very slow
starting netscape would be refused access if someone else had logged in
to the X server.

Cheers,
Tim.

---

From: Mark Rainford <[email-masked]>
Date: Fri, 24 Mar 2000 12:39:05 +0000

Yes, xauth does the job nicely: once the user has logged off xdm changes
the cookie, so an app. which is slow to start is refused even before
another user logs in (ie. while the login banner is up). I guess this
just what Rasmus needs.

Thanks for this, Tim.

-- 

Regards,  Mark.