tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: flock(2): locking against itself?



On Sun, 16 Apr 2023, Mouse wrote:

In particular, I wrote

[...].  I have a program that uses curses for output but wants to do
non-blocking input.  So I set stdin nonblocking and threw fd 0 into
the poll() loop.

But, in normal use, stdin and stdout come from the same open on the
session's tty, so setting stdin nonblocking also sets stdout
nonblocking, which curses is not prepared to handle, leading to large
screen updates getting partially lost.


I think O_NONBLOCK on an input FD would be a problem too for curses.
Otherwise, if only a non-blocking output were the problem, then you
could just re-open the current tty twice and juggle the FDs like this:

```
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int
main(void)
{
	char* tty;
	int fd1, fd2, flg;

	if ((tty = ttyname(STDIN_FILENO)) == NULL)
		err(1, "ttyname failed");

	if ((fd1 = open(tty, O_RDWR)) == -1)
		err(1, "open for FD 0 failed");

	if ((fd2 = open(tty, O_RDWR)) == -1)
		err(1, "open for FDs 1 & 2 failed");

	if (dup2(fd1, 0) == -1)
		err(1, "dup 0 failed");

	if (dup2(fd2, 1) == -1)
		err(1, "dup 1 failed");

	if (dup2(fd2, 2) == -1)
		err(1, "dup 2 failed");

	if (close(fd1) == -1)
		err(1, "close fd1 failed");

	if (close(fd2) == -1)
		err(1, "close fd2 failed");

	if ((flg = fcntl(STDIN_FILENO, F_GETFL, 0)) == -1)
		err(1, "fcntl F_GETFL failed");

	if (fcntl(STDIN_FILENO, F_SETFL, flg | O_NONBLOCK) == -1)
		err(1, "fcntl F_SETFL failed");

	execl("/usr/bin/vi", "vi", NULL);
	err(1, "exec /usr/bin/vi failed");
}
```

But, vi, at least, fails to run like this. So, I think using a pty is
the simplest, not to say standard, solution here...

-RVP


Home | Main Index | Thread Index | Old Index