Crinit -- Configurable Rootfs Init
crinit-client.c File Reference

(2023-08-02, commit: 9434b31)

Implementation of the crinit-client shared library. More...

#include "crinit-client.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "globopt.h"
#include "logio.h"
#include "sockcom.h"
Include dependency graph for crinit-client.c:

Macros

#define CRINIT_LIB_EXPORTED   __attribute__((visibility("default")))
 
#define CRINIT_LIB_CONSTRUCTOR   __attribute__((constructor))
 
#define CRINIT_LIB_DESTRUCTOR   __attribute__((destructor))
 
#define CRINIT_ENV_NOTIFY_NAME_UNDEF   "@undefined"
 

Functions

static int crinitResponseCheck (const crinitRtimCmd_t *res, crinitRtimOp_t resCode)
 
static CRINIT_LIB_CONSTRUCTOR void crinitLibInit (void)
 
static CRINIT_LIB_DESTRUCTOR void crinitLibDestroy (void)
 
CRINIT_LIB_EXPORTED int crinitClientSetVerbose (bool v)
 
CRINIT_LIB_EXPORTED void crinitClientSetErrStream (FILE *errStream)
 
CRINIT_LIB_EXPORTED void crinitClientSetInfoStream (FILE *infoStream)
 
CRINIT_LIB_EXPORTED void crinitClientSetNotifyTaskName (const char *taskName)
 
CRINIT_LIB_EXPORTED void crinitClientSetSocketPath (const char *sockFile)
 
CRINIT_LIB_EXPORTED const crinitVersion_tcrinitClientLibGetVersion (void)
 
CRINIT_LIB_EXPORTED int sd_notify (int unset_environment, const char *state)
 
CRINIT_LIB_EXPORTED int sd_notifyf (int unset_environment, const char *format,...)
 
CRINIT_LIB_EXPORTED int crinitClientTaskAdd (const char *configFilePath, bool overwrite, const char *forceDeps)
 
CRINIT_LIB_EXPORTED int crinitClientSeriesAdd (const char *seriesFilePath, bool overwriteTasks)
 
CRINIT_LIB_EXPORTED int crinitClientTaskEnable (const char *taskName)
 
CRINIT_LIB_EXPORTED int crinitClientTaskDisable (const char *taskName)
 
CRINIT_LIB_EXPORTED int crinitClientTaskStop (const char *taskName)
 
CRINIT_LIB_EXPORTED int crinitClientTaskKill (const char *taskName)
 
CRINIT_LIB_EXPORTED int crinitClientTaskRestart (const char *taskName)
 
CRINIT_LIB_EXPORTED int crinitClientTaskGetStatus (crinitTaskState_t *s, pid_t *pid, const char *taskName)
 
CRINIT_LIB_EXPORTED int crinitClientGetTaskList (crinitTaskList_t **tlptr)
 
CRINIT_LIB_EXPORTED void crinitClientFreeTaskList (crinitTaskList_t *tl)
 
CRINIT_LIB_EXPORTED int crinitClientShutdown (crinitShutdownCmd_t sCmd)
 
CRINIT_LIB_EXPORTED int crinitClientGetVersion (crinitVersion_t *v)
 

Variables

static const char * crinitNotifyName = CRINIT_ENV_NOTIFY_NAME_UNDEF
 
static const char * crinitSockFile = CRINIT_SOCKFILE
 

Detailed Description

Implementation of the crinit-client shared library.

Macro Definition Documentation

◆ CRINIT_ENV_NOTIFY_NAME_UNDEF

#define CRINIT_ENV_NOTIFY_NAME_UNDEF   "@undefined"

String to be used if no task name for sd_notify() is currently set.

◆ CRINIT_LIB_CONSTRUCTOR

#define CRINIT_LIB_CONSTRUCTOR   __attribute__((constructor))

Attribute macro for a function executed on loading of the shared library.

◆ CRINIT_LIB_DESTRUCTOR

