Added API and command line parameter to change user data directory at runtime.

git-svn-id: http://yate.null.ro/svn/yate/trunk@2259 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2008-10-14 20:15:33 +00:00
parent e23d5cfcda
commit 97c6ccf207
3 changed files with 96 additions and 26 deletions

View File

@ -62,6 +62,9 @@ Use specified configuration name, overrides default "yate"
.B \-c \fIpathname\fR
Path to conf files directory, overrides compiled-in value
.TP
.B \-u \fIpathname\fR
Path to user data files directory, overrides compiled-in value
.TP
.B \-m \fIpathname\fR
Path to modules directory, overrides compiled-in value
.TP

View File

@ -167,7 +167,6 @@ static void sighandler(int signal)
String Engine::s_node;
String Engine::s_shrpath(SHR_PATH);
String Engine::s_cfgpath(CFG_PATH);
String Engine::s_cfgsuffix(CFG_SUFFIX);
String Engine::s_modpath(MOD_PATH);
String Engine::s_modsuffix(DLL_SUFFIX);
@ -178,6 +177,9 @@ Engine::RunMode Engine::s_mode = Engine::Stopped;
Engine* Engine::s_self = 0;
int Engine::s_haltcode = -1;
int EnginePrivate::count = 0;
static String s_cfgpath(CFG_PATH);
static String s_usrpath;
static bool s_createusr = true;
static bool s_init = false;
static bool s_dynplugin = false;
static Engine::PluginMode s_loadMode = Engine::LoadFail;
@ -199,6 +201,7 @@ static bool s_numfiles = false;
static bool s_sigabrt = false;
static bool s_lateabrt = false;
static String s_cfgfile;
static String s_userdir(CFG_DIR);
static const char* s_logfile = 0;
static Configuration s_cfg;
static ObjList plugins;
@ -240,6 +243,35 @@ public:
};
// helper function to initialize user application data dir
static void initUsrPath(String& path, const char* newPath = 0)
{
if (path)
return;
if (TelEngine::null(newPath)) {
#ifdef _WINDOWS
// we force using the ANSI version
char szPath[MAX_PATH];
if (SHGetSpecialFolderPathA(NULL,szPath,CSIDL_APPDATA,TRUE))
path = szPath;
#else
path = ::getenv("HOME");
#endif
if (path.null()) {
Debug(DebugWarn,"Could not get per-user application data path!");
return;
}
if (!path.endsWith(PATH_SEP))
path += PATH_SEP;
path += s_userdir;
}
else
path = newPath;
if (path.endsWith(PATH_SEP))
path = path.substr(0,path.length()-1);
}
bool EngineStatusHandler::received(Message &msg)
{
const char *sel = msg.getValue("module");
@ -263,6 +295,7 @@ bool EngineStatusHandler::received(Message &msg)
static char s_cmdsOpt[] = " module {{load|reload} modulefile|unload modulename|list}\r\n";
static char s_cmdsMsg[] = "Controls the modules loaded in the Telephony Engine\r\n";
// get the base name of a module file
static String moduleBase(const String& fname)
{
int sep = fname.rfind(PATH_SEP[0]);
@ -852,6 +885,7 @@ bool SLib::unload(bool unloadNow)
Engine::Engine()
{
DDebug(DebugAll,"Engine::Engine() [%p]",this);
initUsrPath(s_usrpath);
}
Engine::~Engine()
@ -932,6 +966,7 @@ int Engine::run()
s_params.addParam("configname",s_cfgfile);
s_params.addParam("sharedpath",s_shrpath);
s_params.addParam("configpath",s_cfgpath);
s_params.addParam("usercfgpath",s_usrpath);
s_params.addParam("cfgsuffix",s_cfgsuffix);
s_params.addParam("modulepath",s_modpath);
s_params.addParam("modsuffix",s_modsuffix);
@ -1091,27 +1126,23 @@ const char* Engine::pathSeparator()
return PATH_SEP;
}
const String& Engine::configPath(bool user)
{
if (user) {
if (s_createusr) {
// create user data dir on first request
s_createusr = false;
if (::mkdir(s_usrpath,S_IRWXU) == 0)
Debug(DebugNote,"Created user data directory: '%s'",s_usrpath.c_str());
}
return s_usrpath;
}
return s_cfgpath;
}
String Engine::configFile(const char* name, bool user)
{
String path;
if (user) {
#ifdef _WINDOWS
// we force using the ANSI version
char szPath[MAX_PATH];
if (SHGetSpecialFolderPathA(NULL,szPath,CSIDL_APPDATA,TRUE))
path = szPath;
#else
path = ::getenv("HOME");
#endif
}
if (path.null())
path = s_cfgpath;
else {
if (!path.endsWith(PATH_SEP))
path += PATH_SEP;
path += CFG_DIR;
::mkdir(path,S_IRWXU);
}
String path = configPath(user);
if (!path.endsWith(PATH_SEP))
path += PATH_SEP;
return path + name + s_cfgsuffix;
@ -1281,6 +1312,16 @@ void Engine::extraPath(const String& path)
s_extramod.append(new String(path));
}
void Engine::userPath(const String& path)
{
if (path.null())
return;
if (s_usrpath.null())
s_userdir = path;
else
Debug(DebugWarn,"Engine::userPath('%s') called too late!",path.c_str());
}
void Engine::halt(unsigned int code)
{
if (s_haltcode == -1)
@ -1355,6 +1396,7 @@ static void usage(bool client, FILE* f)
" -n configname Use specified configuration name (%s)\n"
" -e pathname Path to shared files directory (" SHR_PATH ")\n"
" -c pathname Path to conf files directory (" CFG_PATH ")\n"
" -u pathname Path to user files directory (%s)\n"
" -m pathname Path to modules directory (" MOD_PATH ")\n"
" -x relpath Relative path to extra modules directory (can be repeated)\n"
" -w directory Change working directory\n"
@ -1391,7 +1433,8 @@ static void usage(bool client, FILE* f)
" -s Supervised, restart if crashes or locks up\n"
" -r Enable rotation of log file (needs -s and -l)\n"
#endif
,s_cfgfile.safe());
,s_cfgfile.safe()
,Engine::configPath(true).safe());
}
static void badopt(bool client, char chr, const char* opt)
@ -1427,6 +1470,7 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
bool colorize = false;
const char* pidfile = 0;
const char* workdir = 0;
const char* usrpath = 0;
int debug_level = debugLevel();
const char* cfgfile = ::strrchr(argv[0],'/');
@ -1452,6 +1496,7 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
continue;
}
if (!::strcmp(pc,"help")) {
initUsrPath(s_usrpath);
usage(client,stdout);
return 0;
}
@ -1476,10 +1521,12 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
continue;
}
#endif
initUsrPath(s_usrpath);
badopt(client,0,argv[i]);
return EINVAL;
break;
case 'h':
initUsrPath(s_usrpath);
usage(client,stdout);
return 0;
case 'v':
@ -1539,6 +1586,14 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
pc = 0;
s_cfgpath=argv[++i];
break;
case 'u':
if (i+1 >= argc) {
noarg(client,argv[i]);
return ENOENT;
}
pc = 0;
usrpath=argv[++i];
break;
case 'm':
if (i+1 >= argc) {
noarg(client,argv[i]);
@ -1626,6 +1681,7 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
tstamp = Debugger::Textual;
break;
default:
initUsrPath(s_usrpath);
badopt(client,*pc,argv[i]);
return EINVAL;
}
@ -1636,6 +1692,7 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
version();
return 0;
default:
initUsrPath(s_usrpath);
badopt(client,*pc,argv[i]);
return EINVAL;
}
@ -1657,6 +1714,8 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
if (s_cfgfile.endsWith(".exe") || s_cfgfile.endsWith(".EXE"))
s_cfgfile = s_cfgfile.substr(0,s_cfgfile.length()-4);
initUsrPath(s_usrpath,usrpath);
if (workdir)
::chdir(workdir);
@ -1822,6 +1881,7 @@ int Engine::main(int argc, const char** argv, const char** env, RunMode mode, bo
void Engine::help(bool client, bool errout)
{
initUsrPath(s_usrpath);
usage(client, errout ? stderr : stdout);
}

View File

@ -820,11 +820,11 @@ public:
static String configFile(const char* name, bool user = false);
/**
* Get the system configuration directory path
* @return The directory path for system configuration files
* Get the system or user configuration directory path
* @param user True to get the user settings path
* @return The directory path for system or user configuration files
*/
inline static const String& configPath()
{ return s_cfgpath; }
static const String& configPath(bool user = false);
/**
* Get the configuration file suffix
@ -846,6 +846,14 @@ public:
*/
static void extraPath(const String& path);
/**
* Set the per user application data path. This method must be called
* by a main program before calling @ref main() or @ref help()
* Path separators are not allowed. The default is taken from CFG_DIR.
* @param path Single relative path component to write user specific data
*/
static void userPath(const String& path);
/**
* Get the module filename suffix
* @return The suffix for module files
@ -1032,7 +1040,6 @@ private:
static Engine* s_self;
static String s_node;
static String s_shrpath;
static String s_cfgpath;
static String s_cfgsuffix;
static String s_modpath;
static String s_modsuffix;