2006-09-19 02:49:20 +04:00
/* Copyright (C) 1992-1998 Free Software Foundation, Inc.
This file is part of the GNU C Library .
The GNU C Library is free software ; you can redistribute it and / or
2007-07-10 08:04:46 +04:00
modify it under the terms of the GNU Lesser General Public License as
2007-07-10 05:52:05 +04:00
published by the Free Software Foundation ; either version 3 of the
2006-09-19 02:49:20 +04:00
License , or ( at your option ) any later version .
The GNU C Library 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
Library General Public License for more details .
2007-07-10 08:04:46 +04:00
You should have received a copy of the GNU Lesser General Public
2006-09-19 02:49:20 +04:00
License along with the GNU C Library ; see the file COPYING . LIB . If
2007-07-10 09:23:25 +04:00
not , see < http : //www.gnu.org/licenses/>. */
2006-09-19 02:49:20 +04:00
/* Modified to use with samba by Jeremy Allison, 8th July 1995. */
# include "replace.h"
2007-10-15 17:41:06 +04:00
# include "system/filesys.h"
# include "system/wait.h"
# include "system/terminal.h"
2007-10-27 23:15:07 +04:00
# include "system/passwd.h"
2006-09-19 02:49:20 +04:00
/*
* Define additional missing types
*/
# ifndef HAVE_SIG_ATOMIC_T_TYPE
typedef int sig_atomic_t ;
# endif
# ifndef SIGCLD
# define SIGCLD SIGCHLD
# endif
# ifdef SYSV_TERMIO
/* SYSTEM V TERMIO HANDLING */
static struct termio t ;
# define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
# define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
# define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
# ifndef TCSAFLUSH
# define TCSAFLUSH 1
# endif
# ifndef TCSANOW
# define TCSANOW 0
# endif
static int tcgetattr ( int fd , struct termio * _t )
{
return ioctl ( fd , TCGETA , _t ) ;
}
static int tcsetattr ( int fd , int flags , struct termio * _t )
{
if ( flags & TCSAFLUSH )
ioctl ( fd , TCFLSH , TCIOFLUSH ) ;
return ioctl ( fd , TCSETS , _t ) ;
}
# elif !defined(TCSAFLUSH)
/* BSD TERMIO HANDLING */
static struct sgttyb t ;
# define ECHO_IS_ON(t) ((t).sg_flags & ECHO)
# define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO)
# define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO)
# define TCSAFLUSH 1
# define TCSANOW 0
static int tcgetattr ( int fd , struct sgttyb * _t )
{
return ioctl ( fd , TIOCGETP , ( char * ) _t ) ;
}
static int tcsetattr ( int fd , int flags , struct sgttyb * _t )
{
return ioctl ( fd , TIOCSETP , ( char * ) _t ) ;
}
# else /* POSIX TERMIO HANDLING */
# define ECHO_IS_ON(t) ((t).c_lflag & ECHO)
# define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO)
# define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO)
static struct termios t ;
# endif /* SYSV_TERMIO */
2010-02-19 13:27:56 +03:00
static void catch_signal ( int signum , void ( * handler ) ( int ) )
2006-09-19 02:49:20 +04:00
{
# ifdef HAVE_SIGACTION
struct sigaction act ;
struct sigaction oldact ;
memset ( & act , 0 , sizeof ( act ) ) ;
act . sa_handler = handler ;
# ifdef SA_RESTART
/*
* We * want * SIGALRM to interrupt a system call .
*/
if ( signum ! = SIGALRM )
act . sa_flags = SA_RESTART ;
# endif
sigemptyset ( & act . sa_mask ) ;
sigaddset ( & act . sa_mask , signum ) ;
sigaction ( signum , & act , & oldact ) ;
# else /* !HAVE_SIGACTION */
/* FIXME: need to handle sigvec and systems with broken signal() */
2007-10-15 13:02:24 +04:00
signal ( signum , handler ) ;
2006-09-19 02:49:20 +04:00
# endif
}
2007-10-05 18:20:38 +04:00
static sig_atomic_t gotintr ;
static int in_fd = - 1 ;
/***************************************************************
Signal function to tell us were ^ C ' ed .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-02-19 13:27:56 +03:00
static void gotintr_sig ( int signum )
2007-10-05 18:20:38 +04:00
{
gotintr = 1 ;
if ( in_fd ! = - 1 )
close ( in_fd ) ; /* Safe way to force a return. */
in_fd = - 1 ;
}
2007-10-15 17:42:13 +04:00
char * rep_getpass ( const char * prompt )
2006-09-19 02:49:20 +04:00
{
2007-10-05 17:55:19 +04:00
FILE * in , * out ;
int echo_off ;
static char buf [ 256 ] ;
static size_t bufsize = sizeof ( buf ) ;
size_t nread ;
/* Catch problematic signals */
2010-02-19 13:27:56 +03:00
catch_signal ( SIGINT , gotintr_sig ) ;
2007-10-05 17:55:19 +04:00
/* Try to write to and read from the terminal if we can.
If we can ' t open the terminal , use stderr and stdin . */
in = fopen ( " /dev/tty " , " w+ " ) ;
if ( in = = NULL ) {
in = stdin ;
out = stderr ;
} else {
out = in ;
2006-09-19 02:49:20 +04:00
}
2007-10-05 17:55:19 +04:00
setvbuf ( in , NULL , _IONBF , 0 ) ;
/* Turn echoing off if it is on now. */
if ( tcgetattr ( fileno ( in ) , & t ) = = 0 ) {
if ( ECHO_IS_ON ( t ) ) {
TURN_ECHO_OFF ( t ) ;
echo_off = tcsetattr ( fileno ( in ) , TCSAFLUSH , & t ) = = 0 ;
TURN_ECHO_ON ( t ) ;
} else {
echo_off = 0 ;
}
} else {
echo_off = 0 ;
}
/* Write the prompt. */
fputs ( prompt , out ) ;
fflush ( out ) ;
/* Read the password. */
buf [ 0 ] = 0 ;
2007-10-05 18:20:38 +04:00
if ( ! gotintr ) {
in_fd = fileno ( in ) ;
2008-02-23 12:42:43 +03:00
if ( fgets ( buf , bufsize , in ) = = NULL ) {
buf [ 0 ] = 0 ;
}
2007-10-05 18:20:38 +04:00
}
2007-10-05 17:55:19 +04:00
nread = strlen ( buf ) ;
2006-06-15 09:32:21 +04:00
if ( nread ) {
if ( buf [ nread - 1 ] = = ' \n ' )
buf [ nread - 1 ] = ' \0 ' ;
}
2007-10-05 17:55:19 +04:00
/* Restore echoing. */
2007-10-05 18:20:38 +04:00
if ( echo_off ) {
2008-05-10 01:51:45 +04:00
if ( gotintr & & in_fd = = - 1 ) {
2007-10-05 18:20:38 +04:00
in = fopen ( " /dev/tty " , " w+ " ) ;
2008-05-10 01:51:45 +04:00
}
2007-10-05 18:20:38 +04:00
if ( in ! = NULL )
tcsetattr ( fileno ( in ) , TCSANOW , & t ) ;
}
2007-10-05 17:55:19 +04:00
2003-10-23 17:47:17 +04:00
fprintf ( out , " \n " ) ;
fflush ( out ) ;
2006-06-17 03:07:42 +04:00
if ( in & & in ! = stdin ) /* We opened the terminal; now close it. */
2007-10-05 17:55:19 +04:00
fclose ( in ) ;
/* Catch problematic signals */
2010-02-19 13:27:56 +03:00
catch_signal ( SIGINT , SIG_DFL ) ;
2007-10-05 17:55:19 +04:00
2007-10-05 18:20:38 +04:00
if ( gotintr ) {
2010-02-21 08:35:10 +03:00
printf ( " Interrupted by signal. \n " ) ;
2007-10-05 18:20:38 +04:00
fflush ( stdout ) ;
exit ( 1 ) ;
}
2007-10-05 17:55:19 +04:00
return buf ;
2006-09-19 02:49:20 +04:00
}