xref: /openbsd/usr.bin/cu/input.c (revision 4bdff4be)
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 
36 volatile sig_atomic_t input_stop;
37 
38 void	input_signal(int);
39 
40 void
41 input_signal(int sig)
42 {
43 	input_stop = 1;
44 }
45 
46 const char *
47 get_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 }
89