I'm writing & deploying a bbs for toorcamp happening soon and my project basically sums down to: I want a unix shell box with the following features
- social components, such as
wall,write,talk,finger, maybenethackleaderboards - I want utility components such as rootless docker, userspace nix, web hosting
- I want some old-school services such as
chargen,echo,discard,daytime,qotd
important context: I'm running on debian trixie (as of 2026-06-12)
what does work:
last:
(with an apt install wtmpdb, apparently the previous last got deprecated)
$ last
io pts/1 10.200.254.12 Thu Jun 11 14:41 - still logged in
m pts/0 10.200.254.12 Thu Jun 11 14:41 - still logged in
m pts/0 10.200.254.12 Thu Jun 11 14:41 - 14:41 (00:00)
m pts/3 10.200.254.12 Thu Jun 11 14:41 - 14:41 (00:00)
io pts/2 10.200.254.12 Thu Jun 11 14:41 - 14:41 (00:00)
debian pts/0 10.200.254.12 Thu Jun 11 14:41 - 14:41 (00:00)
io pts/3 10.200.254.12 Thu Jun 11 14:41 - 14:41 (00:00)
m pts/2 10.200.254.12 Thu Jun 11 14:41 - 14:41 (00:00)
io pts/3 10.200.254.12 Thu Jun 11 14:35 - 14:41 (00:05)
m pts/2 10.200.254.12 Thu Jun 11 14:35 - 14:41 (00:05)
m pts/2 10.200.254.12 Thu Jun 11 14:35 - 14:35 (00:00)
m pts/2 10.200.254.12 Thu Jun 11 14:34 - 14:35 (00:00)
debian pts/0 10.200.254.12 Thu Jun 11 14:29 - 14:41 (00:12)
root pts/0 10.200.254.12 Thu Jun 11 14:29 - 14:29 (00:00)
debian pts/0 10.200.254.13 Sun Jun 7 20:45 - 20:47 (00:01)
wtmpdb begins Sun Jun 7 20:45:52 2026
who:
$ who
io sshd pts/1 2026-06-11 14:41 (10.200.254.12)
m sshd pts/0 2026-06-11 14:41 (10.200.254.12)
w:
$ w
14:48:39 up 24 min, 2 users, load average: 0.00, 0.01, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
io pts/1 10.200.254.12 14:41 6:23 0.02s 0.02s -bash
m pts/0 10.200.254.12 14:41 0.00s 0.03s ? w
and, of note, this is loginctl's output:
$ loginctl
SESSION UID USER SEAT LEADER CLASS TTY IDLE SINCE
14 1001 m - 1357 user - no -
15 1002 io - 1372 user - no -
6 1001 m - 1153 manager - no -
9 1002 io - 1208 manager - no -
4 sessions listed.
what's going on with loginctl's output?
kind of spoilers, but if you notice, loginctl isn't listing any TTYs even if w & who are. what gives?
long story short, but systemd & loginctl and a bunch of other tools are writing to & reading from /run/systemd/sessions/$1 and if you investigate one of these files associatated with my login session:
$ cat /run/systemd/sessions/14
# This is private data. Do not parse.
UID=1001
USER=m
ACTIVE=1
IS_DISPLAY=1
STATE=active
REMOTE=1
LEADER_FD_SAVED=1
TYPE=tty
ORIGINAL_TYPE=tty
CLASS=user
SCOPE=session-14.scope
FIFO=/run/systemd/sessions/14.ref
REMOTE_HOST=10.200.254.12
SERVICE=sshd
POSITION=0
LEADER=1357
AUDIT=14
REALTIME=1781188907150666
there's no tty info! even when TYPE=tty
how are wall and w working?
we're not looking at source code (for now).
who
let's see what w or who does, since those are successfully getting the tty
$ strace who
execve("/usr/bin/who", ["who"], 0x7ffcba8a7b20 /* 20 vars */) = 0
...
access("/var/run/utmpx", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/var/run/utmp", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
access("/var/run/utmpx", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/var/run/utmp", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/var/lib/systemd/random-seed", {st_mode=S_IFREG|0600, st_size=32, ...}, 0) = 0
openat(AT_FDCWD, "/run/systemd/sessions/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=200, ...}) = 0
getdents64(3, 0x560de641ddb0 /* 10 entries */, 32768) = 272
getdents64(3, 0x560de641ddb0 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/dev/pts", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
getdents64(3, 0x560de6425ec0 /* 5 entries */, 32768) = 120
newfstatat(AT_FDCWD, "/dev/pts/1", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/ptmx", {st_mode=S_IFCHR|000, st_rdev=makedev(0x5, 0x2), ...}, 0) = 0
getdents64(3, 0x560de6425ec0 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
kill(1372, 0) = -1 EPERM (Operation not permitted)
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/dev/pts", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
getdents64(3, 0x560de6425ec0 /* 5 entries */, 32768) = 120
newfstatat(AT_FDCWD, "/dev/pts/1", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/ptmx", {st_mode=S_IFCHR|000, st_rdev=makedev(0x5, 0x2), ...}, 0) = 0
getdents64(3, 0x560de6425ec0 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
kill(1357, 0) = -1 EPERM (Operation not permitted)
openat(AT_FDCWD, "/run/systemd/sessions/9", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 305
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/9", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 305
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/9", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 305
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/9", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 305
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/6", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 304
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/6", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 304
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/6", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 304
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/6", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 304
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/dev", O_RDONLY|O_PATH|O_DIRECTORY) = 3
newfstatat(3, "pts/1", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1), ...}, 0) = 0
...
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
write(1, "io sshd pts/1 2026-06-11"..., 55io sshd pts/1 2026-06-11 14:41 (10.200.254.12)
) = 55
newfstatat(3, "pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
newfstatat(AT_FDCWD, "/etc/localtime", {st_mode=S_IFREG|0644, st_size=114, ...}, 0) = 0
write(1, "m sshd pts/0 2026-06-11"..., 55m sshd pts/0 2026-06-11 14:41 (10.200.254.12)
) = 55
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
this makes a lot of sense to me. it's using systemd sessions (although it tries to use utmp, first) but is also parsing the dirstat at /dev/pts/ to presumably map the pseudoterminals to systemd sessions? Unsure how it's making these mappings honestly.
also, I have no idea what that kill is doing in there. Maybe to help with the mappings?
w
$ strace w
execve("/usr/bin/w", ["w"], 0x7ffd474edfd0 /* 20 vars */) = 0
...
openat(AT_FDCWD, "/proc", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f57cafd8000
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f57cafb7000
mmap(NULL, 233472, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f57caf7e000
getdents64(3, 0x56231688e370 /* 148 entries */, 32768) = 3904
newfstatat(AT_FDCWD, "/proc/1", {st_mode=S_IFDIR|0555, st_size=0, ...}, 0) = 0
openat(AT_FDCWD, "/proc/1/stat", O_RDONLY) = 4
read(4, "1 (systemd) S 0 1 1 0 -1 4194560"..., 1024) = 186
close(4) = 0
openat(AT_FDCWD, "/proc/1/status", O_RDONLY) = 4
read(4, "Name:\tsystemd\nUmask:\t0000\nState:"..., 1024) = 1024
read(4, "000,00000000,00000000,00000000,0"..., 1024) = 418
close(4) = 0
openat(AT_FDCWD, "/proc/1/cmdline", O_RDONLY) = 4
read(4, "/sbin/init\0", 131072) = 11
read(4, "", 131061) = 0
close(4) = 0
openat(AT_FDCWD, "/proc/1/ctty", O_RDONLY) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/proc/2", {st_mode=S_IFDIR|0555, st_size=0, ...}, 0) = 0
openat(AT_FDCWD, "/proc/2/stat", O_RDONLY) = 4
read(4, "2 (kthreadd) S 0 0 0 0 -1 212998"..., 2048) = 151
close(4) = 0
openat(AT_FDCWD, "/proc/2/status", O_RDONLY) = 4
read(4, "Name:\tkthreadd\nUmask:\t0000\nState"..., 2048) = 1055
close(4) = 0
openat(AT_FDCWD, "/proc/2/cmdline", O_RDONLY) = 4
read(4, "", 131072) = 0
close(4) = 0
openat(AT_FDCWD, "/proc/2/ctty", O_RDONLY) = -1 ENOENT (No such file or directory)
...
...does this for literally every process lol
...
newfstatat(AT_FDCWD, "/proc/1615", {st_mode=S_IFDIR|0555, st_size=0, ...}, 0) = 0
openat(AT_FDCWD, "/proc/1615/stat", O_RDONLY) = 4
read(4, "1615 (strace) S 1366 1615 1366 3"..., 2048) = 321
close(4) = 0
openat(AT_FDCWD, "/proc/1615/status", O_RDONLY) = 4
read(4, "Name:\tstrace\nUmask:\t0002\nState:\t"..., 2048) = 1499
close(4) = 0
openat(AT_FDCWD, "/proc/1615/cmdline", O_RDONLY) = 4
read(4, "strace\0w\0", 131072) = 9
read(4, "", 131063) = 0
close(4) = 0
openat(AT_FDCWD, "/proc/1615/ctty", O_RDONLY) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/dev/pts0", 0x7ffdf5b3be30, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
newfstatat(AT_FDCWD, "/proc/1618", {st_mode=S_IFDIR|0555, st_size=0, ...}, 0) = 0
openat(AT_FDCWD, "/proc/1618/stat", O_RDONLY) = 4
read(4, "1618 (w) R 1615 1615 1366 34816 "..., 2048) = 302
close(4) = 0
openat(AT_FDCWD, "/proc/1618/status", O_RDONLY) = 4
read(4, "Name:\tw\nUmask:\t0002\nState:\tR (ru"..., 2048) = 1492
close(4) = 0
openat(AT_FDCWD, "/proc/1618/cmdline", O_RDONLY) = 4
read(4, "w\0", 131072) = 2
read(4, "", 131070) = 0
close(4) = 0
openat(AT_FDCWD, "/proc/1618/ctty", O_RDONLY) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/dev/pts0", 0x7ffdf5b3be30, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
getdents64(3, 0x56231688e370 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/etc/localtime", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=114, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=114, ...}) = 0
read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 114
lseek(3, -60, SEEK_CUR) = 54
read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 60
close(3) = 0
openat(AT_FDCWD, "/proc/uptime", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "1903.81 1819.97\n", 1024) = 16
close(3) = 0
faccessat2(AT_FDCWD, "/run/systemd/system/", F_OK, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "/run/systemd/sessions/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=200, ...}) = 0
getdents64(3, 0x56231689a900 /* 10 entries */, 32768) = 272
getdents64(3, 0x56231689a900 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/9", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 305
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/6", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 304
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/proc/loadavg", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "0.00 0.02 0.00 3/91 1618\n", 1024) = 25
close(3) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
write(1, " 14:55:30 up 31 min, 2 users, "..., 63 14:55:30 up 31 min, 2 users, load average: 0.00, 0.02, 0.00
) = 63
write(1, "USER TTY FROM "..., 69USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
) = 69
openat(AT_FDCWD, "/run/systemd/sessions/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=200, ...}) = 0
getdents64(3, 0x56231689a900 /* 10 entries */, 32768) = 272
getdents64(3, 0x56231689a900 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
newfstatat(AT_FDCWD, "/dev/pts/1", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1), ...}, 0) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
newfstatat(AT_FDCWD, "/etc/localtime", {st_mode=S_IFREG|0644, st_size=114, ...}, 0) = 0
newfstatat(AT_FDCWD, "/etc/localtime", {st_mode=S_IFREG|0644, st_size=114, ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/1", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1), ...}, 0) = 0
write(1, "io pts/1 10.200.254.12 "..., 70io pts/1 10.200.254.12 14:41 13:14 0.02s 0.02s -bash
) = 70
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
newfstatat(AT_FDCWD, "/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
newfstatat(AT_FDCWD, "/etc/localtime", {st_mode=S_IFREG|0644, st_size=114, ...}, 0) = 0
newfstatat(AT_FDCWD, "/etc/localtime", {st_mode=S_IFREG|0644, st_size=114, ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
write(1, "m pts/0 10.200.254.12 "..., 66m pts/0 10.200.254.12 14:41 1.00s 0.07s ? w
) = 66
openat(AT_FDCWD, "/run/systemd/sessions/9", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 305
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/6", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 304
read(3, "", 4096) = 0
close(3) = 0
munmap(0x7f57caf7e000, 233472) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
here, we can see similary to who except it's also parsing the entire process tree? and doesn't attempt to open utmp
aside: what is utmp?
https://en.wikipedia.org/wiki/Utmp
https://man7.org/linux/man-pages/man5/utmp.5.html
https://github.com/altlinux/libutempter
util-linux's utmpdump
problem #1: wall doesn't work
$ wall <<< Hello
does nothing. okay, let's dig into the guts of these
$ strace wall <<< "hello"
execve("/usr/bin/wall", ["wall"], 0x7ffc3231da70 /* 20 vars */) = 0
...
...
readlink("/proc/self/fd/1", "/dev/pts/0", 4095) = 10
newfstatat(AT_FDCWD, "/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
...
fstat(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
read(0, "hello\n", 4096) = 6
read(0, "", 4096) = 0
faccessat2(AT_FDCWD, "/run/systemd/system/", F_OK, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "/run/systemd/sessions/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=200, ...}) = 0
getdents64(3, 0x5565eef78680 /* 10 entries */, 32768) = 272
getdents64(3, 0x5565eef78680 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/15", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=330, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 330
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/14", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/9", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 305
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/9", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=305, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 305
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/6", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 304
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/6", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=304, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 304
read(3, "", 4096) = 0
close(3) = 0
access("/var/run/utmpx", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/var/run/utmp", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
dup(1) = 3
close(3) = 0
dup(2) = 3
close(3) = 0
exit_group(0) = ?
+++ exited with 0 +++
Curious, okay. This is doing much different things that what I'm familiar with, the last time I've dipped my toes into this was when this kinda stuff was handled via utmp, which you can kind of see remnants of at the end of that strace there trying to open /var/run/utmp but having no luck. And yeah, wouldn't you know it:
$ ls /var/run/utmp
ls: cannot access '/var/run/utmp': No such file or directory
so we're stuck with having to navigate systemd internals (ugh) to try to figure out why wall is choking.
fix #1: enable utmp?
Investigating wall's source code, I've found the portion hooking into systemd session stuff with regards to the usage of sd_get_sessions, sd_session_get_username & sd_session_get_tty.
Documentation for these functions exists kind of here, although I can't figure out how to install the systemd library documentation on my debian box...
Looking into what sd_session_get_tty is doing (since I assume that's what's going on, validated by loginctl not listing any TTYs), it's just parsing the systemd session files for a TTY key and trying to pull the value from it. which we know aren't being populated for some reason.
Of note, as well, is that in the wall source code if systemd is enabled (sd_booted()) it seems to not pull from utmp at all? or only in specific circumstances? A bit confusing.
as an aside, this in wall's source code, which I definitely found a bit funny:
This program is not related to David Wall, whose Stanford Ph.D. thesis is entitled "Mechanisms for Broadcast and Selective Broadcast".
in my searches I found #36930 which is basically someone reporting this exact problem. no information about the context around this from poettering, but it was mentioned in 886ca21 and fixed in #36958 but there's a lot of mention of the systemd utmp support.
Looking into this more I've found https://earezki.com/ai-news/2026-04-27-utmp-being-phased-out-why-who-returns-empty-output-on-modern-ubuntu/ which yeah basically gives me all the confirmation I need, ubuntu and/or debian devs are rallying against utmp as a concept:
$ systemctl --version
systemd 257 (257.13-1~deb13u1)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +IPE +SMACK +SECCOMP +GCRYPT -GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +BTF -XKBCOMMON -UTMP +SYSVINIT +LIBARCHIVE
no utmp support!
let's fix this.
patching a debian package
I'm rushing through this, but basically a combination of apt build-dep <package>, apt source <package>, modifying debian/rules or other files, and dpkg-buildpackage -us -uc -b (sometime with DEB_BUILD_OPTIONS=nocheck) to build a new .deb to install with dpkg -i
also, upgrading you VM's cpu if you can helps a lot with these compilations. they're typically CPU bound.
diff --git a/debian/rules b/debian/rules
index a42fbae1bb..40546882d7 100755
--- a/debian/rules
+++ b/debian/rules
@@ -111,7 +111,7 @@ CONFFLAGS = \
-Dresolve=true \
-Dstatus-unit-format-default=combined \
-Dstandalone-binaries=true \
- -Dutmp=false \
+ -Dutmp=true \
-Dtty-mode=0600 \
-Dvmspawn=enabled \
-Defi-stub-extra-sections=500 \
diff --git a/debian/systemd.install b/debian/systemd.install
index 24e83c8a16..5b06215c0a 100755
--- a/debian/systemd.install
+++ b/debian/systemd.install
@@ -592,3 +592,14 @@ usr/share/zsh/vendor-completions/_varlinkctl
../extra/sysctl.d/10-coredump-debian.conf usr/lib/sysctl.d/
../extra/limits.d/10-coredump-debian.conf etc/security/limits.d/
../extra/dbus-1/system.d/org.freedesktop.locale1.read-only.conf usr/share/dbus-1/system.d/
+usr/lib/systemd/system/systemd-update-utmp.service
+usr/lib/systemd/system/graphical.target.wants/systemd-update-utmp-runlevel.service
+usr/lib/systemd/system/multi-user.target.wants/systemd-update-utmp-runlevel.service
+usr/lib/systemd/system/rescue.target.wants/systemd-update-utmp-runlevel.service
+usr/lib/systemd/system/sysinit.target.wants/systemd-update-utmp.service
+usr/lib/systemd/system/systemd-update-utmp-runlevel.service
+usr/lib/systemd/system/systemd-update-utmp.service
+usr/lib/systemd/systemd-update-utmp
+usr/share/man/man8/systemd-update-utmp-runlevel.service.8
+usr/share/man/man8/systemd-update-utmp.8
+usr/share/man/man8/systemd-update-utmp.service.8
aaaand after a successful dpkg-buildpackage
# dpkg -i libsystemd-shared_257.13-1~deb13u1_amd64.deb; dpkg -i systemd_257.13-1~deb13u1_amd64.deb
(Reading database ... 47308 files and directories currently installed.)
Preparing to unpack libsystemd-shared_257.13-1~deb13u1_amd64.deb ...
Unpacking libsystemd-shared:amd64 (257.13-1~deb13u1) over (257.13-1~deb13u1) ...
Setting up libsystemd-shared:amd64 (257.13-1~deb13u1) ...
(Reading database ... 47308 files and directories currently installed.)
Preparing to unpack systemd_257.13-1~deb13u1_amd64.deb ...
Unpacking systemd (257.13-1~deb13u1) over (257.13-1~deb13u1) ...
Setting up systemd (257.13-1~deb13u1) ...
/usr/lib/tmpfiles.d/legacy.conf:14: Duplicate line for path "/run/lock", ignoring.
Processing triggers for procps (2:4.0.4-9) ...
Processing triggers for dbus (1.16.2-2) ...
Processing triggers for man-db (2.13.1-1) ...
and after a reboot...
$ systemctl --version
systemd 257 (257.13-1~deb13u1)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +IPE +SMACK +SECCOMP +GCRYPT -GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +BTF -XKBCOMMON +UTMP +SYSVINIT +LIBARCHIVE
and wall works!!!!
and
it looks like loginctl reports correctly now, too:
$ loginctl
SESSION UID USER SEAT LEADER CLASS TTY IDLE SINCE
5 1001 m - 76471 user pts/0 no -
6 1001 m - 76477 manager - no -
7 1002 io - 77208 user pts/1 no -
so it's looking like systemd needs utmp enabled to track user ttys
problem #2: write doesn't work
well, first problem is I can't install it. debian's disabled the write and mesg command due to them being "insecure" and "dead weight" (see: CVE-2024-28085)
so let's fix that:
diff --git a/debian/rules b/debian/rules
index 9dac83138..dd40d6750 100755
--- a/debian/rules
+++ b/debian/rules
@@ -36,8 +36,8 @@ endif
endif
# As a result of CVE-2024-28085, we no longer install mesg/write.
-CONFOPTS += --disable-mesg
-CONFOPTS += --disable-write
+CONFOPTS += --enable-mesg
+CONFOPTS += --enable-write
# build static versions of programs used in fdisk-udeb and util-linux-udeb
CONFOPTS_UDEB += --enable-eject --enable-fallocate --enable-fdisks --enable-blkid
diff --git a/debian/bsdutils.install b/debian/bsdutils.install
index 5bcbe4ab5..35760f345 100755
--- a/debian/bsdutils.install
+++ b/debian/bsdutils.install
@@ -4,6 +4,8 @@ usr/bin/renice
[linux-any] usr/bin/scriptlive
usr/bin/scriptreplay
usr/bin/wall
+usr/bin/write
+usr/bin/mesg
<!nodoc> usr/share/man/man1/renice.1
[linux-any] <!nodoc> usr/share/man/man1/script.1
[linux-any] <!nodoc> usr/share/man/man1/scriptlive.1
@@ -14,3 +16,8 @@ usr/share/bash-completion/completions/renice
[linux-any] usr/share/bash-completion/completions/scriptlive
usr/share/bash-completion/completions/scriptreplay
usr/share/bash-completion/completions/wall
+usr/share/bash-completion/completions/write
+usr/share/bash-completion/completions/mesg
+usr/share/man/man1/utmpdump.1
+usr/share/man/man1/write.1
+usr/share/man/man1/mesg.1
also for shits and giggles you can also enable utmpdump for utmp debugging! yippee!!
index 9dac83138..3d530eece 100755
--- a/debian/rules
+++ b/debian/rules
@@ -58,7 +58,7 @@ CONFOPTS += --disable-chfn-chsh
# => bsdmainutils
CONFOPTS += --disable-cal
# => wtmpdb
-CONFOPTS += --disable-last --disable-utmpdump
+CONFOPTS += --disable-last
# Keep hwclock as GPLv2 (and others)
CONFOPTS += --disable-hwclock-gplv3
... there seem to be compilation race conditions so the more CPUs you have on the box the more likely compilation is to fail for strange and mysterious reasons. maybe.
# dpkg -i bsdutils_2.41-5_amd64.deb
(Reading database ... 47319 files and directories currently installed.)
Preparing to unpack bsdutils_2.41-5_amd64.deb ...
Unpacking bsdutils (1:2.41-5) over (1:2.41-5) ...
Setting up bsdutils (1:2.41-5) ...
Processing triggers for man-db (2.13.1-1) ...
I also had to patch write a bit to solve a strange error:
$ write
write: effective gid does not match group of /dev/pts/0
diff --git a/term-utils/write.c b/term-utils/write.c
index 3dc4df568..0f52d8692 100644
--- a/term-utils/write.c
+++ b/term-utils/write.c
@@ -122,10 +122,6 @@ static int check_tty(const char *tty, int *tty_writeable, time_t *tty_atime, int
if (getuid() == 0) /* root can always write */
*tty_writeable = 1;
else {
- if (getegid() != s.st_gid) {
- warnx(_("effective gid does not match group of %s"), tty);
- return 1;
- }
*tty_writeable = s.st_mode & S_IWGRP;
}
if (tty_atime)
dunno what the better fix for this would be.
$ write
Try 'write --help' for more information.
yippee!
people are very opinionated about this executable's existence:
- https://bugs-devel.debian.org/cgi-bin/bugreport.cgi?bug=1088190&msg=58
- https://unix.stackexchange.com/questions/726573/capture-incoming-terminal-messages-write-mesg
problem #3: talk, so many problems
first problem out of the box is that there are:
- two versions of
talk&talkd - they use
inetd, and old-school version of a "service" manager, mapping socket connections to stdin/stdout of applications I don't have any problems withinetdstuff, I kind of find them cool and think it's a well suited way to write applications. but unfortunately I'm in systemd land, and when in systemd land, do as the systemd. - things just... continue to not work
it turns out the ineutils-talkd is the real (working) one now, so let's go with that one
here's what the inetutils-talkd package installs by default:
learning about inetd
$ dpkg -L inetutils-talkd
/.
/usr
/usr/sbin
/usr/sbin/talkd
/usr/share
/usr/share/doc
/usr/share/doc/inetutils-talkd
/usr/share/doc/inetutils-talkd/AUTHORS
/usr/share/doc/inetutils-talkd/NEWS.gz
/usr/share/doc/inetutils-talkd/THANKS
/usr/share/doc/inetutils-talkd/changelog.Debian.gz
/usr/share/doc/inetutils-talkd/changelog.gz
/usr/share/doc/inetutils-talkd/copyright
/usr/share/man
/usr/share/man/man8
/usr/share/man/man8/talkd.8.gz
notice that there's no actual service definitions of any kind here, the actual way to enable it is to uncomment this line:
$ grep talkd /etc/inetd.conf
#<off># ntalk dgram udp4 wait root /usr/sbin/tcpd /usr/sbin/talkd
talk no work
$ talk io pts/1
[Service connection established.]
[Your party is not logged on]
what's up with this. I thought we fixed the strange tty issues. loginctl even continues to report things properly!!
(in one terminal):
io~$ talk m pts/0
[Service connection established.]
[Your party is not logged on]
and in another:
# strace -p $(pgrep talkd)
strace: Process 338485 attached
recvfrom(0, 0x7ffdf7f7e9c0, 84, 0, 0x7ffdf7f7e990, [16]) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---
alarm(30) = 0
...
openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1590, ...}) = 0
lseek(3, 0, SEEK_SET) = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1590
close(3) = 0
newfstatat(AT_FDCWD, "/home/m/.talkrc", 0x7ffdf7f7e840, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/systemd/sessions/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=200, ...}) = 0
getdents64(3, 0x556a18ed9cf0 /* 10 entries */, 32768) = 272
getdents64(3, 0x556a18ed9cf0 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/dev/pts", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
getdents64(3, 0x556a18ed9cf0 /* 6 entries */, 32768) = 144
newfstatat(AT_FDCWD, "/dev/pts/2", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x2), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/1", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/ptmx", {st_mode=S_IFCHR|000, st_rdev=makedev(0x5, 0x2), ...}, 0) = 0
getdents64(3, 0x556a18ed9cf0 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/13", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=332, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 332
read(3, "", 4096) = 0
close(3) = 0
kill(337545, 0) = 0
openat(AT_FDCWD, "/run/systemd/sessions/12", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 310
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/12", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 310
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/12", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 310
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/12", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=310, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 310
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/dev/pts", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
getdents64(3, 0x556a18ed9cf0 /* 6 entries */, 32768) = 144
newfstatat(AT_FDCWD, "/dev/pts/2", {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x2), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/1", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1), ...}, 0) = 0
newfstatat(AT_FDCWD, "/dev/pts/ptmx", {st_mode=S_IFCHR|000, st_rdev=makedev(0x5, 0x2), ...}, 0) = 0
getdents64(3, 0x556a18ed9cf0 /* 0 entries */, 32768) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/7", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=329, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 329
read(3, "", 4096) = 0
close(3) = 0
kill(77208, 0) = 0
openat(AT_FDCWD, "/run/systemd/sessions/8", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=308, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=308, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 308
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/8", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=308, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=308, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 308
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/8", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=308, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=308, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 308
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/run/systemd/sessions/8", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=308, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=308, ...}) = 0
read(3, "# This is private data. Do not p"..., 4096) = 308
read(3, "", 4096) = 0
close(3) = 0
newfstatat(AT_FDCWD, "/dev/sshd pt", 0x7ffdf7f7e800, 0) = -1 ENOENT (No such file or directory)
sendto(0, "\1\3\1\30\0\0\0\0\0\0\0\0\377\377\377\377\0\350\367\367\375\177\0\0", 24, 0, {sa_family=AF_INET, sin_port=htons(53225), sin_addr=inet_addr("127.0.1.1")}, 16) = 24
recvfrom(0, "\1\2\0\0\0\0\0\0\0\2\261+\177\0\1\1\0\0\0\0\0\0\0\0\0\2\317\351\177\0\1\1"..., 84, 0, {sa_family=AF_INET, sin_port=htons(53225), sin_addr=inet_addr("127.0.1.1")}, [16]) = 84
newfstatat(AT_FDCWD, "/etc/nsswitch.conf", {st_mode=S_IFREG|0644, st_size=531, ...}, 0) = 0
openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1590, ...}) = 0
lseek(3, 0, SEEK_SET) = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1590
close(3) = 0
newfstatat(AT_FDCWD, "/home/m/.talkrc", 0x7ffdf7f7e840, 0) = -1 ENOENT (No such file or directory)
sendto(0, "\1\2\1\30\0\0\0\0\0\0\0\0\377\377\377\377\0\350\367\367\375\177\0\0", 24, 0, {sa_family=AF_INET, sin_port=htons(53225), sin_addr=inet_addr("127.0.1.1")}, 16) = 24
recvfrom(0, "\1\2\0\0\0\0\0\0\0\2\261+\177\0\1\1\0\0\0\0\0\0\0\0\0\2\317\351\177\0\1\1"..., 84, 0, {sa_family=AF_INET, sin_port=htons(53225), sin_addr=inet_addr("127.0.1.1")}, [16]) = 84
newfstatat(AT_FDCWD, "/etc/nsswitch.conf", {st_mode=S_IFREG|0644, st_size=531, ...}, 0) = 0
openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1590, ...}) = 0
lseek(3, 0, SEEK_SET) = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1590
close(3) = 0
newfstatat(AT_FDCWD, "/home/m/.talkrc", 0x7ffdf7f7e840, 0) = -1 ENOENT (No such file or directory)
sendto(0, "\1\2\1\30\0\0\0\0\0\0\0\0\377\377\377\377\0\350\367\367\375\177\0\0", 24, 0, {sa_family=AF_INET, sin_port=htons(53225), sin_addr=inet_addr("127.0.1.1")}, 16) = 24
recvfrom(0,
okay, yeah. looking in /run/systemd/sessions/ & /dev/pts/. what gives?
we're currently trying to talk to user/pts location at session 13:
$ loginctl
SESSION UID USER SEAT LEADER CLASS TTY IDLE SINCE
12 1001 m - 337528 manager - no -
13 1001 m - 337545 user pts/0 no -
7 1002 io - 77208 user pts/1 no -
8 1002 io - 77213 manager - no -
4 sessions listed.
and the strace seems to hit /dev/pts halfway through parsing a session file that maps to a TTY. double checking the files map to TTYs correctly:
$ cat /run/systemd/sessions/13
# This is private data. Do not parse.
UID=1001
USER=m
ACTIVE=1
IS_DISPLAY=1
STATE=active
REMOTE=1
LEADER_FD_SAVED=1
TYPE=tty
ORIGINAL_TYPE=tty
CLASS=user
SCOPE=session-13.scope
FIFO=/run/systemd/sessions/13.ref
REMOTE_HOST=10.200.254.12
SERVICE=sshd
POSITION=0
LEADER=337545
AUDIT=13
REALTIME=1781248558211808
MONOTONIC=25877875386
still NOTHING. what's going on with that?
on an unrelated system I see TTY= info populated:
$ cat /var/run/systemd/sessions/32
# This is private data. Do not parse.
UID=1446800142
ACTIVE=1
IS_DISPLAY=1
STATE=active
REMOTE=1
LEADER_FD_SAVED=1
USER=max
TYPE=tty
ORIGINAL_TYPE=tty
CLASS=user
SCOPE=session-32.scope
TTY=pts/1
TTY_VALIDITY=from-utmp
REMOTE_HOST=10.213.14.75
SERVICE=sshd
LEADER=3898995
LEADER_PIDFDID=3898140
AUDIT=32
REALTIME=1781250380867006
MONOTONIC=1752637959709
mentioning utmp as well. curious.
back to #36940
in my explorations, I learned about loginctl show-session
$ cat /run/systemd/sessions/1
# This is private data. Do not parse.
UID=1001
USER=m
ACTIVE=1
IS_DISPLAY=1
STATE=active
REMOTE=1
LEADER_FD_SAVED=1
TYPE=tty
ORIGINAL_TYPE=tty
CLASS=user
SCOPE=session-1.scope
FIFO=/run/systemd/sessions/1.ref
REMOTE_HOST=10.200.254.12
SERVICE=sshd
POSITION=0
LEADER=873
AUDIT=1
REALTIME=1781254802265125
MONOTONIC=16977710
$ loginctl show-session 1
Id=1
User=1001
Name=m
Timestamp=Fri 2026-06-12 09:00:02 UTC
TimestampMonotonic=16977710
VTNr=0
TTY=pts/0
Remote=yes
RemoteHost=10.200.254.12
Service=sshd
Scope=session-1.scope
Leader=873
Audit=1
Type=tty
Class=user
Active=yes
State=active
IdleHint=no
IdleSinceHint=1781254845000000
IdleSinceHintMonotonic=59712585
CanIdle=yes
CanLock=yes
LockedHint=no
one contains a TTY=, one does not.
it turns out I should've looked much closer at the issue linked above, it gets fixed in v258-rc1 & I'm running 257.13-1~deb13u1. woops.
in the process of trying to install a newer version of systemd than my debian box intended, I rendered it unbootable. but I'm pretty sure this was the problem, as my newer fedora box doesn't suffer from these woes.
aside: migrating inetd activated apps to systemd socket activation
and let's switch it over from inetd real quick by stealing arch linux's .service files
talk.socket:
[Unit]
Description=Talk Server Activation Socket
Documentation=man:talkd(8) man:talk(1)
[Socket]
ListenDatagram=0.0.0.0:518
[Install]
WantedBy=sockets.target
talk.service:
[Unit]
Description=Talk Server
Documentation=man:talkd(8) man:talk(1)
[Service]
User=_talkd
Group=tty
ExecStart=/usr/bin/talkd
StandardInput=socket
[Install]
Also=talk.socket
systemd sockets are kind of cool.
oh yeah, to get these working you have to create a _talkd user, easy peasy:
# adduser --system _talkd
and, importantly, enable the socket but not the service. The service gets auto-started on socket activation.
the overarching solution?
connecting to an existing shellbox in my local hackerspace, a lot of the features I'm trying to solve already work out of the box! with a fedora machine, as opposed to debian :)
my first sanity check is seeing if systemd has the things I've patched it to enable on my testbox:
$ systemctl --version
systemd 259 (259.5-1.fc44)
+PAM +AUDIT +SELINUX -APPARMOR +IMA +IPE +SMACK +SECCOMP -GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +BTF +XKBCOMMON +UTMP +SYSVINIT +LIBARCHIVE
box has a newer version of systemd that has the fixes I'm looking for, and has utmp enabled. yippee
write still doesn't work, but patching the rpm was pretty easy
talk works out of the box, with systemd socket activation, too!:
$ rpm -ql talk-server
/usr/bin/in.ntalkd
/usr/bin/in.talkd
/usr/lib/.build-id
/usr/lib/.build-id/de
/usr/lib/.build-id/de/7a7f422f2a361f134698eecc5cacaa8899f468
/usr/lib/systemd/system/ntalk.service
/usr/lib/systemd/system/ntalk.socket
/usr/share/man/man8/in.ntalkd.8.gz
/usr/share/man/man8/in.talkd.8.gz
/usr/share/man/man8/ntalkd.8.gz
/usr/share/man/man8/talkd.8.gz
https://forums.rockylinux.org/t/write-from-util-linux-not-working-to-users-logged-in-to-ssh/19044
thanks to ducky's new album & twerknation28 (rip) for helping entertain me through this exploration. & orchachillin's breakcore djing ^^
ssh master control
this breaks everything btw