Index | Thread | Search

From:
Ingo Schwarze <schwarze@usta.de>
Subject:
Re: watch(1) - periodically execute a command and display its output
To:
Theo de Raadt <deraadt@openbsd.org>
Cc:
Job Snijders <job@openbsd.org>, tech@openbsd.org
Date:
Wed, 21 May 2025 04:28:57 +0200

Download raw body.

Thread
Hi Theo,

Theo de Raadt wrote on Mon, May 19, 2025 at 06:50:03PM -0600:

> Over my dead body!

Just trying to save your life, 'cause it would be such a pity...  ;-)

I think there is nothing wrong with checking for signals at multiple
points in the command_loop(), for example before every operation
that might potentially take a significant time.

Also, the logical place to put cleanup code is at the end of main().

To be committed after florian@'s cmdstr patch goes in, of course.

OK?
  Ingo


--- watch.c	Wed May 21 04:12:27 2025
+++ watch.c	Wed May 21 04:09:20 2025
@@ -50,7 +50,8 @@ typedef enum {
 	RSLT_UPDATE,
 	RSLT_REDRAW,
 	RSLT_NOTOUCH,
-	RSLT_ERROR
+	RSLT_ERROR,
+	RSLT_QUIT
 }    kbd_result_t;
 
 /*
@@ -64,6 +65,8 @@ struct {
 	.d = DEFAULT_INTERVAL
 };
 
+volatile sig_atomic_t got_signal = 0;
+
 highlight_mode_t highlight_mode = HIGHLIGHT_NONE;
 highlight_mode_t last_highlight_mode = HIGHLIGHT_CHAR;
 
@@ -93,7 +96,6 @@ kbd_result_t kbd_command(int);
 void show_help(void);
 void untabify(wchar_t *, int);
 void on_signal(int);
-void quit(void);
 void usage(void);
 
 int
@@ -206,8 +208,12 @@ main(int argc, char *argv[])
 
 	command_loop();
 
-	/* NOTREACHED */
-	abort();
+	erase();
+	refresh();
+	endwin();
+	free(cmdv);
+
+	return got_signal ? 128 + got_signal : 0;
 }
 
 void
@@ -231,12 +237,21 @@ command_loop(void)
 			prev = &buf0;
 		}
 
+		if (got_signal)
+			break;
+
 		read_result(cur);
 
 redraw:
+		if (got_signal)
+			break;
+
 		display(cur, prev, highlight_mode);
 
 input:
+		if (got_signal)
+			break;
+
 		to = opt_interval.tv;
 		FD_ZERO(&readfds);
 		FD_SET(fileno(stdin), &readfds);
@@ -269,6 +284,8 @@ input:
 			case RSLT_ERROR:	/* error */
 				fprintf(stderr, "\007");
 				goto input;
+			case RSLT_QUIT:
+				return;
 			}
 		}
 	}
@@ -595,8 +612,7 @@ kbd_command(int ch)
 		break;
 
 	case 'q':
-		quit();
-		break;
+		return (RSLT_QUIT);
 
 	default:
 		return (RSLT_ERROR);
@@ -682,17 +698,7 @@ untabify(wchar_t *buf, int maxlen)
 void
 on_signal(int signum)
 {
-	quit();
-}
-
-void
-quit(void)
-{
-	erase();
-	refresh();
-	endwin();
-	free(cmdv);
-	exit(0);
+	got_signal = signum;
 }
 
 void