Diff for /embedaddon/sudo/common/term.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2013/07/22 10:46:11 version 1.1.1.4, 2014/06/15 16:12:54
Line 1 Line 1
 /*  /*
 * Copyright (c) 2011-2012 Todd C. Miller <Todd.Miller@courtesan.com> * Copyright (c) 2011-2014 Todd C. Miller <Todd.Miller@courtesan.com>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 35 Line 35
 #ifdef HAVE_STRINGS_H  #ifdef HAVE_STRINGS_H
 # include <strings.h>  # include <strings.h>
 #endif /* HAVE_STRINGS_H */  #endif /* HAVE_STRINGS_H */
   #include <errno.h>
   #include <signal.h>
 #include <termios.h>  #include <termios.h>
   #include <unistd.h>
   
 #include "missing.h"  #include "missing.h"
 #include "sudo_debug.h"  #include "sudo_debug.h"
   #include "sudo_util.h"
   
 #ifndef TCSASOFT  #ifndef TCSASOFT
 # define TCSASOFT       0  # define TCSASOFT       0
Line 63 Line 67
   
 static struct termios term, oterm;  static struct termios term, oterm;
 static int changed;  static int changed;
   
   /* tgetpass() needs to know the erase and kill chars for cbreak mode. */
 int term_erase;  int term_erase;
 int term_kill;  int term_kill;
   
intstatic volatile sig_atomic_t got_sigttou;
term_restore(int fd, int flush)
 /*
  * SIGTTOU signal handler for term_restore that just sets a flag.
  */
 static void sigttou(int signo)
 {  {
       got_sigttou = 1;
   }
   
   /*
    * Like tcsetattr() but restarts on EINTR _except_ for SIGTTOU.
    * Returns 0 on success or -1 on failure, setting errno.
    * Sets got_sigttou on failure if interrupted by SIGTTOU.
    */
   static int
   tcsetattr_nobg(int fd, int flags, struct termios *tp)
   {
       sigaction_t sa, osa;
       int rc;
   
       /*
        * If we receive SIGTTOU from tcsetattr() it means we are
        * not in the foreground process group.
        * This should be less racy than using tcgetpgrp().
        */
       memset(&sa, 0, sizeof(sa));
       sigemptyset(&sa.sa_mask);
       sa.sa_handler = sigttou;
       got_sigttou = 0;
       sigaction(SIGTTOU, &sa, &osa);
       do {
           rc = tcsetattr(fd, flags, tp);
       } while (rc != 0 && errno == EINTR && !got_sigttou);
       sigaction(SIGTTOU, &osa, NULL);
   
       return rc;
   }
   
   /*
    * Restore saved terminal settings if we are in the foreground process group.
    * Returns true on success or false on failure.
    */
   bool
   term_restore(int fd, bool flush)
   {
     debug_decl(term_restore, SUDO_DEBUG_UTIL)      debug_decl(term_restore, SUDO_DEBUG_UTIL)
   
     if (changed) {      if (changed) {
        int flags = TCSASOFT;        const int flags = flush ? (TCSASOFT|TCSAFLUSH) : (TCSASOFT|TCSADRAIN);
        flags |= flush ? TCSAFLUSH : TCSADRAIN;        if (tcsetattr_nobg(fd, flags, &oterm) != 0)
        if (tcsetattr(fd, flags, &oterm) != 0)            debug_return_bool(false);
            debug_return_int(0); 
         changed = 0;          changed = 0;
     }      }
    debug_return_int(1);    debug_return_bool(true);
 }  }
   
int/*
  * Disable terminal echo.
  * Returns true on success or false on failure.
  */
 bool
 term_noecho(int fd)  term_noecho(int fd)
 {  {
     debug_decl(term_noecho, SUDO_DEBUG_UTIL)      debug_decl(term_noecho, SUDO_DEBUG_UTIL)
   
   again:
     if (!changed && tcgetattr(fd, &oterm) != 0)      if (!changed && tcgetattr(fd, &oterm) != 0)
        debug_return_int(0);        debug_return_bool(false);
     (void) memcpy(&term, &oterm, sizeof(term));      (void) memcpy(&term, &oterm, sizeof(term));
     CLR(term.c_lflag, ECHO|ECHONL);      CLR(term.c_lflag, ECHO|ECHONL);
 #ifdef VSTATUS  #ifdef VSTATUS
     term.c_cc[VSTATUS] = _POSIX_VDISABLE;      term.c_cc[VSTATUS] = _POSIX_VDISABLE;
 #endif  #endif
    if (tcsetattr(fd, TCSADRAIN|TCSASOFT, &term) == 0) {    if (tcsetattr_nobg(fd, TCSADRAIN|TCSASOFT, &term) == 0) {
         changed = 1;          changed = 1;
        debug_return_int(1);        debug_return_bool(true);
     }      }
    debug_return_int(0);    if (got_sigttou) {
         /* We were in the background, so oterm is probably bogus. */
         kill(getpid(), SIGTTOU);
         goto again;
     }
     debug_return_bool(false);
 }  }
   
