2010-08-14 21:59:25 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2010-04-10 07:00:38 +04:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
systemd 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 systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
# include <unistd.h>
# include <stdio.h>
# include <errno.h>
# include <string.h>
# include <stdlib.h>
# include "hostname-setup.h"
# include "macro.h"
# include "util.h"
# include "log.h"
2011-03-08 21:47:29 +03:00
# if defined(TARGET_FEDORA) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA)
2010-05-08 17:00:53 +04:00
# define FILENAME " / etc / sysconfig / network"
2010-11-29 16:42:10 +03:00
# elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE) || defined(TARGET_FRUGALWARE)
2010-05-08 17:00:53 +04:00
# define FILENAME " / etc / HOSTNAME"
# elif defined(TARGET_ARCH)
# define FILENAME " / etc / rc.conf"
2010-05-09 20:13:02 +04:00
# elif defined(TARGET_GENTOO)
# define FILENAME " / etc / conf.d / hostname"
2010-05-08 17:00:53 +04:00
# endif
2010-04-10 07:00:38 +04:00
2010-05-09 21:12:06 +04:00
static char * strip_bad_chars ( char * s ) {
char * p , * d ;
for ( p = s , d = s ; * p ; p + + )
if ( ( * p > = ' a ' & & * p < = ' z ' ) | |
( * p > = ' A ' & & * p < = ' Z ' ) | |
( * p > = ' 0 ' & & * p < = ' 9 ' ) | |
* p = = ' - ' | |
2010-06-02 17:40:43 +04:00
* p = = ' _ ' | |
* p = = ' . ' )
2010-05-09 21:12:06 +04:00
* ( d + + ) = * p ;
* d = 0 ;
return s ;
}
2010-08-19 05:29:43 +04:00
static int read_and_strip_hostname ( const char * path , char * * hn ) {
char * s , * k ;
int r ;
assert ( path ) ;
assert ( hn ) ;
if ( ( r = read_one_line_file ( path , & s ) ) < 0 )
return r ;
k = strdup ( strstrip ( s ) ) ;
free ( s ) ;
if ( ! k )
return - ENOMEM ;
strip_bad_chars ( k ) ;
if ( k [ 0 ] = = 0 ) {
free ( k ) ;
return - ENOENT ;
}
* hn = k ;
return 0 ;
}
2010-08-19 05:02:22 +04:00
static int read_distro_hostname ( char * * hn ) {
2010-04-10 07:00:38 +04:00
2011-03-08 21:47:29 +03:00
# if defined(TARGET_FEDORA) || defined(TARGET_ARCH) || defined(TARGET_GENTOO) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA)
2010-05-05 23:59:24 +04:00
int r ;
FILE * f ;
assert ( hn ) ;
2010-05-08 17:00:53 +04:00
if ( ! ( f = fopen ( FILENAME , " re " ) ) )
2010-05-05 23:59:24 +04:00
return - errno ;
for ( ; ; ) {
char line [ LINE_MAX ] ;
char * s , * k ;
if ( ! fgets ( line , sizeof ( line ) , f ) ) {
if ( feof ( f ) )
break ;
r = - errno ;
goto finish ;
}
s = strstrip ( line ) ;
2010-05-09 20:13:02 +04:00
if ( ! startswith_no_case ( s , " HOSTNAME= " ) )
2010-05-05 23:59:24 +04:00
continue ;
if ( ! ( k = strdup ( s + 9 ) ) ) {
r = - ENOMEM ;
goto finish ;
}
2010-05-09 21:12:06 +04:00
strip_bad_chars ( k ) ;
if ( k [ 0 ] = = 0 ) {
free ( k ) ;
r = - ENOENT ;
2010-05-09 20:13:02 +04:00
goto finish ;
}
2010-05-05 23:59:24 +04:00
* hn = k ;
2010-07-20 23:34:25 +04:00
r = 0 ;
goto finish ;
2010-05-05 23:59:24 +04:00
}
2010-07-20 23:34:25 +04:00
r = - ENOENT ;
2010-05-05 23:59:24 +04:00
finish :
fclose ( f ) ;
return r ;
2010-11-29 16:42:10 +03:00
# elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE) || defined(TARGET_FRUGALWARE)
2010-08-19 05:29:43 +04:00
return read_and_strip_hostname ( FILENAME , hn ) ;
2010-04-10 07:00:38 +04:00
# else
return - ENOENT ;
# endif
2010-08-19 05:02:22 +04:00
}
static int read_hostname ( char * * hn ) {
int r ;
assert ( hn ) ;
/* First, try to load the generic hostname configuration file,
* that we support on all distributions */
2010-08-19 05:29:43 +04:00
if ( ( r = read_and_strip_hostname ( " /etc/hostname " , hn ) ) < 0 ) {
2010-08-19 05:02:22 +04:00
if ( r = = - ENOENT )
return read_distro_hostname ( hn ) ;
return r ;
}
2010-04-10 07:00:38 +04:00
return 0 ;
}
int hostname_setup ( void ) {
int r ;
2010-08-19 05:29:43 +04:00
char * b = NULL ;
const char * hn = NULL ;
2010-04-10 07:00:38 +04:00
2010-08-19 05:29:43 +04:00
if ( ( r = read_hostname ( & b ) ) < 0 ) {
if ( r = = - ENOENT )
log_info ( " No hostname configured. " ) ;
else
2010-04-10 07:00:38 +04:00
log_warning ( " Failed to read configured hostname: %s " , strerror ( - r ) ) ;
2011-03-14 20:05:52 +03:00
hn = NULL ;
2010-08-19 05:29:43 +04:00
} else
hn = b ;
2010-04-10 07:00:38 +04:00
2011-03-14 20:05:52 +03:00
if ( ! hn ) {
/* Don't override the hostname if it is unset and not
* explicitly configured */
char * old_hostname = NULL ;
if ( ( old_hostname = gethostname_malloc ( ) ) ) {
bool already_set ;
already_set = old_hostname [ 0 ] ! = 0 ;
free ( old_hostname ) ;
if ( already_set )
goto finish ;
}
hn = " localhost " ;
}
2010-08-19 05:29:43 +04:00
if ( sethostname ( hn , strlen ( hn ) ) < 0 ) {
log_warning ( " Failed to set hostname to <%s>: %m " , hn ) ;
r = - errno ;
} else
2010-04-10 07:00:38 +04:00
log_info ( " Set hostname to <%s>. " , hn ) ;
2011-03-14 20:05:52 +03:00
finish :
2010-08-19 05:29:43 +04:00
free ( b ) ;
2010-04-10 07:00:38 +04:00
return r ;
}