#define CRINIT_LIB_DESTRUCTOR   __attribute__((destructor))

Attribute macro for a function executed on program exit if the shared library has been loaded before.

◆ CRINIT_LIB_EXPORTED

#define CRINIT_LIB_EXPORTED   __attribute__((visibility("default")))

Attribute macro for exported/visible functions, used together with -fvisibility=hidden to export only selected functions

Function Documentation

◆ crinitClientFreeTaskList()

CRINIT_LIB_EXPORTED void crinitClientFreeTaskList ( crinitTaskList_t tl)

Free the list of tasks obtained from crinitClientGetTaskList().

Parameters
tlThe list of tasks.

◆ crinitClientGetTaskList()

CRINIT_LIB_EXPORTED int crinitClientGetTaskList ( crinitTaskList_t **  tl)

Request Crinit to report the list of task names from its TaskDB.

The returned object should be freed with crinitClientFreeTaskList().

Parameters
tlReturn pointer for the list of tasks.
Returns
0 on success, -1 on error

◆ crinitClientGetVersion()

CRINIT_LIB_EXPORTED int crinitClientGetVersion ( crinitVersion_t v)

Queries the version of the crinit daemon.

See also crinitVersion_t. Depending on the build environment, crinitVersion_t::git may be an empty string.

Parameters
vReturn pointer to an crinitVersion_t in which the crinit daemon's version will be written if the query is successful.
Returns
0 on success, -1 otherwise

◆ crinitClientLibGetVersion()

CRINIT_LIB_EXPORTED const crinitVersion_t* crinitClientLibGetVersion ( void  )

Returns version information for the crinit-client shared library.

See also crinitVersion_t. Depending on the build environment, crinitVersion_t::git may be an empty string.

Returns
A pointer to an crinitVersion_t constant containing this library's version info.

◆ crinitClientSeriesAdd()

CRINIT_LIB_EXPORTED int crinitClientSeriesAdd ( const char *  seriesFilePath,
bool  overwriteTasks 
)

Requests Crinit to load tasks and options from a series file.

If successful, the task configurations and options in the series file will be loaded same as if the series file was specified on startup. Already loaded tasks from a prior series file or loaded via crinit-ctl with the same names will be overwritten if and only if overwriteTasks is set to true. Otherwise, task name collisions are an error.

Config options from the newly loaded file generally take precedence over the existing values.

Crinit will spawn no new processes during loading of a series file in order to preserve ordering through dependencies.

Parameters
seriesFilePathAbsolute path to the series file.
overwriteTasksIf true, tasks with the same name already in the TaskDB will be overwritten.
Returns
0 on success, -1 otherwise

◆ crinitClientSetErrStream()

CRINIT_LIB_EXPORTED void crinitClientSetErrStream ( FILE *  errStream)

Selects the stream on which to output error messages.

By default, the crinit-client library will output error messages to stderr specifying where a failure occurred. This function can be used to pipe them to a logfile instead or to completely suppress them by piping to /dev/null. The stream can be the same as the one used for crinitClientSetInfoStream().

Parameters
errStreamThe stream to use.

◆ crinitClientSetInfoStream()

CRINIT_LIB_EXPORTED void crinitClientSetInfoStream ( FILE *  infoStream)

Selects the stream on which to output (debug) information messages.

By default, the crinit-client library will output debug information messages to stdout if activated by crinitClientSetVerbose(). This function can be used to pipe them to a logfile instead. The stream can be the same as the one used for crinitClientSetInfoStream().

Parameters
infoStreamThe stream to use.

◆ crinitClientSetNotifyTaskName()

CRINIT_LIB_EXPORTED void crinitClientSetNotifyTaskName ( const char *  taskName)

Sets the task name reported to Crinit by sd_notify().

The default is set via the environment variable specified by CRINIT_ENV_NOTIFY_NAME if it is present.

Parameters
taskNameThe task name to use.

◆ crinitClientSetSocketPath()

