Signed-off-by: Soumendra Ganguly <[email protected]>
---
--- src/usr.bin/script/script.c 2020-08-04 02:41:13.226129480 -0500
+++ script.c    2020-08-04 14:13:00.240012281 -0500
@@ -132,7 +132,7 @@
        if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL)
                err(1, "%s", fname);

-       if (isatty(0)) {
+       if (isatty(STDIN_FILENO)) {
                if (tcgetattr(STDIN_FILENO, &tt) == 0 &&
                    ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == 0)
                        istty = 1;
@@ -147,13 +147,13 @@
                cfmakeraw(&rtt);
                rtt.c_lflag &= ~ECHO;
                (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
-       }

-       bzero(&sa, sizeof sa);
-       sigemptyset(&sa.sa_mask);
-       sa.sa_handler = handlesigwinch;
-       sa.sa_flags = SA_RESTART;
-       (void)sigaction(SIGWINCH, &sa, NULL);
+               bzero(&sa, sizeof sa);
+               sigemptyset(&sa.sa_mask);
+               sa.sa_handler = handlesigwinch;
+               sa.sa_flags = SA_RESTART;
+               (void)sigaction(SIGWINCH, &sa, NULL);
+       }

        child = fork();
        if (child == -1) {


On 8/4/20, Soumendra Ganguly <[email protected]> wrote:
> Hello.
>
> On 8/4/20, Ingo Schwarze <[email protected]> wrote:
>> Hi,
>>
>> Soumendra Ganguly wrote on Tue, Aug 04, 2020 at 01:32:33AM -0500:
>>
>>> Program: script(1)
>>>
>>> Issue description: Currently, script(1) passes &tt and &win to openpty
>>> even when isatty(0) == 0. Also, the SIGWINCH handler does not check if
>>> stdin is a tty.
>>>
>>> The patch follows [ also attached ].
>>
>> Don't do that.  Just inline is enough, avoid attachments if you can.
>>
>
> Henceforth, I will avoid attachments.
>
>>
>>> Signed-off-by: Soumendra Ganguly <[email protected]>
>>> ---
>>> --- src/usr.bin/script/script.c     2020-08-03 21:33:44.636187087 -0500
>>> +++ script.c        2020-08-04 01:03:15.925066340 -0500
>>> @@ -74,18 +74,18 @@
>>>  #include <util.h>
>>>  #include <err.h>
>>>
>>> -FILE       *fscript;
>>> -int        master, slave;
>>> +static FILE *fscript;
>>> +static int master, slave;
>>
>> Please do not mix style changes into bugfix patches;
>> they unnecessarily make review harder.
>>
>
> Do you want me to revert these changes?
>
>>>  volatile sig_atomic_t child;
>>> -pid_t      subchild;
>>> -char       *fname;
>>> +static pid_t subchild;
>>> +static char *fname;
>>
>> dto.
>>
>>>  volatile sig_atomic_t dead;
>>>  volatile sig_atomic_t sigdeadstatus;
>>>  volatile sig_atomic_t flush;
>>>
>>> -struct     termios tt;
>>> -int                istty;
>>> +static int istty;
>>> +static struct termios tt;
>>
>> dto.
>>
>>>  __dead void done(int);
>>>  void dooutput(void);
>>> @@ -132,13 +132,18 @@
>>>     if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL)
>>>             err(1, "%s", fname);
>>>
>>> -   if (isatty(0)) {
>>> -           if (tcgetattr(STDIN_FILENO, &tt) == 0 &&
>>> -               ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == 0)
>>> -                   istty = 1;
>>> +   istty = isatty(STDIN_FILENO);
>>> +   if (istty) {
>>
>> This does not look correct.  The existing code only sets istty
>> if isatty(3), tcgetattr(3), and TIOCGWINSZ all succeed.
>> With your change, it is set even if tcgetattr(3) or TIOCGWINSZ
>> fail.
>>
>
> See next response.
>
>>> +           if (tcgetattr(STDIN_FILENO, &tt) == -1)
>>> +                   err(1, "tcgetattr");
>>> +           if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1)
>>> +                   err(1, "ioctl");
>>
>> This doesn't look correct either.  The existing code simply runs
>> without istty if either of these fails.
>> Why would you want to error out instead?
>>
>
> I checked the OpenBSD manpages for tcgetattr and ioctl. This is
> interesting.
>
> In the existing code, let us consider tcgetattr == 0 && ioctl == 0.
> tcgeattr can fail with ENOTTY and EINTR; ioctl can fail with ENOTTY. I
> am not sure, but can ioctl fail with ENOTTY at all if tcgetattr has
> already failed with ENOTTY? The ioctl manpage does give two different
> possibilities for ENOTTY whereas tcgetattr gives only one.
>
> In my code, I believe tcgetattr and ioctl will not fail with ENOTTY
> since istty is true already. Therefore, the check for ioctl error is
> redundant. However, what if tcgetattr fails with EINTR? Should we
> still continue?
>
> In fact, just FYI, I just cross checked that while FreeBSD is
> unnecessarily checking for ioctl error, the Linux version actually
> does if(tcgetattr == -1) then bail but does not bother to check for
> ioctl == -1. This seems to be correct. [
> https://github.com/karelzak/util-linux/blob/master/lib/pty-session.c ]
>
>>> +           if (openpty(&master, &slave, NULL, &tt, &win) == -1)
>>> +                   err(1, "openpty");
>>> +   } else {
>>> +           if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
>>> +                   err(1, "openpty");              
>>>
>>> -   if (openpty(&master, &slave, NULL, &tt, &win) == -1)
>>> -           err(1, "openpty");
>>
>> This is probably correct, there is no point in calling
>> tcsetattr(..., &tt) and ioctl(..., &winp) with tt and winp
>> full of zeros and without a usable terminal.
>>
>> Not sure it does actual harm though - is there a specific problem
>> you are trying to fix?
>>
>
> No. However, if you think that this need not be done, I would like to
> know. Honestly speaking, I have actually seen it being done on Linux
> and FreeBSD [ calling openpty separately if istty == 0 ]. If no harm
> is done by passing &tt and &win to openpty with stdin not a tty, then
> I will learn something new today (yay!) Also, I will check (later) if
> this behavior also works on Linux, FreeBSD, etc.
>
>>>     (void)printf("Script started, output file is %s\n", fname);
>>>     if (istty) {
>>> @@ -227,7 +232,7 @@
>>>     struct winsize win;
>>>     pid_t pgrp;
>>>
>>> -   if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) != -1) {
>>> +   if (istty && ioctl(STDIN_FILENO, TIOCGWINSZ, &win) != -1) {
>>>             ioctl(slave, TIOCSWINSZ, &win);
>>>             if (ioctl(slave, TIOCGPGRP, &pgrp) != -1)
>>>                     killpg(pgrp, SIGWINCH);
>>
>> This looks potentially correct, too.  Though strictly speaking,
>> it would require making the istty variable volatile sig_atomic_t.
>>
>> Then again, in this case, the signal handler does nothing, so why
>> even call it?  If you want to change this, wouldn't it make more
>> sense to not install this signal handler in the first place
>> if istty is not set?
>>
>
> I realized the fact that it should be sig_atomic_t. In fact, I also
> realized that it is better to not register the handler at all if istty
> == 0. That is what my updated diff attachment was doing. Why should we
> unnecessarily register a handler if not necessary and make meaningless
> ioctl calls? I will send a new patch that only makes this one change
> for now.
>
>> Either way, this patch is clearly not ready for commit.
>> Can any developer with experience in terminal handling
>> comment on whether
>>
>>  * passing empty structures to openpty()
>>  * calling the ioctl()s in handlesigwinch()
>>
>> are really problematic if !istty, and worth fixing?
>>
>> Yours,
>>   Ingo
>>
>
> Thank you.
>

Reply via email to