diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 16:14:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 16:14:31 +0000 |
commit | 2d5707c7479eacb3b1ad98e01b53f56a88f8fb78 (patch) | |
tree | d9c334e83692851c02e3e1b8e65570c97bc82481 /lib/getpass.c | |
parent | Initial commit. (diff) | |
download | rsync-2d5707c7479eacb3b1ad98e01b53f56a88f8fb78.tar.xz rsync-2d5707c7479eacb3b1ad98e01b53f56a88f8fb78.zip |
Adding upstream version 3.2.7.upstream/3.2.7
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/getpass.c')
-rw-r--r-- | lib/getpass.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/getpass.c b/lib/getpass.c new file mode 100644 index 0000000..dea3126 --- /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; +} |