root/lib/replace/getpass.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tcgetattr
  2. tcsetattr
  3. tcgetattr
  4. tcsetattr
  5. catch_signal
  6. gotintr_sig
  7. rep_getpass

   1 /* Copyright (C) 1992-1998 Free Software Foundation, Inc.
   2 This file is part of the GNU C Library.
   3 
   4 The GNU C Library is free software; you can redistribute it and/or
   5 modify it under the terms of the GNU Lesser General Public License as
   6 published by the Free Software Foundation; either version 3 of the
   7 License, or (at your option) any later version.
   8 
   9 The GNU C Library is distributed in the hope that it will be useful,
  10 but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12 Library General Public License for more details.
  13 
  14 You should have received a copy of the GNU Lesser General Public
  15 License along with the GNU C Library; see the file COPYING.LIB.  If
  16 not, see <http://www.gnu.org/licenses/>.  */
  17 
  18 /* Modified to use with samba by Jeremy Allison, 8th July 1995. */
  19 
  20 #include "replace.h"
  21 #include "system/filesys.h"
  22 #include "system/wait.h"
  23 #include "system/terminal.h"
  24 #include "system/passwd.h"
  25 
  26 /*
  27  * Define additional missing types
  28  */
  29 #ifndef HAVE_SIG_ATOMIC_T_TYPE
  30 typedef int sig_atomic_t;
  31 #endif
  32 
  33 #ifndef SIGCLD
  34 #define SIGCLD SIGCHLD
  35 #endif
  36 
  37 #ifndef SIGNAL_CAST
  38 #define SIGNAL_CAST (RETSIGTYPE (*)(int))
  39 #endif
  40 
  41 #ifdef SYSV_TERMIO 
  42 
  43 /* SYSTEM V TERMIO HANDLING */
  44 
  45 static struct termio t;
  46 
  47 #define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
  48 #define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
  49 #define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
  50 
  51 #ifndef TCSAFLUSH
  52 #define TCSAFLUSH 1
  53 #endif
  54 
  55 #ifndef TCSANOW
  56 #define TCSANOW 0
  57 #endif
  58 
  59 static int tcgetattr(int fd, struct termio *_t)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61         return ioctl(fd, TCGETA, _t);
  62 }
  63 
  64 static int tcsetattr(int fd, int flags, struct termio *_t)
     /* [<][>][^][v][top][bottom][index][help] */
  65 {
  66         if(flags & TCSAFLUSH)
  67                 ioctl(fd, TCFLSH, TCIOFLUSH);
  68         return ioctl(fd, TCSETS, _t);
  69 }
  70 
  71 #elif !defined(TCSAFLUSH)
  72 
  73 /* BSD TERMIO HANDLING */
  74 
  75 static struct sgttyb t;  
  76 
  77 #define ECHO_IS_ON(t) ((t).sg_flags & ECHO)
  78 #define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO)
  79 #define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO)
  80 
  81 #define TCSAFLUSH 1
  82 #define TCSANOW 0
  83 
  84 static int tcgetattr(int fd, struct sgttyb *_t)
     /* [<][>][^][v][top][bottom][index][help] */
  85 {
  86         return ioctl(fd, TIOCGETP, (char *)_t);
  87 }
  88 
  89 static int tcsetattr(int fd, int flags, struct sgttyb *_t)
     /* [<][>][^][v][top][bottom][index][help] */
  90 {
  91         return ioctl(fd, TIOCSETP, (char *)_t);
  92 }
  93 
  94 #else /* POSIX TERMIO HANDLING */
  95 #define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
  96 #define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
  97 #define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
  98 
  99 static struct termios t;
 100 #endif /* SYSV_TERMIO */
 101 
 102 static void catch_signal(int signum,void (*handler)(int ))
     /* [<][>][^][v][top][bottom][index][help] */
 103 {
 104 #ifdef HAVE_SIGACTION
 105         struct sigaction act;
 106         struct sigaction oldact;
 107 
 108         memset(&act, 0, sizeof(act));
 109 
 110         act.sa_handler = handler;
 111 #ifdef SA_RESTART
 112         /*
 113          * We *want* SIGALRM to interrupt a system call.
 114          */
 115         if(signum != SIGALRM)
 116                 act.sa_flags = SA_RESTART;
 117 #endif
 118         sigemptyset(&act.sa_mask);
 119         sigaddset(&act.sa_mask,signum);
 120         sigaction(signum,&act,&oldact);
 121 #else /* !HAVE_SIGACTION */
 122         /* FIXME: need to handle sigvec and systems with broken signal() */
 123         signal(signum, handler);
 124 #endif
 125 }
 126 
 127 static sig_atomic_t gotintr;
 128 static int in_fd = -1;
 129 
 130 /***************************************************************
 131  Signal function to tell us were ^C'ed.
 132 ****************************************************************/
 133 
 134 static void gotintr_sig(void)
     /* [<][>][^][v][top][bottom][index][help] */
 135 {
 136         gotintr = 1;
 137         if (in_fd != -1)
 138                 close(in_fd); /* Safe way to force a return. */
 139         in_fd = -1;
 140 }
 141 
 142 char *rep_getpass(const char *prompt)
     /* [<][>][^][v][top][bottom][index][help] */
 143 {
 144         FILE *in, *out;
 145         int echo_off;
 146         static char buf[256];
 147         static size_t bufsize = sizeof(buf);
 148         size_t nread;
 149 
 150         /* Catch problematic signals */
 151         catch_signal(SIGINT, SIGNAL_CAST gotintr_sig);
 152 
 153         /* Try to write to and read from the terminal if we can.
 154                 If we can't open the terminal, use stderr and stdin.  */
 155 
 156         in = fopen ("/dev/tty", "w+");
 157         if (in == NULL) {
 158                 in = stdin;
 159                 out = stderr;
 160         } else {
 161                 out = in;
 162         }
 163 
 164         setvbuf(in, NULL, _IONBF, 0);
 165 
 166         /* Turn echoing off if it is on now.  */
 167 
 168         if (tcgetattr (fileno (in), &t) == 0) {
 169                 if (ECHO_IS_ON(t)) {
 170                         TURN_ECHO_OFF(t);
 171                         echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0;
 172                         TURN_ECHO_ON(t);
 173                 } else {
 174                         echo_off = 0;
 175                 }
 176         } else {
 177                 echo_off = 0;
 178         }
 179 
 180         /* Write the prompt.  */
 181         fputs(prompt, out);
 182         fflush(out);
 183 
 184         /* Read the password.  */
 185         buf[0] = 0;
 186         if (!gotintr) {
 187                 in_fd = fileno(in);
 188                 if (fgets(buf, bufsize, in) == NULL) {
 189                         buf[0] = 0;
 190                 }
 191         }
 192         nread = strlen(buf);
 193         if (nread) {
 194                 if (buf[nread - 1] == '\n')
 195                         buf[nread - 1] = '\0';
 196         }
 197 
 198         /* Restore echoing.  */
 199         if (echo_off) {
 200                 if (gotintr && in_fd == -1) {
 201                         in = fopen ("/dev/tty", "w+");
 202                 }
 203                 if (in != NULL)
 204                         tcsetattr (fileno (in), TCSANOW, &t);
 205         }
 206 
 207         fprintf(out, "\n");
 208         fflush(out);
 209 
 210         if (in && in != stdin) /* We opened the terminal; now close it.  */
 211                 fclose(in);
 212 
 213         /* Catch problematic signals */
 214         catch_signal(SIGINT, SIGNAL_CAST SIG_DFL);
 215 
 216         if (gotintr) {
 217                 printf("Interupted by signal.\n");
 218                 fflush(stdout);
 219                 exit(1);
 220         }
 221         return buf;
 222 }

/* [<][>][^][v][top][bottom][index][help] */