Logo Search packages:      
Sourcecode: fbgetty version File versions  Download package

vt.c

/*
 * fbgetty 
 * Copyright (C) 1999 2000 2001 Yann Droneaud <ydroneaud@meuh.eu.org>. 
 *
 * fbgetty 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 2, or (at your option)
 * any later version.
 *
 * fbgetty 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, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
 *
 */

#include <fbgetty/global.h>

#ifdef USE_VT_SWITCHING

#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include <errno.h>
#include <string.h>

#ifdef __linux__
#ifdef HAVE_LINUX_VT_H
#include <linux/vt.h>
#endif
#endif

#ifdef __FreeBSD__
#ifdef HAVE_MACHINE_CONSOLE_H
#include <machine/console.h>
#endif
#endif

#include <fbgetty/options.h>
#include <fbgetty/errors.h>
#include <fbgetty/prompt.h>
#include <fbgetty/vt.h>

static RETSIGTYPE vt_handler(int sig);
static volatile int vt_active;

/* return the state */
int
vt_isactive(void)
{
  return vt_active;
}

/*
 * only install the handler
 * use vt_handler_init() for the first time, then reinstall handler with this function
 */
int 
vt_handler_install(void)
{
  sigset_t set_new;
  sigset_t set_old;

  struct vt_mode vt_mode;
  struct sigaction sa_new;

  /* block SIGUSR1 */
  sigemptyset(&set_new);
  sigaddset(&set_new, SIGUSR1);
  sigprocmask(SIG_BLOCK, &set_new, &set_old); /* we don't want to get SIGUSR1 */

  /* install handler for SIGUSR1 */
  sa_new.sa_handler = vt_handler;
  sigemptyset(&sa_new.sa_mask);
  sa_new.sa_flags = SA_RESTART;
  if (sigaction(SIGUSR1, &sa_new, NULL) == -1)
    error("Can't set handler for SIGUSR1: %s", strerror(errno));

  /* set up the virtual terminal switching */
  if (ioctl(STDIN_FILENO, VT_GETMODE, &vt_mode) == -1)
    fatal_error ("ioctl VT_GETMODE failed: %s", strerror(errno));
  
  vt_mode.mode = VT_PROCESS; /* the switching between is handle by the program */
  vt_mode.relsig = SIGUSR1;  /* signal sent when another VT is activated */
  vt_mode.acqsig = SIGUSR1;  /* signal sent when VT is activated */

  if (ioctl(STDIN_FILENO, VT_SETMODE, &vt_mode) == -1)
    fatal_error("ioctl VT_SETMODE failed: %s", strerror(errno));

  sigprocmask(SIG_SETMASK, &set_old, NULL); /* we can now safely get SIGUSR1 */

  return 0;
}

/*
 * init the Virtual Terminal state and install the handler
 */
int
vt_handler_init(void)
{
  struct vt_stat vt_stat;

  /* get current state of vt */
  if (ioctl(STDIN_FILENO, VT_GETSTATE, &vt_stat) == -1)
    fatal_error("ioctl VT_GETSTATE failed: %s", strerror(errno));

  vt_active = (fgoptions->tty_number != vt_stat.v_active) ? FALSE : TRUE;

#ifdef FB_GETTY_DEBUG
   error("tty number: %d",fgoptions->tty_number);
   error("vt active: %d",vt_stat.v_active);   
#endif

   vt_handler_install();

   return 0;
}

/* SIGUSR handler */
static RETSIGTYPE 
vt_handler(int sig)
{
  sigset_t set_new;
  sigset_t set_old;

#ifdef FB_GETTY_DEBUG
  error("signal %s received",sys_siglist[sig]); 
#endif

  switch (vt_active)
    {
    case FALSE: /* fbgetty activated */
      vt_active = TRUE;

      sigemptyset(&set_new);
      sigaddset(&set_new, SIGUSR1);
      sigprocmask(SIG_UNBLOCK, &set_new, &set_old); /* we want to get SIGUSR1 */

      /* redraw the screen (show issue, prompt) */
      refresh_screen();

      vt_handler_install(); /* resetup vt switch
                         reinstall handler
                         -> prevent changes made by program in issue */
      /* restore sigmask */
      sigprocmask(SIG_SETMASK, &set_old, NULL); 

#ifdef FB_GETTY_DEBUG
      error("- tty acquired");
#endif
      break;
      
    case TRUE: /* Leave vt */
      vt_active = FALSE;
      if (ioctl(STDIN_FILENO, VT_RELDISP, 1) == -1)
      fatal_error("ioctl VT_RELDISP: %s", strerror(errno));

#ifdef FB_GETTY_DEBUG
      error("- leaving console");
#endif
      break;
      
    default: /* this case could not happen,
            * handler is installed by install_vt_handler()
            * that also set vt_state to true or false ! */
      /* get state */
      vt_handler_init(); /* resetup vt switch
                         reinstall handler */

      vt_handler(sig); /* then redo the job */ 
      break;
      
    }

}

/* do some cleanning */
void 
vt_handler_restore(void)
{
  struct vt_mode vt_mode;
  struct sigaction sa_new;

  /* first set vt switch to auto */
  /* restore default vt handling */
  if (ioctl(STDIN_FILENO, VT_GETMODE, &vt_mode) == -1)
    {
      error("ioctl VT_GETMODE failed: %s", strerror(errno));
    }  
  else
    {
      vt_mode.mode = VT_AUTO;
      
      if (ioctl(STDIN_FILENO, VT_SETMODE, &vt_mode) == -1)
      error("ioctl VT_SETMODE failed: %s", strerror(errno));
    }

  /* then, sigusr1 is now unused */

  sa_new.sa_handler = SIG_DFL;
  sigemptyset(&sa_new.sa_mask);
  sa_new.sa_flags = 0;

  if (sigaction(SIGUSR1, &sa_new, NULL) == -1)   /* restore signal handling */
    error("Can't restore handler for SIGUSR1: %s", strerror(errno));

}
#endif /* USE_VT_SWITCHING */

Generated by  Doxygen 1.6.0   Back to index