/* the Music Player Daemon (MPD) * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) * This project's homepage is: http://www.musicpd.org * * 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 */ #include "conf.h" #include "log.h" #include "utils.h" #include "buffer2array.h" #include "audio.h" #include "volume.h" #include <sys/param.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <pwd.h> #define MAX_STRING_SIZE MAXPATHLEN+80 #define CONF_COMMENT '#' #define CONF_NUMBER_OF_PARAMS 27 #define CONF_NUMBER_OF_PATHS 6 #define CONF_NUMBER_OF_REQUIRED 5 #define CONF_NUMBER_OF_ALLOW_CATS 1 #define CONF_CONNECTION_TIMEOUT_DEFAULT "60" #define CONF_MAX_CONNECTIONS_DEFAULT "5" #define CONF_MAX_PLAYLIST_LENGTH_DEFAULT "4096" #define CONF_BUFFER_BEFORE_PLAY_DEFAULT "25%" #define CONF_MAX_COMMAND_LIST_SIZE_DEFAULT "2048" #define CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT "2048" #define CONF_AO_DRIVER_DEFAULT AUDIO_AO_DRIVER_DEFAULT #define CONF_AO_DRIVER_OPTIONS_DEFAULT "" #define CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT "no" #define CONF_BIND_TO_ADDRESS_DEFAULT "any" #define CONF_USER_DEFAULT "" #define CONF_LOG_LEVEL_DEFAULT "default" #define CONF_AUDIO_WRITE_SIZE_DEFAULT "1024" #define CONF_BUFFER_SIZE_DEFAULT "2048" #ifndef NO_OSS_MIXER #define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_OSS #define CONF_MIXER_DEVICE_DEFAULT "" #else #ifdef HAVE_ALSA #define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_ALSA #define CONF_MIXER_DEVICE_DEFAULT "" #else #define CONF_MIXER_TYPE_DEFAULT VOLUME_MIXER_NULL #define CONF_MIXER_DEVICE_DEFAULT "" #endif #endif char * conf_params[CONF_NUMBER_OF_PARAMS]; void initConf() { int i; for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) conf_params[i] = NULL; /* we don't specify these on the command line */ conf_params[CONF_CONNECTION_TIMEOUT] = strdup(CONF_CONNECTION_TIMEOUT_DEFAULT); conf_params[CONF_MIXER_DEVICE] = strdup(CONF_MIXER_DEVICE_DEFAULT); conf_params[CONF_MAX_CONNECTIONS] = strdup(CONF_MAX_CONNECTIONS_DEFAULT); conf_params[CONF_MAX_PLAYLIST_LENGTH] = strdup(CONF_MAX_PLAYLIST_LENGTH_DEFAULT); conf_params[CONF_BUFFER_BEFORE_PLAY] = strdup(CONF_BUFFER_BEFORE_PLAY_DEFAULT); conf_params[CONF_MAX_COMMAND_LIST_SIZE] = strdup(CONF_MAX_COMMAND_LIST_SIZE_DEFAULT); conf_params[CONF_MAX_OUTPUT_BUFFER_SIZE] = strdup(CONF_MAX_OUTPUT_BUFFER_SIZE_DEFAULT); conf_params[CONF_AO_DRIVER] = strdup(CONF_AO_DRIVER_DEFAULT); conf_params[CONF_AO_DRIVER_OPTIONS] = strdup(CONF_AO_DRIVER_OPTIONS_DEFAULT); conf_params[CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS] = strdup(CONF_SAVE_ABSOLUTE_PATHS_IN_PLAYLISTS_DEFAULT); conf_params[CONF_BIND_TO_ADDRESS] = strdup(CONF_BIND_TO_ADDRESS_DEFAULT); conf_params[CONF_MIXER_TYPE] = strdup(CONF_MIXER_TYPE_DEFAULT); conf_params[CONF_USER] = strdup(CONF_USER_DEFAULT); conf_params[CONF_LOG_LEVEL] = strdup(CONF_LOG_LEVEL_DEFAULT); conf_params[CONF_AUDIO_WRITE_SIZE] = strdup(CONF_AUDIO_WRITE_SIZE_DEFAULT); conf_params[CONF_BUFFER_SIZE] = strdup(CONF_BUFFER_SIZE_DEFAULT); } char ** readConf(char * file) { char * conf_strings[CONF_NUMBER_OF_PARAMS] = { "port", "music_directory", "playlist_directory", "log_file", "error_file", "connection_timeout", "mixer_device", "max_connections", "max_playlist_length", "buffer_before_play", "max_command_list_size", "max_output_buffer_size", "ao_driver", "ao_driver_options", "save_absolute_paths_in_playlists", "bind_to_address", "mixer_type", "state_file", "user", "db_file", "log_level", "mixer_control", "audio_write_size", "filesystem_charset", "password", "default_permissions", "buffer_size" }; int conf_absolutePaths[CONF_NUMBER_OF_PATHS] = { CONF_MUSIC_DIRECTORY, CONF_PLAYLIST_DIRECTORY, CONF_LOG_FILE, CONF_ERROR_FILE, CONF_STATE_FILE, CONF_DB_FILE }; int conf_required[CONF_NUMBER_OF_REQUIRED] = { CONF_MUSIC_DIRECTORY, CONF_PLAYLIST_DIRECTORY, CONF_LOG_FILE, CONF_ERROR_FILE, CONF_PORT }; short conf_allowCat[CONF_NUMBER_OF_ALLOW_CATS] = { CONF_PASSWORD }; FILE * fp; char string[MAX_STRING_SIZE+1]; char ** array; int i; int numberOfArgs; short allowCat[CONF_NUMBER_OF_PARAMS]; for(i=0;i<CONF_NUMBER_OF_PARAMS;i++) allowCat[i] = 0; for(i=0;i<CONF_NUMBER_OF_ALLOW_CATS;i++) allowCat[conf_allowCat[i]] = 1; if(!(fp=fopen(file,"r"))) { ERROR("problems opening file %s for reading\n",file); exit(-1); } while(myFgets(string,sizeof(string),fp)) { if(string[0]==CONF_COMMENT) continue; numberOfArgs = buffer2array(string,&array); if(numberOfArgs==0) continue; if(2!=numberOfArgs) { ERROR("need two args in conf at: %s\n",string); exit(-1); } i = 0; while(i<CONF_NUMBER_OF_PARAMS && 0!=strcmp(conf_strings[i],array[0])) i++; if(i>=CONF_NUMBER_OF_PARAMS) { ERROR("unrecognized line in conf: %s\n",string); exit(-1); } if(conf_params[i]!=NULL) { if(allowCat[i]) { conf_params[i] = realloc(conf_params[i], strlen(conf_params[i])+ strlen(CONF_CAT_CHAR)+ strlen(array[1])+1); strcat(conf_params[i],CONF_CAT_CHAR); strcat(conf_params[i],array[1]); } else { free(conf_params[i]); conf_params[i] = strdup(array[1]); } } else conf_params[i] = strdup(array[1]); free(array[0]); free(array[1]); free(array); } fclose(fp); for(i=0;i<CONF_NUMBER_OF_REQUIRED;i++) { if(conf_params[conf_required[i]] == NULL) { ERROR("%s is unassigned in conf file\n", conf_strings[conf_required[i]]); exit(-1); } } for(i=0;i<CONF_NUMBER_OF_PATHS;i++) { if(conf_params[conf_absolutePaths[i]] && conf_params[conf_absolutePaths[i]][0]!='/' && conf_params[conf_absolutePaths[i]][0]!='~') { ERROR("\"%s\" is not an absolute path\n", conf_params[conf_absolutePaths[i]]); exit(-1); } /* Parse ~ in path */ else if(conf_params[conf_absolutePaths[i]] && conf_params[conf_absolutePaths[i]][0]=='~') { struct passwd * pwd = NULL; char * path; int pos = 1; if(conf_params[conf_absolutePaths[i]][1]=='/' || conf_params[conf_absolutePaths[i]][1]=='\0') { uid_t uid = geteuid(); if((pwd = getpwuid(uid)) == NULL) { ERROR("problems getting passwd entry " "for current user\n"); exit(-1); } } else { int foundSlash = 0; char * ch = &( conf_params[conf_absolutePaths[i]][1]); for(;*ch!='\0' && *ch!='/';ch++); if(*ch=='/') foundSlash = 1; * ch = '\0'; pos+= ch- &(conf_params[ conf_absolutePaths[i]][1]); if((pwd = getpwnam(&(conf_params[ conf_absolutePaths[i]][1]))) == NULL) { ERROR("user \"%s\" not found\n", &(conf_params[ conf_absolutePaths[i]][1])); exit(-1); } if(foundSlash) *ch = '/'; } path = malloc(strlen(pwd->pw_dir)+strlen( &(conf_params[conf_absolutePaths[i]][pos]))+1); strcpy(path,pwd->pw_dir); strcat(path,&(conf_params[conf_absolutePaths[i]][pos])); free(conf_params[conf_absolutePaths[i]]); conf_params[conf_absolutePaths[i]] = path; } } return conf_params; } char ** getConf() { return conf_params; }