[GNU Manual] [POSIX requirement] [Linux man] [FreeBSD man]
Summary
who - print who is currently logged in
Lines of code: 837
Principal syscall: None
Support syscalls: None
Options: 31 (14 short, 17 long, does not include legacy digits for field skip)
Oldest spiritual ancestor is WHO from CTSS 2ed. (1969)
Added to Shellutils in November 1992 [First version]
Number of revisions: 171
A substantial amount of work behind who determines what data to display and how to the format it. The source of most data is the utmp file under /var
or /etc
idle_string()
- Builds a string representation of the idle itemis_tty_writable()
- Checks if a user terminal can be written to (for +/- display)list_entries_who()
- Performs the quick user listing (-q option)make_id_equals_comment()
- Adds the 'id' comment fieldprint_boottime()
- Outputs the system boot timeprint_clockchange()
- Prints the last system clock changeprint_deadprocs()
- Prints information about dead processesprint_heading()
- Prints the header above all output entriesprint_initspawn()
- Prints processes spawned by init/systemdprint_line()
- Prints a formatted output line. Used by most print functions in whoprint_login()
- Prints processes information for pending loginsprint_runlevel()
- Prints current and previous (if possible) runlevelsprint_user()
- Parses and prints user informationscan_entries()
- Walks through each utmp entry to print requested informationtime_string()
- Builds a timestamp stringwho()
- The top level procedure for who
die()
- Exit with mandatory non-zero error and message to stderrerror()
- Outputs error message to standard error with possible process terminationread_utmp()
- Reads the contents of system utmp file in to a buffer
Setup
who.c uses existing macros to define the capabilities for the specific system. Not all of the possible data fields are always available. These include:
DEAD_PROCESS
- System identifies processes from exited usersHAVE_STRUCT_XTMP_UT_PID
- The system can search utmp by pidHAVE_STRUCT_XTMP_UT_ID
- The system can search utmp by terminal sourceINIT_PROCESS
- System identifies processes from init/systemdLOGIN_PROCESS
- System identifies processes where user login is in progressNEW_TIME
- The most recent system timeRUN_LVL
- The system's current runlevel
Global variables are set during parsing to control execution behavior. These include:
do_lookup
- Flag to attempt hostname resolution via DNS (--lookup)include_exit
- Flag to include process exit status (-d)include_heading
- Flag to display headers for output records (-H)include_idle
- Flag to include idle time displayinclude_mesg
- Flag to include user message status (-w, --mesg)my_line_only
- Flag to include only current user line (-m)need_boottime
- Flag to display the last boot timeneed_clockchange
- Flag to display the previous clock changeneed_deadprocs
- Flag to display dead processesneed_initspawn
- Flag to display processes started by init/systemdneed_login
- Flag to display processes waiting for user loginneed_runlevel
- Flag to display the current runlevelneed_users
- Flag to display user processesshort_list
- Flag to display only user names and countsshort_output
- Flag to display only name, line, and timestime_format
- The login time formattime_format_width
- The expected output width of login timemain()
adds two local variables:
assumptions
- Flag indiciating default output options used.optc
- The character for the next option to process
Parsing
Parsing answers the following questions to define the execution parameters
- What information should be displayed? (boot times, dead/init processes, runlevels, time, etc)
- Should headers be displayed at the top?
- Should output be limited to only the current user?
Parsing failures
These failure cases are explicitly checked:
- Providing too many operands (more than 2)
- Unknown option used
User specified parsing failures result in a short error message followed by the usage instructions. Access related parsing errors die with an error message.
Execution
who begins by accessing the utmp file, either the system default, or one provided directly by the user. There is a short print procedure for displaying only user names and a longer case for multiple records. We'll look at the longer case.
- Get the current user's tty name
- Check each entry in utmp and print requested data in this order:
- Print user name
- Print run level
- Print boot time
- Print clock changes
- Print init/systemd processes
- Print unassigned processes (users not logged in yet)
- Print dead processes (user has logged off)
The only failure case explicity checked is if who is unable to access the utmp file. The result is an error message to STDERR.