4 * Copyright (c) Tuomo Valkonen 1999-2005.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
16 #include <sys/types.h>
18 #include "readconfig.h"
33 static char *userdir=NULL;
34 static char *sessiondir=NULL;
35 static char *scriptpath=NULL;
38 bool extl_add_searchdir(const char *dir)
41 scriptpath=extl_scopy(dir);
45 char *p=extl_scat3(dir, ":", scriptpath);
56 bool extl_set_searchpath(const char *path)
74 bool extl_set_userdirs(const char *appname)
86 extl_warn(TR("$HOME not set"));
88 libtu_asprintf(&userdir, "%s/.%s", home, appname);
90 fails-=extl_add_searchdir(userdir);
92 libtu_asprintf(&tmp, "%s/.%s/lib", home, appname);
94 fails-=extl_add_searchdir(tmp);
103 bool extl_set_sessiondir(const char *session)
108 if(strchr(session, '/')!=NULL){
109 tmp=extl_scopy(session);
110 }else if(userdir!=NULL){
111 libtu_asprintf(&tmp, "%s/%s", userdir, session);
113 extl_warn(TR("User directory not set. "
114 "Unable to set session directory."));
130 const char *extl_userdir()
136 const char *extl_sessiondir()
142 const char *extl_searchpath()
151 /*{{{ try_etcpath, do_include, etc. */
154 static int do_try(const char *dir, const char *file, ExtlTryConfigFn *tryfn,
160 libtu_asprintf(&tmp, "%s/%s", dir, file);
162 return EXTL_TRYCONFIG_MEMERROR;
164 ret=tryfn(tmp, tryfnparam);
170 static int try_dir(const char *const *files, const char *cfdir,
171 ExtlTryConfigFn *tryfn, void *tryfnparam)
173 const char *const *file;
174 int ret, ret2=EXTL_TRYCONFIG_NOTFOUND;
176 for(file=files; *file!=NULL; file++){
178 ret=tryfn(*file, tryfnparam);
180 ret=do_try(cfdir, *file, tryfn, tryfnparam);
183 if(ret2==EXTL_TRYCONFIG_NOTFOUND)
191 static int try_etcpath(const char *const *files,
192 ExtlTryConfigFn *tryfn, void *tryfnparam)
194 const char *const *file=NULL;
195 int i, ret, ret2=EXTL_TRYCONFIG_NOTFOUND;
196 char *path, *colon, *dir;
198 if(sessiondir!=NULL){
199 for(file=files; *file!=NULL; file++){
200 ret=do_try(sessiondir, *file, tryfn, tryfnparam);
203 if(ret2==EXTL_TRYCONFIG_NOTFOUND)
210 colon=strchr(path, ':');
212 dir=extl_scopyn(path, colon-path);
215 dir=extl_scopy(path);
221 for(file=files; *file!=NULL; file++){
222 ret=do_try(dir, *file, tryfn, tryfnparam);
227 if(ret2==EXTL_TRYCONFIG_NOTFOUND)
239 static int try_lookup(const char *file, char **ptr)
241 if(access(file, F_OK)!=0)
242 return EXTL_TRYCONFIG_NOTFOUND;
243 *ptr=extl_scopy(file);
248 static int try_load(const char *file, TryCallParam *param)
250 if(access(file, F_OK)!=0)
251 return EXTL_TRYCONFIG_NOTFOUND;
254 extl_warn(TR("Falling back to %s."), file);
256 if(!extl_loadfile(file, &(param->fn))){
258 return EXTL_TRYCONFIG_LOAD_FAILED;
261 return EXTL_TRYCONFIG_OK;
265 static int try_call(const char *file, TryCallParam *param)
267 int ret=try_load(file, param);
269 if(ret!=EXTL_TRYCONFIG_OK)
272 ret=extl_call(param->fn, NULL, NULL);
274 extl_unref_fn(param->fn);
276 return (ret ? EXTL_TRYCONFIG_OK : EXTL_TRYCONFIG_CALL_FAILED);
280 static int try_read_savefile(const char *file, TryCallParam *param)
282 int ret=try_load(file, param);
284 if(ret!=EXTL_TRYCONFIG_OK)
287 ret=extl_call(param->fn, NULL, "t", &(param->tab));
289 extl_unref_fn(param->fn);
291 return (ret ? EXTL_TRYCONFIG_OK : EXTL_TRYCONFIG_CALL_FAILED);
295 int extl_try_config(const char *fname, const char *cfdir,
296 ExtlTryConfigFn *tryfn, void *tryfnparam,
297 const char *ext1, const char *ext2)
299 char *files[]={NULL, NULL, NULL, NULL};
300 int n=0, ret=EXTL_TRYCONFIG_NOTFOUND, ret2;
301 bool search=FALSE, has_ext;
303 /* Search etcpath only if path is not absolute */
304 search=(fname[0]!='/');
306 /* Build list of files to look for */
307 has_ext=strrchr(fname, '.')>strrchr(fname, '/');
311 files[n]=extl_scat3(fname, ".", ext1);
317 files[n]=extl_scat3(fname, ".", ext2);
323 if(has_ext || !search){
324 files[n]=extl_scopy(fname);
329 /* NOTE for future changes: cfdir must not be scanned first for
330 * user configuration files to take precedence.
333 /* Scan through all possible files */
335 ret2=try_etcpath((const char**)&files, tryfn, tryfnparam);
336 if(ret==EXTL_TRYCONFIG_NOTFOUND)
339 ret=try_dir((const char**)&files, cfdir, tryfn, tryfnparam);
341 ret=try_dir((const char**)&files, NULL, tryfn, tryfnparam);
352 * Lookup script \var{file}. If \var{try_in_dir} is set, it is tried
353 * before the standard search path.
356 char *extl_lookup_script(const char *file, const char *sp)
358 const char *files[]={NULL, NULL};
365 try_dir(files, sp, (ExtlTryConfigFn*)try_lookup, &tmp);
367 try_etcpath(files, (ExtlTryConfigFn*)try_lookup, &tmp);
374 bool extl_read_config(const char *file, const char *sp, bool warn_nx)
384 retval=extl_try_config(file, sp, (ExtlTryConfigFn*)try_call, ¶m,
385 EXTL_COMPILED_EXTENSION, EXTL_EXTENSION);
387 if(retval==EXTL_TRYCONFIG_NOTFOUND && warn_nx)
388 extl_warn(TR("Unable to find '%s' on search path."), file);
390 return (retval==EXTL_TRYCONFIG_OK);
394 bool extl_read_savefile(const char *basename, ExtlTab *tabret)
400 param.tab=extl_table_none();
402 retval=extl_try_config(basename, NULL, (ExtlTryConfigFn*)try_read_savefile,
403 ¶m, EXTL_EXTENSION, NULL);
407 return (retval==EXTL_TRYCONFIG_OK);
414 EXTL_EXPORT_AS(extl, read_savefile)
415 ExtlTab extl_extl_read_savefile(const char *basename)
418 if(!extl_read_savefile(basename, &tab))
419 return extl_table_none();
427 /*{{{ extl_get_savefile */
430 static bool ensuredir(char *f)
436 if(access(f, F_OK)==0)
439 if(mkdir(f, 0700)==0)
444 extl_warn_err_obj(f);
453 if(mkdir(f, 0700)==0)
456 extl_warn_err_obj(f);
462 * Get a file name to save (session) data in. The string \var{basename}
463 * should contain no path or extension components.
466 char *extl_get_savefile(const char *basename)
473 if(!ensuredir(sessiondir)){
474 extl_warn(TR("Unable to create session directory \"%s\"."),
479 libtu_asprintf(&res, "%s/%s." EXTL_EXTENSION, sessiondir, basename);
486 * Write \var{tab} in file with basename \var{basename} in the
490 bool extl_write_savefile(const char *basename, ExtlTab tab)
493 char *fname=extl_get_savefile(basename);
496 ret=extl_serialise(fname, tab);