| 1 |
/*! |
| 2 |
* @file rc.h |
| 3 |
* @brief Describes how to interface with the RC library |
| 4 |
* @internal |
| 5 |
* |
| 6 |
* Copyright 2007 Gentoo Foundation |
| 7 |
* Released under the GPLv2 |
| 8 |
*/ |
| 9 |
|
| 10 |
#ifndef __RC_H__ |
| 11 |
#define __RC_H__ |
| 12 |
|
| 13 |
#ifdef __GNUC__ |
| 14 |
# define GCC_VERSION (__GNUC__ * 1000 + __GNUC__MINOR) |
| 15 |
# if (GCC_VERSION >= 3005) |
| 16 |
# define SENTINEL __attribute__ ((__sentinel__)) |
| 17 |
# endif |
| 18 |
#endif |
| 19 |
#ifndef SENTINEL |
| 20 |
# define SENTINEL |
| 21 |
#endif |
| 22 |
|
| 23 |
#include <sys/types.h> |
| 24 |
#include <stdbool.h> |
| 25 |
//#include <stdio.h> |
| 26 |
|
| 27 |
/*! @name Reserved runlevel names */ |
| 28 |
#define RC_LEVEL_SYSINIT "sysinit" |
| 29 |
#define RC_LEVEL_SINGLE "single" |
| 30 |
#define RC_LEVEL_SHUTDOWN "shutdown" |
| 31 |
#define RC_LEVEL_REBOOT "reboot" |
| 32 |
|
| 33 |
/*! Return the current runlevel. |
| 34 |
* @return the current runlevel */ |
| 35 |
char *rc_runlevel_get (void); |
| 36 |
|
| 37 |
/*! Checks if the runlevel exists or not |
| 38 |
* @param runlevel to check |
| 39 |
* @return true if the runlevel exists, otherwise false */ |
| 40 |
bool rc_runlevel_exists (const char *runlevel); |
| 41 |
|
| 42 |
/*! Return a NULL terminated list of runlevels |
| 43 |
* @return a NULL terminated list of runlevels */ |
| 44 |
char **rc_runlevel_list (void); |
| 45 |
|
| 46 |
/*! Set the runlevel. |
| 47 |
* This just changes the stored runlevel and does not start or stop any services. |
| 48 |
* @param runlevel to store */ |
| 49 |
bool rc_runlevel_set (const char *runlevel); |
| 50 |
|
| 51 |
/*! Is the runlevel starting? |
| 52 |
* @return true if yes, otherwise false */ |
| 53 |
bool rc_runlevel_starting (void); |
| 54 |
|
| 55 |
/*! Is the runlevel stopping? |
| 56 |
* @return true if yes, otherwise false */ |
| 57 |
bool rc_runlevel_stopping (void); |
| 58 |
|
| 59 |
/*! @name RC |
| 60 |
* A service can be given as a full path or just its name. |
| 61 |
* If its just a name then we try to resolve the service to a full path. |
| 62 |
* This should allow the use if local init.d directories in the future. */ |
| 63 |
|
| 64 |
/*! @brief States a service can be in */ |
| 65 |
typedef enum |
| 66 |
{ |
| 67 |
/* These are actual states |
| 68 |
* The service has to be in one only at all times */ |
| 69 |
RC_SERVICE_STOPPED = 0x0001, |
| 70 |
RC_SERVICE_STARTED = 0x0002, |
| 71 |
RC_SERVICE_STOPPING = 0x0004, |
| 72 |
RC_SERVICE_STARTING = 0x0008, |
| 73 |
RC_SERVICE_INACTIVE = 0x0010, |
| 74 |
|
| 75 |
/* Service may or may not have been coldplugged */ |
| 76 |
RC_SERVICE_COLDPLUGGED = 0x0100, |
| 77 |
|
| 78 |
/* Optional states service could also be in */ |
| 79 |
RC_SERVICE_FAILED = 0x0200, |
| 80 |
RC_SERVICE_SCHEDULED = 0x0400, |
| 81 |
RC_SERVICE_WASINACTIVE = 0x0800, |
| 82 |
} rc_service_state_t; |
| 83 |
|
| 84 |
/*! Add the service to the runlevel |
| 85 |
* @param runlevel to add to |
| 86 |
* @param service to add |
| 87 |
* @return true if successful, otherwise false */ |
| 88 |
bool rc_service_add (const char *runlevel, const char *service); |
| 89 |
|
| 90 |
/*! Remove the service from the runlevel |
| 91 |
* @param runlevel to remove from |
| 92 |
* @param service to remove |
| 93 |
* @return true if sucessful, otherwise false */ |
| 94 |
bool rc_service_delete (const char *runlevel, const char *service); |
| 95 |
|
| 96 |
/*! Save the arguments to find a running daemon |
| 97 |
* @param service to save arguments for |
| 98 |
* @param exec that we started |
| 99 |
* @param name of the process (optional) |
| 100 |
* @param pidfile of the process (optional) |
| 101 |
* @param started if true, add the arguments otherwise remove existing matching arguments */ |
| 102 |
bool rc_service_daemon_set (const char *service, const char *exec, |
| 103 |
const char *name, const char *pidfile, |
| 104 |
bool started); |
| 105 |
|
| 106 |
/*! Returns a description of what the service and/or option does. |
| 107 |
* @param service to check |
| 108 |
* @param option to check (if NULL, service description) |
| 109 |
* @return a newly allocated pointer to the description */ |
| 110 |
char *rc_service_description (const char *service, const char *option); |
| 111 |
|
| 112 |
/*! Checks if a service exists or not. |
| 113 |
* @param service to check |
| 114 |
* @return true if service exists, otherwise false */ |
| 115 |
bool rc_service_exists (const char *service); |
| 116 |
|
| 117 |
/*! Checks if a service is in a runlevel |
| 118 |
* @param service to check |
| 119 |
* @param runlevel it should be in |
| 120 |
* @return true if service is in the runlevel, otherwise false */ |
| 121 |
bool rc_service_in_runlevel (const char *service, const char *runlevel); |
| 122 |
|
| 123 |
/*! Marks the service state |
| 124 |
* @param service to mark |
| 125 |
* @param state service should be in |
| 126 |
* @return true if service state change was successful, otherwise false */ |
| 127 |
bool rc_service_mark (const char *service, rc_service_state_t state); |
| 128 |
|
| 129 |
/*! Lists the extra options a service has |
| 130 |
* @param service to load the options from |
| 131 |
* @return NULL terminated string list of options */ |
| 132 |
char **rc_service_options (const char *service); |
| 133 |
|
| 134 |
/*! Check if the service is allowed to be hot/cold plugged |
| 135 |
* @param service to check |
| 136 |
* @return true if allowed, otherwise false */ |
| 137 |
bool rc_service_plugable (char *service); |
| 138 |
|
| 139 |
/*! Resolves a service name to its full path. |
| 140 |
* @param service to check |
| 141 |
* @return pointer to full path of service */ |
| 142 |
char *rc_service_resolve (const char *service); |
| 143 |
|
| 144 |
/*! Schedule a service to be started when another service starts |
| 145 |
* @param service that starts the scheduled service when started |
| 146 |
* @param service_to_start service that will be started */ |
| 147 |
bool rc_service_schedule_start (const char *service, |
| 148 |
const char *service_to_start); |
| 149 |
/*! Return a NULL terminated list of services that are scheduled to start |
| 150 |
* when the given service has started |
| 151 |
* @param service to check |
| 152 |
* @return NULL terminated list of services scheduled to start */ |
| 153 |
char **rc_services_scheduled_by (const char *service); |
| 154 |
|
| 155 |
/*! Clear the list of services scheduled to be started by this service |
| 156 |
* @param service to clear |
| 157 |
* @return true if no errors, otherwise false */ |
| 158 |
bool rc_service_schedule_clear (const char *service); |
| 159 |
|
| 160 |
/*! Checks if a service in in a state |
| 161 |
* @param service to check |
| 162 |
* @return state of the service */ |
| 163 |
rc_service_state_t rc_service_state (const char *service); |
| 164 |
|
| 165 |
/*! Start a service |
| 166 |
* @param service to start |
| 167 |
* @return pid of the service starting process */ |
| 168 |
pid_t rc_service_start (const char *service); |
| 169 |
|
| 170 |
/*! Stop a service |
| 171 |
* @param service to stop |
| 172 |
* @return pid of service stopping process */ |
| 173 |
pid_t rc_service_stop (const char *service); |
| 174 |
|
| 175 |
/*! Check if the service started the daemon |
| 176 |
* @param service to check |
| 177 |
* @param exec to check |
| 178 |
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc) |
| 179 |
* @return true if started by this service, otherwise false */ |
| 180 |
bool rc_service_started_daemon (const char *service, const char *exec, |
| 181 |
int indx); |
| 182 |
|
| 183 |
/*! Return a saved value for a service |
| 184 |
* @param service to check |
| 185 |
* @param option to load |
| 186 |
* @return saved value */ |
| 187 |
char *rc_service_value_get (const char *service, const char *option); |
| 188 |
|
| 189 |
/*! Save a persistent value for a service |
| 190 |
* @param service to save for |
| 191 |
* @param option to save |
| 192 |
* @param value of the option |
| 193 |
* @return true if saved, otherwise false */ |
| 194 |
bool rc_service_value_set (const char *service, const char *option, |
| 195 |
const char *value); |
| 196 |
|
| 197 |
/*! Wait for a service to finish |
| 198 |
* @param service to wait for |
| 199 |
* @return true if service finished before timeout, otherwise false */ |
| 200 |
bool rc_service_wait (const char *service); |
| 201 |
|
| 202 |
/*! List the services in a runlevel |
| 203 |
* @param runlevel to list |
| 204 |
* @return NULL terminated list of services */ |
| 205 |
char **rc_services_in_runlevel (const char *runlevel); |
| 206 |
|
| 207 |
/*! List the services in a state |
| 208 |
* @param state to list |
| 209 |
* @return NULL terminated list of services */ |
| 210 |
char **rc_services_in_state (rc_service_state_t state); |
| 211 |
|
| 212 |
/*! List the services shceduled to start when this one does |
| 213 |
* @param service to check |
| 214 |
* @return NULL terminated list of services */ |
| 215 |
char **rc_services_scheduled (const char *service); |
| 216 |
|
| 217 |
/*! Checks that all daemons started with start-stop-daemon by the service |
| 218 |
* are still running. |
| 219 |
* @param service to check |
| 220 |
* @return true if all daemons started are still running, otherwise false */ |
| 221 |
bool rc_service_daemons_crashed (const char *service); |
| 222 |
|
| 223 |
/*! @name Dependency options |
| 224 |
* These options can change the services found by the rc_get_depinfo and |
| 225 |
* rc_get_depends functions. */ |
| 226 |
/*! Trace provided services */ |
| 227 |
#define RC_DEP_TRACE 0x01 |
| 228 |
/*! Only use services added to runlevels */ |
| 229 |
#define RC_DEP_STRICT 0x02 |
| 230 |
/*! Runlevel is starting */ |
| 231 |
#define RC_DEP_START 0x04 |
| 232 |
/*! Runlevel is stopping */ |
| 233 |
#define RC_DEP_STOP 0x08 |
| 234 |
|
| 235 |
/*! @name Dependencies |
| 236 |
* We analyse each init script and cache the resultant dependency tree. |
| 237 |
* This tree can be accessed using the below functions. */ |
| 238 |
|
| 239 |
#ifndef _IN_LIBRC |
| 240 |
/* Handles to internal structures */ |
| 241 |
typedef void *rc_depinfo_t; |
| 242 |
#endif |
| 243 |
|
| 244 |
/*! Update the cached dependency tree if it's older than any init script, |
| 245 |
* its configuration file or an external configuration file the init script |
| 246 |
* has specified. |
| 247 |
* @return true if successful, otherwise false */ |
| 248 |
bool rc_deptree_update (void); |
| 249 |
|
| 250 |
/*! Check if the cached dependency tree is older than any init script, |
| 251 |
* its configuration file or an external configuration file the init script |
| 252 |
* has specified. |
| 253 |
* @return true if it needs updating, otherwise false */ |
| 254 |
bool rc_deptree_update_needed (void); |
| 255 |
|
| 256 |
/*! Load the cached dependency tree and return a pointer to it. |
| 257 |
* This pointer should be freed with rc_deptree_free when done. |
| 258 |
* @return pointer to the dependency tree */ |
| 259 |
rc_depinfo_t *rc_deptree_load (void); |
| 260 |
|
| 261 |
/*! List all the services in order that the given services have |
| 262 |
* for the given types and options. |
| 263 |
* @param deptree to search |
| 264 |
* @param types to use (ineed, iuse, etc) |
| 265 |
* @param services to check |
| 266 |
* @param options to pass |
| 267 |
* @return NULL terminated list of services in order */ |
| 268 |
char **rc_deptree_depends (rc_depinfo_t *deptree, char **types, |
| 269 |
char **services, const char *runlevel, int options); |
| 270 |
|
| 271 |
/*! List all the services that should be stoppned and then started, in order, |
| 272 |
* for the given runlevel, including sysinit and boot services where |
| 273 |
* approriate. |
| 274 |
* @param deptree to search |
| 275 |
* @param runlevel to change into |
| 276 |
* @param options to pass |
| 277 |
* @return NULL terminated list of services in order */ |
| 278 |
char **rc_deptree_order (rc_depinfo_t *deptree, const char *runlevel, |
| 279 |
int options); |
| 280 |
|
| 281 |
/*! Free a deptree and its information |
| 282 |
* @param deptree to free */ |
| 283 |
void rc_deptree_free (rc_depinfo_t *deptree); |
| 284 |
|
| 285 |
/*! @name Plugins |
| 286 |
* For each plugin loaded we will call rc_plugin_hook with the below |
| 287 |
* enum and either the runlevel name or service name. |
| 288 |
* |
| 289 |
* Plugins are called when rc does something. This does not indicate an |
| 290 |
* end result and the plugin should use the above functions to query things |
| 291 |
* like service status. |
| 292 |
* |
| 293 |
* The service hooks have extra ones - now and done. This is because after |
| 294 |
* start_in we may start other services before we start the service in |
| 295 |
* question. now shows we really will start the service now and done shows |
| 296 |
* when we have done it as may start scheduled services at this point. */ |
| 297 |
/*! Points at which a plugin can hook into RC */ |
| 298 |
typedef enum |
| 299 |
{ |
| 300 |
RC_HOOK_RUNLEVEL_STOP_IN = 1, |
| 301 |
RC_HOOK_RUNLEVEL_STOP_OUT = 4, |
| 302 |
RC_HOOK_RUNLEVEL_START_IN = 5, |
| 303 |
RC_HOOK_RUNLEVEL_START_OUT = 8, |
| 304 |
/*! We send the abort if an init script requests we abort and drop |
| 305 |
* into single user mode if system not fully booted */ |
| 306 |
RC_HOOK_ABORT = 99, |
| 307 |
RC_HOOK_SERVICE_STOP_IN = 101, |
| 308 |
RC_HOOK_SERVICE_STOP_NOW = 102, |
| 309 |
RC_HOOK_SERVICE_STOP_DONE = 103, |
| 310 |
RC_HOOK_SERVICE_STOP_OUT = 104, |
| 311 |
RC_HOOK_SERVICE_START_IN = 105, |
| 312 |
RC_HOOK_SERVICE_START_NOW = 106, |
| 313 |
RC_HOOK_SERVICE_START_DONE = 107, |
| 314 |
RC_HOOK_SERVICE_START_OUT = 108 |
| 315 |
} rc_hook_t; |
| 316 |
|
| 317 |
/*! Plugin entry point |
| 318 |
* @param hook point |
| 319 |
* @param name of runlevel or service |
| 320 |
* @return 0 for success otherwise -1 */ |
| 321 |
int rc_plugin_hook (rc_hook_t hook, const char *name); |
| 322 |
|
| 323 |
/*! Plugins should write FOO=BAR to this fd to set any environment |
| 324 |
* variables they wish. Variables should be separated by NULLs. */ |
| 325 |
extern FILE *rc_environ_fd; |
| 326 |
|
| 327 |
/*! @name Configuration |
| 328 |
* These functions help to deal with shell based configuration files */ |
| 329 |
/*! Return a NULL terminated list of non comment lines from a file. */ |
| 330 |
char **rc_config_list (const char *file); |
| 331 |
|
| 332 |
/*! Return a NULL terminated list of key=value lines from a file. */ |
| 333 |
char **rc_config_load (const char *file); |
| 334 |
|
| 335 |
/*! Return the value of the entry from a key=value list. */ |
| 336 |
char *rc_config_value (char **list, const char *entry); |
| 337 |
|
| 338 |
/*! Check if an environment variable is a boolean and return it's value. |
| 339 |
* If variable is not a boolean then we set errno to be ENOENT when it does |
| 340 |
* not exist or EINVAL if it's not a boolean. |
| 341 |
* @param variable to check |
| 342 |
* @return true if it matches true, yes or 1, false if otherwise. */ |
| 343 |
bool rc_env_bool (const char *variable); |
| 344 |
|
| 345 |
/*! @name String List functions |
| 346 |
* Handy functions for dealing with string arrays of char **. |
| 347 |
* It's safe to assume that any function here that uses char ** is a string |
| 348 |
* list that can be manipulated with the below functions. Every string list |
| 349 |
* should be released with a call to rc_strlist_free. */ |
| 350 |
|
| 351 |
/*! Duplicate the item, add it to end of the list and return a pointer to it. |
| 352 |
* @param list to add the item too |
| 353 |
* @param item to add. |
| 354 |
* @return pointer to newly added item */ |
| 355 |
char *rc_strlist_add (char ***list, const char *item); |
| 356 |
|
| 357 |
/*! If the item does not exist in the list, duplicate it, add it to the |
| 358 |
* list and then return a pointer to it. |
| 359 |
* @param list to add the item too |
| 360 |
* @param item to add. |
| 361 |
* @return pointer to newly added item */ |
| 362 |
char *rc_strlist_addu (char ***list, const char *item); |
| 363 |
|
| 364 |
/*! Duplicate the item, add it to the list at the point based on locale and |
| 365 |
* then return a pointer to it. |
| 366 |
* @param list to add the item too |
| 367 |
* @param item to add. |
| 368 |
* @return pointer to newly added item */ |
| 369 |
char *rc_strlist_addsort (char ***list, const char *item); |
| 370 |
|
| 371 |
/*! Duplicate the item, add it to the list at the point based on C locale and |
| 372 |
* then return a pointer to it. |
| 373 |
* @param list to add the item too |
| 374 |
* @param item to add. |
| 375 |
* @return pointer to newly added item */ |
| 376 |
char *rc_strlist_addsortc (char ***list, const char *item); |
| 377 |
|
| 378 |
/*! If the item does not exist in the list, duplicate it, add it to the |
| 379 |
* list based on locale and then return a pointer to it. |
| 380 |
* @param list to add the item too |
| 381 |
* @param item to add. |
| 382 |
* @return pointer to newly added item */ |
| 383 |
char *rc_strlist_addsortu (char ***list, const char *item); |
| 384 |
|
| 385 |
/*! Free the item and remove it from the list. Return 0 on success otherwise -1. |
| 386 |
* @param list to add the item too |
| 387 |
* @param item to add. |
| 388 |
* @return true on success, otherwise false */ |
| 389 |
bool rc_strlist_delete (char ***list, const char *item); |
| 390 |
|
| 391 |
/*! Moves the contents of list2 onto list1, so list2 is effectively emptied. |
| 392 |
* Returns a pointer to the last item on the new list. |
| 393 |
* @param list1 to append to |
| 394 |
* @param list2 to move from |
| 395 |
* @return pointer to the last item on the list */ |
| 396 |
char *rc_strlist_join (char ***list1, char **list2); |
| 397 |
|
| 398 |
/*! Reverses the contents of the list. |
| 399 |
* @param list to reverse */ |
| 400 |
void rc_strlist_reverse (char **list); |
| 401 |
|
| 402 |
/*! Frees each item on the list and the list itself. |
| 403 |
* @param list to free */ |
| 404 |
void rc_strlist_free (char **list); |
| 405 |
|
| 406 |
/*! Concatenate paths adding '/' if needed. The resultant pointer should be |
| 407 |
* freed when finished with. |
| 408 |
* @param path1 starting path |
| 409 |
* @param paths NULL terminated list of paths to add |
| 410 |
* @return pointer to the new path */ |
| 411 |
char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL; |
| 412 |
|
| 413 |
/*! Find processes based on criteria. |
| 414 |
* All of these are optional. |
| 415 |
* pid overrides anything else. |
| 416 |
* If both exec and cmd are given then we ignore exec. |
| 417 |
* @param exec to check for |
| 418 |
* @param cmd to check for |
| 419 |
* @param uid to check for |
| 420 |
* @param pid to check for |
| 421 |
* @return NULL terminated list of pids */ |
| 422 |
pid_t *rc_find_pids (const char *exec, const char *cmd, |
| 423 |
uid_t uid, pid_t pid); |
| 424 |
|
| 425 |
#endif |