From 12a77d2c4e2b7da26b052b5a19d68cd6935e449d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=BE=D0=BC=D0=B0=D0=BD=20=D0=94=D0=BE=D0=BD=D1=87=D0?= =?UTF-8?q?=B5=D0=BD=D0=BA=D0=BE?= Date: Mon, 6 May 2013 21:36:54 +0400 Subject: [PATCH 3/4] Add an implementation of getpass for systems that lack one. --- configure.ac | 2 + lib/getpass.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ rsync.h | 4 +++ 3 files changed, 75 insertions(+), 0 deletions(-) create mode 100644 lib/getpass.c diff --git a/configure.ac b/configure.ac index a73fce6..9c7b411 100644 --- a/configure.ac +++ b/configure.ac @@ -749,6 +749,8 @@ if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then AC_DEFINE(HAVE_SOCKETPAIR, 1, [Define to 1 if you have the "socketpair" function]) fi +AC_CHECK_FUNCS(getpass, , [AC_LIBOBJ(lib/getpass)]) + if test x"$with_included_popt" != x"yes"; then AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes]) fi diff --git a/lib/getpass.c b/lib/getpass.c new file mode 100644 index 0000000..07d0eaa --- /dev/null +++ b/lib/getpass.c @@ -0,0 +1,69 @@ +/* + * An implementation of getpass for systems that lack one. + * + * Copyright (C) 2013 Roman Donchenko + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, visit the http://fsf.org website. + */ + +#include +#include +#include + +#include "rsync.h" + +char *getpass(const char *prompt) +{ + static char password[256]; + + BOOL tty_changed = False, read_success; + struct termios tty_old, tty_new; + FILE *in = stdin, *out = stderr; + FILE *tty = fopen("/dev/tty", "w+"); + + if (tty) in = out = tty; + + if (tcgetattr(fileno(in), &tty_old) == 0) { + tty_new = tty_old; + tty_new.c_lflag &= ~(ECHO | ISIG); + + if (tcsetattr(fileno(in), TCSAFLUSH, &tty_new) == 0) + tty_changed = True; + } + + if (!tty_changed) fputs("(WARNING: will be visible) ", out); + fputs(prompt, out); + fflush(out); + + read_success = fgets(password, sizeof password, in) != NULL; + + /* Print the newline that hasn't been echoed. */ + fputc('\n', out); + + if (tty_changed) + tcsetattr(fileno(in), TCSAFLUSH, &tty_old); + + if (tty) fclose(tty); + + if (read_success) { + /* Remove the trailing newline. */ + size_t password_len = strlen(password); + if (password[password_len - 1] == '\n') + password[password_len - 1] = '\0'; + + return password; + } else { + return NULL; + } +} diff --git a/rsync.h b/rsync.h index 3b6ca03..714906a 100644 --- a/rsync.h +++ b/rsync.h @@ -1282,6 +1282,10 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size); int inet_pton(int af, const char *src, void *dst); #endif +#ifndef HAVE_GETPASS +char *getpass(const char *prompt); +#endif + #ifdef MAINTAINER_MODE const char *get_panic_action(void); #endif -- 1.7.9