Skip to content
This repository
Fetching contributors…

Cannot retrieve contributors at this time

file 75 lines (62 sloc) 1.972 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
/*
Mosh: the mobile shell
Copyright 2012 Keith Winstein

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/signalfd.h>

#include "fatal_assert.h"

static sigset_t caught;
static int fd = -1;

#define SIGNALFD_FLAGS ( SFD_NONBLOCK | SFD_CLOEXEC )

int sigfd_init( void )
{
  if ( fd != -1 ) {
    errno = EBUSY;
    return -1;
  }
  sigemptyset( &caught );
  fd = signalfd( -1, &caught, SIGNALFD_FLAGS );
  return fd;
}

int sigfd_trap( int sig )
{
  /* The callers all fatal_assert on error, so we can do the same here.
We still return 'int' in order to have the same API as libstddjb. */
  fatal_assert( 0 <= fd );
  fatal_assert( 0 <= sigaddset( &caught, sig ) );
  fatal_assert( 0 <= sigprocmask( SIG_BLOCK, &caught, NULL ) );
  fatal_assert( 0 <= signalfd( fd, &caught, SIGNALFD_FLAGS ) );
  return 0;
}

int sigfd_read( void )
{
  int r;
  struct signalfd_siginfo si;

  do {
    r = read( fd, &si, sizeof( si ) );
  } while ( ( r == -1 ) && ( errno == EINTR ) );

  if ( r == -1 ) {
    if ( errno == EAGAIN || errno == EWOULDBLOCK )
      /* No signal available */
      return 0;
    return -1;
  } else if ( r != sizeof( si ) ) {
    /* Should never happen?
Includes r = 0, i.e. end of file */
    errno = EPIPE;
    return -1;
  }

  return (int) si.ssi_signo;
}
Something went wrong with that request. Please try again.