Skip to content

Commit fd15b2d

Browse files
committed
Ensure ^C gets printed to Windows console
1 parent e228aa3 commit fd15b2d

File tree

5 files changed

+37
-9
lines changed

5 files changed

+37
-9
lines changed

libc/calls/BUILD.mk

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,6 @@ o//libc/calls/writev.o: private \
216216
-mgeneral-regs-only
217217

218218
# these assembly files are safe to build on aarch64
219-
o/$(MODE)/libc/calls/getcontext.o: libc/calls/getcontext.S
220-
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
221-
o/$(MODE)/libc/calls/swapcontext.o: libc/calls/swapcontext.S
222-
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
223-
o/$(MODE)/libc/calls/tailcontext.o: libc/calls/tailcontext.S
224-
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
225219
o/$(MODE)/libc/calls/stackjump.o: libc/calls/stackjump.S
226220
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
227221

libc/calls/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ int CountConsoleInputBytes(void);
3030
int FlushConsoleInputBytes(void);
3131
int64_t GetConsoleInputHandle(void);
3232
int64_t GetConsoleOutputHandle(void);
33+
void EchoConsoleNt(const char *, size_t, bool);
3334
int IsWindowsExecutable(int64_t, const char16_t *);
3435
void InterceptTerminalCommands(const char *, size_t);
3536

libc/calls/read-nt.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,12 @@ textwindows static int ProcessKeyEvent(const struct NtInputRecord *r, char *p) {
320320
// note we define _POSIX_VDISABLE as zero
321321
// tcsetattr() lets anyone reconfigure these keybindings
322322
if (c && !(__ttyconf.magic & kTtyNoIsigs) && !__keystroke.bypass_mode) {
323+
char b[] = {c};
323324
if (c == __ttyconf.vintr) {
325+
EchoConsoleNt(b, 1, false);
324326
return AddSignal(SIGINT);
325327
} else if (c == __ttyconf.vquit) {
328+
EchoConsoleNt(b, 1, false);
326329
return AddSignal(SIGQUIT);
327330
}
328331
}
@@ -457,7 +460,8 @@ textwindows static void WriteCtl(const char *p, size_t n, bool escape_harder) {
457460
}
458461
}
459462

460-
textwindows static void EchoTty(const char *p, size_t n, bool escape_harder) {
463+
textwindows void EchoConsoleNt(const char *p, size_t n, bool escape_harder) {
464+
InitConsole();
461465
if (!(__ttyconf.magic & kTtySilence)) {
462466
if (__ttyconf.magic & kTtyEchoRaw) {
463467
WriteTty(p, n);
@@ -517,7 +521,7 @@ textwindows static void IngestConsoleInputRecord(struct NtInputRecord *r) {
517521
memcpy(k->buf, buf, sizeof(k->buf));
518522
k->buflen = len;
519523
dll_make_last(&__keystroke.line, &k->elem);
520-
EchoTty(buf, len, true);
524+
EchoConsoleNt(buf, len, true);
521525
if (!__keystroke.freekeys) {
522526
dll_make_last(&__keystroke.list, __keystroke.line);
523527
__keystroke.line = 0;
@@ -616,7 +620,7 @@ textwindows static void IngestConsoleInputRecord(struct NtInputRecord *r) {
616620

617621
// echo input if it was successfully recorded
618622
// assuming the win32 console isn't doing it already
619-
EchoTty(buf, len, false);
623+
EchoConsoleNt(buf, len, false);
620624

621625
// save keystroke to appropriate list
622626
if (__ttyconf.magic & kTtyUncanon) {

libc/intrin/BUILD.mk

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ o/$(MODE)/libc/intrin/windowstimetotimespec.o: private \
119119
-O2
120120

121121
# these assembly files are safe to build on aarch64
122+
o/$(MODE)/libc/intrin/getcontext.o: libc/intrin/getcontext.S
123+
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
124+
o/$(MODE)/libc/intrin/swapcontext.o: libc/intrin/swapcontext.S
125+
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
126+
o/$(MODE)/libc/intrin/tailcontext.o: libc/intrin/tailcontext.S
127+
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
122128
o/$(MODE)/libc/intrin/aarch64/%.o: libc/intrin/aarch64/%.S
123129
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
124130
o/$(MODE)/libc/intrin/fenv.o: libc/intrin/fenv.S

libc/intrin/sig.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "libc/sysv/consts/sig.h"
2020
#include "ape/sections.internal.h"
2121
#include "libc/calls/calls.h"
22+
#include "libc/calls/internal.h"
2223
#include "libc/calls/sig.internal.h"
2324
#include "libc/calls/state.internal.h"
2425
#include "libc/calls/struct/sigaction.h"
@@ -34,6 +35,7 @@
3435
#include "libc/intrin/describebacktrace.h"
3536
#include "libc/intrin/dll.h"
3637
#include "libc/intrin/maps.h"
38+
#include "libc/intrin/nomultics.h"
3739
#include "libc/intrin/strace.h"
3840
#include "libc/intrin/weaken.h"
3941
#include "libc/nt/console.h"
@@ -54,6 +56,7 @@
5456
#include "libc/sysv/consts/sa.h"
5557
#include "libc/sysv/consts/sicode.h"
5658
#include "libc/sysv/consts/ss.h"
59+
#include "libc/sysv/consts/termios.h"
5760
#include "libc/thread/posixthread.internal.h"
5861
#ifdef __x86_64__
5962

@@ -622,12 +625,32 @@ static textwindows int __sig_console_sig(uint32_t dwCtrlType) {
622625
}
623626
}
624627

628+
static textwindows int __sig_console_char(uint32_t dwCtrlType) {
629+
switch (dwCtrlType) {
630+
case kNtCtrlCEvent:
631+
return __ttyconf.vintr;
632+
case kNtCtrlBreakEvent:
633+
return __ttyconf.vquit;
634+
default:
635+
return _POSIX_VDISABLE;
636+
}
637+
}
638+
625639
__msabi textwindows dontinstrument bool32 __sig_console(uint32_t dwCtrlType) {
626640
// win32 launches a thread to deliver ctrl-c and ctrl-break when typed
627641
// it only happens when kNtEnableProcessedInput is in play on console.
628642
// otherwise we need to wait until read-nt.c discovers that keystroke.
629643
struct CosmoTib tls;
630644
__bootstrap_tls(&tls, __builtin_frame_address(0));
645+
646+
// ensure that ^C or ^\ gets printed to console appropriately
647+
if (_weaken(EchoConsoleNt)) {
648+
char c;
649+
if ((c = __sig_console_char(dwCtrlType)) != _POSIX_VDISABLE)
650+
_weaken(EchoConsoleNt)(&c, sizeof(c), false);
651+
}
652+
653+
// take control of random thread and inject call to signal handler
631654
__sig_generate(__sig_console_sig(dwCtrlType), SI_KERNEL);
632655
return true;
633656
}

0 commit comments

Comments
 (0)