From patchwork Fri Mar 4 13:11:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Wood X-Patchwork-Id: 12769070 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A0D78C433EF for ; Fri, 4 Mar 2022 13:11:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232631AbiCDNMY (ORCPT ); Fri, 4 Mar 2022 08:12:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60630 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232267AbiCDNMV (ORCPT ); Fri, 4 Mar 2022 08:12:21 -0500 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 88F3360ABC for ; Fri, 4 Mar 2022 05:11:33 -0800 (PST) Received: by mail-wr1-x435.google.com with SMTP id ay10so12646323wrb.6 for ; Fri, 04 Mar 2022 05:11:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=fMvRl4h/fanebrP5dlRHisvRofIjp58PSliTs9GG+BU=; b=nWyyMqjz2oD0a+tWOgCftP9uaVwbq+2u2XyEPokUC+eFch4K5GJJGmgXnFkKE6vuJI VBXM1dyyo57XUz5XMbb6Z1PuXUVJadNRLHL3mALqHoCD5te1i4sHI2o7btvPGS/Nf9d2 nG7ozo0p6J6xK8LFkdvtfPttL55bVyJts6zqoS5OB9AlwJeRj4nifJev5Y5LziJZAr2C MmKxlt3YrWqx7wN89OwP/N6hfbRYk+HFoNhb0+WxGjhpBXEX9uvhtJTwO2oEGcuTbOCf GtPB27HIviAfnUgl4zjiNQmxfswJH08csXzPnwcp9V9OzK/bIK/oXYbXx4yKsfyKzbvv 2N5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=fMvRl4h/fanebrP5dlRHisvRofIjp58PSliTs9GG+BU=; b=RLIwSA6j3M72JxBFVG3xzeLy7hCk6L7Hft1/t4ls0GntoU8zyJgcRZByPEyFBIbkfa IPKrP/dgLV1vS0VtgS9enxRy3ok4pVUcZi/3fS4Bs09gimxsbG/pZ2bcsGlr9KmvYh87 8ba3b0g1lOKeWY5+559V/nMCOWBgaUVqEJEgYRWkURRMAjGjQP4vwhgG1hVU2VdJ/zdB uigOr/9l8EsqZRkP8eOaSVd4u+aCQA/lDPCRe0NhWEyT1n1QbCx54yh3AZiATjCvX927 uhs5NffNez9thlu4q7x3VjIpgPFUmcNOmcRa92k2MJefo9HK6oUxXfmOWtTIx1+/JaCU 1USA== X-Gm-Message-State: AOAM533GQsan1NRVGgIUw6GqcPO9NOySb0D60dGk+1sMrCF+xlot4XkQ O4qrghElphxZEE9jyWYlKabu9UYRAUA= X-Google-Smtp-Source: ABdhPJy6HZsqj79bmr0e68JZ6AZKs7M+UdBETrx+iZiO2aIQOKUBZKkRFUFgbfCGEbs1Pe+CfQ5TOA== X-Received: by 2002:a5d:5687:0:b0:1f0:9663:c80e with SMTP id f7-20020a5d5687000000b001f09663c80emr1823200wrv.343.1646399492133; Fri, 04 Mar 2022 05:11:32 -0800 (PST) Received: from localhost.localdomain (230.2.7.51.dyn.plus.net. [51.7.2.230]) by smtp.gmail.com with ESMTPSA id c4-20020adffb04000000b001f0494de239sm4634042wrr.21.2022.03.04.05.11.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Mar 2022 05:11:31 -0800 (PST) From: Phillip Wood To: Git Mailing List Cc: carenas@gmail.com, Johannes Schindelin , Phillip Wood Subject: [PATCH 1/4] terminal: use flags for save_term() Date: Fri, 4 Mar 2022 13:11:23 +0000 Message-Id: <20220304131126.8293-2-phillip.wood123@gmail.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220304131126.8293-1-phillip.wood123@gmail.com> References: <20220304131126.8293-1-phillip.wood123@gmail.com> Reply-To: Phillip Wood MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Phillip Wood The next commit will add another flag in addition to the existing full_duplex so change the function signature to take an unsigned flags argument. Also alter the functions that call save_term() so that they can pass flags down to it. Signed-off-by: Phillip Wood --- compat/terminal.c | 41 +++++++++++++++++++++-------------------- compat/terminal.h | 5 ++++- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index d882dfa06e..bad8e04cd8 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -34,7 +34,7 @@ void restore_term(void) sigchain_pop_common(); } -int save_term(int full_duplex) +int save_term(unsigned flags) { if (term_fd < 0) term_fd = open("/dev/tty", O_RDWR); @@ -47,11 +47,11 @@ int save_term(int full_duplex) return 0; } -static int disable_bits(tcflag_t bits) +static int disable_bits(unsigned flags, tcflag_t bits) { struct termios t; - if (save_term(0) < 0) + if (save_term(flags) < 0) goto error; t = old_term; @@ -71,14 +71,14 @@ static int disable_bits(tcflag_t bits) return -1; } -static int disable_echo(void) +static int disable_echo(unsigned flags) { - return disable_bits(ECHO); + return disable_bits(flags, ECHO); } -static int enable_non_canonical(void) +static int enable_non_canonical(unsigned flags) { - return disable_bits(ICANON | ECHO); + return disable_bits(flags, ICANON | ECHO); } #elif defined(GIT_WINDOWS_NATIVE) @@ -126,15 +126,15 @@ void restore_term(void) hconin = hconout = INVALID_HANDLE_VALUE; } -int save_term(int full_duplex) +int save_term(unsigned flags) { hconin = CreateFileA("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hconin == INVALID_HANDLE_VALUE) return -1; - if (full_duplex) { + if (flags & SAVE_TERM_DUPLEX) { hconout = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); @@ -154,7 +154,7 @@ int save_term(int full_duplex) return -1; } -static int disable_bits(DWORD bits) +static int disable_bits(unsigned flags, DWORD bits) { if (use_stty) { struct child_process cp = CHILD_PROCESS_INIT; @@ -191,7 +191,7 @@ static int disable_bits(DWORD bits) use_stty = 0; } - if (save_term(0) < 0) + if (save_term(flags) < 0) return -1; if (!SetConsoleMode(hconin, cmode_in & ~bits)) { @@ -204,14 +204,15 @@ static int disable_bits(DWORD bits) return 0; } -static int disable_echo(void) +static int disable_echo(unsigned flags) { - return disable_bits(ENABLE_ECHO_INPUT); + return disable_bits(ENABLE_ECHO_INPUT, flags); } -static int enable_non_canonical(void) +static int enable_non_canonical(unsigned flags) { - return disable_bits(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); + return disable_bits(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT, + flags); } /* @@ -267,7 +268,7 @@ char *git_terminal_prompt(const char *prompt, int echo) return NULL; } - if (!echo && disable_echo()) { + if (!echo && disable_echo(0)) { fclose(input_fh); fclose(output_fh); return NULL; @@ -361,7 +362,7 @@ int read_key_without_echo(struct strbuf *buf) static int warning_displayed; int ch; - if (warning_displayed || enable_non_canonical() < 0) { + if (warning_displayed || enable_non_canonical(0) < 0) { if (!warning_displayed) { warning("reading single keystrokes not supported on " "this platform; reading line instead"); @@ -413,10 +414,10 @@ int read_key_without_echo(struct strbuf *buf) #else -int save_term(int full_duplex) +int save_term(unsigned flags) { - /* full_duplex == 1, but no support available */ - return -full_duplex; + /* no duplex support available */ + return -!!(flags & SAVE_TERM_DUPLEX); } void restore_term(void) diff --git a/compat/terminal.h b/compat/terminal.h index 0fb9fa147c..f24b91390d 100644 --- a/compat/terminal.h +++ b/compat/terminal.h @@ -1,14 +1,17 @@ #ifndef COMPAT_TERMINAL_H #define COMPAT_TERMINAL_H +/* Save input and output settings */ +#define SAVE_TERM_DUPLEX (1u << 0) + /* * Save the terminal attributes so they can be restored later by a * call to restore_term(). Note that every successful call to * save_term() must be matched by a call to restore_term() even if the * attributes have not been changed. Returns 0 on success, -1 on * failure. */ -int save_term(int full_duplex); +int save_term(unsigned flags); /* Restore the terminal attributes that were saved with save_term() */ void restore_term(void); From patchwork Fri Mar 4 13:11:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Wood X-Patchwork-Id: 12769072 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 42D3BC433F5 for ; Fri, 4 Mar 2022 13:11:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236280AbiCDNM1 (ORCPT ); Fri, 4 Mar 2022 08:12:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60646 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232760AbiCDNMW (ORCPT ); Fri, 4 Mar 2022 08:12:22 -0500 Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2ACB4159EBC for ; Fri, 4 Mar 2022 05:11:34 -0800 (PST) Received: by mail-wr1-x436.google.com with SMTP id i8so12617808wrr.8 for ; Fri, 04 Mar 2022 05:11:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=X7UFKt20OzqJRkq7F0/bLmm138QCw2Ra5GrakKUyHwk=; b=a9RWE64dvPKSc5R4ZA0bM37WQ0YPZlhM1uKQmTcjY7v6zzqPCwI2dmlykPt2smgn0u +ReM7f3A4FsJSMkn2biDancifHDuYabktIQC02ZUrpJtjY0z9occ7VOOd+8u2G0aq9Gp VumtF8yfnHWc65Lb/xUby+i+ZAcILcw7irrUCqP/cl0kcc+4IvGDRQezRqGmPU/e8kkT J/nPAQbVV/Pb0EUzgZ3POUmbZBWu9AoisHEWjGaAP+XBS+jJ0rp0HQiRO1vQ+w5iZNan pGFaANAaRRPnbeIz5hyryDnoRcBSwWyaHPQGFdBjzkFGu6HNCu2vcW2SZ6m772uJArVX ptZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=X7UFKt20OzqJRkq7F0/bLmm138QCw2Ra5GrakKUyHwk=; b=SPmWSXU/R7OgWx19JRYhnyQX+IRPyIot950DvakDZcJor2bFIqRlfNzccWXrWJFdBh ATtrccoXYIY72W43eluQ/b6N/C+UzvYK2COMMGdC1FpCWQe1tVODuEqnelmtwO9sPDY2 HO/4akvPrLOEbeVCV34r+PBvTYwk3Lxy4xhLVF04I4F4CU4II5haNNRLItRzoGtF1S68 7DvriCy9Cm8LiQ9NTVYnLaNRGEMgB3D2/M0I6wkMjFARRC1HODPgCAOP47ah3LLszvVi IknqIpM9OpMTb/oMK1a6jQG1Jm3pz9mJA84/gQGKyaeERUPo+87FAX40TgScLuFW6amI jYsg== X-Gm-Message-State: AOAM531P7OgupDWU1Ii4GtLTBcvkqsfeM17I2yYNU/89p2+ZcNqZkdn0 1Dkf8AOFAsfluMO4bmsQWvAJ8+i1DOs= X-Google-Smtp-Source: ABdhPJxCVSvhzysUnH3WKYljC5Po4Z/xnZdRZfsFx6R4m+zBsN9RtFBSbMMG75XhpP18cFibGsMtAg== X-Received: by 2002:a5d:59a1:0:b0:1f0:436c:f01d with SMTP id p1-20020a5d59a1000000b001f0436cf01dmr8835851wrr.360.1646399492744; Fri, 04 Mar 2022 05:11:32 -0800 (PST) Received: from localhost.localdomain (230.2.7.51.dyn.plus.net. [51.7.2.230]) by smtp.gmail.com with ESMTPSA id c4-20020adffb04000000b001f0494de239sm4634042wrr.21.2022.03.04.05.11.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Mar 2022 05:11:32 -0800 (PST) From: Phillip Wood To: Git Mailing List Cc: carenas@gmail.com, Johannes Schindelin , Phillip Wood Subject: [PATCH 2/4] terminal: don't assume stdin is /dev/tty Date: Fri, 4 Mar 2022 13:11:24 +0000 Message-Id: <20220304131126.8293-3-phillip.wood123@gmail.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220304131126.8293-1-phillip.wood123@gmail.com> References: <20220304131126.8293-1-phillip.wood123@gmail.com> Reply-To: Phillip Wood MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Phillip Wood read_key_without_echo() reads from stdin but uses /dev/tty when it disables echo. This is unfortunate as there no guarantee that stdin is the same device as /dev/tty. The perl version of "add -p" uses stdin when it sets the terminal mode, this commit does the same for the builtin version. There is still a difference between the perl and builtin versions though - the perl version will ignore any errors when setting the terminal mode[1] and will still read single bytes when stdin is not a terminal. The builtin version displays a warning if setting the terminal mode fails and switches to reading a line at a time. [1] https://github.com/jonathanstowe/TermReadKey/blob/b061c913bbf7ff9bad9b4eea6caae189eacd6063/ReadKey.xs#L1090 Signed-off-by: Phillip Wood --- compat/terminal.c | 5 +++-- compat/terminal.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index bad8e04cd8..249836e78f 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -37,7 +37,8 @@ void restore_term(void) int save_term(unsigned flags) { if (term_fd < 0) - term_fd = open("/dev/tty", O_RDWR); + term_fd = (flags & SAVE_TERM_STDIN) ? 0 + : open("/dev/tty", O_RDWR); if (term_fd < 0) return -1; if (tcgetattr(term_fd, &old_term) < 0) @@ -362,7 +363,7 @@ int read_key_without_echo(struct strbuf *buf) static int warning_displayed; int ch; - if (warning_displayed || enable_non_canonical(0) < 0) { + if (warning_displayed || enable_non_canonical(SAVE_TERM_STDIN) < 0) { if (!warning_displayed) { warning("reading single keystrokes not supported on " "this platform; reading line instead"); diff --git a/compat/terminal.h b/compat/terminal.h index f24b91390d..f5655d0d0b 100644 --- a/compat/terminal.h +++ b/compat/terminal.h @@ -3,7 +3,8 @@ /* Save input and output settings */ #define SAVE_TERM_DUPLEX (1u << 0) - +/* Save stdin rather than /dev/tty (fails is stdin is not a terminal) */ +#define SAVE_TERM_STDIN (1u << 1) /* * Save the terminal attributes so they can be restored later by a * call to restore_term(). Note that every successful call to From patchwork Fri Mar 4 13:11:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Wood X-Patchwork-Id: 12769071 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 358A2C433FE for ; Fri, 4 Mar 2022 13:11:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233187AbiCDNMZ (ORCPT ); Fri, 4 Mar 2022 08:12:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60674 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233403AbiCDNMX (ORCPT ); Fri, 4 Mar 2022 08:12:23 -0500 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C6E271AA074 for ; Fri, 4 Mar 2022 05:11:34 -0800 (PST) Received: by mail-wr1-x434.google.com with SMTP id j26so2274247wrb.1 for ; Fri, 04 Mar 2022 05:11:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=EjX+jn1l1pdirTUkQ+a4XwOKdnO74LpiX3BzJx8D/Hk=; b=Wg7ll3JhBjefsM2z/flXYDvOYBIogHrPTFA/oMvNSnMxkI4A24f+IQeaaNMQd4TyNc O+xc76LKJAbXo9OdZoZdCd5bQQ9Cz25EUssUG95kLMs8l+fiOSMjxzGjkyZWGu1utSKu B6Knt38wXty5sxOP+Ug/ZCy5LQhO1TIJ6ClP3rvUCkJCQ9Kjo9ELA/tL+7jN9Fs/57Xg TPscekrkubSefrJjbdAgxjUCbOV9bN9tt7ik4skNkAISodjN+QJ/8cYI4IVXscL0wvCL J7Q7hK6Q1oQhMmCru+nRtG+qxsCWXDRgzrvO39nO1HVhzRe/zaevT56dyb19HQYOwUH5 eAdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=EjX+jn1l1pdirTUkQ+a4XwOKdnO74LpiX3BzJx8D/Hk=; b=FYUw6VZI9OYkXXXdXG8EDwErwS3IkL9iCPvv+fWit1C5hiASBkMED2iClwsHQ6iARV TAS4v2+2VU2Ud1Ric19/xd1C0yr8wSPh+A9DR5pqrCtBSnOuGcO7q09j0KBAUP8i3ThG +wYMgpgFEwykZJOjfWdqWzKEKe/4LbAdfFdYJQYdLp9I3/dKvh6m3KU/fXqKRqzl302W cKvQo16d2yYtqEQO4EogJva8Rky1KLk4LPUbi6seyuiU2UICIOa6GtjD1I4nAaOBh2VU xU7slAprgjC7vU6CY4JqOblr+R8r5CXyRy08Ku7v9Ctr6g5cfZz2XDX7xMpOXGgRw824 pEKA== X-Gm-Message-State: AOAM530Fw4PhuGdFlp0DXcRVkfis7UsntKj1Jz5KBPmIMQe+6kDt8+IL PXprmJ19pd1ysL5JH0XMHUgGUCB9KPM= X-Google-Smtp-Source: ABdhPJzHKMZJbKbxo22xZ3Asni5KX8etbRYW7fNyTlyr68/72acGuChpLmHBDdOIur+UTs5WHb/58w== X-Received: by 2002:adf:fb47:0:b0:1ed:9f2c:492e with SMTP id c7-20020adffb47000000b001ed9f2c492emr30179423wrs.196.1646399493337; Fri, 04 Mar 2022 05:11:33 -0800 (PST) Received: from localhost.localdomain (230.2.7.51.dyn.plus.net. [51.7.2.230]) by smtp.gmail.com with ESMTPSA id c4-20020adffb04000000b001f0494de239sm4634042wrr.21.2022.03.04.05.11.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Mar 2022 05:11:33 -0800 (PST) From: Phillip Wood To: Git Mailing List Cc: carenas@gmail.com, Johannes Schindelin , Phillip Wood Subject: [PATCH 3/4] terminal: work around macos poll() bug Date: Fri, 4 Mar 2022 13:11:25 +0000 Message-Id: <20220304131126.8293-4-phillip.wood123@gmail.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220304131126.8293-1-phillip.wood123@gmail.com> References: <20220304131126.8293-1-phillip.wood123@gmail.com> Reply-To: Phillip Wood MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Phillip Wood On macos the builtin "add -p" does not handle keys that generate escape sequences because poll() does not work with terminals there. Switch to using select() on non-windows platforms to work around this. Signed-off-by: Phillip Wood --- compat/terminal.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index 249836e78f..5d516ff546 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -82,6 +82,32 @@ static int enable_non_canonical(unsigned flags) return disable_bits(flags, ICANON | ECHO); } +/* + * On macos it is not possible to use poll() with a terminal so use select + * instead. + */ +#include +static int getchar_with_timeout(int timeout) +{ + struct timeval tv, *tvp = NULL; + fd_set readfds; + int res; + + if (timeout >= 0) { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + tvp = &tv; + } + + FD_ZERO(&readfds); + FD_SET(0, &readfds); + res = select(1, &readfds, NULL, NULL, tvp); + if (res < 0) + return EOF; + + return getchar(); +} + #elif defined(GIT_WINDOWS_NATIVE) #define INPUT_PATH "CONIN$" @@ -247,6 +273,16 @@ static int mingw_getchar(void) } #define getchar mingw_getchar +static int getchar_with_timeout(int timeout) +{ + struct pollfd pfd = { .fd = 0, .events = POLLIN }; + + if (poll(&pfd, 1, timeout) < 1) + return EOF; + + return getchar(); +} + #endif #ifndef FORCE_TEXT @@ -397,12 +433,7 @@ int read_key_without_echo(struct strbuf *buf) * half a second when we know that the sequence is complete. */ while (!is_known_escape_sequence(buf->buf)) { - struct pollfd pfd = { .fd = 0, .events = POLLIN }; - - if (poll(&pfd, 1, 500) < 1) - break; - - ch = getchar(); + ch = getchar_with_timeout(500); if (ch == EOF) return 0; strbuf_addch(buf, ch); From patchwork Fri Mar 4 13:11:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Wood X-Patchwork-Id: 12769073 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1BF0FC433F5 for ; Fri, 4 Mar 2022 13:11:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236876AbiCDNMb (ORCPT ); Fri, 4 Mar 2022 08:12:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60676 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234833AbiCDNMX (ORCPT ); Fri, 4 Mar 2022 08:12:23 -0500 Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 79C0F1B45C0 for ; Fri, 4 Mar 2022 05:11:35 -0800 (PST) Received: by mail-wm1-x32c.google.com with SMTP id c192so4978716wma.4 for ; Fri, 04 Mar 2022 05:11:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references:reply-to :mime-version:content-transfer-encoding; bh=NPEMsN0F3SCoBPcIhcH21JDnWJgXiVPVbr0+v7/Cc9c=; b=ZMSUzqEiUPQj4l8OsBfQjeO52JYo/6qANPeEkMUDWH9sOosM2mbkspckkaOcnSwDkd fhVmCJk7aOvkfeVCxDpJbksppanWe8TRw8+C1vgaso8NtoEPH9ApnjqhGvxQWiW5+iQx p7QKlu8WTKEJWFuhK3rt31Bajy5QocrirYr5tZxl9KT1X1XAqZrK3zr5ko2mxSdZI+JV +Mv9rV86ybZANGbDnu9K4JK3xtCgvBJh/KryP4A5Tc7MQwUnaBgccjVByT/C4SeEpqtx jslJ5NJln+S5LAUE6maDnX7Bc3UYCjnSvwNwQy87OrV0GJC/iyE72arfJPf8k41EDcWY YuRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:reply-to:mime-version:content-transfer-encoding; bh=NPEMsN0F3SCoBPcIhcH21JDnWJgXiVPVbr0+v7/Cc9c=; b=4wH7Ajpl5ixBs31ymd0dxcsC3CuMqcWlqWslRa8VbTpR/6cKwW/12qQsvd9eYSaBBb LfIKX8y3xL79s9JwL8oWOPo6j6og7lmelcjfih60h8Fd/Hn+O/g2sZ2tuXnF1sFZKcGW jcSSpzl2DLi2mKuotmHG7Ff9G0LHpXsgkZ6G58+Icy/qRVBXwnCBRJzGWhrHrHGkR+Mx 6yF5YTrgUOh/juzo3tTvYa3WxAYyNuzj2+MgK77yeBQyer83OJAoHTV2pfA8zjsbUnq2 l1zEL73BphjXUK8cLQGocWuvs8yF+JK1/9P9W2apNcmMktaQOhmDlwbOLL0f2JtclotG vfSQ== X-Gm-Message-State: AOAM531LFHUK51otk/0mOjxigGnoaRCcr5wsyuj+HdrQ4+n3RbMQ/dkv r1GtaVqUSZSCftl0JYl71x0XDk5kDkI= X-Google-Smtp-Source: ABdhPJwl3+Ja0/1ddJyabSGmx1O/kWRXVGDZwIdC1lFF1ifae5hVWYXN0EcOEA4nFperA0+LiNO0gw== X-Received: by 2002:a1c:6a14:0:b0:383:a58c:3635 with SMTP id f20-20020a1c6a14000000b00383a58c3635mr7535416wmc.129.1646399493976; Fri, 04 Mar 2022 05:11:33 -0800 (PST) Received: from localhost.localdomain (230.2.7.51.dyn.plus.net. [51.7.2.230]) by smtp.gmail.com with ESMTPSA id c4-20020adffb04000000b001f0494de239sm4634042wrr.21.2022.03.04.05.11.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Mar 2022 05:11:33 -0800 (PST) From: Phillip Wood To: Git Mailing List Cc: carenas@gmail.com, Johannes Schindelin , Phillip Wood Subject: [PATCH 4/4] terminal: restore settings on SIGTSTP Date: Fri, 4 Mar 2022 13:11:26 +0000 Message-Id: <20220304131126.8293-5-phillip.wood123@gmail.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220304131126.8293-1-phillip.wood123@gmail.com> References: <20220304131126.8293-1-phillip.wood123@gmail.com> Reply-To: Phillip Wood MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Phillip Wood If the user suspends git while it is waiting for a keypress reset the terminal before stopping and restore the settings when git resumes. If the user tries to resume in the background print an error message (taking care to use async safe functions) before stopping again. Ideally we would reprint the prompt for the user when git resumes but this patch just restarts the read(). The signal handler is established with sigaction() rather than using sigchain_push() as this allows us to control the signal mask when the handler is invoked and ensure SA_RESTART is used to restart the read() when resuming. Signed-off-by: Phillip Wood --- compat/terminal.c | 124 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 4 deletions(-) diff --git a/compat/terminal.c b/compat/terminal.c index 5d516ff546..79ab54c2f8 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -1,4 +1,4 @@ -#include "git-compat-util.h" +#include "cache.h" #include "compat/terminal.h" #include "sigchain.h" #include "strbuf.h" @@ -23,6 +23,89 @@ static void restore_term_on_signal(int sig) static int term_fd = -1; static struct termios old_term; +static char *background_resume_msg; +static char *restore_error_msg; +static volatile sig_atomic_t ttou_received; + +static void write_msg(const char *msg) +{ + write_in_full(2, msg, strlen(msg)); + write_in_full(2, "\n", 1); +} + +static void print_background_resume_msg(int signo) +{ + int saved_errno = errno; + sigset_t mask; + struct sigaction old_sa; + struct sigaction sa = { .sa_handler = SIG_DFL }; + + ttou_received = 1; + write_msg(background_resume_msg); + sigaction(signo, &sa, &old_sa); + raise(signo); + sigemptyset(&mask); + sigaddset(&mask, signo); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + /* Stopped here */ + sigprocmask(SIG_BLOCK, &mask, NULL); + sigaction(signo, &old_sa, NULL); + errno = saved_errno; +} + +static void restore_terminal_on_suspend(int signo) +{ + int saved_errno = errno; + int res; + struct termios t; + sigset_t mask; + struct sigaction old_sa; + struct sigaction sa = { .sa_handler = SIG_DFL }; + int can_restore = 1; + + if (tcgetattr(term_fd, &t) < 0) + can_restore = 0; + + if (tcsetattr(term_fd, TCSAFLUSH, &old_term) < 0) + write_msg(restore_error_msg); + + sigaction(signo, &sa, &old_sa); + raise(signo); + sigemptyset(&mask); + sigaddset(&mask, signo); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + /* Stopped here */ + sigprocmask(SIG_BLOCK, &mask, NULL); + sigaction(signo, &old_sa, NULL); + if (!can_restore) { + write_msg(restore_error_msg); + goto out; + } + /* + * If we resume in the background then we receive SIGTTOU when calling + * tcsetattr() below. Set up a handler to print an error message in that + * case. + */ + sigemptyset(&mask); + sigaddset(&mask, SIGTTOU); + sa.sa_mask = old_sa.sa_mask; + sa.sa_handler = print_background_resume_msg; + sa.sa_flags = SA_RESTART; + sigaction(SIGTTOU, &sa, &old_sa); + again: + ttou_received = 0; + sigprocmask(SIG_UNBLOCK, &mask, NULL); + res = tcsetattr(term_fd, TCSAFLUSH, &t); + sigprocmask(SIG_BLOCK, &mask, NULL); + if (ttou_received) + goto again; + else if (res < 0) + write_msg(restore_error_msg); + sigaction(SIGTTOU, &old_sa, NULL); + out: + errno = saved_errno; +} + void restore_term(void) { if (term_fd < 0) @@ -32,10 +115,19 @@ void restore_term(void) close(term_fd); term_fd = -1; sigchain_pop_common(); + if (restore_error_msg) { + signal(SIGTTIN, SIG_DFL); + signal(SIGTTOU, SIG_DFL); + signal(SIGTSTP, SIG_DFL); + FREE_AND_NULL(restore_error_msg); + FREE_AND_NULL(background_resume_msg); + } } int save_term(unsigned flags) { + struct sigaction sa; + if (term_fd < 0) term_fd = (flags & SAVE_TERM_STDIN) ? 0 : open("/dev/tty", O_RDWR); @@ -44,6 +136,26 @@ int save_term(unsigned flags) if (tcgetattr(term_fd, &old_term) < 0) return -1; sigchain_push_common(restore_term_on_signal); + /* + * If job control is disabled then the shell will have set the + * disposition of SIGTSTP to SIG_IGN. + */ + sigaction(SIGTSTP, NULL, &sa); + if (sa.sa_handler == SIG_IGN) + return 0; + + /* avoid calling gettext() from signal handler */ + background_resume_msg = xstrdup(_("error: cannot resume in the background")); + restore_error_msg = xstrdup(_("error: cannot restore terminal settings")); + sa.sa_handler = restore_terminal_on_suspend; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGTSTP); + sigaddset(&sa.sa_mask, SIGTTIN); + sigaddset(&sa.sa_mask, SIGTTOU); + sigaction(SIGTSTP, &sa, NULL); + sigaction(SIGTTIN, &sa, NULL); + sigaction(SIGTTOU, &sa, NULL); return 0; } @@ -93,6 +205,7 @@ static int getchar_with_timeout(int timeout) fd_set readfds; int res; + again: if (timeout >= 0) { tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; @@ -102,9 +215,12 @@ static int getchar_with_timeout(int timeout) FD_ZERO(&readfds); FD_SET(0, &readfds); res = select(1, &readfds, NULL, NULL, tvp); - if (res < 0) - return EOF; - + if (res < 0) { + if (errno == EINTR) + goto again; + else + return EOF; + } return getchar(); }