summaryrefslogtreecommitdiff
path: root/usr.bin/bc
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2011-08-03 08:48:20 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2011-08-03 08:48:20 +0000
commite55ab35365dcfbded607c1343250e012364300c1 (patch)
treeea376906d73486df5160062d5b33067b0b55c9b0 /usr.bin/bc
parent463b9cfa17b8ead66a88d09f608b50ee1a7efe61 (diff)
save/restore tty state on SIGTSTP/SIGCONT. ok deraadt@ nicm@
Diffstat (limited to 'usr.bin/bc')
-rw-r--r--usr.bin/bc/bc.y9
-rw-r--r--usr.bin/bc/extern.h7
-rw-r--r--usr.bin/bc/scan.l47
3 files changed, 55 insertions, 8 deletions
diff --git a/usr.bin/bc/bc.y b/usr.bin/bc/bc.y
index 2a98248a846..4314d99e205 100644
--- a/usr.bin/bc/bc.y
+++ b/usr.bin/bc/bc.y
@@ -1,5 +1,5 @@
%{
-/* $OpenBSD: bc.y,v 1.38 2011/07/08 23:29:46 tedu Exp $ */
+/* $OpenBSD: bc.y,v 1.39 2011/08/03 08:48:19 otto Exp $ */
/*
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
@@ -43,6 +43,7 @@
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
+#include <termios.h>
#include <unistd.h>
#include "extern.h"
@@ -1061,12 +1062,13 @@ sigchld(int signo)
int status, save_errno = errno;
for (;;) {
- pid = waitpid(dc, &status, WCONTINUED);
+ pid = waitpid(dc, &status, WCONTINUED | WNOHANG);
if (pid == -1) {
if (errno == EINTR)
continue;
_exit(0);
- }
+ } else if (pid == 0)
+ break;
if (WIFEXITED(status) || WIFSIGNALED(status))
_exit(0);
else
@@ -1139,6 +1141,7 @@ main(int argc, char *argv[])
close(p[0]);
close(p[1]);
if (interactive) {
+ gettty(&ttysaved);
el = el_init("bc", stdin, stderr, stderr);
hist = history_init();
history(hist, &he, H_SETSIZE, 100);
diff --git a/usr.bin/bc/extern.h b/usr.bin/bc/extern.h
index be03bd33a5f..3fb7e318daa 100644
--- a/usr.bin/bc/extern.h
+++ b/usr.bin/bc/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.8 2011/06/03 06:10:33 otto Exp $ */
+/* $OpenBSD: extern.h,v 1.9 2011/08/03 08:48:19 otto Exp $ */
/*
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
@@ -27,6 +27,7 @@ int yylex(void);
void yyerror(char *);
void fatal(const char *);
void abort_line(int);
+int gettty(struct termios *);
unsigned char bc_eof(EditLine *, int);
extern int lineno;
@@ -41,5 +42,5 @@ extern EditLine *el;
extern History *hist;
extern HistEvent he;
extern char *cmdexpr;
-
-bool interactive;
+extern struct termios ttysaved;
+extern bool interactive;
diff --git a/usr.bin/bc/scan.l b/usr.bin/bc/scan.l
index 8cef4b294f9..a49ef2cb38c 100644
--- a/usr.bin/bc/scan.l
+++ b/usr.bin/bc/scan.l
@@ -1,5 +1,5 @@
%{
-/* $OpenBSD: scan.l,v 1.26 2011/06/03 06:10:33 otto Exp $ */
+/* $OpenBSD: scan.l,v 1.27 2011/08/03 08:48:19 otto Exp $ */
/*
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
@@ -22,6 +22,7 @@
#include <signal.h>
#include <stdbool.h>
#include <string.h>
+#include <termios.h>
#include <unistd.h>
#include "extern.h"
@@ -40,6 +41,7 @@ static size_t strbuf_sz = 1;
static bool dot_seen;
static int use_el;
static volatile sig_atomic_t skipchars;
+struct termios ttysaved, ttyedit;
static void init_strbuf(void);
static void add_str(const char *);
@@ -253,6 +255,45 @@ abort_line(int sig)
errno = save_errno;
}
+int
+settty(struct termios *t)
+{
+ int ret;
+
+ while ((ret = tcsetattr(0, TCSADRAIN, t) == -1) && errno == EINTR)
+ continue;
+ return ret;
+}
+
+int
+gettty(struct termios *t)
+{
+ int ret;
+
+ while ((ret = tcgetattr(0, t) == -1) && errno == EINTR)
+ continue;
+ return ret;
+}
+
+/* ARGSUSED */
+void
+tstpcont(int sig)
+{
+ int save_errno = errno;
+
+ if (sig == SIGTSTP) {
+ signal(SIGCONT, tstpcont);
+ gettty(&ttyedit);
+ settty(&ttysaved);
+ } else {
+ signal(SIGTSTP, tstpcont);
+ settty(&ttyedit);
+ }
+ signal(sig, SIG_DFL);
+ kill(0, sig);
+ errno = save_errno;
+}
+
/*
* Avoid the echo of ^D by the default code of editline and take
* into account skipchars to make ^D work when the cursor is at start of
@@ -307,8 +348,10 @@ yywrap(void)
} else if (fileindex == sargc) {
fileindex++;
yyin = stdin;
- if (interactive)
+ if (interactive) {
signal(SIGINT, abort_line);
+ signal(SIGTSTP, tstpcont);
+ }
lineno = 1;
filename = "stdin";
return (0);