jcs's openbsd hax
openbsd
1/* $OpenBSD: input.c,v 1.2 2012/07/10 10:28:05 nicm Exp $ */
2
3/*
4 * Copyright (c) 2012 Nicholas Marriott <nicm@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <ctype.h>
22#include <errno.h>
23#include <signal.h>
24#include <stdio.h>
25#include <string.h>
26#include <termios.h>
27#include <unistd.h>
28
29#include "cu.h"
30
31/*
32 * Prompt and read a line of user input from stdin. We want to use the termios
33 * we were started with so restore and stick in a signal handler for ^C.
34 */
35
36volatile sig_atomic_t input_stop;
37
38void input_signal(int);
39
40void
41input_signal(int sig)
42{
43 input_stop = 1;
44}
45
46const char *
47get_input(const char *prompt)
48{
49 static char s[BUFSIZ];
50 struct sigaction act, oact;
51 char c, *cp, *out = NULL;
52 ssize_t n;
53
54 memset(&act, 0, sizeof(act));
55 sigemptyset(&act.sa_mask);
56 act.sa_flags = 0;
57 act.sa_handler = input_signal;
58 if (sigaction(SIGINT, &act, &oact) != 0)
59 cu_err(1, "sigaction");
60 input_stop = 0;
61
62 restore_termios();
63
64 printf("%s ", prompt);
65 fflush(stdout);
66
67 cp = s;
68 while (cp != s + sizeof(s) - 1) {
69 n = read(STDIN_FILENO, &c, 1);
70 if (n == -1 && errno != EINTR)
71 cu_err(1, "read");
72 if (n != 1 || input_stop)
73 break;
74 if (c == '\n') {
75 out = s;
76 break;
77 }
78 if (!iscntrl((u_char)c))
79 *cp++ = c;
80 }
81 *cp = '\0';
82
83 set_termios();
84
85 sigaction(SIGINT, &oact, NULL);
86
87 return (out);
88}