CRINIT_LIB_EXPORTED void crinitClientSetSocketPath ( const char *  sockFile)

Sets the path to Crinit's AF_UNIX communication socket.

The default is set by CRINIT_SOCKFILE.

Parameters
sockFilePath to the socket file.

◆ crinitClientSetVerbose()

CRINIT_LIB_EXPORTED int crinitClientSetVerbose ( bool  v)

Turns debug output on or off.

The default is no debug output.

Parameters
vIf there should be debug output (YES==true).

◆ crinitClientShutdown()

CRINIT_LIB_EXPORTED int crinitClientShutdown ( crinitShutdownCmd_t  sCmd)

Request Crinit to initiate an immediate shutdown or reboot.

Calling process must have the CAP_SYS_BOOT capability or Crinit will refuse with "Permission denied." Before issuing the shutdown or reboot syscall, Crinit will send SIGCONT+SIGTERM to all processes, wait a grace period (which can be set in the main series config file as SHUTDOWN_GRACE_PERIOD_US = <microseconds>), send SIGKILL to remaining processes, detach or read-only-remount all filesystems, and finally call sync().

Parameters
sCmdThe shutdown command to be performed, either CRINIT_SHD_POWEROFF (for poweroff) or CRINIT_SHD_POWEROFF (for reboot).
Returns
0 on success, -1 on error

◆ crinitClientTaskAdd()

CRINIT_LIB_EXPORTED int crinitClientTaskAdd ( const char *  configFilePath,
bool  overwrite,
const char *  forceDeps 
)

Requests Crinit to add a task from a given task config.

If successful, the given task configuration will be parsed and added to the TaskDB. Task execution takes place once all dependencies have been fulfilled, as with pre-loaded tasks.

Using forceDeps, it is possible to specify a DEPENDS value which overrides the one in the configuration file. An empty string will cause the task to be started immediately. Specifying @ctl:enable will let the task wait for crinitClientTaskEnable(). If the dependencies from the task config file should be used, forceDeps must be NULL or "@unchanged".

Note, that Crinit does not keep track of already fulfilled dependencies, i.e. in order to not be blocked forever a task configuration must only contain dependencies which will be fulfilled in the future.

Parameters
configFilePathAbsolute path to the task configuration file.
overwriteIf an existing task with the same name should be overwritten (==true). Otherwise Crinit would return an error in this case.
forceDepsString to override the value of DEPENDS in the config file, can be "" for no dependencies (immediate start), an arbitrary list of dependencies, or NULL/"@unchanged" to keep the dependencies in the config.
Returns
0 on success, -1 otherwise

◆ crinitClientTaskDisable()

CRINIT_LIB_EXPORTED int crinitClientTaskDisable ( const char *  taskName)

Requests Crinit to add the dependency "@ctl:enable" to a specific task.

This can be used in tandem with crinitClientTaskEnable() to implement starting on command.

Note, that this function can also be used to prevent tasks with the RESPAWN option set to YES from respawning, temporarily or permanently.

Parameters
taskNameThe name of the task.
Returns
0 on success, -1 on error

◆ crinitClientTaskEnable()

CRINIT_LIB_EXPORTED int crinitClientTaskEnable ( const char *  taskName)

Requests Crinit to remove the dependency "@ctl:enable" from a specific task.

This can be used in tandem with crinitClientTaskDisable() or config files which already contain the above dependency to implement starting on command.

Parameters
taskNameThe name of the task.
Returns
0 on success, -1 on error

◆ crinitClientTaskGetStatus()

CRINIT_LIB_EXPORTED int crinitClientTaskGetStatus ( crinitTaskState_t s,
pid_t *  pid,
const char *  taskName 
)

Request Crinit to report the current state and PID of a task from its TaskDB.

Parameters
sReturn pointer for the task's state.
pidReturn pointer for the task's PID.
taskNameThe name of the task.
Returns
0 on success, -1 on error

◆ crinitClientTaskKill()

