fa4bb2a5693121f4a303c72ca24f266e304450b5 — наб a month ago 857723f
HISTORYise who, users
4 files changed, 724 insertions(+), 9 deletions(-)

M man/aliases
M man/du.1
M man/expand.1
M man/who.1
M man/aliases => man/aliases +1 -0
@@ 9,3 9,4 @@ mkfifo.1   mknod.8
basename.1 dirname.1
test.1     [.1
chown.1    chgrp.1     chown.8
who.1      users.1

M man/du.1 => man/du.1 +1 -1
@@ 793,7 793,7 @@ moves
to the base spec, since its
User Portability Utilities
are exclusively interactive.
.\" ^ same text as expand.1
.\" ^ same text as expand.1, who.1
.\" TODO: .St -p1003.1-202x
.Tn \%IEEE No Std 1003.1-202x Pq Dq Tn \%POSIX Ns .1

M man/expand.1 => man/expand.1 +1 -1
@@ 219,4 219,4 @@ moves
to the base spec, since its
User Portability Utilities
are exclusively interactive.
.\" ^ same text as du.1
.\" ^ same text as du.1, who.1

M man/who.1 => man/who.1 +721 -7
@@ 5,7 5,7 @@
.Nm who
.Nm who , users
.Nd list login and system state

@@ 26,6 26,9 @@
.Op Fl ublrpdt
.Cm am I
.Nm users
.Op Ar utmp
Processes and filters the default
.Xr utmpx 5

@@ 62,6 65,11 @@ output the login name
.Pq Fa ut_user ,
and a space separator.
The second line lists the amount of users in the first.
.Nm users
.Sx Quick Format ,
but sorts the login names byte-wise and removes the second line.
.Ss Full Format
For each

@@ 303,9 311,13 @@ Conforms to
.D1 Nm Op Fl mTu
and the output is
.D1 in an implementation-defined format, subject only to the requirement of containing the information described above .
The XSI-marked bits are (largely) equivalent to this implementation's invocation and match
.At V ,
.\" TODO: which?
The XSI-marked bits are (largely) equivalent to this implementation's invocation and are similar to
.At V.3
.Sy Comment
.Bx 4.2 ,
except for
.Fl -ips , -lookup ,
which are extensions, originating from the GNU system, and

@@ 316,9 328,7 @@ The only XSI
.Cm am I
spellings are such and
.Cm am i .
Some implementations allow any two arguments.
.\" TODO: all? some?
Some implementations also allow
Some implementations allow any two arguments or
.Ar utmp

@@ 378,3 388,707 @@ and
.Pf all- Sy 0
.Nm users
is compatible with
.Bx 4.3 .
.Ss Nm
.Ss Research \s[-1z]UNIX\s0
.\" Copied from Unix Programmer's Manual, unix72 has v2, and v2, v6, 3BSD
Appears in the first edition of the UNIX Programmer's Manual as
.Xr who I :
.Bl -tag -compact -offset Ds -width ".Li DESCRIPTION"
.Li "who  --  who is on the system"
.Li "\z\(ulw\z\(ulh\z\(ulo"
.Li "\z\(ulw\z\(ulh\z\(ulo lists the name, typewriter channel, and login time for each current UNIX user."
This corresponds to all data in
.Pa /tmp/utmp .
.\" unix72:
.\" # who
.\" root    tty8 Jan  1 00:00:15
.\" # who /tmp/utmp
.\"          Jan  1 00:00:00
.\"          Jan  1 00:00:00
.\"          Jan  1 00:00:00
.\"          Jan  1 00:00:00
.\"          Jan  1 00:00:00
.\"          Jan  1 00:00:00
.\"          Jan  1 00:00:00
.\"          Jan  1 00:00:00
.\" root    8 Jan  1 00:00:12
.\" # who /tmp/wtmp
.\"         8 Jan  1 00:02:11
.\" root    8 Jan  1 00:02:13
.\"         x Jan  1 00:02:11
.\" root    8 Jan  1 00:02:14
.At v2 ,
with the advent of
.Xr wtmp V ,
.Dl "\z\(ulw\z\(ulh\z\(ulo [ who-file ]"
.Ar who-file ,
the output format is
.Bd -literal -compact -offset Ds
# who
root    tty8 Jan  1 00:00:15
and all-zero-name (dead) entries are filtered out; with
.Ar who-file
the format becomes
.Bd -literal -compact -offset Ds
# who /usr/adm/wtmp
        x Jan  1 00:02:02
root    8 Jan  1 00:02:11
        8 Jan  1 00:03:32
Usernames are
.Sy 8
bytes, the teletype is just the bottom byte as a character
.Pq corresponding to the Pa /dev/tty Ns " suffix"
.Pq so doing the same on Xr utmp V No would write the null byte instead ,
.Sy x
indicates system reboot, as written by
.Nm init ,
and empty names indicate logouts.
.At v4
.Li tty
to the with-file format.
.At v5
uses a
.Sy ~
line field indicate shutdown instead.
.At v6
sees a misleading
.D1 "\fBwho\fP [ who-file ] [ \fBam I\fP ]"
.Ar who-file
.Pq now Pa /etc/utmp Ns " by" default
.Cm "am I"
(any two arguments);
if specified, the first line matching the teletype corresponding to the standard input streeam is written, or "Nobody.",
but the format is otherwise equivalent.
.At v7
sees a modernised
.Xr utmp 5
format with
.Fa ut_time
.Sy 8 Ns -byte
.Fa ut_line , ut_name ,
with present-day semantics
.Pq and Xr date 1 No adding Sy |\& No and Sy \&{ Xr wtmp 5 No entries for before/after clock change ;
format gains a space after the name field
.Pq such that even Sy 8 Ns -byte names are separated
and the time format is truncated to
.Qq Li "%b %e %R"
\(em the seconds removed.
.Cm "am I"
mode, if the corresponding entry wasn't found, there's just no output,
or, if the standard input stream is not a teletype, a line is synthesised
with the name equal to
.Xr getpwuid 3
of the current user
.Pq or Sy ?\& ,
the line to
.Sy "tty??" ,
and the current time.
.\" and if the file couldn't be opened it exits 1 but who cares. this is already way too fucking busy
On the
Interdata 7/32,
the non-synthetic
.Cm "am I"
output line is prepended with
.Qq Li "(Interdata) " .
.At 32v ,
on the
.Tn VAX ,
.Qq Li "(Vax) " .
.Ss The BSD
.Bx 4
uses the
.In whoami.h
.Dv sysname
macro \(em the system's hostname \(em with the first character upper-cased, similarly wrapped in parenthees and followed by a space, instead.
.Bx 4.2
replaces that with
.Xr gethostname 3
and a
.Qq Ar hostname Ns Sy !\&
format, producing a bang path for the current machine,
It also sees the introduction of a
.Sy 16 Ns -byte
.Fa ut_host
.Pq filled in by remote Nm rlogin Ns " &c." and Nm ftpd Ns " for" Xr wtmp 5 ,
written, if non-empty, after the time, a tab, and in parentheses.
.Bx 4.3 Tahoe
removes the hostname prefix and falls back to the
.Xr getpwuid 3
username (with the current line) if nothing was found in
.Cm "am I"
.Bx 4.3 Reno
sees a "shutdown" name field for
.Sy ~
entries and "date" for
.Sy |{\&
.Pq and moves the files to their common modern locations at Pa /var/run/utmp Ns " and" Pa /var/log/wtmp ;
is re-written once more:
the only substantive change appears to be that the no-argument case filters by non-empty
.Fa ut_name
.Em and
.Fa ut_line
.Pq for Cm "am I" , Ns " a" nonfunctional attempt was made to only filter out entries with empty usernames .
.\" https://twitter.com/nabijaczleweli/status/1555341949011361793
.Ss System V
.At 32v
.Nm ,
except it hides the
.Qq Li "(Vax) "
prefix and falls back to also probing the standard output and error streams in
.Cm "am I"
.Pq which it allows as any argument count \(>= Sy 2 .
.\" index(+1) -> strrchr() for ttyname() result too but that's equivalent before Unix98 PTYs
.At V.1
sees present-day
.Xr getutxent 3
&c. API
.Pq though without the Li x
as its primary
.Xr utmp 5
interface and
.Dl "Usage:  who [-rbtpludAasT] [am i] [utmp_like_file]"
.Pq with Fl u Ns " described" as \&"useful data"
.\"  66  1217 ATT-SYSIII/src/cmd/who.c
.\" 638 15947 ATT-SYSVr1/sysv-pdp11_usr-src/cmd/who.c
.\" 9.(6)x line and 13.1x the byte-wise size
at 13x the code size:
the three optional-marked arguments can be interleft in any order at any amount,
.Cm "am i"
must be exactly
.Cm "am i" ,
probes all standard I/O streams, doesn't exit after the first found entry, and selects
.Pq this is also the default filter, but Cm "am i" Fl d Ns " is" equivalent to present-day Fl mud Ns " except" it produces short format ;
.Fl ublrpdt T
as present-day except both
.Fl lu
enable wide format and are overriden with
.Fl s
.Pq actually the default ,
.Fl A
.Pq no additional data beyond Sy Name Line Time ,
.Fl a
.Em actually
enables all entry types
.Pq incl. Dv EMPTY , No yielding Qq Li "Empty slot.\&"
and doesn't imply
.Fl T ,
the write status is always present, but always a space unless
.Fl T .
Empty or all-blank
.Sy Name Line
fields are replaced with a single
.Sy .\&
in the middle.
The write status is considered for
and by
.Em opening
.Pa /dev/ Ns Fa ut_line
.Pq and with Dv O_NDELAY :
if that
.Pq or closing
times out
.Pq after Sy 3 No seconds per ,
.Sy ?\&
(described as "hung")
is written;
if it fails as root
.Sy x
is written for "exclusive use";
.Sy -
is written if the open fails otherwise, or it succeeds as root or the invoking user is the same as the entry's user and the
.Xr fstat 3
fails, or the line is not other-writable;
.Sy +
then means that the open succeeded for a different user's line or
.Nm mesg Fl y
is set for one's own line (or when run as root).
The idle time is considered for
in long mode, based on "time since the last character was sent to the device" (modification time, in contrast to present-day's access time):
.Sy .\&
for less than a minute
.Pq or Xr stat 2 No failure ,
.Sy old
for more than a day, and
.Ar HH Ns Sy :\& Ns Ar MM
.Pq with space-padded Ar HH
.Nm init
.Fa ut_exit.e_termination
.Fa ut_exit.e_exit
as the current and previous run-level, and
.Fa ut_pid
as the count of times it had been at the current run-level.
Those are written verbatim by
.Nm :
centrer-aligned for
.Sy Idle ,
at the start of the
.Sy Comment
field, and left-aligned for
.Sy PID ;
this is written regardless of the shortness of the output mode.
In long mode,
see the
field, right-aligned,
.Sy id= Ns Fa ut_id
with non-printables replaced with
.Sy ^@ Ns …
.Pq in this case they're Pa /etc/lines Ns " line" numbers
.Sy term= , exit= ,
as present-day but left-aligned to three columns;
instead, see
.Pq and hence the Sy Comment No designation ,
the comment corresponding to their
.Xr inittab 5
entry \(em the
.Fa ut_id
field matched to the first field with the end-of-line comment found via
.Qq Li @
.Qq Li ":; " ,
stripped of initial blanks, and written verbatim,
or the empty string if not found or any error occurred.
No processing is done to replace or prettify the lines or users for
.Nm init
.Pq Li \&"system boot" , \&"run-level %c"
.Nm date
.Pq Li \&"old time" , \&"new time"
log them verbatim.
.At V.2
.Cm "am I"
and adds
.Fl H ,
which writes
an empty line if
.Fl abrt
(to "leave a space between stats and output")
followed by
.Pq or ending at Sy TIME No in short mode
the first time it encounters a
.Fl q
which aborts processing all flags, selects
and collects
.Fa ut_user
after the
special case
.Cm "am I"
filtering, but overridng all usual processing
.Pq such that Fl aq Cm "am I" Ns " collects" all Fa ut_user Ns " fields" attached to the current teletype , but Fl qa Cm am I No only the user ones attached to the current teletype .
There's space for a reasonable
.Sy 50
users (more segfaults), which are then bubble-sorted, broken at
.Sy 80
columns, and followed with the familiar
.Li "# users="
and the count.
.At V.3
sees another rewrite, although largely equivalent;
the usage string is equivalent, but flags are parsed with
.Xr getopt 3 ,
.Ar utmp_like_file
must be the
.Em only
argument following flags
.Pq and is explicitly validated for readability and being a multiple of Vt "struct utmp" Ns " in" size ; a if it's empty, Nm Ns " exits" instantly, since \&"we are all done" \(em neglecting to write Fl H , Ns " if" specified
.Cm "am I"
is only recognised if they're the
.Em only
.Fl n Ar #
limits the number of users per line with
.Fl q
(which no longer has special parsing semantics);
the default of
.Sy 8
.Sy 8 Ns -byte
(now left-columnated)
usernames yields a default wrap of
.Sy 72
columns, output during processing and therefore unsorted and unlimited.
.Fl lrA
set long format
.Pq and override previous Fl s
.Fl au
set long format but don't:
.Fl s
at the end always works.
.Fl H
is always written before processing starts
.Pq regardless of Fl q .
.Cm "am I"
matches both the login username
.Pq as obtained via Xr cuserid 3
.Em and
current teletype, and exits after writing the first matching entry.
The idle time is always checked and not just not output if the
.Xr stat 2
failed; since this predates
.Xr pty 7 Ns s ,
much less dynamic ones this only realistically affects changed system configurations when passed
.Xr wtmp 5 .
The write status is derived just from the
.Xr stat 2 ,
as present-day, except the check is for other-writability.
.Fa ut_pid
is also output for
and is aligned for
.Fa ut_id
isn't properly limited to
.Sy 4
bytes (since it's not NUL-terminated), so it may include
.Fa ut_line .
.Sy exit=
isn't aligned, just has two spaces afterward.
.Pq instead of just Dv LOGIN_PROCESS , USER_PROCESS
entries are checked against
.Xr inittab 5 ,
with the comment only allowed to start with a
.Li # .
.At V.4
moves both files from
.Pa /etc
.Pa /var/adm
and removes
.Fl A
from the usage string and
.Xr getopt 3
.Pq but, curiously, keeping the rest of its option handling ,
describing it as "non-functional"
.Pq for no apparent reason, it seems to be equivalent to At V.3  ;
on i386, if
.Pa /etc/inittab
fails, it's retried as
.Pa /etc/conf/cf.d/init.base
with a diagnostic,
.Fa ut_id
is properly limited.
.Sy Time
is, for the first time, formatted explicitly as
.Qq Li "%b %e %H:%M"
instead of substringing
.Xr ctime 3
to the same effect
.Pq unless in a non- Ns Sy C No locale .
.Cm "am I" ,
if no entries matched ("must be a vt", "Assuming utmp hasn't been updated with vt name"),
.Xr utmp 5
is scanned again, this time matching only on the username \(em the 178-line output function is duplicated and identical,
except it uses the saved name of the teletype attached to the standard I/O streams instead of
.Fa ut_line .
.Ss Standards
.Tn X/Open No Portability Guide Issue\~2 Pq Dq Tn XPG Ns \^2  \" .St -xpg2
.D1 "\fBwho\fP"
.D1 "\fBwho [ options ] [ file ]\fP"
.D1 "\fBwho am i\fP"
.D1 "\fBwho am I\fP"
all marked
OF ("Output format incompletely specified"),
the second additionally marked
UN ("Possibly unsupportable feature"),
loosely describing "the general format for output entries" as
.D1 "name [state] line time activity pid [comment] [exit]"
"[e]xcept for the default \fI-s\fP option",
and listing
.Bd -filled -compact -offset indent
the user's name, terminal line, login time, elapsed time since
activity occurred on the line and the process ID of the command interpreter for each
current system user.
.Cm "am I"
identifying the invoking user.
.Bl -tag -compact -width ".Fl H"
.It Fl q
writes "only the names and the number of users", ignoring all other options \(em
this matches
.At V.4 ;
.It Fl s
"is the default and lists only the \fIname\fP, \fIline\fP and \fItime\fP fields"
\(em this is similar to
.At V.4
to some degree, except that
always ignores it, and
.Fl aulrA
make it not be the default or disable it;
.It Fl T
"is the same as the \fI-u\fP option, except that the \fIstate\fP of the terminal line" is written:
.Sy +
is writable by anyone,
.Sy -
.Sy ?\&
means a "bad line"
\(em except for the
.Fl u
part, matches
.At V.4 ;
.It Fl H
adds "column headings";
.It Fl a
"[t]urns on all options" \(em
obviously wrong.
.It Fl u
is as present-day and
.At V.4 ,
including codifying the
.Sy .\& Ns / Ns Ar HH Ns Sy :\& Ns Ar HH Ns / Ns Sy old
format for time "since activity last occurred on that particular line"
.It Fl l
"lists only those lines on which the system is waiting for someone to login" (sic!),
.Sy Name
to be
and same format as for users sans the write status \(em
this doesn't match
.At V.4 ;
.It Fl d
lists "all processes that have expired and not been respawned by \fIinit\fP",
mandating that the "exit" column contain the "the termination and exit values of the dead process"
\(em this matches
.At V.4 ;
.It Fl b , r , p , t
are described as laconic filters
("time and date of the last reboot",
"current \fIrun-level\fP of the \fIinit\fP process",
"any other process which is currently active and has been previously spawned by \fIinit\fP",
"last change to the system clock") with no format requirements.
.St -xpg3
mandates, marked
IN ("Internationalised functionality", defined as optional),
that the "time" column is affected by
.Dv LC_TIME Ns -category
locale, like
.At V.4 .
.St -p1003.2a-92
\(em User Portability Extension \(em
sees an unrelated
.D1 Nm Op Fl mTu
.\" CR instead of CB but meh
Listing "various pieces of information about accessible users" (who they are is implementation-defined);
by default it's to output "in an unspecified format: the user’s login name, terminal name, and time at which the user logged in",
.Fl m
limiting for the "current terminal",
.Fl u
additionally writing "each displayed user’s »idle time«", otherwise entirely unspecified format-wise save for coming after
.Fl T ,
.Fl T
writing the "state of each terminal", conversely requiring an explicit blank-delimited
.Sy Name No write status Sy Line Time
and write status of
.Sy +-?\&
for "allows/denies write access to other users"/"write-access state cannot be determined";
.Sy Time
is required to be
.Pq the At V.4 Ns -identical
.Qq Li "%b %e %H:%M"
in the
.Sx Rationale
is a lot of hand-wringing over
.At V
determining who you can
.Nm talk
to and
.Bd -filled -compact -offset indent
The historical
.Nm Cm "am I"
command, while being one of the more intuitively obvious
system commands, had to succumb to the tide of internationalization.
It is replaced by the somewhat less charming
.Fl m
The format being unspecified (and, similarly, deviations of this implementation from the standard),
"[i]n such an obviously user-oriented command, designed only for human consumption" is "not considered to be a deficiency".
.St -xpg4.2
"aligns" with
.St -p1003.2 :
this realistically means merging
.St -xpg3 ,
EX ((XSI) "Extension")
thereinto, yielding the present-day clumsy
.D1 Nm Oo Fl mu Oc Fl s Oo Fl bHlprt Oc Op Ar file
.D1 Nm Oo Fl mTu Oc Oo Fl abdHlprt Oc Op Ar file
.D1 Nm Fl q Op Ar file
.D1 Nm Cm am i
.D1 Nm Cm am I
and speccing
.Cm "am I"
as equivalent to
.Fl m .
.St -p1003.1-2008
requires that
.Sy Line
is "system boot"
.Pq and Sy Name No is explicitly unspecified
and moves
to the base spec, since its
User Portability Utilities
are exclusively interactive.
.\" ^ same text as du.1, expand.1
.Ss Nm users
Appeared in
.Bx 3
.Xr users 1 :
.D1 users \- compact list of users who are on the system
listing "the login names of the users currently on the system in a compact, one-line format":
that format being all non-empty login names
.Pq up to Sy 128 , No segfaulting on overrun ,
sorted, on one line, separated by a space.
Despite being unmentioned in the
one argument is allowed to override the default
.Pa /etc/utmp
.Bx 4.3
skips the terminating newline if no logins were processed.
This is as present-day.
.Bx 4.3 Tahoe
sees a rewrite, always using
.Pa /etc/utmp
and stopping processing (with a diagnostic) when it encounters too many
.Pq now Sy 200
non-empty login names.
.Bx 4.3 Reno
sees another, using the
.Pq Pa /var/run/utmp ,
deduplicating login names, and (since they're not NUL-terminated) potentially merging subsequent ones into the first.
.\" also the sorting, but it's unaffected result-wise so
.Bx 4.4
fixes this.