diff options
author | Wayne Davison <wayned@samba.org> | 2013-05-19 21:28:02 +0000 |
---|---|---|
committer | Wayne Davison <wayned@samba.org> | 2013-05-19 22:01:29 +0000 |
commit | 333e3a9ff0bd3783b81542e112a63fdb3f4678b0 (patch) | |
tree | 72e45ffdc8b478372e00012f97d2053ba24861a1 | |
parent | 94073d20e43505f2a5caa25877b2641548c0000e (diff) | |
download | rsync-333e3a9ff0bd3783b81542e112a63fdb3f4678b0.tar.gz rsync-333e3a9ff0bd3783b81542e112a63fdb3f4678b0.tar.bz2 rsync-333e3a9ff0bd3783b81542e112a63fdb3f4678b0.zip |
Add an implementation of getpass for systems that lack one.
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | lib/getpass.c | 72 | ||||
-rw-r--r-- | rsync.h | 4 |
3 files changed, 78 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index a73fce69..9c7b4113 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 00000000..dea31268 --- /dev/null +++ b/lib/getpass.c @@ -0,0 +1,72 @@ +/* + * 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 <stdio.h> +#include <string.h> +#include <termios.h> + +#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_len && password[password_len - 1] == '\n') + password[password_len - 1] = '\0'; + + return password; + } + + return NULL; +} @@ -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 |