/* This file is part of Eclat. Copyright (C) 2012-2018 Sergey Poznyakoff. Eclat 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, or (at your option) any later version. Eclat 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 Eclat. If not, see . */ #include "libeclat.h" #include #include #include #include #include void eclat_trimnl(char *s) { size_t len = strlen(s); while (len > 0 && s[len-1] == '\n') --len; s[len] = 0; } #ifndef TCSASOFT # define TCSASOFT 0 #endif char * eclat_getans(char *prompt, char *dfl, int pass) { char *buf = NULL; size_t size = 0; struct termios t, tsave; int rc; int fd = fileno(stdin); sigset_t oldset; fprintf(stdout, "%s", prompt); if (dfl) fprintf(stdout, " [%s]", dfl); fprintf(stdout, ": "); fflush(stdout); if (pass) { sigset_t set; static int signum[] = { SIGHUP, SIGINT, SIGQUIT, SIGABRT, SIGPIPE, SIGALRM, SIGTERM }; int i; if (tcgetattr(fd, &t)) die(EX_SOFTWARE, "cannot query console attributes: %s", strerror(errno)); tsave = t; t.c_lflag &= ~(ECHO | ISIG); if (tcsetattr(fd, TCSAFLUSH | TCSASOFT, &t)) die(EX_SOFTWARE, "cannot turn echo off; %s", strerror(errno)); sigemptyset(&set); for (i = 0; i < sizeof(signum)/sizeof(signum[0]); i++) sigaddset(&set, signum[i]); sigprocmask(SIG_BLOCK, &set, &oldset); } rc = grecs_getline(&buf, &size, stdin); if (pass) { if (tcsetattr(fd, TCSAFLUSH | TCSASOFT, &tsave)) die(EX_SOFTWARE, "failed to restore echo state: %s", strerror(errno)); sigprocmask(SIG_SETMASK, &oldset, NULL); } if (rc <= 0) { free(buf); return NULL; } eclat_trimnl(buf); if (buf[0] == 0 && dfl) { free(buf); buf = grecs_strdup(dfl); } return buf; }