ClickHouse
201 строка · 6.3 Кб
1/* $OpenBSD: readpassphrase.c,v 1.26 2016/10/18 12:47:18 millert Exp $ */
2
3/*
4* Copyright (c) 2000-2002, 2007, 2010
5* Todd C. Miller <Todd.Miller@courtesan.com>
6*
7* Permission to use, copy, modify, and distribute this software for any
8* purpose with or without fee is hereby granted, provided that the above
9* copyright notice and this permission notice appear in all copies.
10*
11* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*
19* Sponsored in part by the Defense Advanced Research Projects
20* Agency (DARPA) and Air Force Research Laboratory, Air Force
21* Materiel Command, USAF, under agreement number F39502-99-1-0512.
22*/
23
24/* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */
25
26#ifndef _PATH_TTY27#define _PATH_TTY "/dev/tty"28#endif29
30#pragma clang diagnostic ignored "-Wreserved-identifier"31
32#include <termios.h>33#include <signal.h>34#include <ctype.h>35#include <fcntl.h>36#include "readpassphrase.h"37#include <errno.h>38#include <string.h>39#include <unistd.h>40
41#ifndef TCSASOFT42/* If we don't have TCSASOFT define it so that ORing it it below is a no-op. */
43# define TCSASOFT 044#endif45
46/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
47#if !defined(_POSIX_VDISABLE) && defined(VDISABLE)48# define _POSIX_VDISABLE VDISABLE49#endif50
51static volatile sig_atomic_t signo[NSIG];52
53static void handler(int);54
55char *56readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)57{
58ssize_t nr;59int input, output, save_errno, i, need_restart;60char ch, *p, *end;61struct termios term, oterm;62struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;63struct sigaction savetstp, savettin, savettou, savepipe;64
65/* I suppose we could alloc on demand in this case (XXX). */66if (bufsiz == 0) {67errno = EINVAL;68return(NULL);69}70
71restart:72for (i = 0; i < NSIG; i++)73signo[i] = 0;74nr = -1;75save_errno = 0;76need_restart = 0;77/*78* Read and write to /dev/tty if available. If not, read from
79* stdin and write to stderr unless a tty is required.
80*/
81if ((flags & RPP_STDIN) ||82(input = output = open(_PATH_TTY, O_RDWR)) == -1) {83if (flags & RPP_REQUIRE_TTY) {84errno = ENOTTY;85return(NULL);86}87input = STDIN_FILENO;88output = STDERR_FILENO;89}90
91/*92* Turn off echo if possible.
93* If we are using a tty but are not the foreground pgrp this will
94* generate SIGTTOU, so do it *before* installing the signal handlers.
95*/
96if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {97memcpy(&term, &oterm, sizeof(term));98if (!(flags & RPP_ECHO_ON))99term.c_lflag &= ~((unsigned int) (ECHO | ECHONL));100#ifdef VSTATUS101if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)102term.c_cc[VSTATUS] = _POSIX_VDISABLE;103#endif104(void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);105} else {106memset(&term, 0, sizeof(term));107term.c_lflag |= ECHO;108memset(&oterm, 0, sizeof(oterm));109oterm.c_lflag |= ECHO;110}111
112/*113* Catch signals that would otherwise cause the user to end
114* up with echo turned off in the shell. Don't worry about
115* things like SIGXCPU and SIGVTALRM for now.
116*/
117sigemptyset(&sa.sa_mask);118sa.sa_flags = 0; /* don't restart system calls */119sa.sa_handler = handler;120(void)sigaction(SIGALRM, &sa, &savealrm);121(void)sigaction(SIGHUP, &sa, &savehup);122(void)sigaction(SIGINT, &sa, &saveint);123(void)sigaction(SIGPIPE, &sa, &savepipe);124(void)sigaction(SIGQUIT, &sa, &savequit);125(void)sigaction(SIGTERM, &sa, &saveterm);126(void)sigaction(SIGTSTP, &sa, &savetstp);127(void)sigaction(SIGTTIN, &sa, &savettin);128(void)sigaction(SIGTTOU, &sa, &savettou);129
130if (!(flags & RPP_STDIN))131(void)write(output, prompt, strlen(prompt));132end = buf + bufsiz - 1;133p = buf;134while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {135if (p < end) {136if ((flags & RPP_SEVENBIT))137ch &= 0x7f;138if (isalpha((unsigned char)ch)) {139if ((flags & RPP_FORCELOWER))140ch = (char)tolower((unsigned char)ch);141if ((flags & RPP_FORCEUPPER))142ch = (char)toupper((unsigned char)ch);143}144*p++ = ch;145}146}147*p = '\0';148save_errno = errno;149if (!(term.c_lflag & ECHO))150(void)write(output, "\n", 1);151
152/* Restore old terminal settings and signals. */153if (memcmp(&term, &oterm, sizeof(term)) != 0) {154const int sigttou = (int)signo[SIGTTOU];155
156/* Ignore SIGTTOU generated when we are not the fg pgrp. */157while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&158errno == EINTR && !signo[SIGTTOU])159continue;160signo[SIGTTOU] = sigttou;161}162(void)sigaction(SIGALRM, &savealrm, NULL);163(void)sigaction(SIGHUP, &savehup, NULL);164(void)sigaction(SIGINT, &saveint, NULL);165(void)sigaction(SIGQUIT, &savequit, NULL);166(void)sigaction(SIGPIPE, &savepipe, NULL);167(void)sigaction(SIGTERM, &saveterm, NULL);168(void)sigaction(SIGTSTP, &savetstp, NULL);169(void)sigaction(SIGTTIN, &savettin, NULL);170(void)sigaction(SIGTTOU, &savettou, NULL);171if (input != STDIN_FILENO)172(void)close(input);173
174/*175* If we were interrupted by a signal, resend it to ourselves
176* now that we have restored the signal handlers.
177*/
178for (i = 0; i < NSIG; i++) {179if (signo[i]) {180kill(getpid(), i);181switch (i) {182case SIGTSTP:183case SIGTTIN:184case SIGTTOU:185need_restart = 1;186}187}188}189if (need_restart)190goto restart;191
192if (save_errno)193errno = save_errno;194return(nr == -1 ? NULL : buf);195}
196//DEF_WEAK(readpassphrase);
197
198static void handler(int s)199{
200signo[s] = 1;201}
202