blob: eafc3f6c2f3409eba1dcb6797cbb08ed4bd667c5 [file] [log] [blame]
/* upstart
*
* Copyright © 2011 Canonical Ltd.
* Author: James Hunt <james.hunt@canonical.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef INITCTL_H
#define INITCTL_H
/**
* IS_OP_AND:
* @token: string token to check.
*
* Return TRUE if @token is an 'AND' operator, else FALSE.
**/
#define IS_OP_AND(token) \
(! strcmp ((token), "/AND"))
/**
* IS_OP_OR:
* @token: string token to check.
*
* Return TRUE if @token is an 'OR' operator, else FALSE.
**/
#define IS_OP_OR(token) \
(! strcmp ((token), "/OR"))
/**
* IS_OPERATOR
* @token: string token to check.
*
* Return TRUE if @token is either an 'AND' or an 'OR' operator,
* else FALSE.
**/
#define IS_OPERATOR(token) \
IS_OP_AND (token) || IS_OP_OR (token)
/**
* GET_JOB_NAME:
*
* @var: char pointer variable which will be set to the name
* of a job, or NULL,
* @index: zero-based index of tokens where zero represents
* the first token after the initial token,
* @token: string to check.
*
* Determine name of job considering the specified token and its
* index. If not a job, sets @name to NULL.
*
* Handles the following cases:
*
* [start|stop] on <job_event> foo
* (index==0, job="foo" => name="foo")
*
* [start|stop] on <job_event> JOB=foo
* (index==0, job="JOB=foo" => name="foo")
*
* [start|stop] on <job_event> A=B JOB=foo
* (index==1, job="JOB=foo" => name="foo")
*
* [start|stop] on <job_event> A=B c=hello JOB=foo
* (index==2, job="JOB=foo" => name="foo")
*
* [start|stop] on <job_event> $JOB A=B c=hello
* (index==0, job="$JOB" => name="$JOB")
*
**/
#define GET_JOB_NAME(var, index, token) \
{ \
char *_##var; \
\
nih_assert (index >= 0); \
nih_assert (token); \
\
var = NULL; \
\
_##var = strstr (token, "JOB="); \
\
if (_##var && _##var == token) \
var = _##var + strlen ("JOB="); \
else if (index == 0 ) { \
if (!strstr (token, "=")) \
var = token; \
} \
}
/**
* IS_JOB_EVENT:
* @token: string to check.
*
* Return TRUE if specified token refers to a standard job event, else
* FALSE.
**/
#define IS_JOB_EVENT(token) \
(!strcmp (token, JOB_STARTING_EVENT) || \
!strcmp (token, JOB_STARTED_EVENT) || \
!strcmp (token, JOB_STOPPING_EVENT) || \
!strcmp (token, JOB_STOPPED_EVENT))
/**
* IS_INIT_EVENT:
* @token: string to check.
*
* Return TRUE if specified token refers to an event emitted internally,
* else FALSE.
*
* Note: the raw string entries below are required to accommodate
* production versus debug builds (STARTUP_EVENT changes name depending
* on build type).
**/
#define IS_INIT_EVENT(token) \
(!strcmp (token, STARTUP_EVENT) || \
!strcmp (token, "debug") || \
!strcmp (token, "startup") || \
!strcmp (token, CTRLALTDEL_EVENT) || \
!strcmp (token, KBDREQUEST_EVENT) || \
!strcmp (token, PWRSTATUS_EVENT) || \
IS_JOB_EVENT (token))
/**
* STACK_EMPTY:
* @stack: address of stack to check.
*
* Return TRUE if @stack is empty, else FALSE.
**/
#define STACK_EMPTY(stack) \
(NIH_LIST_EMPTY (stack))
/**
* STACK_CREATE:
* @name: nih_list variable to assign stack to.
**/
#define STACK_CREATE(name) \
name = NIH_MUST (nih_list_new (NULL))
/**
* STACK_SHOW_POP:
* @stack: Address of stack,
* @str: string representing element popped off stack.
*
* Display message to denote that @str has been popped off @stack.
* Does nothing if debug build not enabled.
*
* Note: we cannot assert that stack is not empty since a caller may
* have just removed the last entry before calling us. Thus, it is up to
* the caller to perform such checks.
*
* Does nothing if debug build not enabled.
**/
#ifdef DEBUG_STACK
#define STACK_SHOW_POP(stack, str) \
STACK_SHOW_CHANGE (stack, "popped", str)
#else
#define STACK_SHOW_POP(stack, str)
#endif
/**
* STACK_SHOW_PUSH:
* @stack: Address of stack,
* @str: string representing element pushed onto stack.
*
* Display message to denote that @str has been pushed onto @stack.
*
* Does nothing if debug build not enabled.
**/
#ifdef DEBUG_STACK
#define STACK_SHOW_PUSH(stack, str) \
STACK_SHOW_CHANGE (stack, "pushed", str) \
\
nih_assert (! STACK_EMPTY (stack))
#else
#define STACK_SHOW_PUSH(stack, str)
#endif
/**
* STACK_SHOW:
* @stack: Address of stack.
*
* Display contents of @stack.
*
* Does nothing if debug build not enabled.
**/
#ifdef DEBUG_STACK
#define STACK_SHOW(stack) \
{ \
size_t depth = 0; \
\
nih_assert (stack); \
\
NIH_LIST_FOREACH (stack, iter) { \
depth++; \
} \
\
if (STACK_EMPTY (stack)) { \
nih_message ("STACK@%p: empty", stack); \
} else { \
for (NihList *iter = (stack)->next; \
iter != (stack) && \
((NihListEntry *)iter)->str; \
iter = iter->next, depth--) { \
nih_message ("STACK@%p[%u]='%s'", \
(void *)stack, \
(unsigned int)(depth-1), \
((NihListEntry *)iter)->str); \
} \
} \
}
#else
#define STACK_SHOW(stack)
#endif
/**
* STACK_SHOW_CHANGE:
* @stack: Address of stack,
* @msg: message to show a stack change,
* @element_str: string representing element changed on @stack.
*
* Display a message showing that the stack has been changed.
*
* Does nothing if debug build not enabled.
**/
#ifdef DEBUG_STACK
#define STACK_SHOW_CHANGE(stack, msg, element_str) \
nih_assert (msg); \
nih_assert (element_str); \
\
nih_message ("STACK@%p: %s '%s'", \
(void *)stack, msg, element_str); \
\
STACK_SHOW (stack); \
\
nih_message (" "); /* spacer */
#else
#define STACK_SHOW_CHANGE(stack, msg, element_str)
#endif
/**
* STACK_PUSH:
* @stack: Address of stack,
* @elem: element of type NihListEntry to add to stack.
*
* Add @elem to @stack and display message showing how stack changed.
**/
#define STACK_PUSH(stack, elem) \
nih_list_add_after (stack, &(elem)->entry); \
\
STACK_SHOW_PUSH (stack, \
((NihListEntry *)(elem))->str); \
\
nih_assert (! STACK_EMPTY (stack))
/**
* STACK_PUSH_NEW_ELEM:
* @stack: Address of stack,
* @string: String to convert into a new NihListEntry
* stack element and push onto @stack.
*
* Create new stack element from @string and push onto @stack,
* displaying a message showing how stack changed.
**/
#define STACK_PUSH_NEW_ELEM(stack, string) \
{ \
NihListEntry *e; \
\
nih_assert (stack); \
nih_assert (string); \
\
e = NIH_MUST (nih_new (stack, NihListEntry)); \
nih_list_init (&e->entry); \
e->str = NIH_MUST (nih_strdup (e, string)); \
STACK_PUSH (stack, e); \
}
/**
* STACK_POP:
* @stack: Address of stack,
* @list: list which top stack element will be added to.
*
* Remove top element from @stack, returning to caller as @list
* and display message showing how stack changed.
*
* Note that @list is assumed to have had nih_list_new() called
* on it already.
**/
#define STACK_POP(stack, list) \
nih_assert (stack); \
nih_assert ((stack)->next); \
\
list = nih_list_add (list, (stack)->next); \
STACK_SHOW_POP (stack, \
((NihListEntry *)(list))->str)
/**
* STACK_PEEK:
* @stack: Address of stack.
*
* Return string value of top element on stack.
**/
#define STACK_PEEK(stack) \
(((NihListEntry *)(stack)->next)->str)
/**
* ConditionHandlerData:
*
* @condition_name: "start on" or "stop on",
* @job_class_name: name of *.conf file less the extension.
*
* Used to pass multiple values to job_class_get_start_on() /
* job_class_get_stop_on() handlers.
*
**/
typedef struct condition_handler_data {
const char *condition_name;
const char *job_class_name;
} ConditionHandlerData;
#endif /* INITCTL_H */