Which file descriptor should be used in ioctl to know terminal screen size? - rust

I want to reliably know terminal size even when the application is running in a subshell.
It seems like the only working way is to use stdin fd, but I would like to know why have links to documentation that proves it.
There's a lot of questions like why would one even use stdout (or stdin for that matter) fd to know terminal size?
fn main() {
let mut size = winsize {
ws_row: 0,
ws_col: 0,
ws_xpixel: 0,
ws_ypixel: 0,
};
let fd = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/tty")
.map(|file| file.as_raw_fd())
.unwrap()
;
unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut size) };
println!("/dev/tty cols: {}, lines: {}", size.ws_row, size.ws_col);
unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ.into(), &mut size) };
println!("stdout cols: {}, lines: {}", size.ws_row, size.ws_col);
unsafe { ioctl(STDERR_FILENO, TIOCGWINSZ.into(), &mut size) };
println!("stderr cols: {}, lines: {}", size.ws_row, size.ws_col);
unsafe { ioctl(STDIN_FILENO, TIOCGWINSZ.into(), &mut size) };
println!("stdin cols: {}, lines: {}", size.ws_row, size.ws_col);
}
I ran echo (cargo run 2>&1) in the fish shell and got this:
Compiling test_term_size v0.1.0 (/home/m/code/test_term_size) warning: unused import: `File` --> src/main.rs:2:15 | 2 | use std::fs::{File}; | ^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused imports: `O_RDWR`, `open` --> src/main.rs:4:5 | 4 | O_RDWR, | ^^^^^^ 5 | open, ioctl, winsize, STDIN_FILENO, | ^^^^ Finished dev [unoptimized + debuginfo] target(s) in 0.21s Running `target/debug/test_term_size` /dev/tty cols: 0, lines: 0 stdout cols: 0, lines: 0 stderr cols: 0, lines: 0 stdin cols: 52, lines: 106
strace -e trace=ioctl,open target/debug/test_term_size
ioctl(3, TIOCGWINSZ, 0x7ffdb9805578) = -1 EBADF (Bad file descriptor)
/dev/tty cols: 0, lines: 0
ioctl(1, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdout cols: 52, lines: 213
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stderr cols: 52, lines: 213
ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdin cols: 52, lines: 213
+++ exited with 0 +++
strace -e trace=ioctl,open cargo run
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/test_term_size`
ioctl(3, TIOCGWINSZ, 0x7ffea819b008) = -1 EBADF (Bad file descriptor)
/dev/tty cols: 0, lines: 0
ioctl(1, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdout cols: 52, lines: 213
ioctl(2, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stderr cols: 52, lines: 213
ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0
stdin cols: 52, lines: 213
+++ exited with 0 +++
echo (strace -e trace=ioctl,open cargo run 2>&1)
ioctl(2, TCGETS, 0x7ffdae149cb0) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, TCGETS, 0x7ffdae149a30) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, TCGETS, 0x7ffdae149a30) = -1 ENOTTY (Inappropriate ioctl for device) ioctl(2, TCGETS, 0x7ffdae149540) = -1 ENOTTY (Inappropriate ioctl for device) warning: unused import: `File` --> src/main.rs:2:15 | 2 | use std::fs::{File}; | ^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused imports: `O_RDWR`, `open` --> src/main.rs:4:5 | 4 | O_RDWR, | ^^^^^^ 5 | open, ioctl, winsize, STDIN_FILENO, | ^^^^ Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/test_term_size` ioctl(3, TIOCGWINSZ, 0x7ffd8c3ae728) = -1 EBADF (Bad file descriptor) /dev/tty cols: 0, lines: 0 ioctl(1, TIOCGWINSZ, 0x7ffd8c3ae728) = -1 ENOTTY (Inappropriate ioctl for device) stdout cols: 0, lines: 0 ioctl(2, TIOCGWINSZ, 0x7ffd8c3ae728) = -1 ENOTTY (Inappropriate ioctl for device) stderr cols: 0, lines: 0 ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0 stdin cols: 52, lines: 213 +++ exited with 0 +++
echo (strace -e trace=ioctl,open target/debug/test_term_size 2>&1)
ioctl(3, TIOCGWINSZ, 0x7fffdc82e938) = -1 EBADF (Bad file descriptor) /dev/tty cols: 0, lines: 0 ioctl(1, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stdout cols: 0, lines: 0 ioctl(2, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stderr cols: 0, lines: 0 ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0 stdin cols: 52, lines: 213 +++ exited with 0 +++
echo (strace -e trace=ioctl,open target/debug/test_term_size 2>&1)
ioctl(3, TIOCGWINSZ, 0x7fffdc82e938) = -1 EBADF (Bad file descriptor) /dev/tty cols: 0, lines: 0 ioctl(1, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stdout cols: 0, lines: 0 ioctl(2, TIOCGWINSZ, 0x7fffdc82e938) = -1 ENOTTY (Inappropriate ioctl for device) stderr cols: 0, lines: 0 ioctl(0, TIOCGWINSZ, {ws_row=52, ws_col=213, ws_xpixel=3834, ws_ypixel=2028}) = 0 stdin cols: 52, lines: 213 +++ exited with 0 +++

The right source of TTY info is always /dev/tty. Don't use stdin or any other weird hacks. Here's why it looks like that isn't working for you:
let fd = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/tty")
.map(|file| file.as_raw_fd())
.unwrap()
;
You're opening /dev/tty and getting its FD, but the file is then getting dropped, and hence closed, before you can use it, so the ioctl on it fails with EBADF "Bad file descriptor". To fix the problem, either keep the file alive until after you're done using the raw FD, or use into_raw_fd instead of as_raw_fd and then close the raw FD yourself when you're done with it.

Related

USB serial console is not exiting from Linux device

I am working on an embedded linux device, and the kernel has support for a USB serial console. You can log in fine, but when you type 'exit', the session is not exited, and you get stuck.
> exit
# The session hangs here forever
Hotplugging is enabled, so you can start a new session by removing and plugging the cable back in, but I don't want to do that every time I exit.
dmesg doesn't print anything useful after I type exit, so something is stuck.
I also tried attaching strace to getty, and it looks like it exited normally
) = 1 ([{fd=0, revents=POLLIN}])
read(0, "\n", 1) = 1
write(1, "\n", 1) = 1
open("/root/.ash_history", O_WRONLY|O_CREAT|O_APPEND, 0600) = 3
_llseek(3, 0, [42052], SEEK_END) = 0
write(3, "exit\n", 5) = 5
close(3) = 0
ioctl(0, SNDCTL_TMR_START or TCSETS, {B115200 opost isig icanon echo ...}) = 0
rt_sigaction(SIGWINCH, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0xb6dadd61}, NULL, 8) = 0
wait4(-1, 0xbee98a2c, WNOHANG|WSTOPPED, NULL) = -1 ECHILD (No child processes)
ioctl(10, TIOCSPGRP, [2578]) = 0
setpgid(0, 2578) = -1 EPERM (Operation not permitted)
close(10) = 0
exit_group(0) = ?
+++ exited with 0 +++
What is causing this session to hang forever?

Implicit system calls in UNIX commands

I've been studying UNIX and system calls and I came across a low-level and tricky questions. The question asks what system calls are called for this command:
grep word1 word2 > file.txt
I did some research and I was unable to find a huge number of resources on the underlying UNIX calls. However, it seems to me that the answer would be open (to open and the file descriptor for the file file.txt), then dup2 (to change the STDOUT of grep to the file descriptor of open), then write to write the STDOUT of grep (which is now the file descriptor of file.txt), and finally close(), to close the file descriptor of file.txt... However, I have no idea if I am right or on the correct path, can anyone with experience in UNIX enlighten me on this topic?
You are on correct direction in your research. This command is very helpful to trace system calls in any program:
strace
On my PC it shows output (without stream redirection):
$ strace grep abc ss.txt
execve("/bin/grep", ["grep", "abc", "ss.txt"], [/* 237 vars */]) = 0
brk(0) = 0x13de000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1785694000
close(3) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
stat("ss.txt", {st_mode=S_IFREG|0644, st_size=13, ...}) = 0
open("ss.txt", O_RDONLY) = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffa0e4f370) = -1 ENOTTY (Inappropriate ioctl for device)
read(3, "abc\n123\n321\n\n", 32768) = 13
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f178568c000
write(1, "abc\n", 4abc
) = 4
read(3, "", 32768) = 0
close(3) = 0
close(1) = 0
munmap(0x7f178568c000, 4096) = 0
close(2) = 0
exit_group(0) = ?

How to start multiple processes inside a linux service construct?

I am attempting to start multiple memcached processes from the linux service framework using the following logic:
RETVAL=0
pcount="$CACHES"
if [ ! -z "$pcount" ]; then
while [ $pcount -gt 0 ];
do
(( pcount-- ))
(( port=PORT + pcount ))
daemon --pidfile ${pidfile}${pcount}.pid memcached -d -p $port -u $USER -m $CACHESIZE -c $MAXCONN -P ${pidfile}${pcount}.pid $OPTIONS
(( RETVAL=RETVAL + $? ))
done
else
daemon --pidfile ${pidfile}.pid memcached -d -p $PORT -u $USER -m $CACHESIZE -c $MAXCONN -P ${pidfile}.pid $OPTIONS
RETVAL=$?
fi
When run using the command service memcached start, it creates and updates pid files for each cycle in the loop, but only the last instance of the process remains running. That is, while each of the /var/run/memcached/memcached(1 through 5).pid are created and updated with a PID; those processes do not exist. /var/run/memcached/memcached0.pid is also created and updated and the PID points to a running process.
I turned on tracing and I can see that the loop is executed and the process invocation is made; however the process does not start (or likely, starts and immediately terminates so I dont see it as having started).
On the other hand, running this script directly as /etc/init.d/memcached start results in all the processes getting started correctly.
Can someone help me understand why the service framework is preventing the starting of the other instances except the last one?
As suggested by #nos, I added strace -f to trace the calls during the service memcached start operation. I compared the traced calls between the unsuccessful/terminated process and the successful process. The only lines of significant difference that I found were:
< bind(26, {sa_family=AF_INET, sin_port=htons(11216), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EACCES (Permission denied)
< dup(2) = 27
< fcntl(27, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE)
< fstat(27, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
< ioctl(27, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff20d5d780) = -1 ENOTTY (Inappropriate ioctl for device)
< mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5dae958000
< lseek(27, 0, SEEK_CUR) = 0
< write(27, "bind(): Permission denied\n", 26) = 26
< close(27) = 0
< munmap(0x7f5dae958000, 4096) = 0
< close(26) = 0
< dup(2) = 26
< fcntl(26, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE)
< fstat(26, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
< ioctl(26, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff20d5d730) = -1 ENOTTY (Inappropriate ioctl for device)
< mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5dae958000
< lseek(26, 0, SEEK_CUR) = 0
< write(26, "failed to listen on TCP port 112"..., 54) = 54
< close(26) = 0
< munmap(0x7f5dae958000, 4096) = 0
< exit_group(71) = ?
---
> bind(26, {sa_family=AF_INET, sin_port=htons(11211), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
> listen(26, 1024) = 0
> epoll_ctl(3, EPOLL_CTL_ADD, 26, {EPOLLIN, {u32=26, u64=26}}) = 0
> socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP) = 27
> fcntl(27, F_GETFL) = 0x2 (flags O_RDWR)
> fcntl(27, F_SETFL, O_RDWR|O_NONBLOCK) = 0
> setsockopt(27, SOL_IPV6, IPV6_V6ONLY, [1], 4) = 0
> setsockopt(27, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> setsockopt(27, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
> setsockopt(27, SOL_SOCKET, SO_LINGER, {onoff=0, linger=0}, 8) = 0
> setsockopt(27, SOL_TCP, TCP_NODELAY, [1], 4) = 0
> bind(27, {sa_family=AF_INET6, sin6_port=htons(11211), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
> listen(27, 1024) = 0
> epoll_ctl(3, EPOLL_CTL_ADD, 27, {EPOLLIN, {u32=27, u64=27}}) = 0
> socket(PF_NETLINK, SOCK_RAW, 0) = 28
> bind(28, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
> getsockname(28, {sa_family=AF_NETLINK, pid=31943, groups=00000000}, [12]) = 0
> gettimeofday({1393735036, 191154}, NULL) = 0
> sendto(28, "\24\0\0\0\26\0\1\3|\265\22S\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
> recvmsg(28, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0|\265\22S\307|\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 108
> recvmsg(28, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"#\0\0\0\24\0\2\0|\265\22S\307|\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 128
> recvmsg(28, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0|\265\22S\307|\0\0\0\0\0\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
> close(28) = 0
> socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 28
The top (<) one being from a terminated process and bottom one (>) from the last (successful) process. It is clear that the process is terminating due to lack of permission to bind to the port. On looking further, I realized that the SELinux was set to ENFORCE, which was preventing the memcached service from binding to port other than 11211 (the default port).
To the best of what I could figure, when I was running it without the service command, the behavior was simply that of a process (not a service) and hence the binding was not being enforced.
Turning off the ENFORCED mode of SELinux, got the service memcached start command working!

Perforce strange 10s delay/lag on some commands [raspberry-pi / cubieboard]

i am trying to setup perforce server on cubieboard2 (raspberry-pi clone)
i have downloaded p4d and p4 for Linux ARM (2011.1)
i am running server like this:
p4d -d -r root_path -p 12345 -L log
statistics of running commands directly on server machine (server ip 192.168.1.1)
p4 -p 12345 users # it returns immediately
p4 -p 127.0.0.1:12345 users # it returns immediately
p4 -p localhost:12345 users # it returns immediately
p4 -p 192.168.1.1:12345 users # it returns immediately
p4 -p 12345 info # it returns immediately
p4 -p 127.0.0.1:12345 info # it returns immediately
p4 -p localhost:12345 info # it returns immediately
p4 -p 192.168.1.1:12345 info # returns after ~10 sec
i want to connect to this perforce server from my windows pc, since i am in LAN with the server, i am connecting with p4 -p 192.168.1.1:12345 users command returns immediately, info with 10sec lag (using p4 on my windows pc)
i didn't checked other commands, i am unable to connect with p4Admin or p4v, they hang/do nothing, thus my server is unusable
starting server with
p4d -d -r root_path -p 192.168.1.1:12345 -L log
makes it impossible to run commands with p4 -p 12345 or localhost:12345 or 127.0.0.1:12345
but its same story with 192.168.1.1:12345
Note. i am also running ftp on it, and it runs fine, when connecting through 192.168.1.1
Edit. added strace log for p4d
strace of 'p4 -p 192.168.1.1:12345 users' ran from win7 pc (ip ends with '13', returns immed.)
{sa_family=AF_INET, sin_port=htons(61483), sin_addr=inet_addr("192.168.1.13")}, [16]) = 4
fcntl64(4, F_SETFD, FD_CLOEXEC) = 0
fcntl64(4, F_GETFL) = 0x2 (flags O_RDWR)
fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
setsockopt(4, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
rt_sigaction(SIGCHLD, {0x16d160, [CHLD], SA_RESTART|0x4000000}, {0x16d160, [CHLD], SA_RESTART|0x4000000}, 8) = 0
wait4(-1, 0xbea31744, WNOHANG, NULL) = -1 ECHILD (No child processes)
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb6e45068) = 2890
close(4) = 0
gettimeofday({1380359365, 320807}, NULL) = 0
accept(3, 0xbea31734, [16]) = ? ERESTARTSYS (To be restarted)
--- SIGCHLD (Child exited) # 0 (0) ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2890
wait4(-1, 0xbea3141c, WNOHANG, NULL) = -1 ECHILD (No child processes)
rt_sigaction(SIGCHLD, {0x16d160, [CHLD], SA_RESTART|0x4000000}, {0x16d160, [CHLD], SA_RESTART|0x4000000}, 8) = 0
sigreturn() = ? (mask now [HUP INT QUIT])
accept(3,
strace for p4 -p 192.168.1.1:12345 info
{sa_family=AF_INET, sin_port=htons(61486), sin_addr=inet_addr("192.168.1.13")}, [16]) = 4
fcntl64(4, F_SETFD, FD_CLOEXEC) = 0
fcntl64(4, F_GETFL) = 0x2 (flags O_RDWR)
fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
setsockopt(4, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
rt_sigaction(SIGCHLD, {0x16d160, [CHLD], SA_RESTART|0x4000000}, {0x16d160, [CHLD], SA_RESTART|0x4000000}, 8) = 0
wait4(-1, 0xbea31744, WNOHANG, NULL) = -1 ECHILD (No child processes)
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb6e45068) = 2894
close(4) = 0
gettimeofday({1380359462, 822219}, NULL) = 0
accept(3,
now it lags, and after, following lines appear
0xbea31734, [16]) = ? ERESTARTSYS (To be restarted)
--- SIGCHLD (Child exited) # 0 (0) ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 2894
wait4(-1, 0xbea3141c, WNOHANG, NULL) = -1 ECHILD (No child processes)
rt_sigaction(SIGCHLD, {0x16d160, [CHLD], SA_RESTART|0x4000000}, {0x16d160, [CHLD], SA_RESTART|0x4000000}, 8) = 0
sigreturn() = ? (mask now [HUP INT QUIT])
accept(3,
its not telling me much, but as you can see, the exact same line
accept(3, 0xbea31734, [16]) = ? ERESTARTSYS (To be restarted)
appears in both logs, and on the latter it stops for 10 sec after 'accept(3, '
As for swap, i had it enabled as swap file on external drive connected to the board, while i am booting from sd-card, either way, no change after disabling it.

Program shows console output even though stdout and stderr are redirected

How does the vncpasswd program produce output on the console even though both standard out and standard error have been redirected to /dev/null?
$ vncpasswd > /dev/null 2> /dev/null
Password:
Edit: Here's a partial strace:
open("/dev/tty", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(3, SNDCTL_TMR_CONTINUE or TCSETSF, {B38400 opost -isig icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost -isig icanon -echo ...}) = 0
fstat(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(5, 0), ...}) = 0
ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost -isig icanon -echo ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb7c3eda000
write(3, "Password: ", 10Password: ) = 10
read(3,
It's opening the underlying terminal directly (something like open("/dev/tty", ...)). No amount of redirecting will get rid of that. If you don't want to see it, you'll have to run it not attached to a tty (e.g. through cron or something).
It opens your terminal and writes there:
open("/dev/tty", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 3
...
write(3, "Password: ", 10Password: ) = 10
Run it under setsid if you want to make that impossible.
You're just redirecting stderr to /dev/null try vncpasswd &> /dev/null instead.

Resources