Blame hurd/ctty-input.c

Packit Service 82fcde
/* _hurd_ctty_input -- Do an input RPC and generate SIGTTIN if necessary.
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <hurd.h>
Packit Service 82fcde
#include <hurd/signal.h>
Packit Service 82fcde
Packit Service 82fcde
/* Call *RPC on PORT and/or CTTY.  If a call on CTTY returns EBACKGROUND,
Packit Service 82fcde
   generate SIGTTIN or EIO as appropriate.  */
Packit Service 82fcde
Packit Service 82fcde
error_t
Packit Service 82fcde
_hurd_ctty_input (io_t port, io_t ctty, error_t (*rpc) (io_t))
Packit Service 82fcde
{
Packit Service 82fcde
  error_t err;
Packit Service 82fcde
Packit Service 82fcde
  if (ctty == MACH_PORT_NULL)
Packit Service 82fcde
    return (*rpc) (port);
Packit Service 82fcde
Packit Service 82fcde
  do
Packit Service 82fcde
    {
Packit Service 82fcde
      err = (*rpc) (ctty);
Packit Service 82fcde
      if (err == EBACKGROUND)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* We are a background job and tried to read from the tty.
Packit Service 82fcde
	     We should probably get a SIGTTIN signal.  */
Packit Service 82fcde
	  if (_hurd_orphaned)
Packit Service 82fcde
	    /* Our process group is orphaned.  Don't stop; just fail.  */
Packit Service 82fcde
	    err = EIO;
Packit Service 82fcde
	  else
Packit Service 82fcde
	    {
Packit Service 82fcde
	      struct hurd_sigstate *ss = _hurd_self_sigstate ();
Packit Service 82fcde
	      __spin_lock (&ss->lock);
Packit Service 82fcde
	      if (__sigismember (&ss->blocked, SIGTTIN) ||
Packit Service 82fcde
		  ss->actions[SIGTTIN].sa_handler == SIG_IGN)
Packit Service 82fcde
		/* We are blocking or ignoring SIGTTIN.  Just fail.  */
Packit Service 82fcde
		err = EIO;
Packit Service 82fcde
	      __spin_unlock (&ss->lock);
Packit Service 82fcde
Packit Service 82fcde
	      if (err == EBACKGROUND)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* Send a SIGTTIN signal to our process group.
Packit Service 82fcde
Packit Service 82fcde
		     We must remember here not to clobber ERR, since
Packit Service 82fcde
		     the loop condition below uses it to recall that
Packit Service 82fcde
		  we should retry after a stop.  */
Packit Service 82fcde
Packit Service 82fcde
		  __USEPORT (CTTYID, _hurd_sig_post (0, SIGTTIN, port));
Packit Service 82fcde
		  /* XXX what to do if error here? */
Packit Service 82fcde
Packit Service 82fcde
		  /* At this point we should have just run the handler for
Packit Service 82fcde
		     SIGTTIN or resumed after being stopped.  Now this is
Packit Service 82fcde
		     still a "system call", so check to see if we should
Packit Service 82fcde
		  restart it.  */
Packit Service 82fcde
		  __spin_lock (&ss->lock);
Packit Service 82fcde
		  if (!(ss->actions[SIGTTIN].sa_flags & SA_RESTART))
Packit Service 82fcde
		    err = EINTR;
Packit Service 82fcde
		  __spin_unlock (&ss->lock);
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
      /* If the last RPC generated a SIGTTIN, loop to try it again.  */
Packit Service 82fcde
    } while (err == EBACKGROUND);
Packit Service 82fcde
Packit Service 82fcde
  return err;
Packit Service 82fcde
}