9fans / plan9port

Plan 9 from User Space
https://9fans.github.io/plan9port/
Other
1.64k stars 326 forks source link

`tail +1c` doesn't work when stdin is from terminal #499

Open falsifian opened 3 years ago

falsifian commented 3 years ago

Running in xterm:

falsifian moth ~ $ 9 tail +1c
hello
hello
falsifian moth ~ $ echo hello | 9 tail +1c
ello

For some reason, in the first case, it's not skipping the "h". The effect is similar with numbers other than 1.

This is plan9port-20210323 from OpenBSD ports, which should be at commit 88a87fadae6629932d9c160f53ad5d79775f8f94

orthros commented 3 years ago

This seems to be an OpenBSD Issue, or has been resolved by a later commit. I tried it on Debian at commit 70cc6e5ba7798b315c3fb3aae19620a01604a459, and the behaviour seems consistent.

root@ae6a19674251:/src/plan9port# 9 tail +1c
hello
ello
^C
root@ae6a19674251:/src/plan9port# echo hello | 9 tail +1c
ello
root@ae6a19674251:/src/plan9port# 

I'll try on an OpenBSD machine later today and see if I can reproduce.

orthros commented 3 years ago

Just installed OpenBSD from the amd64/install69.iso into a VM, ran pkg_add git, cloned this repository at 70cc6e5ba7798b315c3fb3aae19620a01604a459 and ran ./INSTALL

planport# 9 tail +1c
hello
hello
^C
planport# echo "hello" | 9 tail +1c
ello

So the issue is for sure not fixed after 88a87fadae6629932d9c160f53ad5d79775f8f94.

I suspect there is some issue with the way STDIN is being read by the utility on BSD systems (but not Linux). Will take a look at some point, but I'm not terribly familiar with BSD systems so I might not be a great help.

falsifian commented 3 years ago

Thanks for taking the time to reproduce it.

I can also take a look, but it might be a few days before I get around to it. I'm not deeply familiar with the quirks of reading, writing and terminals but it could be a learning experience for me.

jxy commented 3 years ago

From truss(1) on FreeBSD,

[ ... omit ...]
getcontext(0x7fffffffd320)                       = 0 (0x0)
sysarch(AMD64_GET_XFPUSTATE,0x7fffffffd2e8)      = 0 (0x0)
mprotect(0x20f000,4096,PROT_READ)                = 0 (0x0)
getpid()                                         = 63815 (0xf947)
lseek(0,0x0,SEEK_SET)                            = 0 (0x0)
lseek(0,0x1,SEEK_SET)                            = 1 (0x1)
hello
read(0,"hello\n",8192)                           = 6 (0x6)
hello
write(1,"hello\n",6)                             = 6 (0x6)

comparing to using pipe,

[ ... omit ...]
getcontext(0x7fffffffd320)                       = 0 (0x0)
sysarch(AMD64_GET_XFPUSTATE,0x7fffffffd2e8)      = 0 (0x0)
mprotect(0x20f000,4096,PROT_READ)                = 0 (0x0)
getpid()                                         = 68480 (0x10b80)
lseek(0,0x0,SEEK_SET)                            ERR#29 'Illegal seek'
read(0,"h",1)                                    = 1 (0x1)
read(0,"ello\n",8192)                            = 5 (0x5)
ello
write(1,"ello\n",5)                              = 5 (0x5)

comparing to strace(1) on Linux,

[ ... omit ...]
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
getpid()                                = 126670
lseek(0, 0, SEEK_SET)                   = -1 ESPIPE (Illegal seek)
read(0, hello
"h", 1)                         = 1
read(0, "ello\n", 8192)                 = 5
write(1, "ello\n", 5ello
)                   = 5

which means the line seekable = seek(file,0L,0) == 0; makes seekable = 1 with file = 0 and is not a proper test on BSD when input is from tty.