Browse Source

Implement non-interruptible command

Serj Kalichev 6 months ago
parent
commit
2f83cc8ddb
3 changed files with 44 additions and 9 deletions
  1. 1 1
      klish/kexec.h
  2. 16 7
      klish/ksession/kexec.c
  3. 27 1
      klish/ktp/ktpd_session.c

+ 1 - 1
klish/kexec.h

@@ -60,7 +60,7 @@ bool_t kexec_exec(kexec_t *exec);
 bool_t kexec_need_stdin(const kexec_t *exec);
 bool_t kexec_interactive(const kexec_t *exec);
 bool_t kexec_set_winsize(kexec_t *exec);
-
+const kaction_t *kexec_current_action(const kexec_t *exec);
 
 C_DECL_END
 

+ 16 - 7
klish/ksession/kexec.c

@@ -570,13 +570,6 @@ static bool_t exec_action_async(const kexec_t *exec, kcontext_t *context,
 
 	// Unblock signals
 	sigemptyset(&sigs);
-	// Block signals for children processes if action is non-interruptible.
-	// The block state is inherited
-	if (!kaction_interrupt(action)) {
-		sigaddset(&sigs, SIGINT);
-		sigaddset(&sigs, SIGQUIT);
-		sigaddset(&sigs, SIGHUP);
-	}
 	sigprocmask(SIG_SETMASK, &sigs, NULL);
 
 	// Reopen streams if the pseudoterminal is used.
@@ -845,3 +838,19 @@ bool_t kexec_need_stdin(const kexec_t *exec)
 
 	return BOOL_FALSE;
 }
+
+
+const kaction_t *kexec_current_action(const kexec_t *exec)
+{
+	kcontext_t *context = NULL;
+
+	assert(exec);
+	if (!exec)
+		return NULL;
+
+	context = (kcontext_t *)faux_list_data(faux_list_head(exec->contexts));
+	if (!context)
+		return NULL;
+
+	return kcontext_action(context);
+}

+ 27 - 1
klish/ktp/ktpd_session.c

@@ -941,6 +941,8 @@ static bool_t ktpd_session_process_stdin(ktpd_session_t *ktpd, faux_msg_t *msg)
 	unsigned int len = 0;
 	faux_buf_t *bufin = NULL;
 	int fd = -1;
+	bool_t interrupt = BOOL_FALSE;
+	const kaction_t *action = NULL;
 
 	assert(ktpd);
 	assert(msg);
@@ -957,7 +959,31 @@ static bool_t ktpd_session_process_stdin(ktpd_session_t *ktpd, faux_msg_t *msg)
 		return BOOL_TRUE;
 	bufin = kexec_bufin(ktpd->exec);
 	assert(bufin);
-	faux_buf_write(bufin, line, len);
+
+	action = kexec_current_action(ktpd->exec);
+	if (action)
+		interrupt = kaction_interrupt(action);
+	// If current action is non-interruptible and action's stdin is terminal
+	// then remove ^C (0x03) symbol from stdin stream to don't deliver
+	// SIGINT to process
+	if (isatty(fd) && !interrupt) {
+		// 0x03 is a ^C
+		const char chars_to_search[] = {0x03, 0};
+		const char *start = line;
+		const char *pos = NULL;
+		size_t cur_len = len;
+		while ((pos = faux_str_charsn(start, chars_to_search, cur_len))) {
+			size_t written = pos - start;
+			faux_buf_write(bufin, start, written);
+			start = pos + 1;
+			cur_len = cur_len - written - 1;
+		}
+		if (cur_len > 0)
+			faux_buf_write(bufin, start, cur_len);
+	} else {
+		faux_buf_write(bufin, line, len);
+	}
+
 	stdin_out(fd, bufin); // Non-blocking write
 	if (faux_buf_len(bufin) == 0)
 		return BOOL_TRUE;