2006-09-18 22:49:20 +00: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 04:04:46 +00:00
modify it under the terms of the GNU Lesser General Public License as
2007-07-10 01:52:05 +00:00
published by the Free Software Foundation ; either version 3 of the
2006-09-18 22:49:20 +00: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 04:04:46 +00:00
You should have received a copy of the GNU Lesser General Public
2006-09-18 22:49:20 +00:00
License along with the GNU C Library ; see the file COPYING . LIB . If
2007-07-10 05:23:25 +00:00
not , see < http : //www.gnu.org/licenses/>. */
2006-09-18 22:49:20 +00:00
/* Modified to use with samba by Jeremy Allison, 8th July 1995. */
# include "replace.h"
2007-10-15 15:41:06 +02:00
# include "system/filesys.h"
# include "system/wait.h"
# include "system/terminal.h"
2007-10-27 21:15:07 +02:00
# include "system/passwd.h"
2006-09-18 22:49:20 +00:00
/*
* Define additional missing types
*/
# ifndef HAVE_SIG_ATOMIC_T_TYPE
typedef int sig_atomic_t ;
# endif
# ifndef SIGCLD
# define SIGCLD SIGCHLD
# endif
# ifndef SIGNAL_CAST
# define SIGNAL_CAST (RETSIGTYPE (*)(int))
# 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 */
static void catch_signal ( int signum , void ( * handler ) ( int ) )
{
# 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 11:02:24 +02:00
signal ( signum , handler ) ;
2006-09-18 22:49:20 +00:00
# endif
}
2007-10-05 16:20:38 +02:00
static sig_atomic_t gotintr ;
static int in_fd = - 1 ;
/***************************************************************
Signal function to tell us were ^ C ' ed .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void gotintr_sig ( void )
{
gotintr = 1 ;
if ( in_fd ! = - 1 )
close ( in_fd ) ; /* Safe way to force a return. */
in_fd = - 1 ;
}
2007-10-15 15:42:13 +02:00
char * rep_getpass ( const char * prompt )
2006-09-18 22:49:20 +00:00
{
2007-10-05 15:55:19 +02:00
FILE * in , * out ;
int echo_off ;
static char buf [ 256 ] ;
static size_t bufsize = sizeof ( buf ) ;
size_t nread ;
/* Catch problematic signals */
2007-10-05 16:20:38 +02:00
catch_signal ( SIGINT , SIGNAL_CAST gotintr_sig ) ;
2007-10-05 15:55:19 +02: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-18 22:49:20 +00:00
}
2007-10-05 15:55:19 +02: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 16:20:38 +02:00
if ( ! gotintr ) {
in_fd = fileno ( in ) ;
2008-02-23 10:42:43 +01:00
if ( fgets ( buf , bufsize , in ) = = NULL ) {
buf [ 0 ] = 0 ;
}
2007-10-05 16:20:38 +02:00
}
2007-10-05 15:55:19 +02:00
nread = strlen ( buf ) ;
2006-06-15 05:32:21 +00:00
if ( nread ) {
if ( buf [ nread - 1 ] = = ' \n ' )
buf [ nread - 1 ] = ' \0 ' ;
}
2007-10-05 15:55:19 +02:00
/* Restore echoing. */
2007-10-05 16:20:38 +02:00
if ( echo_off ) {
2008-05-09 14:51:45 -07:00
if ( gotintr & & in_fd = = - 1 ) {
2007-10-05 16:20:38 +02:00
in = fopen ( " /dev/tty " , " w+ " ) ;
2008-05-09 14:51:45 -07:00
}
2007-10-05 16:20:38 +02:00
if ( in ! = NULL )
tcsetattr ( fileno ( in ) , TCSANOW , & t ) ;
}
2007-10-05 15:55:19 +02:00
2003-10-23 13:47:17 +00:00
fprintf ( out , " \n " ) ;
fflush ( out ) ;
2006-06-16 23:07:42 +00:00
if ( in & & in ! = stdin ) /* We opened the terminal; now close it. */
2007-10-05 15:55:19 +02:00
fclose ( in ) ;
/* Catch problematic signals */
catch_signal ( SIGINT , SIGNAL_CAST SIG_DFL ) ;
2007-10-05 16:20:38 +02:00
if ( gotintr ) {
printf ( " Interupted by signal. \n " ) ;
fflush ( stdout ) ;
exit ( 1 ) ;
}
2007-10-05 15:55:19 +02:00
return buf ;
2006-09-18 22:49:20 +00:00
}