CRINIT_LIB_EXPORTED int crinitClientTaskKill ( const char *  taskName)

Request Crinit to send SIGKILL to a task process.

Will only send a signal if a corresponding PID has been saved in the TaskDB, either through sd_notify() or the Process Dispatcher during process start.

Parameters
taskNameThe name of the task.
Returns
0 on success, -1 on error

◆ crinitClientTaskRestart()

CRINIT_LIB_EXPORTED int crinitClientTaskRestart ( const char *  taskName)

Request Crinit to reset the state of a task within the TaskDB.

State will be reset to 0 it is currently CRINIT_TASK_STATE_DONE or CRINIT_TASK_STATE_FAILED. If the task has no unfulfilled dependencies, this will cause an immediate restart.

Note, that the semantics are different than with e.g. systemctl restart. To get equivalent behaviour, i.e. restart a task that is currently running, a possibility is a call to crinitClientTaskStop() followed by a call to this function.

Parameters
taskNameThe name of the task.
Returns
0 on success, -1 on error

◆ crinitClientTaskStop()

CRINIT_LIB_EXPORTED int crinitClientTaskStop ( const char *  taskName)

Request Crinit to send SIGTERM to a task process.

Will only send a signal if a corresponding PID has been saved in the TaskDB, either through sd_notify() or the Process Dispatcher during process start.

Parameters
taskNameThe name of the task.
Returns
0 on success, -1 on error

◆ crinitLibDestroy()

static CRINIT_LIB_DESTRUCTOR void crinitLibDestroy ( void  )
static

Library cleanup function.

Gets called on program end through CRINIT_LIB_DESTRUCTOR attribute if the shared library was loaded. Frees global option memory allocated as a consequence of crinitLibInit().

◆ crinitLibInit()

static CRINIT_LIB_CONSTRUCTOR void crinitLibInit ( void  )
static

Library initialization function.

Gets called on shared object loading through CRINIT_LIB_CONSTRUCTOR attribute. Initializes options to default values and tries to get the task name for sd_notify() from the environment if it is present.

◆ crinitResponseCheck()

static int crinitResponseCheck ( const crinitRtimCmd_t res,
crinitRtimOp_t  resCode 
)
inlinestatic

Check if a response from Crinit is valid and/or an error.

Parameters
resThe response to check.
resCodeThe expected response opcode.
Returns
0 if res is valid and indicates success, -1 if not

◆ sd_notify()

CRINIT_LIB_EXPORTED int sd_notify ( int  unset_environment,
const char *  state 
)

Notifies Crinit of task state changes.

Partially implements the SD_NOTIFY interface of systemd. Specifically, the commands READY and MAINPID are supported. Others are currently unimplemented and will be ignored. The unset_environment argument is also unimplemented, i.e. the environment will not be unset. If unset_environment is not 0, a warning will be printed.

READY=1 lets Crinit know the task is currently running. MAINPID=[pid] tells Crinit its PID. Delimiting character is a newline.

Example: "READY=1\nMAINPID=42" will update the task's state to CRINIT_TASK_STATE_RUNNING and its PID to 42.

For more information regarding the use cases of this interface, refer to the official SD_NOTIFY documentation.

Parameters
unset_environmentUnimplemented, should be set to 0.
stateSD_NOTIFY string. A newline-separated list of commands, as in the above example.
Returns
0 on success, -1 otherwise

◆ sd_notifyf()

CRINIT_LIB_EXPORTED int sd_notifyf ( int  unset_environment,
const char *  format,
  ... 
)

Notifies Crinit of task state changes.

Like sd_notify() but uses printf-style formatting for the input string.

Variable Documentation

◆ crinitNotifyName

const char* crinitNotifyName = CRINIT_ENV_NOTIFY_NAME_UNDEF
static

Holds the task name for sd_notify()

◆ crinitSockFile

const char* crinitSockFile = CRINIT_SOCKFILE
static

Holds the path to the Crinit AF_UNIX socket file