From e8c9a0437669cc8479906af5e460633693300c5a Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Wed, 8 Apr 2009 19:22:55 +0200 Subject: [PATCH] Remove OS abstraction layer Migrate daemon startup code in main.c, migrate functions with a single callsite to that file. Remove setpgrp() usage in favor of setsid(), remove configure check for setpgrp(). --- configure.in | 2 - src/Makefile.am | 4 +- src/conf.c | 40 ++++- src/configfile.c | 10 +- src/daapd.h | 3 + src/err.c | 26 ++- src/main.c | 211 ++++++++++++++++++++---- src/mp3-scanner.c | 9 +- src/os-unix.c | 410 ---------------------------------------------- src/os-unix.h | 17 -- src/os.h | 51 ------ src/plugin.c | 18 +- src/scan-xml.c | 3 +- src/xml-rpc.c | 3 +- 14 files changed, 263 insertions(+), 544 deletions(-) delete mode 100644 src/os-unix.c delete mode 100644 src/os-unix.h delete mode 100644 src/os.h diff --git a/configure.in b/configure.in index 02263b2f..b1c651cf 100644 --- a/configure.in +++ b/configure.in @@ -23,8 +23,6 @@ AC_CHECK_FUNCS(timegm) AC_CHECK_FUNCS(va_copy) AC_CHECK_FUNCS(__va_copy) -AC_FUNC_SETPGRP - if test "x$prefix" != xNONE -a "x$prefix" != "x/usr"; then CONFFILE="$prefix/etc/mt-daapd.conf" else diff --git a/src/Makefile.am b/src/Makefile.am index 14908a99..1bce194b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,8 +23,8 @@ mt_daapd_SOURCES = main.c daapd.h webserver.c \ rxml.c rxml.h redblack.c redblack.h \ scan-xml.c scan-wma.c scan-url.c \ smart-parser.c smart-parser.h xml-rpc.c xml-rpc.h \ - os.h ll.c ll.h conf.c conf.h util.c util.h \ - os-unix.h os-unix.c os.h plugin.c plugin.h db-sql-updates.c \ + ll.c ll.h conf.c conf.h util.c util.h \ + plugin.c plugin.h db-sql-updates.c \ io.h io.c io-errors.h io-plugin.h \ db-sql.c db-sql.h db-sql-sqlite3.c db-sql-sqlite3.h\ $(FLACSRC) $(MUSEPACKSRC) diff --git a/src/conf.c b/src/conf.c index 1ac1b21b..16b410f6 100644 --- a/src/conf.c +++ b/src/conf.c @@ -46,12 +46,13 @@ #endif #include #include +#include +#include #include "daapd.h" #include "conf.h" #include "err.h" #include "ll.h" -#include "os.h" #include "util.h" #include "webserver.h" #include "xml-rpc.h" @@ -191,6 +192,36 @@ void _conf_remap_entry(char *old_section, char *old_key, char **new_section, cha *new_key = old_key; } +static int _conf_chown(char *path, char *user) { + struct passwd *pw=NULL; + + DPRINTF(E_DBG,L_MISC,"Chowning %s to %s\n",path,user); + + /* drop privs */ + if(getuid() == (uid_t)0) { + if(atoi(user)) { + pw=getpwuid((uid_t)atoi(user)); /* doh! */ + } else { + pw=getpwnam(user); + } + + if(pw) { + if(initgroups(user,pw->pw_gid) != 0 || + chown(path, pw->pw_uid, pw->pw_gid) != 0) { + DPRINTF(E_LOG,L_MISC,"Couldn't chown %s, gid=%d, uid=%d\n", + user,pw->pw_gid, pw->pw_uid); + return FALSE; + } + } else { + DPRINTF(E_LOG,L_MISC,"Couldn't lookup user %s for chown\n",user); + return FALSE; + } + } + + DPRINTF(E_DBG,L_MISC,"Success!\n"); + return TRUE; +} + /** * Try and create a directory, including parents (probably * in response to a config file entry that does not exist). @@ -233,7 +264,7 @@ int _conf_makedir(char *path,char *user) { path_buffer,strerror(errno)); return FALSE; } - os_chown(path_buffer,user); + _conf_chown(path_buffer,user); } retval = TRUE; } @@ -254,9 +285,8 @@ int _conf_existdir(char *path) { DPRINTF(E_DBG,L_CONF,"Checking existence of %s\n",path); - if(os_stat(path,&sb)) { - return FALSE; - } + if (stat(path, &sb)) + return FALSE; if(sb.st_mode & S_IFDIR) return TRUE; diff --git a/src/configfile.c b/src/configfile.c index 36779b94..c7a29657 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -54,7 +54,6 @@ #include "configfile.h" #include "db-generic.h" #include "err.h" -#include "os.h" #include "xml-rpc.h" @@ -175,7 +174,8 @@ int config_password_required(WS_CONNINFO *pwsc, char *role) { /* don't need a password from localhost when the password isn't set */ - if((ws_hostname(pwsc)) && (os_islocaladdr(ws_hostname(pwsc)))) { + if((ws_hostname(pwsc)) + && (strncmp(ws_hostname(pwsc), "127.", 4) == 0)) { if(pw) free(pw); return FALSE; } @@ -394,7 +394,7 @@ void config_handler(WS_CONNINFO *pwsc) { } /* FIXME: should feed this file directly, so as to bypass perms */ - if(!os_islocaladdr(ws_hostname(pwsc))) { + if(strncmp(ws_hostname(pwsc), "127.", 4) != 0) { pw=conf_alloc_string("general","admin_pw",NULL); if((!pw) || (strlen(pw) == 0)) { if(pw) free(pw); @@ -446,7 +446,7 @@ void config_handler(WS_CONNINFO *pwsc) { } /* this is quite broken, but will work */ - os_stat(resolved_path,&sb); + stat(resolved_path,&sb); if(S_ISDIR(sb.st_mode)) { ws_addresponseheader(pwsc,"Location","index.html"); ws_returnerror(pwsc,302,"Moved"); @@ -942,7 +942,7 @@ void config_emit_include(WS_CONNINFO *pwsc, void *value, char *arg) { } /* this should really return a 302:Found */ - os_stat(resolved_path,&sb); + stat(resolved_path,&sb); if(sb.st_mode & S_IFDIR) { ws_writefd(pwsc,"
error: cannot include dir %s
",arg); return; diff --git a/src/daapd.h b/src/daapd.h index 3e41b72c..18448bfb 100644 --- a/src/daapd.h +++ b/src/daapd.h @@ -38,6 +38,9 @@ # include #endif +#define PATHSEP '/' +#define PATHSEP_STR "/" + #ifdef DEBUG # ifndef ASSERT # define ASSERT(f) \ diff --git a/src/err.c b/src/err.c index feee38d5..c4bdd228 100644 --- a/src/err.c +++ b/src/err.c @@ -46,12 +46,13 @@ #include #include +#include + #include "daapd.h" #include "err.h" #include "io.h" #ifndef ERR_LEAN -# include "os.h" # include "plugin.h" #endif @@ -82,6 +83,14 @@ static char *err_categorylist[] = { static ERR_THREADLIST err_threadlist = { 0, NULL }; +static int lvl2syslog[10] = + { + LOG_ALERT, LOG_ALERT, + LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, + LOG_INFO, LOG_INFO, LOG_INFO, LOG_INFO, + LOG_DEBUG + }; + /* * Forwards */ @@ -245,9 +254,10 @@ void err_log(int level, unsigned int cat, char *fmt, ...) /* always log fatals and level 1 to syslog */ if(level <= 1) { if(!err_syslog_open) - os_opensyslog(); + openlog(PACKAGE, LOG_PID, LOG_DAEMON); + err_syslog_open=1; - os_syslog(level,errbuf); + syslog((level > E_DBG) ? LOG_DEBUG : lvl2syslog[level], "%s", errbuf); if(syslog_only && !level) { fprintf(stderr,"Aborting\n"); @@ -361,8 +371,9 @@ int err_setlogfile(char *file) { if(!err_file) { err_logdest &= ~LOGDEST_LOGFILE; if(!err_syslog_open) - os_opensyslog(); - os_syslog(1,"Error initializing logfile"); + openlog(PACKAGE, LOG_PID, LOG_DAEMON); + + syslog(lvl2syslog[1], "Error initializing logfile"); } } @@ -385,8 +396,9 @@ int err_setlogfile(char *file) { err_logdest &= ~LOGDEST_LOGFILE; if(!err_syslog_open) - os_opensyslog(); - os_syslog(1,"Error opening logfile"); + openlog(PACKAGE, LOG_PID, LOG_DAEMON); + + syslog(lvl2syslog[1], "Error opening logfile"); result=FALSE; } diff --git a/src/main.c b/src/main.c index cf6c9032..d4f3a5fa 100644 --- a/src/main.c +++ b/src/main.c @@ -77,6 +77,9 @@ #endif #include +#include +#include + #include "daapd.h" #include "conf.h" @@ -85,7 +88,6 @@ #include "mp3-scanner.h" #include "webserver.h" #include "db-generic.h" -#include "os.h" #include "plugin.h" #include "util.h" #include "io.h" @@ -108,6 +110,10 @@ # define atoll(a) atol(a) #endif +#ifndef PIDFILE +#define PIDFILE "/var/run/mt-daapd.pid" +#endif + /* * Globals */ @@ -156,7 +162,6 @@ int main_auth(WS_CONNINFO *pwsc, char *username, char *password) { void usage(char *program) { printf("Usage: %s [options]\n\n",program); printf("Options:\n"); - printf(" -a Set cwd to app dir before starting\n"); printf(" -d Debug level (0-9)\n"); printf(" -D Debug modules\n"); printf(" -c Use configfile specified\n"); @@ -217,6 +222,160 @@ int load_plugin_dir(char *plugindir) { return loaded; } +static int +sigterm_server(char *pidfile) +{ + FILE *fp; + pid_t pid; + int ret; + + fp = fopen(pidfile, "r"); + if (!fp) + { + DPRINTF(E_LOG, L_MAIN, "Failed to open pidfile %s: %s\n", pidfile, strerror(errno)); + + return -1; + } + + ret = fscanf(fp, "%d\n", &pid); + + fclose(fp); + + if (ret < 1) + { + DPRINTF(E_LOG, L_MAIN, "Failed to get pid from pidfile %s\n", pidfile); + + return -1; + } + + ret = kill(pid, SIGTERM); + if (ret != 0) + { + DPRINTF(E_LOG, L_MAIN, "Failed to kill pid %d: %s\n", pid, strerror(errno)); + + return -1; + } + + return 0; +} + +static int +daemonize(int foreground, char *runas, char *pidfile) +{ + FILE *fp; + int fd; + pid_t childpid; + pid_t ret; + int iret; + struct passwd *pw; + + if (geteuid() == (uid_t) 0) + { + pw = getpwnam(runas); + + if (!pw) + { + DPRINTF(E_FATAL, L_MAIN, "Could not lookup user %s: %s\n", runas, strerror(errno)); + + return -1; + } + } + else + pw = NULL; + + if (!foreground) + { + fp = fopen(pidfile, "w"); + if (!fp) + { + DPRINTF(E_LOG, L_MAIN, "Error opening pidfile (%s): %s\n", pidfile, strerror(errno)); + + return -1; + } + + fd = open("/dev/null", O_RDWR, 0); + if (fd < 0) + { + DPRINTF(E_LOG, L_MAIN, "Error opening /dev/null: %s\n", strerror(errno)); + + fclose(fp); + return -1; + } + + signal(SIGTTOU, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + signal(SIGTSTP, SIG_IGN); + + childpid = fork(); + + if (childpid > 0) + exit(EXIT_SUCCESS); + else if (childpid < 0) + { + DPRINTF(E_FATAL, L_MAIN, "Fork failed: %s\n", strerror(errno)); + + close(fd); + fclose(fp); + return -1; + } + + ret = setsid(); + if (ret == (pid_t) -1) + { + DPRINTF(E_FATAL, L_MAIN, "setsid() failed: %s\n", strerror(errno)); + + close(fd); + fclose(fp); + return -1; + } + + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + + if (fd > 2) + close(fd); + + chdir("/"); + umask(0); + + fprintf(fp, "%d\n", getpid()); + fclose(fp); + + DPRINTF(E_DBG, L_MAIN, "PID: %d\n", getpid()); + } + + if (pw) + { + iret = initgroups(runas, pw->pw_gid); + if (iret != 0) + { + DPRINTF(E_FATAL, L_MAIN, "initgroups() failed: %s\n", strerror(errno)); + + return -1; + } + + iret = setgid(pw->pw_gid); + if (iret != 0) + { + DPRINTF(E_FATAL, L_MAIN, "setgid() failed: %s\n", strerror(errno)); + + return -1; + } + + iret = setuid(pw->pw_uid); + if (iret != 0) + { + DPRINTF(E_FATAL, L_MAIN, "setuid() failed: %s\n", strerror(errno)); + + return -1; + } + } + + return 0; +} + + /** * set up an errorhandler for io errors * @@ -381,11 +540,11 @@ int main(int argc, char *argv[]) { char **mp3_dir_array; char *servername; char *ffid = NULL; - int appdir = 0; char *perr=NULL; char *txtrecord[10]; void *phandle; char *plugindir; + char *pidfile = PIDFILE; struct event *main_timer; struct timeval tv; sigset_t sigs; @@ -395,19 +554,14 @@ int main(int argc, char *argv[]) { int i; int err; - char *apppath; int debuglevel=0; err_setlevel(2); config.foreground=0; - while((option=getopt(argc,argv,"D:d:c:P:mfrysiuvab:Vk")) != -1) { + while((option=getopt(argc,argv,"D:d:c:P:frysiuvb:Vk")) != -1) { switch(option) { - case 'a': - appdir = 1; - break; - case 'b': ffid=optarg; break; @@ -434,7 +588,7 @@ int main(int argc, char *argv[]) { break; case 'P': - os_set_pidfile(optarg); + pidfile = optarg; break; case 'r': @@ -477,10 +631,14 @@ int main(int argc, char *argv[]) { } - if(kill_server) { - os_signal_server(S_STOP); - exit(0); - } + if (kill_server) + { + ret = sigterm_server(pidfile); + if (ret == 0) + exit(EXIT_SUCCESS); + else + exit(EXIT_FAILURE); + } io_init(); io_set_errhandler(main_io_errhandler); @@ -491,15 +649,6 @@ int main(int argc, char *argv[]) { config.stats.start_time=start_time=(int)time(NULL); config.stop=0; - /* set appdir first, that way config resolves relative to appdir */ - if(appdir) { - apppath = os_apppath(argv[0]); - DPRINTF(E_INF,L_MAIN,"Changing cwd to %s\n",apppath); - chdir(apppath); - free(apppath); - configfile="mt-daapd.conf"; - } - if(CONF_E_SUCCESS != conf_read(configfile)) { fprintf(stderr,"Error reading config file (%s)\n",configfile); exit(EXIT_FAILURE); @@ -556,13 +705,18 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } - runas = conf_alloc_string("general","runas","nobody"); + /* Daemonize and drop privileges */ + runas = conf_alloc_string("general", "runas", "nobody"); - if(!os_init(config.foreground,runas)) { - DPRINTF(E_LOG,L_MAIN,"Could not initialize server\n"); + ret = daemonize(config.foreground, runas, pidfile); + if (ret < 0) + { + DPRINTF(E_LOG, L_MAIN, "Could not initialize server\n"); - exit(EXIT_FAILURE); - } + exit(EXIT_FAILURE); + } + + free(runas); /* Initialize libevent (after forking) */ evbase_main = event_init(); @@ -573,7 +727,6 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } - free(runas); DPRINTF(E_LOG, L_MAIN, "mDNS init\n"); ret = mdns_init(); diff --git a/src/mp3-scanner.c b/src/mp3-scanner.c index a08494e8..5cbe8c12 100644 --- a/src/mp3-scanner.c +++ b/src/mp3-scanner.c @@ -48,7 +48,6 @@ #include "err.h" #include "io.h" #include "mp3-scanner.h" -#include "os.h" #include "util.h" @@ -295,7 +294,7 @@ int scan_path(char *path) { snprintf(relative_path,PATH_MAX,"%s/%s",path,pde->d_name); - if(!os_lstat(relative_path,&sb)) { + if(!lstat(relative_path, &sb)) { if(S_ISLNK(sb.st_mode) && !follow_symlinks) continue; } @@ -303,7 +302,7 @@ int scan_path(char *path) { mp3_path[0] = '\x0'; realpath(relative_path,mp3_path); DPRINTF(E_DBG,L_SCAN,"Found %s\n",relative_path); - if(os_stat(mp3_path,&sb)) { + if (stat(mp3_path, &sb)) { DPRINTF(E_INF,L_SCAN,"Error statting %s: %s\n",mp3_path,strerror(errno)); } else { if(S_ISDIR(sb.st_mode)) { /* follow dir */ @@ -353,7 +352,7 @@ int scan_static_playlist(char *path) { int ret; DPRINTF(E_WARN,L_SCAN|L_PL,"Processing static playlist: %s\n",path); - if(os_stat(path,&sb)) { + if (stat(path, &sb)) { DPRINTF(E_INF,L_SCAN,"Error statting %s: %s\n",path,strerror(errno)); return FALSE; } @@ -535,7 +534,7 @@ void scan_filename(char *path, int compdir, char *extensions) { } - if(os_stat(mp3_path,&sb)) { + if(stat(mp3_path, &sb)) { DPRINTF(E_INF,L_SCAN,"Error statting: %s\n",strerror(errno)); } else { /* we assume this is regular file */ diff --git a/src/os-unix.c b/src/os-unix.c deleted file mode 100644 index 4e84f8cd..00000000 --- a/src/os-unix.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Abstracts os interface - * - * Copyright (c) 2006 Ron Pedde (rpedde@users.sourceforge.net) - * - * 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 -# include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#ifdef HAVE_SYS_WAIT_H -# include -#endif -#include -#include - -#include "daapd.h" -#include "conf.h" -#include "err.h" -#include "os.h" - -/** You say po-tay-to, I say po-tat-o */ -#ifndef SIGCLD -# define SIGCLD SIGCHLD -#endif - -/** Where to dump the pidfile */ -#ifndef PIDFILE -#define PIDFILE "/var/run/mt-daapd.pid" -#endif - -/* Forwards */ -static int _os_daemon_start(void); - -/* Globals */ -char *_os_pidfile = PIDFILE; - -/** - * this initializes the platform... sets up signal handlers, forks to the - * background, etc - * - * @param foreground whether to run in fg or fork to bg - * @returns TRUE on success, FALSE otherwise - */ -int os_init(int foreground, char *runas) { - int pid_fd; - FILE *pid_fp=NULL; - - /* open the pidfile, so it can be written once we detach */ - if(!foreground) { - if(-1 == (pid_fd = open(_os_pidfile,O_CREAT | O_WRONLY | O_TRUNC, 0644))) { - DPRINTF(E_LOG,L_MAIN,"Error opening pidfile (%s): %s\n", - _os_pidfile,strerror(errno)); - } else { - if(0 == (pid_fp = fdopen(pid_fd, "w"))) - DPRINTF(E_LOG,L_MAIN,"fdopen: %s\n",strerror(errno)); - } - _os_daemon_start(); - fprintf(pid_fp,"%d\n",getpid()); - fclose(pid_fp); - DPRINTF(E_DBG,L_MAIN,"Pid: %d\n",getpid()); - } - - // Drop privs here - if(os_drop_privs(runas)) { - DPRINTF(E_FATAL,L_MAIN,"Error in drop_privs: %s\n",strerror(errno)); - } - - return TRUE; -} - -/** - * start syslogging - * - * @returns TRUE on success, FALSE otherwise - */ -int os_opensyslog(void) { - openlog(PACKAGE,LOG_PID,LOG_DAEMON); - return TRUE; -} - - -/** - * stop syslogging - * - * @returns TRUE on success, FALSE otherwise - */ -int os_closesyslog(void) { - closelog(); - return TRUE; -} - -/** - * log a syslog message - * - * @param level log level (1-9: 1=fatal, 9=debug) - * @param msg message to log to the syslog - * @returns TRUE on success, FALSE otherwise - */ -int os_syslog(int level, char *msg) { - int priority; - - switch(level) { - case 0: - case 1: - priority = LOG_ALERT; - break; - case 2: - case 3: - case 4: - priority = LOG_NOTICE; - break; - case 5: - case 6: - case 7: - case 8: - priority = LOG_INFO; - break; - - case 9: - default: - priority = LOG_DEBUG; - break; - } - - syslog(priority,"%s",msg); - return TRUE; -} - - -/** - * os-specific chown - * - * - */ -extern int os_chown(char *path, char *user) { - struct passwd *pw=NULL; - - DPRINTF(E_DBG,L_MISC,"Chowning %s to %s\n",path,user); - - /* drop privs */ - if(getuid() == (uid_t)0) { - if(atoi(user)) { - pw=getpwuid((uid_t)atoi(user)); /* doh! */ - } else { - pw=getpwnam(user); - } - - if(pw) { - if(initgroups(user,pw->pw_gid) != 0 || - chown(path, pw->pw_uid, pw->pw_gid) != 0) { - DPRINTF(E_LOG,L_MISC,"Couldn't chown %s, gid=%d, uid=%d\n", - user,pw->pw_gid, pw->pw_uid); - return FALSE; - } - } else { - DPRINTF(E_LOG,L_MISC,"Couldn't lookup user %s for chown\n",user); - return FALSE; - } - } - - DPRINTF(E_DBG,L_MISC,"Success!\n"); - return TRUE; -} - -/** - * find the old service pid and send it a SIGTERM - */ -int os_signal_server(int what) { - FILE *pid_fp; - int pid; - int result = TRUE; - int signal = 0; - - if(NULL == (pid_fp = fopen(_os_pidfile, "r"))) { - DPRINTF(E_LOG,L_MAIN,"fdopen: %s\n",strerror(errno)); - return FALSE; - } - - if(fscanf(pid_fp,"%d\n",&pid)) { - kill(pid,SIGTERM); - } else { - DPRINTF(E_LOG,L_MAIN,"os_service_kill: can't get pid from pidfile\n"); - result = FALSE; - } - - fclose(pid_fp); - - switch(what) { - case S_SCAN: - signal=SIGUSR1; - break; - case S_FULL: - signal=SIGUSR2; - break; - case S_STOP: - signal=SIGTERM; - default: - break; - - } - - if(kill(pid,signal)) { - perror("kill"); - result = FALSE; - } - return result; -} - - -/** - * Fork and exit. Stolen pretty much straight from Stevens. - * - * @returns 0 on success, -1 with errno set on error - */ -int _os_daemon_start(void) { - int childpid, fd; - - signal(SIGTTOU, SIG_IGN); - signal(SIGTTIN, SIG_IGN); - signal(SIGTSTP, SIG_IGN); - - // Fork and exit - if ((childpid = fork()) < 0) { - fprintf(stderr, "Can't fork!\n"); - return -1; - } else if (childpid > 0) - exit(0); - -#ifdef SETPGRP_VOID - setpgrp(); -#else - setpgrp(0,0); -#endif - -#ifdef TIOCNOTTY - if ((fd = open("/dev/tty", O_RDWR)) >= 0) { - ioctl(fd, TIOCNOTTY, (char *) NULL); - close(fd); - } -#endif - - if((fd = open("/dev/null", O_RDWR, 0)) != -1) { - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - if (fd > 2) - close(fd); - } - - /* - for (fd = 0; fd < FOPEN_MAX; fd++) - close(fd); - */ - - errno = 0; - - chdir("/"); - umask(0); - - return 0; -} - - -/** - * Drop privs. This allows mt-daapd to run as a non-privileged user. - * Hopefully this will limit the damage it could do if exploited - * remotely. Note that only the user need be specified. GID - * is set to the primary group of the user. - * - * \param user user to run as (or UID) - */ -int os_drop_privs(char *user) { - int err; - struct passwd *pw=NULL; - - /* drop privs */ - if(getuid() == (uid_t)0) { - if(atoi(user)) { - pw=getpwuid((uid_t)atoi(user)); /* doh! */ - } else { - pw=getpwnam(user); - } - - if(pw) { - if(initgroups(user,pw->pw_gid) != 0 || - setgid(pw->pw_gid) != 0 || - setuid(pw->pw_uid) != 0) { - err=errno; - fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n", - user,pw->pw_gid, pw->pw_uid); - errno=err; - return -1; - } - } else { - err=errno; - fprintf(stderr,"Couldn't lookup user %s\n",user); - errno=err; - return -1; - } - } - - return 0; -} - - -/** - * set the pidfile to a non-default value - * - * @param file file to use as pidfile - */ - void os_set_pidfile(char *file) { - _os_pidfile = file; - } - -/** - * load a shared library - * - * @param - */ -void *os_loadlib(char **pe, char *path) { - void *retval; - - if(!(retval = dlopen(path,RTLD_NOW))) - *pe = strdup(dlerror()); - - return retval; -} - -void *os_libfunc(char **pe, void *handle, char *function) { - void *retval; - - if((!(retval = dlsym(handle,function))) && (pe)) - *pe = strdup(dlerror()); - - return retval; -} - -int os_unload(void *handle) { - return dlclose(handle); -} - -/** - * Determine if an address is local or not - * - * @param hostaddr the address to test for locality - */ -int os_islocaladdr(char *hostaddr) { - /* how can we check interfaces without something like libnet? */ - - if(strncmp(hostaddr,"127.",4) == 0) - return TRUE; - - return FALSE; -} - -char *os_apppath(char *parm) { - char path[PATH_MAX]; - - realpath(parm,path); - if(strrchr(path,'/')) { - *strrchr(path,'/') = '\0'; - } - - return strdup(path); -} - -/** - * stat wrapper - */ -int os_stat(const char *path, struct stat *sb) { - return stat(path, sb); -} - -int os_lstat(const char *path, struct stat *sb) { - return lstat(path, sb); -} diff --git a/src/os-unix.h b/src/os-unix.h deleted file mode 100644 index d4ea184b..00000000 --- a/src/os-unix.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net) - * - */ - -#ifndef _OS_UNIX_H_ -#define _OS_UNIX_H_ - -#define PATHSEP '/' -#define PATHSEP_STR "/" -#define OS_SOCKETTYPE unsigned int - -/* unix-specific functions */ -extern int os_drop_privs(char *user); -void os_set_pidfile(char *file); -#endif - diff --git a/src/os.h b/src/os.h deleted file mode 100644 index 1f95accb..00000000 --- a/src/os.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Abstract os interface for non-unix platforms - * - * Copyright (C) 2006 Ron Pedde (rpedde@users.sourceforge.net) - * - * 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 - */ - -#ifndef _OS_H_ -#define _OS_H_ - -#define S_STOP 0 -#define S_SCAN 1 -#define S_FULL 2 - -/* backgrounding, signal handling, etc */ -extern int os_init(int foreground, char *runas); - -/* system native logging functions */ -extern int os_opensyslog(void); -extern int os_closesyslog(void); -extern int os_syslog(int level, char *msg); -extern int os_chown(char *path, char *user); - -/* library loading functions */ -extern void *os_loadlib(char **pe, char *path); -extern void *os_libfunc(char **pe, void *handle, char *function); -extern int os_unload(void *handle); - -/* misc */ -extern int os_stat(const char *path, struct stat *sb); -extern int os_lstat(const char *path, struct stat *sb); -extern int os_islocaladdr(char *hostaddr); -extern char *os_apppath(char *parm); -extern int os_signal_server(int what); /* signal a running server */ - -#include "os-unix.h" - -#endif diff --git a/src/plugin.c b/src/plugin.c index 1b8e9ed3..daf9106e 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -49,13 +49,15 @@ #ifdef HAVE_UNISTD_H #include #endif + +#include + #include "daapd.h" #include "conf.h" #include "configfile.h" #include "db-generic.h" #include "err.h" #include "io.h" -#include "os.h" #include "plugin.h" #include "smart-parser.h" #include "xml-rpc.h" @@ -230,8 +232,9 @@ int plugin_load(char **pe, char *path) { DPRINTF(E_DBG,L_PLUG,"Attempting to load plugin %s\n",path); - phandle = os_loadlib(pe, path); - if(!phandle) { + phandle = dlopen(path, RTLD_NOW); + if (!phandle) { + *pe = strdup(dlerror()); DPRINTF(E_INF,L_PLUG,"Couldn't get lib handle for %s\n",path); return PLUGIN_E_NOLOAD; } @@ -241,10 +244,11 @@ int plugin_load(char **pe, char *path) { ppi->phandle = phandle; - info_func = (PLUGIN_INFO*(*)(void)) os_libfunc(pe, phandle,"plugin_info"); + info_func = (PLUGIN_INFO*(*)(void)) dlsym(phandle, "plugin_info"); if(info_func == NULL) { + *pe = strdup(dlerror()); DPRINTF(E_INF,L_PLUG,"Couldn't get info_func for %s\n",path); - os_unload(phandle); + dlclose(phandle); free(ppi); return PLUGIN_E_BADFUNCS; } @@ -254,7 +258,7 @@ int plugin_load(char **pe, char *path) { if(!pinfo) { if(pe) *pe = strdup("plugin declined to load"); - os_unload(phandle); + dlclose(phandle); free(ppi); return PLUGIN_E_NOLOAD; } @@ -262,7 +266,7 @@ int plugin_load(char **pe, char *path) { if(pinfo->version != PLUGIN_VERSION) { DPRINTF(E_INF,L_PLUG,"Plugin is too old: version %d, expecting %d\n", pinfo->version, PLUGIN_VERSION); - os_unload(phandle); + dlclose(phandle); free(ppi); return PLUGIN_E_NOLOAD; } diff --git a/src/scan-xml.c b/src/scan-xml.c index 42220d1c..87a3dec7 100644 --- a/src/scan-xml.c +++ b/src/scan-xml.c @@ -38,7 +38,6 @@ #include "db-generic.h" #include "err.h" #include "mp3-scanner.h" -#include "os.h" #include "rxml.h" #include "redblack.h" #include "util.h" @@ -165,7 +164,7 @@ int scan_xml_rb_compare(const void *pa, const void *pb, const void *cfg) { int scan_xml_is_file(char *path) { struct stat sb; - if(os_stat(path,&sb)) + if(stat(path, &sb)) return 0; if(sb.st_mode & S_IFREG) diff --git a/src/xml-rpc.c b/src/xml-rpc.c index a93d3f0c..ac4050e9 100644 --- a/src/xml-rpc.c +++ b/src/xml-rpc.c @@ -34,7 +34,6 @@ #include "db-generic.h" #include "err.h" #include "mp3-scanner.h" -#include "os.h" #include "plugin.h" #include "webserver.h" #include "xml-rpc.h" @@ -458,7 +457,7 @@ void xml_browse_path(WS_CONNINFO *pwsc) { snprintf(full_path,PATH_MAX,"%s%c%s",base_path,PATHSEP,pde->d_name); realpath(full_path,resolved_path); - if(os_stat(resolved_path,&sb)) { + if(stat(resolved_path, &sb)) { DPRINTF(E_INF,L_XML,"Error statting %s: %s\n", resolved_path,strerror(errno)); continue;