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-26 23:39:06 +03:00
# define FOLLOW_MAX 8
static char * build_path ( const char * path , const char * filename ) {
char * e , * r ;
size_t k ;
assert ( path ) ;
assert ( filename ) ;
/* This removes the last component of path and appends
* filename , unless the latter is absolute anyway or the
* former isn ' t */
2010-01-27 02:15:56 +03:00
if ( path_is_absolute ( filename ) )
2010-01-26 23:39:06 +03:00
return strdup ( filename ) ;
if ( ! ( e = strrchr ( path , ' / ' ) ) )
return strdup ( filename ) ;
k = strlen ( filename ) ;
if ( ! ( r = new ( char , e - path + 1 + k + 1 ) ) )
return NULL ;
memcpy ( r , path , e - path + 1 ) ;
memcpy ( r + ( e - path ) + 1 , filename , k + 1 ) ;
return r ;
}
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-27 02:15:56 +03:00
k = build_path ( * 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 } , \
{ " Environment " , config_parse_strv , & ( context ) . environment , 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 " } ,
{ " 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 ) {
int r = - ENOENT ;
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
return r ;
2009-11-20 01:13:20 +03:00
}