| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* _hurd_ctty_output -- Do an output RPC and generate SIGTTOU if necessary. | 
 | 2 |    Copyright (C) 1995-2016 Free Software Foundation, Inc. | 
 | 3 |    This file is part of the GNU C Library. | 
 | 4 |  | 
 | 5 |    The GNU C Library is free software; you can redistribute it and/or | 
 | 6 |    modify it under the terms of the GNU Lesser General Public | 
 | 7 |    License as published by the Free Software Foundation; either | 
 | 8 |    version 2.1 of the License, or (at your option) any later version. | 
 | 9 |  | 
 | 10 |    The GNU C Library is distributed in the hope that it will be useful, | 
 | 11 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 12 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 | 13 |    Lesser General Public License for more details. | 
 | 14 |  | 
 | 15 |    You should have received a copy of the GNU Lesser General Public | 
 | 16 |    License along with the GNU C Library; if not, see | 
 | 17 |    <http://www.gnu.org/licenses/>.  */ | 
 | 18 |  | 
 | 19 | #include <hurd.h> | 
 | 20 | #include <hurd/signal.h> | 
 | 21 |  | 
 | 22 | /* Call *RPC on PORT and/or CTTY.  If a call on CTTY returns EBACKGROUND, | 
 | 23 |    generate SIGTTOU if appropriate.  */ | 
 | 24 |  | 
 | 25 | error_t | 
 | 26 | _hurd_ctty_output (io_t port, io_t ctty, error_t (*rpc) (io_t)) | 
 | 27 | { | 
 | 28 |   if (ctty == MACH_PORT_NULL) | 
 | 29 |     return (*rpc) (port); | 
 | 30 |   else | 
 | 31 |     { | 
 | 32 |       struct hurd_sigstate *ss = _hurd_self_sigstate (); | 
 | 33 |       error_t err; | 
 | 34 |  | 
 | 35 |       do | 
 | 36 | 	{ | 
 | 37 | 	  /* Don't use the ctty io port if we are blocking or ignoring | 
 | 38 | 	     SIGTTOU.  We redo this check at the top of the loop in case | 
 | 39 | 	     the signal handler changed the state.  */ | 
 | 40 | 	  __spin_lock (&ss->lock); | 
 | 41 | 	  if (__sigismember (&ss->blocked, SIGTTOU) || | 
 | 42 | 	      ss->actions[SIGTTOU].sa_handler == SIG_IGN) | 
 | 43 | 	    err = EIO; | 
 | 44 | 	  else | 
 | 45 | 	    err = 0; | 
 | 46 | 	  __spin_unlock (&ss->lock); | 
 | 47 |  | 
 | 48 | 	  if (err) | 
 | 49 | 	    return (*rpc) (port); | 
 | 50 |  | 
 | 51 | 	  err = (*rpc) (ctty); | 
 | 52 | 	  if (err == EBACKGROUND) | 
 | 53 | 	    { | 
 | 54 | 	      if (_hurd_orphaned) | 
 | 55 | 		/* Our process group is orphaned, so we never generate a | 
 | 56 | 		   signal; we just fail.  */ | 
 | 57 | 		err = EIO; | 
 | 58 | 	      else | 
 | 59 | 		{ | 
 | 60 | 		  /* Send a SIGTTOU signal to our process group. | 
 | 61 |  | 
 | 62 | 		     We must remember here not to clobber ERR, since | 
 | 63 | 		     the loop condition below uses it to recall that | 
 | 64 | 		  we should retry after a stop.  */ | 
 | 65 |  | 
 | 66 | 		  __USEPORT (CTTYID, _hurd_sig_post (0, SIGTTOU, port)); | 
 | 67 | 		  /* XXX what to do if error here? */ | 
 | 68 |  | 
 | 69 | 		  /* At this point we should have just run the handler for | 
 | 70 | 		     SIGTTOU or resumed after being stopped.  Now this is | 
 | 71 | 		     still a "system call", so check to see if we should | 
 | 72 | 		  restart it.  */ | 
 | 73 | 		  __spin_lock (&ss->lock); | 
 | 74 | 		  if (!(ss->actions[SIGTTOU].sa_flags & SA_RESTART)) | 
 | 75 | 		    err = EINTR; | 
 | 76 | 		  __spin_unlock (&ss->lock); | 
 | 77 | 		} | 
 | 78 | 	    } | 
 | 79 | 	  /* If the last RPC generated a SIGTTOU, loop to try it again.  */ | 
 | 80 | 	} while (err == EBACKGROUND); | 
 | 81 |  | 
 | 82 |       return err; | 
 | 83 |     } | 
 | 84 | } |