2009-11-20 01:13:20 +03:00
/*-*- Mode: C; c-basic-offset: 8 -*-*/
2010-01-26 23:39:06 +03:00
# include <linux/oom.h>
2009-11-20 01:13:20 +03:00
# include <assert.h>
# include <errno.h>
# include <string.h>
2010-01-26 23:39:06 +03:00
# include <unistd.h>
# include <fcntl.h>
2009-11-20 01:13:20 +03:00
2010-01-26 23:39:06 +03:00
# include "unit.h"
2009-11-20 01:13:20 +03:00
# include "strv.h"
# include "conf-parser.h"
# include "load-fragment.h"
2010-01-20 21:19:53 +03:00
# include "log.h"
2009-11-20 01:13:20 +03:00
2010-01-19 04:56:37 +03:00
static int config_parse_deps (
2009-11-20 01:13:20 +03:00
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
2010-01-26 23:39:06 +03:00
UnitDependency d = PTR_TO_UINT ( data ) ;
Unit * u = userdata ;
2009-11-20 01:13:20 +03:00
char * w ;
size_t l ;
char * state ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
FOREACH_WORD ( w , & l , rvalue , state ) {
char * t ;
int r ;
2010-01-26 23:39:06 +03:00
Unit * other ;
2009-11-20 01:13:20 +03:00
if ( ! ( t = strndup ( w , l ) ) )
return - ENOMEM ;
2010-01-26 23:39:06 +03:00
r = manager_load_unit ( u - > meta . manager , t , & other ) ;
2009-11-20 01:13:20 +03:00
free ( t ) ;
if ( r < 0 )
return r ;
2010-01-26 23:39:06 +03:00
if ( ( r = unit_add_dependency ( u , d , other ) ) < 0 )
2009-11-20 01:13:20 +03:00
return r ;
}
return 0 ;
}
2010-01-19 04:56:37 +03:00
static int config_parse_names (
2010-01-19 01:50:13 +03:00
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
2010-01-26 23:39:06 +03:00
Unit * u = userdata ;
2010-01-19 01:50:13 +03:00
char * w ;
size_t l ;
char * state ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
FOREACH_WORD ( w , & l , rvalue , state ) {
char * t ;
int r ;
2010-01-26 23:39:06 +03:00
Unit * other ;
2010-01-19 01:50:13 +03:00
if ( ! ( t = strndup ( w , l ) ) )
return - ENOMEM ;
2010-01-26 23:39:06 +03:00
other = manager_get_unit ( u - > meta . manager , t ) ;
2010-01-19 01:50:13 +03:00
if ( other ) {
2010-01-26 23:39:06 +03:00
if ( other ! = u ) {
2010-01-19 01:50:13 +03:00
2010-01-26 23:39:06 +03:00
if ( other - > meta . load_state ! = UNIT_STUB ) {
2010-01-19 01:50:13 +03:00
free ( t ) ;
return - EEXIST ;
}
2010-01-26 23:39:06 +03:00
if ( ( r = unit_merge ( u , other ) ) < 0 ) {
2010-01-19 01:50:13 +03:00
free ( t ) ;
return r ;
}
}
} else {
2010-01-26 23:39:06 +03:00
if ( ( r = unit_add_name ( u , t ) ) < 0 ) {
2010-01-19 01:50:13 +03:00
free ( t ) ;
return r ;
}
}
free ( t ) ;
}
return 0 ;
}
2010-01-19 04:56:37 +03:00
static int config_parse_listen (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
2010-01-20 21:19:53 +03:00
int r ;
2010-01-23 05:35:54 +03:00
SocketPort * p ;
Socket * s ;
2010-01-20 21:19:53 +03:00
2010-01-19 04:56:37 +03:00
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
2010-01-23 05:35:54 +03:00
s = ( Socket * ) data ;
if ( ! ( p = new0 ( SocketPort , 1 ) ) )
return - ENOMEM ;
if ( streq ( lvalue , " ListenFIFO " ) ) {
p - > type = SOCKET_FIFO ;
if ( ! ( p - > path = strdup ( rvalue ) ) ) {
free ( p ) ;
return - ENOMEM ;
}
} else {
p - > type = SOCKET_SOCKET ;
if ( ( r = socket_address_parse ( & p - > address , rvalue ) ) < 0 ) {
log_error ( " [%s:%u] Failed to parse address value: %s " , filename , line , rvalue ) ;
free ( p ) ;
return r ;
}
if ( streq ( lvalue , " ListenStream " ) )
p - > address . type = SOCK_STREAM ;
else if ( streq ( lvalue , " ListenDatagram " ) )
p - > address . type = SOCK_DGRAM ;
else {
assert ( streq ( lvalue , " ListenSequentialPacket " ) ) ;
p - > address . type = SOCK_SEQPACKET ;
}
if ( socket_address_family ( & p - > address ) ! = AF_LOCAL & & p - > address . type = = SOCK_SEQPACKET ) {
free ( p ) ;
return - EPROTONOSUPPORT ;
}
2010-01-20 21:19:53 +03:00
}
2010-01-23 05:35:54 +03:00
p - > fd = - 1 ;
2010-01-26 06:18:44 +03:00
LIST_PREPEND ( SocketPort , port , s - > ports , p ) ;
2010-01-23 05:35:54 +03:00
2010-01-20 21:19:53 +03:00
return 0 ;
2010-01-19 04:56:37 +03:00
}
2010-01-26 06:18:44 +03:00
static int config_parse_socket_bind (
2010-01-19 04:56:37 +03:00
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
2010-01-23 05:35:54 +03:00
int r ;
Socket * s ;
2010-01-19 04:56:37 +03:00
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
2010-01-23 05:35:54 +03:00
s = ( Socket * ) data ;
if ( ( r = parse_boolean ( rvalue ) ) < 0 ) {
log_error ( " [%s:%u] Failed to parse bind IPv6 only value: %s " , filename , line , rvalue ) ;
return r ;
2010-01-20 21:19:53 +03:00
}
2010-01-19 04:56:37 +03:00
2010-01-23 05:35:54 +03:00
s - > bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH ;
2010-01-19 04:56:37 +03:00
return 0 ;
}
2010-01-26 06:18:44 +03:00
static int config_parse_nice (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
int * i = data , priority , r ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( ( r = safe_atoi ( rvalue , & priority ) ) < 0 ) {
log_error ( " [%s:%u] Failed to parse nice priority: %s " , filename , line , rvalue ) ;
return r ;
}
if ( priority < PRIO_MIN | | priority > = PRIO_MAX ) {
log_error ( " [%s:%u] Nice priority out of range: %s " , filename , line , rvalue ) ;
return - ERANGE ;
}
* i = priority ;
return 0 ;
}
static int config_parse_oom_adjust (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
int * i = data , oa , r ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( ( r = safe_atoi ( rvalue , & oa ) ) < 0 ) {
log_error ( " [%s:%u] Failed to parse OOM adjust value: %s " , filename , line , rvalue ) ;
return r ;
}
if ( oa < OOM_DISABLE | | oa > OOM_ADJUST_MAX ) {
log_error ( " [%s:%u] OOM adjust value out of range: %s " , filename , line , rvalue ) ;
return - ERANGE ;
}
* i = oa ;
return 0 ;
}
static int config_parse_umask (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
mode_t * m = data ;
long l ;
char * x = NULL ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
errno = 0 ;
l = strtol ( rvalue , & x , 8 ) ;
if ( ! x | | * x | | errno ) {
log_error ( " [%s:%u] Failed to parse umask value: %s " , filename , line , rvalue ) ;
return errno ? - errno : - EINVAL ;
}
if ( l < 0000 | | l > 0777 ) {
log_error ( " [%s:%u] umask value out of range: %s " , filename , line , rvalue ) ;
return - ERANGE ;
}
* m = ( mode_t ) l ;
return 0 ;
}
static int config_parse_exec (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
ExecCommand * * e = data , * ee , * nce = NULL ;
char * * n ;
char * w ;
unsigned k ;
size_t l ;
char * state ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
k = 0 ;
FOREACH_WORD_QUOTED ( w , l , rvalue , state )
k + + ;
if ( ! ( n = new ( char * , k + 1 ) ) )
return - ENOMEM ;
2010-01-26 09:02:51 +03:00
k = 0 ;
2010-01-26 06:18:44 +03:00
FOREACH_WORD_QUOTED ( w , l , rvalue , state )
if ( ! ( n [ k + + ] = strndup ( w , l ) ) )
goto fail ;
n [ k ] = NULL ;
2010-01-27 02:15:56 +03:00
if ( ! n [ 0 ] | | ! path_is_absolute ( n [ 0 ] ) ) {
2010-01-26 06:18:44 +03:00
log_error ( " [%s:%u] Invalid executable path in command line: %s " , filename , line , rvalue ) ;
strv_free ( n ) ;
return - EINVAL ;
}
if ( ! ( nce = new0 ( ExecCommand , 1 ) ) )
goto fail ;
nce - > argv = n ;
if ( ! ( nce - > path = strdup ( n [ 0 ] ) ) )
goto fail ;
if ( * e ) {
/* It's kinda important that we keep the order here */
LIST_FIND_TAIL ( ExecCommand , command , * e , ee ) ;
LIST_INSERT_AFTER ( ExecCommand , command , * e , ee , nce ) ;
} else
* e = nce ;
return 0 ;
fail :
for ( ; k > 0 ; k - - )
free ( n [ k - 1 ] ) ;
free ( n ) ;
free ( nce ) ;
return - ENOMEM ;
}
static int config_parse_usec (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
usec_t * usec = data ;
unsigned long long u ;
int r ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( ( r = safe_atollu ( rvalue , & u ) ) < 0 ) {
log_error ( " [%s:%u] Failed to parse time value: %s " , filename , line , rvalue ) ;
return r ;
}
/* We actually assume the user configures seconds. Later on we
* might choose to support suffixes for time values , to
* configure bigger or smaller units */
* usec = u * USEC_PER_SEC ;
return 0 ;
}
static int config_parse_service_type (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
Service * s = data ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( streq ( rvalue , " forking " ) )
s - > type = SERVICE_FORKING ;
else if ( streq ( rvalue , " simple " ) )
s - > type = SERVICE_SIMPLE ;
else {
log_error ( " [%s:%u] Failed to parse service type: %s " , filename , line , rvalue ) ;
return - EBADMSG ;
}
return 0 ;
}
static int config_parse_service_restart (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
Service * s = data ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( streq ( rvalue , " once " ) )
s - > restart = SERVICE_ONCE ;
else if ( streq ( rvalue , " on-success " ) )
s - > type = SERVICE_RESTART_ON_SUCCESS ;
else if ( streq ( rvalue , " always " ) )
s - > type = SERVICE_RESTART_ALWAYS ;
else {
log_error ( " [%s:%u] Failed to parse service type: %s " , filename , line , rvalue ) ;
return - EBADMSG ;
}
return 0 ;
}
2010-01-27 06:31:52 +03:00
int config_parse_bindtodevice (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
Socket * s = data ;
char * n ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( rvalue [ 0 ] & & ! streq ( rvalue , " * " ) ) {
if ( ! ( n = strdup ( rvalue ) ) )
return - ENOMEM ;
} else
n = NULL ;
free ( s - > bind_to_device ) ;
s - > bind_to_device = n ;
return 0 ;
}
2010-01-28 04:06:20 +03:00
int config_parse_output (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
ExecOutput * o = data ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
if ( streq ( rvalue , " syslog " ) )
* o = EXEC_SYSLOG ;
else if ( streq ( rvalue , " null " ) )
* o = EXEC_NULL ;
else if ( streq ( rvalue , " syslog " ) )
* o = EXEC_SYSLOG ;
else if ( streq ( rvalue , " kernel " ) )
* o = EXEC_KERNEL ;
else {
log_error ( " [%s:%u] Failed to parse log output: %s " , filename , line , rvalue ) ;
return - EBADMSG ;
}
return 0 ;
}
2010-01-26 23:39:06 +03:00
2010-01-28 04:06:20 +03:00
int config_parse_facility (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
static const char * const table [ LOG_NFACILITIES ] = {
[ LOG_FAC ( LOG_KERN ) ] = " kern " ,
[ LOG_FAC ( LOG_USER ) ] = " user " ,
[ LOG_FAC ( LOG_MAIL ) ] = " mail " ,
[ LOG_FAC ( LOG_DAEMON ) ] = " daemon " ,
[ LOG_FAC ( LOG_AUTH ) ] = " auth " ,
[ LOG_FAC ( LOG_SYSLOG ) ] = " syslog " ,
[ LOG_FAC ( LOG_LPR ) ] = " lpr " ,
[ LOG_FAC ( LOG_NEWS ) ] = " news " ,
[ LOG_FAC ( LOG_UUCP ) ] = " uucp " ,
[ LOG_FAC ( LOG_CRON ) ] = " cron " ,
[ LOG_FAC ( LOG_AUTHPRIV ) ] = " authpriv " ,
[ LOG_FAC ( LOG_FTP ) ] = " ftp " ,
[ LOG_FAC ( LOG_LOCAL0 ) ] = " local0 " ,
[ LOG_FAC ( LOG_LOCAL1 ) ] = " local1 " ,
[ LOG_FAC ( LOG_LOCAL2 ) ] = " local2 " ,
[ LOG_FAC ( LOG_LOCAL3 ) ] = " local3 " ,
[ LOG_FAC ( LOG_LOCAL4 ) ] = " local4 " ,
[ LOG_FAC ( LOG_LOCAL5 ) ] = " local5 " ,
[ LOG_FAC ( LOG_LOCAL6 ) ] = " local6 " ,
[ LOG_FAC ( LOG_LOCAL7 ) ] = " local7 "
} ;
ExecOutput * o = data ;
int i ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
for ( i = 0 ; i < ( int ) ELEMENTSOF ( table ) ; i + + )
if ( streq ( rvalue , table [ i ] ) ) {
* o = LOG_MAKEPRI ( i , LOG_PRI ( * o ) ) ;
break ;
}
if ( i > = ( int ) ELEMENTSOF ( table ) ) {
/* Second try, let's see if this is a number. */
if ( safe_atoi ( rvalue , & i ) > = 0 & &
i > = 0 & &
i < ( int ) ELEMENTSOF ( table ) )
* o = LOG_MAKEPRI ( i , LOG_PRI ( * o ) ) ;
else {
log_error ( " [%s:%u] Failed to parse log output: %s " , filename , line , rvalue ) ;
return - EBADMSG ;
}
}
return 0 ;
}
int config_parse_level (
const char * filename ,
unsigned line ,
const char * section ,
const char * lvalue ,
const char * rvalue ,
void * data ,
void * userdata ) {
static const char * const table [ LOG_DEBUG + 1 ] = {
[ LOG_EMERG ] = " emerg " ,
[ LOG_ALERT ] = " alert " ,
[ LOG_CRIT ] = " crit " ,
[ LOG_ERR ] = " err " ,
[ LOG_WARNING ] = " warning " ,
[ LOG_NOTICE ] = " notice " ,
[ LOG_INFO ] = " info " ,
[ LOG_DEBUG ] = " debug "
} ;
ExecOutput * o = data ;
int i ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
for ( i = 0 ; i < ( int ) ELEMENTSOF ( table ) ; i + + )
if ( streq ( rvalue , table [ i ] ) ) {
* o = LOG_MAKEPRI ( LOG_FAC ( * o ) , i ) ;
break ;
}
if ( i > = LOG_NFACILITIES ) {
/* Second try, let's see if this is a number. */
if ( safe_atoi ( rvalue , & i ) > = 0 & &
i > = 0 & &
i < ( int ) ELEMENTSOF ( table ) )
* o = LOG_MAKEPRI ( LOG_FAC ( * o ) , i ) ;
else {
log_error ( " [%s:%u] Failed to parse log output: %s " , filename , line , rvalue ) ;
return - EBADMSG ;
}
}
return 0 ;
}
# define FOLLOW_MAX 8
2010-01-26 23:39:06 +03:00
2010-01-27 02:15:56 +03:00
static int open_follow ( char * * filename , FILE * * _f , Set * names , char * * _id ) {
unsigned c = 0 ;
2010-01-26 23:39:06 +03:00
int fd , r ;
FILE * f ;
2010-01-27 02:15:56 +03:00
char * id = NULL ;
2010-01-26 23:39:06 +03:00
assert ( filename ) ;
assert ( * filename ) ;
assert ( _f ) ;
assert ( names ) ;
2010-01-27 02:15:56 +03:00
/* This will update the filename pointer if the loaded file is
* reached by a symlink . The old string will be freed . */
2010-01-26 23:39:06 +03:00
2010-01-27 02:15:56 +03:00
for ( ; ; ) {
2010-01-26 23:39:06 +03:00
char * target , * k , * name ;
2010-01-27 02:15:56 +03:00
if ( c + + > = FOLLOW_MAX )
return - ELOOP ;
2010-01-26 23:39:06 +03:00
/* Add the file name we are currently looking at to
* the names of this unit */
2010-01-27 02:15:56 +03:00
name = file_name_from_path ( * filename ) ;
if ( ! ( id = set_get ( names , name ) ) ) {
2010-01-26 23:39:06 +03:00
2010-01-27 02:15:56 +03:00
if ( ! ( id = strdup ( name ) ) )
return - ENOMEM ;
2010-01-26 23:39:06 +03:00
2010-01-27 02:15:56 +03:00
if ( ( r = set_put ( names , id ) ) < 0 ) {
free ( id ) ;
return r ;
2010-01-26 23:39:06 +03:00
}
}
2010-01-27 02:15:56 +03:00
/* Try to open the file name, but don't if its a symlink */
if ( ( fd = open ( * filename , O_RDONLY | O_CLOEXEC | O_NOCTTY | O_NOFOLLOW ) ) > = 0 )
2010-01-26 23:39:06 +03:00
break ;
2010-01-27 02:15:56 +03:00
if ( errno ! = ELOOP )
return - errno ;
2010-01-26 23:39:06 +03:00
/* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2010-01-27 02:15:56 +03:00
if ( ( r = readlink_malloc ( * filename , & target ) ) < 0 )
return r ;
2010-01-26 23:39:06 +03:00
2010-01-28 00:39:10 +03:00
k = file_in_same_dir ( * filename , target ) ;
2010-01-26 23:39:06 +03:00
free ( target ) ;
2010-01-27 02:15:56 +03:00
if ( ! k )
return - ENOMEM ;
2010-01-26 23:39:06 +03:00
2010-01-27 02:15:56 +03:00
free ( * filename ) ;
* filename = k ;
2010-01-26 23:39:06 +03:00
}
if ( ! ( f = fdopen ( fd , " r " ) ) ) {
r = - errno ;
assert ( close_nointr ( fd ) = = 0 ) ;
2010-01-27 02:15:56 +03:00
return r ;
2010-01-26 23:39:06 +03:00
}
* _f = f ;
2010-01-27 02:15:56 +03:00
* _id = id ;
return 0 ;
2010-01-26 23:39:06 +03:00
}
2010-01-27 02:15:56 +03:00
static int load_from_path ( Unit * u , const char * path ) {
2010-01-26 23:39:06 +03:00
static const char * const section_table [ _UNIT_TYPE_MAX ] = {
[ UNIT_SERVICE ] = " Service " ,
[ UNIT_TIMER ] = " Timer " ,
[ UNIT_SOCKET ] = " Socket " ,
[ UNIT_TARGET ] = " Target " ,
[ UNIT_DEVICE ] = " Device " ,
[ UNIT_MOUNT ] = " Mount " ,
[ UNIT_AUTOMOUNT ] = " Automount " ,
[ UNIT_SNAPSHOT ] = " Snapshot "
2010-01-19 04:56:37 +03:00
} ;
2010-01-26 06:18:44 +03:00
# define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \
2010-01-27 04:16:11 +03:00
{ " Directory " , config_parse_path , & ( context ) . directory , section } , \
{ " User " , config_parse_string , & ( context ) . user , section } , \
{ " Group " , config_parse_string , & ( context ) . group , section } , \
{ " SupplementaryGroups " , config_parse_strv , & ( context ) . supplementary_groups , section } , \
{ " Nice " , config_parse_nice , & ( context ) . nice , section } , \
{ " OOMAdjust " , config_parse_oom_adjust , & ( context ) . oom_adjust , section } , \
{ " UMask " , config_parse_umask , & ( context ) . umask , section } , \
2010-01-28 04:06:20 +03:00
{ " Environment " , config_parse_strv , & ( context ) . environment , section } , \
{ " Output " , config_parse_output , & ( context ) . output , section } , \
{ " SyslogIdentifier " , config_parse_string , & ( context ) . syslog_identifier , section } , \
{ " SyslogFacility " , config_parse_facility , & ( context ) . syslog_priority , section } , \
{ " SyslogLevel " , config_parse_level , & ( context ) . syslog_priority , section }
2010-01-26 06:18:44 +03:00
2009-11-20 01:13:20 +03:00
const ConfigItem items [ ] = {
2010-01-27 04:16:11 +03:00
{ " Names " , config_parse_names , u , " Meta " } ,
{ " Description " , config_parse_string , & u - > meta . description , " Meta " } ,
{ " Requires " , config_parse_deps , UINT_TO_PTR ( UNIT_REQUIRES ) , " Meta " } ,
{ " SoftRequires " , config_parse_deps , UINT_TO_PTR ( UNIT_SOFT_REQUIRES ) , " Meta " } ,
{ " Wants " , config_parse_deps , UINT_TO_PTR ( UNIT_WANTS ) , " Meta " } ,
{ " Requisite " , config_parse_deps , UINT_TO_PTR ( UNIT_REQUISITE ) , " Meta " } ,
{ " SoftRequisite " , config_parse_deps , UINT_TO_PTR ( UNIT_SOFT_REQUISITE ) , " Meta " } ,
{ " Conflicts " , config_parse_deps , UINT_TO_PTR ( UNIT_CONFLICTS ) , " Meta " } ,
{ " Before " , config_parse_deps , UINT_TO_PTR ( UNIT_BEFORE ) , " Meta " } ,
{ " After " , config_parse_deps , UINT_TO_PTR ( UNIT_AFTER ) , " Meta " } ,
{ " PIDFile " , config_parse_path , & u - > service . pid_file , " Service " } ,
{ " ExecStartPre " , config_parse_exec , u - > service . exec_command + SERVICE_EXEC_START_PRE , " Service " } ,
{ " ExecStart " , config_parse_exec , u - > service . exec_command + SERVICE_EXEC_START , " Service " } ,
{ " ExecStartPost " , config_parse_exec , u - > service . exec_command + SERVICE_EXEC_START_POST , " Service " } ,
{ " ExecReload " , config_parse_exec , u - > service . exec_command + SERVICE_EXEC_RELOAD , " Service " } ,
{ " ExecStop " , config_parse_exec , u - > service . exec_command + SERVICE_EXEC_STOP , " Service " } ,
{ " ExecStopPost " , config_parse_exec , u - > service . exec_command + SERVICE_EXEC_STOP_POST , " Service " } ,
{ " RestartSec " , config_parse_usec , & u - > service . restart_usec , " Service " } ,
{ " TimeoutSec " , config_parse_usec , & u - > service . timeout_usec , " Service " } ,
{ " Type " , config_parse_service_type , & u - > service , " Service " } ,
{ " Restart " , config_parse_service_restart , & u - > service , " Service " } ,
2010-01-26 23:39:06 +03:00
EXEC_CONTEXT_CONFIG_ITEMS ( u - > service . exec_context , " Service " ) ,
2010-01-27 04:16:11 +03:00
{ " ListenStream " , config_parse_listen , & u - > socket , " Socket " } ,
{ " ListenDatagram " , config_parse_listen , & u - > socket , " Socket " } ,
{ " ListenSequentialPacket " , config_parse_listen , & u - > socket , " Socket " } ,
{ " ListenFIFO " , config_parse_listen , & u - > socket , " Socket " } ,
{ " BindIPv6Only " , config_parse_socket_bind , & u - > socket , " Socket " } ,
{ " Backlog " , config_parse_unsigned , & u - > socket . backlog , " Socket " } ,
2010-01-27 06:31:52 +03:00
{ " BindToDevice " , config_parse_bindtodevice , & u - > socket , " Socket " } ,
2010-01-27 04:16:11 +03:00
{ " ExecStartPre " , config_parse_exec , u - > socket . exec_command + SOCKET_EXEC_START_PRE , " Socket " } ,
{ " ExecStartPost " , config_parse_exec , u - > socket . exec_command + SOCKET_EXEC_START_POST , " Socket " } ,
{ " ExecStopPre " , config_parse_exec , u - > socket . exec_command + SOCKET_EXEC_STOP_PRE , " Socket " } ,
{ " ExecStopPost " , config_parse_exec , u - > socket . exec_command + SOCKET_EXEC_STOP_POST , " Socket " } ,
2010-01-26 23:39:06 +03:00
EXEC_CONTEXT_CONFIG_ITEMS ( u - > socket . exec_context , " Socket " ) ,
EXEC_CONTEXT_CONFIG_ITEMS ( u - > automount . exec_context , " Automount " ) ,
2010-01-26 06:18:44 +03:00
2009-11-20 01:13:20 +03:00
{ NULL , NULL , NULL , NULL }
} ;
2010-01-26 06:18:44 +03:00
# undef EXEC_CONTEXT_CONFIG_ITEMS
2010-01-19 04:56:37 +03:00
const char * sections [ 3 ] ;
2010-01-27 02:15:56 +03:00
char * k ;
int r ;
2010-01-26 23:39:06 +03:00
Set * symlink_names ;
2010-01-27 02:15:56 +03:00
FILE * f ;
char * filename , * id ;
2009-11-20 01:13:20 +03:00
2010-01-19 04:56:37 +03:00
sections [ 0 ] = " Meta " ;
2010-01-26 23:39:06 +03:00
sections [ 1 ] = section_table [ u - > meta . type ] ;
2010-01-19 04:56:37 +03:00
sections [ 2 ] = NULL ;
2010-01-26 23:39:06 +03:00
if ( ! ( symlink_names = set_new ( string_hash_func , string_compare_func ) ) )
return - ENOMEM ;
2009-11-20 01:13:20 +03:00
2010-01-27 02:15:56 +03:00
/* Instead of opening the path right away, we manually
* follow all symlinks and add their name to our unit
* name set while doing so */
if ( ! ( filename = path_make_absolute ( path , unit_path ( ) ) ) ) {
r = - ENOMEM ;
goto finish ;
}
2009-11-20 01:13:20 +03:00
2010-01-27 02:15:56 +03:00
if ( ( r = open_follow ( & filename , & f , symlink_names , & id ) ) < 0 ) {
if ( r = = - ENOENT )
r = 0 ; /* returning 0 means: no suitable config file found */
2010-01-26 06:18:44 +03:00
2010-01-27 02:15:56 +03:00
goto finish ;
}
2010-01-26 23:39:06 +03:00
2010-01-27 02:15:56 +03:00
/* Now, parse the file contents */
r = config_parse ( filename , f , sections , items , u ) ;
if ( r < 0 )
goto finish ;
2010-01-26 23:39:06 +03:00
2010-01-27 02:15:56 +03:00
/* Let's try to add in all symlink names we found */
while ( ( k = set_steal_first ( symlink_names ) ) ) {
if ( ( r = unit_add_name ( u , k ) ) < 0 )
2010-01-26 23:39:06 +03:00
goto finish ;
2010-01-27 02:15:56 +03:00
if ( id = = k )
assert_se ( u - > meta . id = set_get ( u - > meta . names , k ) ) ;
2010-01-26 23:39:06 +03:00
2010-01-27 02:15:56 +03:00
free ( k ) ;
2010-01-26 06:18:44 +03:00
}
2010-01-27 02:15:56 +03:00
free ( u - > meta . load_path ) ;
u - > meta . load_path = filename ;
filename = NULL ;
2010-01-26 23:39:06 +03:00
2010-01-27 02:15:56 +03:00
r = 1 ; /* returning 1 means: suitable config file found and loaded */
2010-01-26 23:39:06 +03:00
finish :
while ( ( k = set_steal_first ( symlink_names ) ) )
free ( k ) ;
set_free ( symlink_names ) ;
2010-01-27 02:15:56 +03:00
free ( filename ) ;
return r ;
}
int unit_load_fragment ( Unit * u ) {
2010-01-28 04:44:47 +03:00
int r = 0 ;
2010-01-28 04:06:20 +03:00
ExecContext * c ;
2010-01-27 02:15:56 +03:00
assert ( u ) ;
assert ( u - > meta . load_state = = UNIT_STUB ) ;
if ( u - > meta . load_path )
r = load_from_path ( u , u - > meta . load_path ) ;
else {
Iterator i ;
char * t ;
/* Try to find a name we can load this with */
SET_FOREACH ( t , u - > meta . names , i )
if ( ( r = load_from_path ( u , t ) ) ! = 0 )
return r ;
}
2010-01-26 23:39:06 +03:00
2010-01-28 04:06:20 +03:00
if ( u - > meta . type = = UNIT_SOCKET )
c = & u - > socket . exec_context ;
else if ( u - > meta . type = = UNIT_SERVICE )
c = & u - > service . exec_context ;
else
c = NULL ;
if ( r > = 0 & & c & &
( c - > output = = EXEC_KERNEL | | c - > output = = EXEC_SYSLOG ) ) {
2010-01-28 04:44:47 +03:00
int k ;
2010-01-28 04:06:20 +03:00
/* If syslog or kernel logging is requested, make sure
* our own logging daemon is run first . */
2010-01-28 04:44:47 +03:00
if ( ( k = unit_add_dependency ( u , UNIT_AFTER , u - > meta . manager - > special_units [ SPECIAL_LOGGER_SOCKET ] ) ) < 0 )
return k ;
2010-01-28 04:06:20 +03:00
2010-01-28 04:44:47 +03:00
if ( ( k = unit_add_dependency ( u , UNIT_REQUIRES , u - > meta . manager - > special_units [ SPECIAL_LOGGER_SOCKET ] ) ) < 0 )
return k ;
2010-01-28 04:06:20 +03:00
}
2010-01-26 23:39:06 +03:00
return r ;
2009-11-20 01:13:20 +03:00
}