2009-04-18 08:14:26 -04:00
|
|
|
/*
|
2011-07-09 05:50:27 -04:00
|
|
|
* Copyright (C) 2009-2011 Julien BLACHE <jb@jblache.org>
|
2009-04-18 08:14:26 -04:00
|
|
|
*
|
|
|
|
* This program 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.
|
|
|
|
*
|
|
|
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
2010-02-02 15:00:47 -05:00
|
|
|
# include <config.h>
|
2009-04-18 08:14:26 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
2010-04-02 12:28:43 -04:00
|
|
|
#include <stdint.h>
|
2009-04-18 08:14:26 -04:00
|
|
|
|
2011-07-09 05:50:27 -04:00
|
|
|
#include <sys/types.h>
|
2009-04-18 08:14:26 -04:00
|
|
|
#include <sys/utsname.h>
|
2011-07-09 05:50:27 -04:00
|
|
|
#include <pwd.h>
|
2009-04-18 08:14:26 -04:00
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include <confuse.h>
|
|
|
|
|
2009-05-08 11:46:32 -04:00
|
|
|
#include "logger.h"
|
2010-04-02 12:28:43 -04:00
|
|
|
#include "misc.h"
|
2009-04-18 08:14:26 -04:00
|
|
|
#include "conffile.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* Forward */
|
|
|
|
static int cb_loglevel(cfg_t *cfg, cfg_opt_t *opt, const char *value, void *result);
|
|
|
|
|
|
|
|
/* general section structure */
|
|
|
|
static cfg_opt_t sec_general[] =
|
|
|
|
{
|
|
|
|
CFG_STR("uid", "nobody", CFGF_NONE),
|
2010-03-21 06:33:05 -04:00
|
|
|
CFG_STR("db_path", STATEDIR "/cache/" PACKAGE "/songs3.db", CFGF_NONE),
|
2020-07-11 09:10:11 -04:00
|
|
|
CFG_STR("db_backup_path", NULL, CFGF_NONE),
|
2017-10-28 18:05:20 -04:00
|
|
|
CFG_STR("logfile", STATEDIR "/log/" PACKAGE ".log", CFGF_NONE),
|
2009-04-18 08:14:26 -04:00
|
|
|
CFG_INT_CB("loglevel", E_LOG, CFGF_NONE, &cb_loglevel),
|
2017-10-28 18:05:20 -04:00
|
|
|
CFG_STR("admin_password", NULL, CFGF_NONE),
|
|
|
|
CFG_INT("websocket_port", 3688, CFGF_NONE),
|
2017-11-11 15:17:42 -05:00
|
|
|
CFG_STR_LIST("trusted_networks", "{localhost,192.168,fd}", CFGF_NONE),
|
2015-12-03 16:08:55 -05:00
|
|
|
CFG_BOOL("ipv6", cfg_true, CFGF_NONE),
|
2014-11-10 16:53:08 -05:00
|
|
|
CFG_STR("cache_path", STATEDIR "/cache/" PACKAGE "/cache.db", CFGF_NONE),
|
|
|
|
CFG_INT("cache_daap_threshold", 1000, CFGF_NONE),
|
2020-05-04 11:41:57 -04:00
|
|
|
CFG_BOOL("speaker_autoselect", cfg_false, CFGF_NONE),
|
2017-06-26 17:32:24 -04:00
|
|
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
|
|
|
CFG_BOOL("high_resolution_clock", cfg_false, CFGF_NONE),
|
|
|
|
#else
|
|
|
|
CFG_BOOL("high_resolution_clock", cfg_true, CFGF_NONE),
|
|
|
|
#endif
|
2017-10-28 18:05:20 -04:00
|
|
|
// Hidden options
|
|
|
|
CFG_INT("db_pragma_cache_size", -1, CFGF_NONE),
|
|
|
|
CFG_STR("db_pragma_journal_mode", NULL, CFGF_NONE),
|
|
|
|
CFG_INT("db_pragma_synchronous", -1, CFGF_NONE),
|
2016-10-17 16:03:32 -04:00
|
|
|
CFG_STR("allow_origin", "*", CFGF_NONE),
|
2018-08-12 13:49:23 -04:00
|
|
|
CFG_STR("user_agent", PACKAGE_NAME "/" PACKAGE_VERSION, CFGF_NONE),
|
2020-05-12 14:16:44 -04:00
|
|
|
CFG_BOOL("timer_test", cfg_false, CFGF_NONE),
|
2009-04-18 08:14:26 -04:00
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
|
|
|
/* library section structure */
|
|
|
|
static cfg_opt_t sec_library[] =
|
|
|
|
{
|
2010-03-19 14:06:47 -04:00
|
|
|
CFG_STR("name", "My Music on %h", CFGF_NONE),
|
2009-04-18 08:14:26 -04:00
|
|
|
CFG_INT("port", 3689, CFGF_NONE),
|
|
|
|
CFG_STR("password", NULL, CFGF_NONE),
|
|
|
|
CFG_STR_LIST("directories", NULL, CFGF_NONE),
|
2017-11-08 19:16:44 -05:00
|
|
|
CFG_BOOL("follow_symlinks", cfg_true, CFGF_NONE),
|
2013-10-24 17:14:26 -04:00
|
|
|
CFG_STR_LIST("podcasts", NULL, CFGF_NONE),
|
2013-12-08 17:03:03 -05:00
|
|
|
CFG_STR_LIST("audiobooks", NULL, CFGF_NONE),
|
2009-04-18 08:14:26 -04:00
|
|
|
CFG_STR_LIST("compilations", NULL, CFGF_NONE),
|
2013-10-24 17:14:26 -04:00
|
|
|
CFG_STR("compilation_artist", NULL, CFGF_NONE),
|
2015-12-12 17:28:48 -05:00
|
|
|
CFG_BOOL("hide_singles", cfg_false, CFGF_NONE),
|
2015-03-30 15:10:59 -04:00
|
|
|
CFG_BOOL("radio_playlists", cfg_false, CFGF_NONE),
|
2013-11-30 06:57:38 -05:00
|
|
|
CFG_STR("name_library", "Library", CFGF_NONE),
|
|
|
|
CFG_STR("name_music", "Music", CFGF_NONE),
|
|
|
|
CFG_STR("name_movies", "Movies", CFGF_NONE),
|
|
|
|
CFG_STR("name_tvshows", "TV Shows", CFGF_NONE),
|
|
|
|
CFG_STR("name_podcasts", "Podcasts", CFGF_NONE),
|
2013-12-08 17:03:03 -05:00
|
|
|
CFG_STR("name_audiobooks", "Audiobooks", CFGF_NONE),
|
2015-03-30 15:10:59 -04:00
|
|
|
CFG_STR("name_radio", "Radio", CFGF_NONE),
|
2020-05-11 11:02:14 -04:00
|
|
|
CFG_STR("name_unknown_title", "Unknown title", CFGF_NONE),
|
|
|
|
CFG_STR("name_unknown_artist", "Unknown artist", CFGF_NONE),
|
|
|
|
CFG_STR("name_unknown_album", "Unknown album", CFGF_NONE),
|
|
|
|
CFG_STR("name_unknown_genre", "Unknown genre", CFGF_NONE),
|
|
|
|
CFG_STR("name_unknown_composer", "Unknown composer", CFGF_NONE),
|
2013-10-22 15:19:11 -04:00
|
|
|
CFG_STR_LIST("artwork_basenames", "{artwork,cover,Folder}", CFGF_NONE),
|
2015-01-02 18:31:48 -05:00
|
|
|
CFG_BOOL("artwork_individual", cfg_false, CFGF_NONE),
|
2020-02-21 13:51:35 -05:00
|
|
|
CFG_STR_LIST("artwork_online_sources", NULL, CFGF_NONE),
|
2017-01-14 17:35:19 -05:00
|
|
|
CFG_STR_LIST("filetypes_ignore", "{.db,.ini,.db-journal,.pdf,.metadata}", CFGF_NONE),
|
2015-01-14 15:50:25 -05:00
|
|
|
CFG_STR_LIST("filepath_ignore", NULL, CFGF_NONE),
|
2014-01-28 16:40:07 -05:00
|
|
|
CFG_BOOL("filescan_disable", cfg_false, CFGF_NONE),
|
2020-02-01 18:52:00 -05:00
|
|
|
CFG_BOOL("m3u_overrides", cfg_false, CFGF_NONE),
|
2009-11-22 10:45:13 -05:00
|
|
|
CFG_BOOL("itunes_overrides", cfg_false, CFGF_NONE),
|
2016-06-04 17:30:01 -04:00
|
|
|
CFG_BOOL("itunes_smartpl", cfg_false, CFGF_NONE),
|
2015-10-09 17:58:27 -04:00
|
|
|
CFG_STR_LIST("no_decode", NULL, CFGF_NONE),
|
|
|
|
CFG_STR_LIST("force_decode", NULL, CFGF_NONE),
|
2017-01-14 17:35:19 -05:00
|
|
|
CFG_BOOL("pipe_autostart", cfg_true, CFGF_NONE),
|
2019-01-11 13:34:36 -05:00
|
|
|
CFG_INT("pipe_sample_rate", 44100, CFGF_NONE),
|
|
|
|
CFG_INT("pipe_bits_per_sample", 16, CFGF_NONE),
|
2018-08-19 03:45:35 -04:00
|
|
|
CFG_BOOL("rating_updates", cfg_false, CFGF_NONE),
|
2019-04-10 15:04:00 -04:00
|
|
|
CFG_BOOL("allow_modifying_stored_playlists", cfg_false, CFGF_NONE),
|
|
|
|
CFG_STR("default_playlist_directory", NULL, CFGF_NONE),
|
2009-04-18 08:14:26 -04:00
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2010-05-02 05:24:07 -04:00
|
|
|
/* local audio section structure */
|
|
|
|
static cfg_opt_t sec_audio[] =
|
|
|
|
{
|
|
|
|
CFG_STR("nickname", "Computer", CFGF_NONE),
|
2015-03-31 11:31:14 -04:00
|
|
|
CFG_STR("type", NULL, CFGF_NONE),
|
2017-11-05 00:59:56 -04:00
|
|
|
CFG_STR("server", NULL, CFGF_NONE),
|
2010-05-02 05:24:07 -04:00
|
|
|
CFG_STR("card", "default", CFGF_NONE),
|
2011-07-08 05:18:20 -04:00
|
|
|
CFG_STR("mixer", NULL, CFGF_NONE),
|
2016-09-25 16:10:22 -04:00
|
|
|
CFG_STR("mixer_device", NULL, CFGF_NONE),
|
2019-04-09 15:45:16 -04:00
|
|
|
CFG_BOOL("sync_disable", cfg_false, CFGF_NONE),
|
2019-08-23 13:22:33 -04:00
|
|
|
CFG_INT("offset", 0, CFGF_DEPRECATED),
|
2019-02-23 17:24:36 -05:00
|
|
|
CFG_INT("offset_ms", 0, CFGF_NONE),
|
2019-04-09 15:45:16 -04:00
|
|
|
CFG_INT("adjust_period_seconds", 100, CFGF_NONE),
|
2010-05-02 05:24:07 -04:00
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2019-12-22 14:08:43 -05:00
|
|
|
|
|
|
|
/* local ALSA audio section structure */
|
|
|
|
static cfg_opt_t sec_alsa[] =
|
|
|
|
{
|
2020-01-03 04:06:58 -05:00
|
|
|
CFG_STR("nickname", NULL, CFGF_NONE),
|
2019-12-22 14:08:43 -05:00
|
|
|
CFG_STR("mixer", NULL, CFGF_NONE),
|
|
|
|
CFG_STR("mixer_device", NULL, CFGF_NONE),
|
|
|
|
CFG_INT("offset_ms", 0, CFGF_NONE),
|
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2020-04-11 17:44:41 -04:00
|
|
|
/* AirPlay/ApEx shared section structure */
|
2020-04-11 17:30:27 -04:00
|
|
|
static cfg_opt_t sec_airplay_shared[] =
|
|
|
|
{
|
|
|
|
CFG_INT("control_port", 0, CFGF_NONE),
|
|
|
|
CFG_INT("timing_port", 0, CFGF_NONE),
|
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2014-02-09 10:07:00 -05:00
|
|
|
/* AirPlay/ApEx device section structure */
|
|
|
|
static cfg_opt_t sec_airplay[] =
|
2010-04-04 08:48:25 -04:00
|
|
|
{
|
2014-02-09 10:07:00 -05:00
|
|
|
CFG_INT("max_volume", 11, CFGF_NONE),
|
2017-03-12 17:11:56 -04:00
|
|
|
CFG_BOOL("exclude", cfg_false, CFGF_NONE),
|
2019-02-07 15:14:13 -05:00
|
|
|
CFG_BOOL("permanent", cfg_false, CFGF_NONE),
|
2020-07-22 18:39:29 -04:00
|
|
|
CFG_BOOL("reconnect", cfg_false, CFGF_NODEFAULT),
|
2010-04-04 08:48:25 -04:00
|
|
|
CFG_STR("password", NULL, CFGF_NONE),
|
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2019-01-09 14:26:31 -05:00
|
|
|
/* Chromecast device section structure */
|
|
|
|
static cfg_opt_t sec_chromecast[] =
|
|
|
|
{
|
2020-11-16 14:01:55 -05:00
|
|
|
CFG_INT("max_volume", 11, CFGF_NONE),
|
2019-01-09 14:26:31 -05:00
|
|
|
CFG_BOOL("exclude", cfg_false, CFGF_NONE),
|
2019-08-23 13:22:33 -04:00
|
|
|
CFG_INT("offset_ms", 0, CFGF_NONE),
|
2019-01-09 14:26:31 -05:00
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2016-10-25 15:23:09 -04:00
|
|
|
/* FIFO section structure */
|
|
|
|
static cfg_opt_t sec_fifo[] =
|
|
|
|
{
|
|
|
|
CFG_STR("nickname", "fifo", CFGF_NONE),
|
|
|
|
CFG_STR("path", NULL, CFGF_NONE),
|
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2014-03-11 18:20:29 -04:00
|
|
|
/* Spotify section structure */
|
|
|
|
static cfg_opt_t sec_spotify[] =
|
|
|
|
{
|
|
|
|
CFG_STR("settings_dir", STATEDIR "/cache/" PACKAGE "/libspotify", CFGF_NONE),
|
|
|
|
CFG_STR("cache_dir", "/tmp", CFGF_NONE),
|
2014-03-29 17:26:46 -04:00
|
|
|
CFG_INT("bitrate", 0, CFGF_NONE),
|
2015-03-29 18:59:55 -04:00
|
|
|
CFG_BOOL("base_playlist_disable", cfg_false, CFGF_NONE),
|
2015-03-08 04:04:26 -04:00
|
|
|
CFG_BOOL("artist_override", cfg_false, CFGF_NONE),
|
2015-03-08 04:24:23 -04:00
|
|
|
CFG_BOOL("album_override", cfg_false, CFGF_NONE),
|
2014-03-11 18:20:29 -04:00
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2014-11-10 16:53:08 -05:00
|
|
|
/* SQLite section structure */
|
|
|
|
static cfg_opt_t sec_sqlite[] =
|
|
|
|
{
|
|
|
|
CFG_INT("pragma_cache_size_library", -1, CFGF_NONE),
|
|
|
|
CFG_INT("pragma_cache_size_cache", -1, CFGF_NONE),
|
|
|
|
CFG_STR("pragma_journal_mode", NULL, CFGF_NONE),
|
|
|
|
CFG_INT("pragma_synchronous", -1, CFGF_NONE),
|
2015-09-13 03:10:42 -04:00
|
|
|
CFG_INT("pragma_mmap_size_library", -1, CFGF_NONE),
|
|
|
|
CFG_INT("pragma_mmap_size_cache", -1, CFGF_NONE),
|
2015-01-14 14:32:36 -05:00
|
|
|
CFG_BOOL("vacuum", cfg_true, CFGF_NONE),
|
2014-11-10 16:53:08 -05:00
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2014-12-21 14:41:44 -05:00
|
|
|
/* MPD section structure */
|
|
|
|
static cfg_opt_t sec_mpd[] =
|
|
|
|
{
|
|
|
|
CFG_INT("port", 6600, CFGF_NONE),
|
2015-07-16 21:22:24 -04:00
|
|
|
CFG_INT("http_port", 0, CFGF_NONE),
|
2016-02-28 04:34:18 -05:00
|
|
|
CFG_BOOL("clear_queue_on_stop_disable", cfg_false, CFGF_NONE),
|
2019-05-30 02:20:00 -04:00
|
|
|
CFG_BOOL("allow_modifying_stored_playlists", cfg_false, CFGF_NODEFAULT | CFGF_DEPRECATED),
|
|
|
|
CFG_STR("default_playlist_directory", NULL, CFGF_NODEFAULT | CFGF_DEPRECATED),
|
2014-12-21 14:41:44 -05:00
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2019-08-23 11:22:11 -04:00
|
|
|
/* streaming section structure */
|
|
|
|
static cfg_opt_t sec_streaming[] =
|
|
|
|
{
|
|
|
|
CFG_INT("sample_rate", 44100, CFGF_NONE),
|
|
|
|
CFG_INT("bit_rate", 192, CFGF_NONE),
|
2019-09-12 08:48:30 -04:00
|
|
|
CFG_INT("icy_metaint", 16384, CFGF_NONE),
|
2019-08-23 11:22:11 -04:00
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2009-04-18 08:14:26 -04:00
|
|
|
/* Config file structure */
|
|
|
|
static cfg_opt_t toplvl_cfg[] =
|
|
|
|
{
|
|
|
|
CFG_SEC("general", sec_general, CFGF_NONE),
|
2010-03-19 14:06:47 -04:00
|
|
|
CFG_SEC("library", sec_library, CFGF_NONE),
|
2010-05-02 05:24:07 -04:00
|
|
|
CFG_SEC("audio", sec_audio, CFGF_NONE),
|
2019-12-22 14:08:43 -05:00
|
|
|
CFG_SEC("alsa", sec_alsa, CFGF_MULTI | CFGF_TITLE),
|
2020-04-11 17:30:27 -04:00
|
|
|
CFG_SEC("airplay_shared", sec_airplay_shared, CFGF_NONE),
|
2014-02-09 10:07:00 -05:00
|
|
|
CFG_SEC("airplay", sec_airplay, CFGF_MULTI | CFGF_TITLE),
|
2019-01-09 14:26:31 -05:00
|
|
|
CFG_SEC("chromecast", sec_chromecast, CFGF_MULTI | CFGF_TITLE),
|
2016-10-25 15:23:09 -04:00
|
|
|
CFG_SEC("fifo", sec_fifo, CFGF_NONE),
|
2014-03-11 18:20:29 -04:00
|
|
|
CFG_SEC("spotify", sec_spotify, CFGF_NONE),
|
2014-11-10 16:53:08 -05:00
|
|
|
CFG_SEC("sqlite", sec_sqlite, CFGF_NONE),
|
2014-12-21 14:41:44 -05:00
|
|
|
CFG_SEC("mpd", sec_mpd, CFGF_NONE),
|
2019-08-23 11:22:11 -04:00
|
|
|
CFG_SEC("streaming", sec_streaming, CFGF_NONE),
|
2009-04-18 08:14:26 -04:00
|
|
|
CFG_END()
|
|
|
|
};
|
|
|
|
|
2009-04-18 11:18:37 -04:00
|
|
|
cfg_t *cfg;
|
2010-04-02 12:28:43 -04:00
|
|
|
uint64_t libhash;
|
2011-07-09 05:50:27 -04:00
|
|
|
uid_t runas_uid;
|
|
|
|
gid_t runas_gid;
|
2009-04-18 08:14:26 -04:00
|
|
|
|
|
|
|
|
2019-06-15 06:08:56 -04:00
|
|
|
static void
|
2020-08-10 16:26:42 -04:00
|
|
|
logger_confuse(cfg_t *config, const char *format, va_list args)
|
2019-06-15 06:08:56 -04:00
|
|
|
{
|
|
|
|
char fmt[80];
|
|
|
|
|
2020-08-10 16:26:42 -04:00
|
|
|
if (config && config->name && config->line)
|
|
|
|
snprintf(fmt, sizeof(fmt), "[%s:%d] %s\n", config->name, config->line, format);
|
2019-06-15 06:08:56 -04:00
|
|
|
else
|
|
|
|
snprintf(fmt, sizeof(fmt), "%s\n", format);
|
|
|
|
|
|
|
|
DVPRINTF(E_LOG, L_CONF, fmt, args);
|
|
|
|
}
|
|
|
|
|
2009-04-18 08:14:26 -04:00
|
|
|
static int
|
2020-08-10 16:26:42 -04:00
|
|
|
cb_loglevel(cfg_t *config, cfg_opt_t *opt, const char *value, void *result)
|
2009-04-18 08:14:26 -04:00
|
|
|
{
|
|
|
|
if (strcasecmp(value, "fatal") == 0)
|
|
|
|
*(long int *)result = E_FATAL;
|
|
|
|
else if (strcasecmp(value, "log") == 0)
|
|
|
|
*(long int *)result = E_LOG;
|
|
|
|
else if (strcasecmp(value, "warning") == 0)
|
|
|
|
*(long int *)result = E_WARN;
|
|
|
|
else if (strcasecmp(value, "info") == 0)
|
2009-05-08 11:52:56 -04:00
|
|
|
*(long int *)result = E_INFO;
|
2009-04-18 08:14:26 -04:00
|
|
|
else if (strcasecmp(value, "debug") == 0)
|
|
|
|
*(long int *)result = E_DBG;
|
|
|
|
else if (strcasecmp(value, "spam") == 0)
|
|
|
|
*(long int *)result = E_SPAM;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINTF(E_WARN, L_CONF, "Unrecognised loglevel '%s'\n", value);
|
|
|
|
/* Default to warning */
|
|
|
|
*(long int *)result = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
conffile_expand_libname(cfg_t *lib)
|
|
|
|
{
|
|
|
|
char *libname;
|
|
|
|
char *hostname;
|
|
|
|
char *s;
|
|
|
|
char *d;
|
|
|
|
char *expanded;
|
|
|
|
struct utsname sysinfo;
|
|
|
|
size_t len;
|
|
|
|
size_t olen;
|
|
|
|
size_t hostlen;
|
|
|
|
size_t verlen;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
libname = cfg_getstr(lib, "name");
|
2010-04-02 12:28:43 -04:00
|
|
|
olen = strlen(libname);
|
2009-04-18 08:14:26 -04:00
|
|
|
|
|
|
|
/* Fast path */
|
|
|
|
s = strchr(libname, '%');
|
|
|
|
if (!s)
|
2010-04-02 12:28:43 -04:00
|
|
|
{
|
|
|
|
libhash = murmur_hash64(libname, olen, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
2009-04-18 08:14:26 -04:00
|
|
|
|
|
|
|
/* Grab what we need */
|
|
|
|
ret = uname(&sysinfo);
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
|
|
|
DPRINTF(E_WARN, L_CONF, "Could not get system name: %s\n", strerror(errno));
|
|
|
|
hostname = "Unknown host";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
hostname = sysinfo.nodename;
|
|
|
|
|
|
|
|
hostlen = strlen(hostname);
|
|
|
|
verlen = strlen(VERSION);
|
|
|
|
|
|
|
|
/* Compute expanded size */
|
2010-04-02 12:28:43 -04:00
|
|
|
len = olen;
|
2009-04-18 08:14:26 -04:00
|
|
|
s = libname;
|
|
|
|
while (*s)
|
|
|
|
{
|
|
|
|
if (*s == '%')
|
|
|
|
{
|
|
|
|
s++;
|
|
|
|
|
|
|
|
switch (*s)
|
|
|
|
{
|
|
|
|
case 'h':
|
|
|
|
len += hostlen;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'v':
|
|
|
|
len += verlen;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
expanded = (char *)malloc(len + 1);
|
|
|
|
if (!expanded)
|
|
|
|
{
|
|
|
|
DPRINTF(E_FATAL, L_CONF, "Out of memory\n");
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
memset(expanded, 0, len + 1);
|
|
|
|
|
|
|
|
/* Do the actual expansion */
|
|
|
|
s = libname;
|
|
|
|
d = expanded;
|
|
|
|
while (*s)
|
|
|
|
{
|
|
|
|
if (*s == '%')
|
|
|
|
{
|
|
|
|
s++;
|
|
|
|
|
|
|
|
switch (*s)
|
|
|
|
{
|
|
|
|
case 'h':
|
|
|
|
strcat(d, hostname);
|
|
|
|
d += hostlen;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'v':
|
|
|
|
strcat(d, VERSION);
|
|
|
|
d += verlen;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*d = *s;
|
|
|
|
|
|
|
|
s++;
|
|
|
|
d++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg_setstr(lib, "name", expanded);
|
|
|
|
|
2010-04-02 12:28:43 -04:00
|
|
|
libhash = murmur_hash64(expanded, strlen(expanded), 0);
|
|
|
|
|
2009-04-18 08:14:26 -04:00
|
|
|
free(expanded);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
conffile_load(char *file)
|
|
|
|
{
|
|
|
|
cfg_t *lib;
|
2011-07-09 05:50:27 -04:00
|
|
|
struct passwd *pw;
|
|
|
|
char *runas;
|
2009-04-18 08:14:26 -04:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
cfg = cfg_init(toplvl_cfg, CFGF_NONE);
|
|
|
|
|
2019-06-15 06:08:56 -04:00
|
|
|
cfg_set_error_function(cfg, logger_confuse);
|
|
|
|
|
2009-04-18 08:14:26 -04:00
|
|
|
ret = cfg_parse(cfg, file);
|
|
|
|
|
|
|
|
if (ret == CFG_FILE_ERROR)
|
|
|
|
{
|
|
|
|
DPRINTF(E_FATAL, L_CONF, "Could not open config file %s\n", file);
|
|
|
|
|
2010-03-19 14:06:47 -04:00
|
|
|
goto out_fail;
|
2009-04-18 08:14:26 -04:00
|
|
|
}
|
|
|
|
else if (ret == CFG_PARSE_ERROR)
|
|
|
|
{
|
|
|
|
DPRINTF(E_FATAL, L_CONF, "Parse error in config file %s\n", file);
|
|
|
|
|
2010-03-19 14:06:47 -04:00
|
|
|
goto out_fail;
|
2009-04-18 08:14:26 -04:00
|
|
|
}
|
|
|
|
|
2011-07-09 05:50:27 -04:00
|
|
|
/* Resolve runas username */
|
|
|
|
runas = cfg_getstr(cfg_getsec(cfg, "general"), "uid");
|
|
|
|
pw = getpwnam(runas);
|
|
|
|
if (!pw)
|
|
|
|
{
|
|
|
|
DPRINTF(E_FATAL, L_CONF, "Could not lookup user %s: %s\n", runas, strerror(errno));
|
|
|
|
|
|
|
|
goto out_fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
runas_uid = pw->pw_uid;
|
|
|
|
runas_gid = pw->pw_gid;
|
|
|
|
|
2010-03-19 14:06:47 -04:00
|
|
|
lib = cfg_getsec(cfg, "library");
|
2009-04-18 08:14:26 -04:00
|
|
|
|
2010-03-19 14:06:47 -04:00
|
|
|
if (cfg_size(lib, "directories") == 0)
|
2009-04-18 08:14:26 -04:00
|
|
|
{
|
2010-03-19 14:06:47 -04:00
|
|
|
DPRINTF(E_FATAL, L_CONF, "No directories specified for library\n");
|
2009-04-18 08:14:26 -04:00
|
|
|
|
2010-03-19 14:06:47 -04:00
|
|
|
goto out_fail;
|
2009-04-18 08:14:26 -04:00
|
|
|
}
|
|
|
|
|
2010-03-19 14:06:47 -04:00
|
|
|
/* Do keyword expansion on library names */
|
|
|
|
ret = conffile_expand_libname(lib);
|
|
|
|
if (ret != 0)
|
2009-04-18 08:14:26 -04:00
|
|
|
{
|
2010-03-19 14:06:47 -04:00
|
|
|
DPRINTF(E_FATAL, L_CONF, "Could not expand library name\n");
|
2009-04-18 08:14:26 -04:00
|
|
|
|
2010-03-19 14:06:47 -04:00
|
|
|
goto out_fail;
|
2009-04-18 08:14:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2010-03-19 14:06:47 -04:00
|
|
|
|
|
|
|
out_fail:
|
|
|
|
cfg_free(cfg);
|
|
|
|
|
|
|
|
return -1;
|
2009-04-18 08:14:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
conffile_unload(void)
|
|
|
|
{
|
|
|
|
cfg_free(cfg);
|
|
|
|
}
|