utmps
Software
skarnet.org

# The `utmps` library interface

## General information

`libutmps` is a client library meant to be used by client programs needing utmp functionality. It interacts with the utmps-utmpd and utmps-wtmpd daemons.

Application programs can use it directly, but most existing programs simply use the standard utmpx.h interface, which in utmps is implemented as a series of thin wrappers around the utmps library.

A suitable `utmpx.h` header can be found in the `utmps/` subdirectory of the header installation directory; if the `--enable-libc-includes` option has been given to configure, it can also be found directly in that directory. (Example: `/usr/include/utmps/utmpz.h` is always installed, but if the option has been given at nsss build time, `/usr/include/utmpx.h` is also installed and replaces the version provided by the libc.)

## Compiling

- Make sure the utmps headers, as well as the skalibs headers, are visible in your header search path.
- Use `#include <utmps/utmps.h>`
- To use the standard `utmpx.h` interface, you can just `#include <utmpx.h>`, which will work:
  - either if the `--enable-libc-includes` option has been given at utmps build time
  - or if you give the `-I/usr/include/utmps` option to your compiler. (Depending on your standard header location, specify that the header search path should include the `utmps` subdirectory of that location.) This is useful when the administrator did not want to overwrite the libc-provided `utmpx.h` file when they installed utmps.

## Linking

- Make sure the utmps library, as well as the skalibs library, are visible in your library search path.
- Link against `-lutmps`, `-lskarnet`, ``cat $SYSDEPS/socket.lib`` and ``cat $SYSDEPS/sysclock.lib``, $SYSDEPS being your skalibs sysdeps directory.

## Programming

Check the `utmps/utmps.h` header for the exact function list, and the `utmps/utmpx.h` header for the definition of the standard `struct utmpx` data type.

### Synchronous functions with a specified maximum execution time

The standard utmpx.h functions are fully synchronous. They were not initially meant to perform inter-processus communication; however, in utmps, they do. Their synchronous nature is obviously not changed here, but the underlying utmps functions use a safety mechanism to bound their execution time in case daemons fail to respond. This mechanism is described, for instance, here.

### Starting and ending a session

`int utmps_start (utmps *a, char const *path, tain_t const *deadline, tain_t *stamp)`
Connects to a `utmps-utmpd` service listening on a Unix domain socket at path. a must point to a previously allocated utmps object, which is flat and can be allocated in the stack. This object must have been initialized to UTMPS_ZERO before the call. a will be a handle describing the session, and must be given to all utmps functions called in that session. deadline and stamp are used to bound the execution time as described in the above link. The function returns 1 if it succeeds; it returns 0, and sets errno, if it fails.

`void utmps_end (utmps *a)`
Ends the session described by a, and releases all used resources.

### Reading from the utmp database

Any user authorized to connect to the utmpd service can call these functions. In other words, if `utmps_start()` succeeded, then these functions should not fail due to insufficient permissions.

`int utmps_rewind (utmps *a, tain_t const *deadline, tain_t *stamp)`
Performs the `setutxent()` functionality on the utmp database addressed via a, i.e. sets the internal pointer at the start of the database. On success, returns 1. On failure, returns 0 and sets errno.

`int utmps_getent (utmps *a, struct utmpx *b, tain_t const *deadline, tain_t *stamp)`
Performs the `getutxent()` functionality on the utmp database addressed via a. On success, stores the result into *b and returns 1. On failure, returns 0 and sets errno.

`int utmps_getid (utmps *a, unsigned short type, char const *id, struct utmpx *b, tain_t const *deadline, tain_t *stamp)`
Performs the `getutxid()` functionality on the utmp database addressed via a, using ut_type type and ut_id id. id must be a null-terminated string; only its first UTMPS_UT_IDSIZE-1 characters will be taken into account. On success, the function stores the result into *b and returns 1. On failure, it returns 0 and sets errno.

`int utmps_getline (utmps *a, char const *line, struct utmpx *b, tain_t const *deadline, tain_t *stamp)`
Performs the `getutxline()` functionality on the utmp database addressed via a, using ut_line line. line must be a null-terminated string; only its first UTMPS_UT_LINESIZE-1 characters will be taken into account. On success, the function stores the result into *b and returns 1. On failure, it returns 0 and sets errno.

### Writing to the utmp database

Currently, only the super-user, and users belonging to the same group `utmps-utmpd` is running as, are allowed to use this function.

`int utmps_putline (utmps *a, struct utmpx const *b, tain_t const *deadline, tain_t *stamp)`
Performs the `pututxline()` functionality on the utmp database addressed via a, i.e. writes the *b structure into the utmp database looking for an appropriate record to replace, and appending to the database if no such record can be found. On success, the function returns 1. On failure, it returns 0 and sets errno.

### Writing to the wtmp database

`int utmps_updwtmpx (char const *path, struct utmpx const *b, tain_t const *deadline, tain_t *stamp)`
Unlike the previous functions, `utmps_updwtmpx()` does not use a utmps handle, because it does not connect to an utmpd service. Instead, it connects to a wtmpd service listening on Unix domain socket path, once for every call. It appends the *b structure to the wtmp database, returning 1 on success and 0 (and setting errno) on failure.

`utmps_updwtmpx()` will only succeed if the caller is root, or if b→ut_user resolves (according to `getpwnam()`) to the effective uid of the caller. In other words: users can append phony records for themselves, but not for others, and only root can spoof the whole wtmp database.