int/*
  * Set terminal to raw mode.
  * Returns true on success or false on failure.
  */
 bool
 term_raw(int fd, int isig)  term_raw(int fd, int isig)
 {  {
     struct termios term;      struct termios term;
     debug_decl(term_raw, SUDO_DEBUG_UTIL)      debug_decl(term_raw, SUDO_DEBUG_UTIL)
   
   again:
     if (!changed && tcgetattr(fd, &oterm) != 0)      if (!changed && tcgetattr(fd, &oterm) != 0)
         return 0;          return 0;
     (void) memcpy(&term, &oterm, sizeof(term));      (void) memcpy(&term, &oterm, sizeof(term));
Line 117  term_raw(int fd, int isig) Line 180  term_raw(int fd, int isig)
     CLR(term.c_lflag, ECHO | ICANON | ISIG | IEXTEN);      CLR(term.c_lflag, ECHO | ICANON | ISIG | IEXTEN);
     if (isig)      if (isig)
         SET(term.c_lflag, ISIG);          SET(term.c_lflag, ISIG);
    if (tcsetattr(fd, TCSADRAIN|TCSASOFT, &term) == 0) {    if (tcsetattr_nobg(fd, TCSADRAIN|TCSASOFT, &term) == 0) {
         changed = 1;          changed = 1;
        debug_return_int(1);        debug_return_bool(true);
     }      }
    debug_return_int(0);    if (got_sigttou) {
         /* We were in the background, so oterm is probably bogus. */
         kill(getpid(), SIGTTOU);
         goto again;
     }
     debug_return_bool(false);
 }  }
   
int/*
  * Set terminal to cbreak mode.
  * Returns true on success or false on failure.
  */
 bool
 term_cbreak(int fd)  term_cbreak(int fd)
 {  {
     debug_decl(term_cbreak, SUDO_DEBUG_UTIL)      debug_decl(term_cbreak, SUDO_DEBUG_UTIL)
   
   again:
     if (!changed && tcgetattr(fd, &oterm) != 0)      if (!changed && tcgetattr(fd, &oterm) != 0)
         return 0;          return 0;
     (void) memcpy(&term, &oterm, sizeof(term));      (void) memcpy(&term, &oterm, sizeof(term));
     /* Set terminal to half-cooked mode */      /* Set terminal to half-cooked mode */
     term.c_cc[VMIN] = 1;      term.c_cc[VMIN] = 1;
     term.c_cc[VTIME] = 0;      term.c_cc[VTIME] = 0;
       /* cppcheck-suppress redundantAssignment */
     CLR(term.c_lflag, ECHO | ECHONL | ICANON | IEXTEN);      CLR(term.c_lflag, ECHO | ECHONL | ICANON | IEXTEN);
       /* cppcheck-suppress redundantAssignment */
     SET(term.c_lflag, ISIG);      SET(term.c_lflag, ISIG);
 #ifdef VSTATUS  #ifdef VSTATUS
     term.c_cc[VSTATUS] = _POSIX_VDISABLE;      term.c_cc[VSTATUS] = _POSIX_VDISABLE;
 #endif  #endif
    if (tcsetattr(fd, TCSADRAIN|TCSASOFT, &term) == 0) {    if (tcsetattr_nobg(fd, TCSADRAIN|TCSASOFT, &term) == 0) {
         term_erase = term.c_cc[VERASE];          term_erase = term.c_cc[VERASE];
         term_kill = term.c_cc[VKILL];          term_kill = term.c_cc[VKILL];
         changed = 1;          changed = 1;
        debug_return_int(1);        debug_return_bool(true);
     }      }
    debug_return_int(0);    if (got_sigttou) {
         /* We were in the background, so oterm is probably bogus. */
         kill(getpid(), SIGTTOU);
         goto again;
     }
     debug_return_bool(false);
 }  }
   
int/*
  * Copy terminal settings from one descriptor to another.
  * Returns true on success or false on failure.
  */
 bool
 term_copy(int src, int dst)  term_copy(int src, int dst)
 {  {
     struct termios tt;      struct termios tt;
     debug_decl(term_copy, SUDO_DEBUG_UTIL)      debug_decl(term_copy, SUDO_DEBUG_UTIL)
   
   again:
     if (tcgetattr(src, &tt) != 0)      if (tcgetattr(src, &tt) != 0)
        debug_return_int(0);        debug_return_bool(false);
    if (tcsetattr(dst, TCSANOW|TCSASOFT, &tt) != 0)    if (tcsetattr_nobg(dst, TCSANOW|TCSASOFT, &tt) == 0)
        debug_return_int(0);        debug_return_bool(true);
    debug_return_int(1);    if (got_sigttou) {
         /* We were in the background, so oterm is probably bogus. */
         kill(getpid(), SIGTTOU);
         goto again;
     }
     debug_return_bool(false);
 }  }

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>