#include "config.h"
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <stdlib.h>
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include "fetchmail.h"
#include "i18n.h"
#define INPUT_BUF_SIZE PASSWORDLEN
#if defined(HAVE_TERMIOS_H) && defined(HAVE_TCSETATTR)
# include <termios.h>
#else
#if defined(HAVE_TERMIO_H)
# include <sys/ioctl.h>
# include <termio.h>
#else
#if defined(HAVE_SGTTY_H)
# include <sgtty.h>
#endif
#endif
#endif
static int ttyfd;
#if defined(HAVE_TCSETATTR)
static struct termios termb;
static tcflag_t flags;
#else
#if defined(HAVE_TERMIO_H)
static struct termio termb;
static unsigned short flags;
#else
#if defined(HAVE_STTY)
static struct sgttyb ttyb;
static int flags;
#endif
#endif
#endif
void static save_tty_state(void);
void static disable_tty_echo(void);
void static restore_tty_state(void);
static RETSIGTYPE sigint_handler(int);
char *fm_getpassword(prompt)
char *prompt;
{
#if !(defined(HAVE_TCSETATTR) || defined(HAVE_TERMIO_H) || defined(HAVE_STTY))
#if defined(HAVE_GETPASS)
char *getpass();
return getpass(prompt);
#else
fputs(GT_("ERROR: no support for getpassword() routine\n"),stderr);
exit(1);
#endif
#else
register char *p;
register int c;
FILE *fi;
static char pbuf[INPUT_BUF_SIZE];
RETSIGTYPE (*sig)(int) = 0;
RETSIGTYPE sigint_handler(int);
int istty = isatty(0);
if (istty)
{
if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL)
fi = stdin;
else
setbuf(fi, (char *)NULL);
}
else
fi = stdin;
ttyfd = fileno(fi);
if (istty)
{
save_tty_state();
sig = signal(SIGINT, sigint_handler);
disable_tty_echo();
fprintf(stderr, "%s", prompt);
}
for (p = pbuf; (c = getc(fi))!='\n' && c!=EOF;)
{
if (p < &pbuf[INPUT_BUF_SIZE - 1])
*p++ = c;
}
*p = '\0';
if (fi != stdin)
fprintf(stderr, "\n");
if (istty)
{
restore_tty_state();
signal(SIGINT, sig);
}
if (fi != stdin)
fclose(fi);
return(pbuf);
#endif
}
static void save_tty_state (void)
{
#if defined(HAVE_TCSETATTR)
tcgetattr(ttyfd, &termb);
flags = termb.c_lflag;
#else
#if defined(HAVE_TERMIO_H)
ioctl(ttyfd, TCGETA, (char *) &termb);
flags = termb.c_lflag;
#else
gtty(ttyfd, &ttyb);
flags = ttyb.sg_flags;
#endif
#endif
}
static void disable_tty_echo(void)
{
#if defined(HAVE_TCSETATTR)
termb.c_lflag &= ~ECHO;
tcsetattr(ttyfd, TCSAFLUSH, &termb);
#else
#if defined(HAVE_TERMIO_H)
termb.c_lflag &= ~ECHO;
ioctl(ttyfd, TCSETA, (char *) &termb);
#else
ttyb.sg_flags &= ~ECHO;
stty(ttyfd, &ttyb);
#endif
#endif
}
static void restore_tty_state(void)
{
#if defined(HAVE_TCSETATTR)
termb.c_lflag = flags;
tcsetattr(ttyfd, TCSAFLUSH, &termb);
#else
#if defined(HAVE_TERMIO_H)
termb.c_lflag = flags;
ioctl(ttyfd, TCSETA, (char *) &termb);
#else
ttyb.sg_flags = flags;
stty(ttyfd, &ttyb);
#endif
#endif
}
static RETSIGTYPE sigint_handler(int signum)
{
restore_tty_state();
report(stderr, GT_("\nCaught SIGINT... bailing out.\n"));
exit(1);
}