Logo Search packages:      
Sourcecode: gretl version File versions

gretl_paths.c

/* 
 *  gretl -- Gnu Regression, Econometrics and Time-series Library
 *  Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
 * 
 *  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 3 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, see <http://www.gnu.org/licenses/>.
 * 
 */

/* gretl_paths.c for gretl  */

#include "libgretl.h"
#include "libset.h"
#include "gretl_string_table.h"
#include "gretl_www.h"
#include "texprint.h"
#ifdef USE_RLIB
# include "gretl_foreign.h"
#endif

#include <unistd.h>

#ifdef WIN32
# include <windows.h>
#else
# include <sys/stat.h>
# include <sys/types.h>
# include <dirent.h>
# include <errno.h>
#endif

#include <fcntl.h> /* for 'open' */

#include <glib.h>

#if (GLIB_MAJOR_VERSION > 2 || GLIB_MINOR_VERSION >= 6)
#include <glib/gstdio.h>
#endif

struct INTERNAL_PATHS {
    char dotdir[MAXLEN];
    char workdir[MAXLEN];
    char gnuplot[MAXLEN];
    char plotfile[MAXLEN];
    char libpath[MAXLEN];
    char x12a[MAXLEN];
    char x12adir[MAXLEN];
    char tramo[MAXLEN];
    char tramodir[MAXLEN];
    char rlibpath[MAXLEN];
    char pngfont[128];
    unsigned char status;
};

static struct INTERNAL_PATHS gretl_paths;

static int add_suffix (char *fname, const char *sfx)
{
    if (strrchr(fname, '.') == NULL) {
      strcat(fname, sfx);
      return 1;
    }

    return 0;
}

/* Heuristic: filename contains non-ascii characters, and
   validates as UTF-8 */

int string_is_utf8 (const unsigned char *s)
{
    const unsigned char *p = s;
    int sevenbit = 1;
    int ret = 0;

    while (*p) {
      if (*p > 127) {
          sevenbit = 0;
          break;
      }
      p++;
    }

    if (!sevenbit && g_utf8_validate((gchar *) s, -1, NULL)) {
      ret = 1;
    }

    return ret;
}

static int stdio_use_utf8;

/**
 * set_stdio_use_utf8:
 *
 * Sets gretl's internal state so as to ensure that filenames
 * are given in UTF-8 when passed to functions such as the C 
 * library's fopen().
 */

void set_stdio_use_utf8 (void)
{
    stdio_use_utf8 = 1;
}

/**
 * get_stdio_use_utf8:
 *
 * Returns: 1 if filenames should be in UTF-8 when passed to the C
 * library's fopen() and friends, otherwise 0.
 */

int get_stdio_use_utf8 (void)
{
    return stdio_use_utf8;
}

#define FDEBUG 0

/* Try to handle both possible 'cases of need': we should be using 
   UTF-8 but the path is not in UTF-8, or the path is in UTF-8
   but should be in locale encoding.
*/

static int maybe_recode_path (const char *path, int want_utf8, char **pconv)
{
    int err = 0;

#if FDEBUG
    fprintf(stderr, "maybe_recode_path: want_utf8 = %d\n", want_utf8);
#endif

    if (want_utf8) {
      if (!g_utf8_validate(path, -1, NULL)) {
          /* need to convert from locale to UTF-8 */
          GError *gerr = NULL;
          gsize sz;
          
          *pconv = g_locale_to_utf8(path, -1, NULL, &sz, &gerr);
          if (*pconv == NULL) {
            if (gerr != NULL) {
                gretl_errmsg_set(gerr->message);
                g_error_free(gerr);
            }
            err = 1;
          }
      }
    } else if (string_is_utf8((unsigned char *) path)) {
      /* need to convert from UTF-8 to locale */
      GError *gerr = NULL;
      gsize sz;

      *pconv = g_locale_from_utf8(path, -1, NULL, &sz, &gerr);
      if (*pconv == NULL) {
          if (gerr != NULL) {
            gretl_errmsg_set(gerr->message);
            g_error_free(gerr);
          }
          err = 1;
      }     
    }     

    return err;
}

/**
 * gretl_fopen:
 * @fname: name of file to be opened.
 * @mode: mode in which to open the file.
 *
 * A wrapper for  the C library's fopen(), making allowance for
 * the possibility that @fname has to be converted from
 * UTF-8 to the locale encoding or vice versa.
 *
 * Returns: file pointer, or %NULL on failure.
 */

FILE *gretl_fopen (const char *fname, const char *mode)
{
    gchar *fconv = NULL;
    FILE *fp = NULL;
    int err;

    gretl_error_clear();

#if FDEBUG
    fprintf(stderr, "gretl_fopen: got '%s'\n", fname);
#endif

    err = maybe_recode_path(fname, stdio_use_utf8, &fconv);

    if (!err) {
      if (fconv != NULL) {
          fp = fopen(fconv, mode);
#if FDEBUG
            fprintf(stderr, "using fconv, fp = %p\n", (void *) fp);
#endif
          g_free(fconv);
      } else {
          fp = fopen(fname, mode);
      }
    }

#if FDEBUG
    fprintf(stderr, "after fopen, errno = %d\n", errno);
#endif

    if (errno != 0) {
      gretl_errmsg_set_from_errno(fname);
    }

    return fp;
}

/**
 * gretl_open:
 * @pathname: name of file to be opened.
 * @flags: flags to pass to the system open().
 *
 * A wrapper for the C library's open(), making allowance for
 * the possibility that @pathname has to be converted from
 * UTF-8 to the locale encoding or vice versa.
 *
 * Returns: new file descriptor, or -1 on error.
 */

int gretl_open (const char *pathname, int flags)
{
    gchar *pconv = NULL;
    int fd = -1;
    int err = 0;

    gretl_error_clear();

    err = maybe_recode_path(pathname, stdio_use_utf8, &pconv);

    if (!err) {
      if (pconv != NULL) {
          fd = open(pconv, flags);
          g_free(pconv);
      } else {
          fd = open(pathname, flags);
      }
    }

    if (errno != 0) {
      gretl_errmsg_set_from_errno(pathname);
    }

    return fd;
}

/**
 * gretl_stat:
 * @fname: name of file to be examined.
 * @buf: pointer to %struct %stat.
 *
 * A wrapper for the C library's stat(), making allowance for
 * the possibility that @fname has to be converted from UTF-8 
 * to the locale encoding or vice versa.
 *
 * Returns: 0 on success, non-zero on failure.
 */

int gretl_stat (const char *fname, struct stat *buf)
{
    gchar *pconv = NULL;
    int err;

    gretl_error_clear();

    err = maybe_recode_path(fname, stdio_use_utf8, &pconv);
    
    if (err) {
      /* emulate 'stat' */
      err = -1;
    } else {
      if (pconv != NULL) {
            err = stat(pconv, buf);
          g_free(pconv);
      } else {
            err = stat(fname, buf);
      }
    }

    return err;
}

/**
 * gretl_rename:
 * @oldpath: name of file to be opened.
 * @newpath: new name to give the file.
 *
 * A wrapper for the C library's rename(), making allowance for
 * the possibility that @oldpath and/or @newpath have to be 
 * converted from UTF-8 to the locale encoding or vice versa.
 *
 * Returns: 0 on success, non-zero on failure.
 */

int gretl_rename (const char *oldpath, const char *newpath)
{
    gchar *oldconv = NULL, *newconv = NULL;
    int err;

    gretl_error_clear();

    err = maybe_recode_path(oldpath, stdio_use_utf8, &oldconv);

    if (!err) {
      err = maybe_recode_path(newpath, stdio_use_utf8, &newconv);
    }

    if (!err) {
      if (oldconv == NULL && newconv == NULL) {
          err = rename(oldpath, newpath);
      } else if (oldconv != NULL && newconv != NULL) {
          err = rename(oldconv, newconv);
      } else if (oldconv != NULL) {
          err = rename(oldconv, newpath);
      } else if (newconv != NULL) {
          err = rename(oldpath, newconv);
      }
    }

    if (oldconv != NULL || newconv != NULL) {
      g_free(oldconv);
      g_free(newconv);
    }

    if (errno != 0) {
      gretl_errmsg_set_from_errno("gretl_rename");
    }

    return err;
}

/**
 * gretl_remove:
 * @path: name of file or directory to remove.
 *
 * A wrapper for remove(), making allowance for
 * the possibility that @path has to be converted from
 * UTF-8 to the locale encoding or vice versa.
 *
 * Returns: 0 on sucess, non-zero on failure.
 */

int gretl_remove (const char *path)
{
    gchar *pconv = NULL;
    int ret = -1;
    int err;

    err = maybe_recode_path(path, stdio_use_utf8, &pconv);

    if (!err) {
      if (pconv != NULL) {
          ret = remove(pconv);
          g_free(pconv);
      } else {
          ret = remove(path);
      }
    }

#ifdef WIN32
    /* allow for the possibility that we're trying to remove a
       directory on win32 -> use g_remove */
    if (ret == -1) {
      err = maybe_recode_path(path, 1, &pconv);
      if (!err) {
          if (pconv != NULL) {
            ret = g_remove(pconv);
            g_free(pconv);
          } else {
            ret = g_remove(path);
          }
      }         
    }
#endif

    return ret;
}

/**
 * gretl_gzopen:
 * @fname: name of gzipped file to be opened.
 * @mode: mode in which to open the file.
 *
 * A wrapper for zlib's gzopen(), making allowance for
 * the possibility that @fname has to be converted from
 * UTF-8 to the locale encoding or vice versa. 
 *
 * Returns: pointer to gzip stream, or %NULL on failure.
 */

gzFile gretl_gzopen (const char *fname, const char *mode)
{
    gchar *fconv = NULL;
    gzFile fz = NULL;
    int err;

    gretl_error_clear();

    err = maybe_recode_path(fname, stdio_use_utf8, &fconv);

    if (!err) {
      if (fconv != NULL) {
          fz = gzopen(fconv, mode);
          g_free(fconv);
      } else {
          fz = gzopen(fname, mode);
      }
    }

    if (errno != 0) {
      gretl_errmsg_set_from_errno("gzopen");
    }

    return fz;
}

/**
 * gretl_chdir:
 * @path: name of directory.
 *
 * A wrapper for POSIX chdir(), making allowance for
 * the possibility that @path has to be converted from
 * UTF-8 to the locale encoding or vice versa.
 *
 * Returns: 0 on sucess, non-zero on failure.
 */

int gretl_chdir (const char *path)
{
    gchar *pconv = NULL;
    int err;

    gretl_error_clear();

    err = maybe_recode_path(path, stdio_use_utf8, &pconv);

    if (!err) {
      if (pconv != NULL) {
          err = chdir(pconv);
          g_free(pconv);
      } else {
          err = chdir(path);
      }
    }

    if (errno != 0) {
      gretl_errmsg_set_from_errno("chdir");
    }
    
    return err;
}

/**
 * gretl_isdir:
 * @path: path to check.
 *
 * A test for whether or not @path is the name of a directory,
 * allowing for the possibility that @path has to be converted 
 * from UTF-8 to the locale encoding or vice versa.
 *
 * Returns: 1 if @path is the name of a directory, else 0.
 */

int gretl_isdir (const char *path)
{
    struct stat buf;
    int err;

    err = gretl_stat(path, &buf);

    return (err)? 0 : S_ISDIR(buf.st_mode);
}

#ifdef WIN32

int gretl_mkdir (const char *path)
{
    gchar *pconv = NULL;
    DIR *test;
    int done = 0;

    if (string_is_utf8((unsigned char *) path)) {
      gsize wrote;

      pconv = g_locale_from_utf8(path, -1, NULL, &wrote, NULL);
    }

    if (pconv != NULL) {
      test = win32_opendir(pconv);
      if (test != NULL) {
          closedir(test);
          done = 1;
      } else {
          done = CreateDirectory(pconv, NULL);
      }
      g_free(pconv);
    } else {
      test = win32_opendir(path);
      if (test != NULL) {
          closedir(test);
          done = 1;
      } else {
          done = CreateDirectory(path, NULL);
      }
    }
    
    return !done;
}

/**
 * gretl_mkstemp:
 * @tmpl: template filename.
 *
 * Returns: A file handle (as from open()) to the file opened for 
 * reading and writing, or -1 on failure.
 */

int gretl_mkstemp (char *tmpl)
{
    int fd = -1;

    if (!g_utf8_validate(tmpl, -1, NULL)) {
      /* g_mkstemp requires UTF-8 input */
      gchar *pconv;
      gsize bytes;

      pconv = g_locale_to_utf8(tmpl, -1, NULL, &bytes, NULL);
      if (pconv != NULL) {
          strcpy(tmpl, pconv);
          fd = g_mkstemp(tmpl);
          g_free(pconv);
          pconv = g_locale_from_utf8(tmpl, -1, NULL, &bytes, NULL);
          if (pconv != NULL) {
            strcpy(tmpl, pconv);
            g_free(pconv);
          }
      }     
    } else {
      fd = g_mkstemp(tmpl);
    }

    return fd;
}

#else /* !win32 */

/**
 * gretl_mkdir:
 * @path: name of directory to be created.
 *
 * Calls the underlying library function to create the
 * specified directory with mode 0755.  If the directory in
 * question already exists, this does not count as an error.
 *
 * Returns: 0 on success, non-zero on error.
 */

int gretl_mkdir (const char *path)
{
    int err = 0;
    extern int errno;

    errno = 0;

    if (mkdir(path, 0755)) {
      if (errno != EEXIST) { 
          fprintf(stderr, "%s: %s\n", path, strerror(errno));
          err = 1;
      }
    }

    return err;
}

static const char *gretl_readd (DIR *d)
{
    struct dirent *e = readdir(d);

    return (e == NULL)? NULL : e->d_name;
}

/* recursive deletion of directory tree: must be located
   in the directory above the one to be deleted at the
   outset */

/**
 * gretl_deltree:
 * @path: name of directory to be deleted.
 *
 * Carries out recursive deletion of the specified directory.
 * Note: the current working directory should be set to one
 * level above @path when this function is called. FIXME.
 *
 * Returns: 0 on success, non-zero on error.
 */

int gretl_deltree (const char *path)
{
    const char *fname;
    DIR *dir;
    int err = 0;

    errno = 0;

    dir = opendir(path);

    if (dir == NULL) {
      err = 1;
    } else {
      err = chdir(path);
      while ((fname = gretl_readd(dir)) != NULL && !err) {
          if (strcmp(fname, ".") && strcmp(fname, "..")) {
            if (gretl_isdir(fname)) {
                err = gretl_deltree(fname);
            } else {
                err = gretl_remove(fname);
            }
          }
      }
      if (!err) {
          closedir(dir);
          chdir("..");
          err = gretl_remove(path);
      }
    }

    if (err) {
      gretl_errmsg_set_from_errno(path);
      err = E_FOPEN;
    }
    
    return err;
}

#endif /* WIN32 or not */

/**
 * gretl_setenv:
 * @name: name of variable to be set.
 * @value: value to set.
 *
 * Cross-platform wrapper for setenv().
 *
 * Returns: 0 on success, non-zero on failure.
 */

int gretl_setenv (const char *name, const char *value)
{
#ifdef WIN32
    char estr[1024];
    int ok;

    /* belt and braces */
    if (strlen(name) + strlen(value) + 1 < 1024) {
      sprintf(estr, "%s=%s", name, value);
      putenv(estr);
    }

    ok = SetEnvironmentVariable(name, value);

    return !ok;
#else
    return setenv(name, value, 1);
#endif
}

/**
 * gretl_write_access:
 * @fname: name of file to test.
 *
 * Returns: 0 on success (meaning that the current user has
 * write access to @fname), non-zero on failure.
 */

int gretl_write_access (char *fname)
{
    gchar *fconv = NULL;
    int err;

    gretl_error_clear();

    err = maybe_recode_path(fname, stdio_use_utf8, &fconv);
    if (err) {
      return err;
    }

    if (fconv != NULL) {
#ifdef WIN32
      err = !win32_write_access(fconv);
#else
      err = access(fconv, W_OK);
#endif
      g_free(fconv);
    } else {
#ifdef WIN32
      err = !win32_write_access(fname);
#else
      err = access(fname, W_OK);
#endif
    }

#ifndef WIN32
    if (errno != 0) {
      gretl_errmsg_set_from_errno(fname);
    }
#endif

    return err;
}

/**
 * gretl_is_xml_file:
 * @fname: name of file to test.
 *
 * Returns: 1 if @fname appears to be a (possibly gzipped) XML file,
 * otherwise 0.
 */

int gretl_is_xml_file (const char *fname)
{
    gzFile fz;
    char test[6];
    int ret = 0;

    fz = gretl_gzopen(fname, "rb");
    if (fz != Z_NULL) {
      if (gzread(fz, test, 5)) {
          test[5] = '\0';
          if (!strcmp(test, "<?xml")) ret = 1;
      } 
      gzclose(fz);
    } 

    return ret;
} 

/**
 * gretl_path_prepend:
 * @file: target filename.
 * @path: path to prepend.
 *
 * Creates a path string by prepending @path, plus an appropriate
 * separator if needed, to @file.  The result is written back into
 * @file: this variable is assumed to have storage for at least
 * #MAXLEN characters.
 *
 * Returns: 0 on success, or 1 if the final path string would
 * exceed #MAXLEN characters (including nul-termination).
 */

int gretl_path_prepend (char *file, const char *path)
{
    char temp[MAXLEN];
    int n = strlen(file) + strlen(path) + 1;

    if (n > MAXLEN) {
      return 1;
    }

    strcpy(temp, path);
    n = strlen(temp);

    if (temp[n-1] != SLASH && n < MAXLEN - 1) {
      strcat(temp, SLASHSTR);
    }

    strcat(temp, file);
    strcpy(file, temp);

    return 0;
}

#ifdef WIN32

static int try_open_file (char *targ, const char *finddir, 
                    WIN32_FIND_DATA *fdata, int code)
{
    FILE *fp = NULL;
    char tmp[MAXLEN];
    int n = strlen(finddir);
    int found = 0;
    
    strcpy(tmp, finddir);
    tmp[n-1] = '\0';
    strcat(tmp, fdata->cFileName);
    strcat(tmp, "\\");
    strcat(tmp, targ);

    fp = gretl_fopen(tmp, "r");
    if (fp == NULL && code == DATA_SEARCH) {
      if (add_suffix(tmp, ".gdt")) {
          fp = gretl_fopen(tmp, "r");
      }
    }

    if (fp != NULL) {
      fclose(fp);
      strcpy(targ, tmp);
      found = 1;
    } 

    return found;
}

static void make_findname (char *targ, const char *src)
{
    strcpy(targ, src);

    if (string_is_utf8(targ)) {
      gchar *tmp;
      gsize sz;
      
      tmp = g_locale_from_utf8(src, -1, NULL, &sz, NULL);
      if (tmp != NULL) {
          strcpy(targ, tmp);
          g_free(tmp);
      }
    }

    if (targ[strlen(targ)-1] != '\\') {
      strcat(targ, "\\*");
    } else {
      strcat(targ, "*");
    }
}

static int got_subdir (WIN32_FIND_DATA *fdata)
{
    int ret = 0;

    if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
      if (strcmp(fdata->cFileName, ".") &&
          strcmp(fdata->cFileName, "..")) {
          ret = 1;
      }
    }

    return ret;
}

static int find_in_subdir (const char *topdir, char *fname, int code)
{
    HANDLE handle;
    WIN32_FIND_DATA fdata;
    char finddir[MAXLEN];
    int found = 0;

    /* make find target */
    make_findname(finddir, topdir);

    handle = FindFirstFile(finddir, &fdata); 
    if (handle != INVALID_HANDLE_VALUE) {
      if (got_subdir(&fdata)) {
          found = try_open_file(fname, finddir, &fdata, code);
      } 
      while (!found && FindNextFile(handle, &fdata)) {
          if (got_subdir(&fdata)) {
            found = try_open_file(fname, finddir, &fdata, code);
          }
      } 
      FindClose(handle);
    }

    return found;
}

#else /* end of win32 file-finding, on to posix */

static int try_open_file (char *targ, const char *finddir, 
                    struct dirent *dirent, int code)
{
    FILE *fp = NULL;
    char tmp[MAXLEN];
    int found = 0;
    
    strcpy(tmp, finddir);
    strcat(tmp, dirent->d_name);
    strcat(tmp, "/");
    strcat(tmp, targ);

    fp = gretl_fopen(tmp, "r");
    if (fp == NULL && code == DATA_SEARCH) {
      if (add_suffix(tmp, ".gdt")) {
          fp = gretl_fopen(tmp, "r");
      }
    }

    if (fp != NULL) {
      fclose(fp);
      strcpy(targ, tmp);
      found = 1;
    } 

    return found;
}

static void make_findname (char *targ, const char *src)
{
    int n = strlen(src);

    strcpy(targ, src);

    if (targ[n-1] != '/') {
      strcat(targ, "/");
    } 
}

static int got_subdir (const char *topdir, struct dirent *dirent)
{
    int ret = 0;

    if (strcmp(dirent->d_name, ".") && strcmp(dirent->d_name, "..")) {
      char tmp[MAXLEN];
      DIR *sub;

      strcpy(tmp, topdir);
      strcat(tmp, dirent->d_name);
      sub = opendir(tmp);
      if (sub != NULL) {
          closedir(sub);
          ret = 1;
      }
    }

    return ret;
}

static int find_in_subdir (const char *topdir, char *fname, int code)
{
    DIR *dir;
    struct dirent *dirent;
    char finddir[MAXLEN];
    int found = 0;

    /* make find target */
    make_findname(finddir, topdir);

    dir = opendir(finddir);
    if (dir != NULL) {
      while (!found && (dirent = readdir(dir))) {
          if (got_subdir(finddir, dirent)) {
            found = try_open_file(fname, finddir, dirent, code);
          }
      }
      closedir(dir);
    }

    return found;
}

#endif /* win32 vs posix */

static char *search_dir (char *fname, const char *topdir, int code)
{
    FILE *test;
    char orig[MAXLEN];

    strcpy(orig, fname);

    if (gretl_path_prepend(fname, topdir) == 0) {
      test = gretl_fopen(fname, "r");
      if (test != NULL) {
          fclose(test);
          return fname;
      }
      if (code == DATA_SEARCH && add_suffix(fname, ".gdt")) {
          test = gretl_fopen(fname, "r");
          if (test != NULL) {
            fclose(test);
            return fname;
          }
      } else if (code == FUNCS_SEARCH && add_suffix(fname, ".gfn")) {
          test = gretl_fopen(fname, "r");
          if (test != NULL) {
            fclose(test);
            return fname;
          }
      }         
      strcpy(fname, orig);
      if (code != CURRENT_DIR && find_in_subdir(topdir, fname, code)) {
          return fname;
      }
    }

    return NULL;
}

#ifdef WIN32
# define fslash(c) (c == '/' || c == '\\')
#else
# define fslash(c) (c == '/')
#endif

static int dotpath (const char *fname)
{
    if (fname[0] == '.') {
      if (fslash(fname[1])) {
          return 1;
      } else if (fname[1] == '.' && fslash(fname[2])) {
          return 1;
      }
    }

    return 0;
}

static char *fname_strstr (char *fname, char *dname)
{
#ifdef WIN32
    char lfname[MAXLEN], ldname[MAXLEN];

    *lfname = *ldname = '\0';
    strncat(lfname, fname, MAXLEN - 1);
    strncat(ldname, dname, MAXLEN - 1);
    lower(lfname);
    lower(ldname);
    return strstr(lfname, ldname);
#else
    return strstr(fname, dname);
#endif
}

int fname_has_path (const char *fname)
{
    return g_path_is_absolute(fname) || dotpath(fname);
}

static void real_make_path_absolute (char *targ, const char *src,
                             const char *dirname)
{
    int offset = 0;

    strcpy(targ, dirname);
    trim_slash(targ);
    strcat(targ, SLASHSTR);
    if (*src == '.' && src[1] == SLASH && strlen(src) > 2) {
      offset = 2;
    }
    strcat(targ, src + offset);
}

static void make_path_absolute (char *fname, const char *orig)
{
    char thisdir[MAXLEN];

    if (getcwd(thisdir, MAXLEN - 1) != NULL) {
      if (fname_strstr(fname, thisdir) == NULL) {
          real_make_path_absolute(fname, orig, thisdir);
      }
    }
}

/* When given a filename such as "./foo", see if shelldir is
   set -- if so, try opening the file as if shelldir was
   the CWD.
*/

static int shelldir_open_dotfile (char *fname, char *orig)
{
    char *sdir = get_shelldir();
    FILE *test;
    int ret = 0;

    if (sdir != NULL && *sdir != '\0') {
      real_make_path_absolute(fname, orig, sdir);
      test = gretl_fopen(fname, "r");
      if (test != NULL) {
          fclose(test);
          ret = 1;
      } else {
          strcpy(fname, orig);
      }
    }

    return ret;
}

/**
 * addpath:
 * @fname: initially given file name.
 * @ppaths: path information struct.
 * @script: if non-zero, suppose the file is a command script.
 * 
 * Elementary path-searching: try adding various paths to the given
 * @fname and see if it can be opened.  Usually called by getopenfile().
 *
 * Returns: the full name of the file that was found, or %NULL if no
 * file could be found.
 */

char *addpath (char *fname, PATHS *ppaths, int script)
{
    char orig[MAXLEN];
    char *tmp = fname;
    FILE *test;

    strcpy(orig, fname);

    if (dotpath(fname) && shelldir_open_dotfile(fname, orig)) {
      return fname;
    }  

    if (!g_path_is_absolute(orig) && has_suffix(orig, ".gfn")) {
      /* new as of 2009-08-27, AC */
      const char *gfnpath = get_include_path();

      if (gfnpath != NULL) {
          sprintf(fname, "%s%s", gfnpath, orig);
          return fname;
      }
    }

    /* try opening filename as given */
    test = gretl_fopen(fname, "r");
    if (test != NULL) { 
      fclose(test); 
      if (!fname_has_path(fname)) {
          make_path_absolute(fname, orig);
      }
      return fname;
    } else if (g_path_is_absolute(fname)) {  
      /* unable to open file as given: if the path was absolute, fail */
      return NULL;
    }

    if (ppaths != NULL) {
      char trydir[MAXLEN];

      /* try looking where script was found */
      if (*ppaths->currdir != '\0') {
          if ((fname = search_dir(fname, ppaths->currdir, CURRENT_DIR))) {
            return fname;
          }
      }

      fname = tmp;
      strcpy(fname, orig);

      if (script) {
          sprintf(trydir, "%sscripts", ppaths->gretldir);
          if ((fname = search_dir(fname, trydir, SCRIPT_SEARCH))) { 
            return fname;
          } else {
            fname = tmp;
            strcpy(fname, orig);
            sprintf(trydir, "%sfunctions", ppaths->gretldir);
            if ((fname = search_dir(fname, trydir, FUNCS_SEARCH))) { 
                return fname;
            }
          }
      } else {
          /* data file */
          sprintf(trydir, "%sdata", ppaths->gretldir);
          if ((fname = search_dir(fname, trydir, DATA_SEARCH))) { 
            return fname;
          }
      } 
    }

    /* or try looking in user's dir (and subdirs) */
    fname = tmp;
    strcpy(fname, orig);
    if ((fname = search_dir(fname, gretl_work_dir(), USER_SEARCH))) { 
      return fname;
    }

    /* try looking in default workdir? */
    if (ppaths != NULL) {
      char *dwork = gretl_default_workdir(ppaths);

      if (dwork != NULL) {
          int ok = 0;

          fname = tmp;
          strcpy(fname, orig);
          if ((fname = search_dir(fname, dwork, USER_SEARCH))) { 
            ok = 1;
          }
          free(dwork);
          if (ok) {
            return fname;
          }
      }
    }

#ifdef WIN32
    /* try looking on the desktop? */
    if (1) {
      char *dtdir = desktop_path();
      char *ret = NULL;

      fname = tmp;
      strcpy(fname, orig);

      if (dtdir != NULL) {
          ret = search_dir(fname, dtdir, CURRENT_DIR);
          free(dtdir);
      }
      if (ret != NULL) {
          return ret;
      }
    }     
#endif

    fname = tmp;
    strcpy(fname, orig);

    gretl_error_clear();

    return NULL;
}

static int get_quoted_filename (const char *s, char *fname)
{
    int ret = 0;

    if (*s == '"' || *s == '\'') {
      const char *p = strchr(s + 1, *s);

      if (p != NULL) {
          size_t len = p - s;

          if (len > 0) {
            *fname = 0;
            strncat(fname, s+1, len-1);
            ret = 1;
          } 
      }
    }

    return ret;
}

static int substitute_homedir (char *fname)
{
    char *homedir = getenv("HOME");
    int err = 0;

    if (homedir != NULL) {
      int len = strlen(fname);
      int homelen = strlen(homedir);

      if (len + homelen > MAXLEN) {
          err = 1;
      } else {
          char tmp[MAXLEN];

          strcpy(tmp, homedir);
          strcat(tmp, fname + 1);
          strcpy(fname, tmp);
      }
    }

    return err;
}

/**
 * getopenfile:
 * @line: command line (e.g. "open foo").
 * @fname: filename to be filled out.
 * @ppaths: pointer to paths information struct.
 * @opt: if includes %OPT_W, treat as web filename and don't
 * try to add path, if %OPT_S, treat as a script.
 * 
 * Elementary path-searching: try adding various paths to the given
 * @fname and see if it can be opened.
 *
 * Returns: 0 on successful parsing of @line, 1 on error.
 */

int getopenfile (const char *line, char *fname, PATHS *ppaths,
             gretlopt opt)
{
    int script = (opt & OPT_S)? 1 : 0;
    char *fullname;

    /* skip past command word */
    line += strcspn(line, " ");
    line += strspn(line, " ");

    if (get_quoted_filename(line, fname)) {
      /* if the filename was quoted, leave it as is */
      return 0; 
    }

    if (sscanf(line, "%s", fname) != 1) {
      return E_PARSE;
    }

    if (opt & OPT_W) {
      return 0;
    }

    /* handle tilde == HOME */
    if (fname[0] == '~' && fname[1] == '/') {
      substitute_homedir(fname);
    }

    if (g_path_is_absolute(fname)) {
      return 0;
    }

    /* try a basic path search on this filename */
    fullname = addpath(fname, ppaths, script);

    if (ppaths != NULL && fullname != NULL && script) {
      int spos = slashpos(fname);

      if (spos) {
          *ppaths->currdir = '\0';
          strncat(ppaths->currdir, fname, spos + 1);
      } else {
          ppaths->currdir[0] = '.';
          ppaths->currdir[1] = SLASH;
          ppaths->currdir[2] = '\0';
      }
    }

    return 0;
}

int has_system_prefix (const char *fname, const PATHS *ppaths, 
                   int locus)
{
    int n = strlen(ppaths->gretldir);
    int ret = 0;

    if (strlen(fname) < n) return 0;
    
    if (!strncmp(fname, ppaths->gretldir, n)) {
      if (locus == DATA_SEARCH &&
          !strncmp(fname + n, "data", 4)) {
          ret = 1;
      } else if (locus == SCRIPT_SEARCH &&
               !strncmp(fname + n, "scripts", 7)) { 
          ret = 1;
      }
    }

    return ret;
}

enum paths_status_flags {
    STRING_TABLE_WRITTEN = 1 << 0
};

static void set_gretl_libpath (const char *path)
{
#ifdef WIN32
    strcpy(gretl_paths.libpath, path);
#else
    const char *sfx = "-gtk2/";
    char *p = strstr(path, "/share");

    if (p) {
      size_t len = p - path;

      *gretl_paths.libpath = 0;
      strncat(gretl_paths.libpath, path, len);
      strcat(gretl_paths.libpath, "/lib/gretl");
      strcat(gretl_paths.libpath, sfx);
    } else {
      sprintf(gretl_paths.libpath, "%s/lib/gretl%s", path, sfx);
    }
#endif /* !WIN32 */
}

#if defined(HAVE_X12A) || defined(HAVE_TRAMO)

static int set_tramo_x12a_dirs (PATHS *ppaths, int baddir)
{
    char dirname[MAXLEN];
    size_t n;
    int err = 0;

    if (baddir) {
# ifdef HAVE_TRAMO
      *ppaths->tramodir = '\0';
# endif
# ifdef HAVE_X12A
      *ppaths->x12adir = '\0';
# endif
      return baddir;
    }

    strcpy(dirname, ppaths->dotdir);
    n = strlen(dirname);

    if (n > 0 && (dirname[n-1] == '\\' || dirname[n-1] == '/')) {
      dirname[n-1] = '\0';
    }

# ifdef HAVE_X12A
    build_path(ppaths->x12adir, ppaths->dotdir, "x12arima", NULL);
    err = gretl_mkdir(ppaths->x12adir);
    if (err) {
      *ppaths->x12adir = '\0';
    }
# endif

# ifdef HAVE_TRAMO
    build_path(ppaths->tramodir, ppaths->dotdir, "tramo", NULL);
    if (gretl_mkdir(ppaths->tramodir)) {
      *ppaths->tramodir = '\0';
      return E_FOPEN;
    }

    sprintf(dirname, "%s%coutput", ppaths->tramodir, SLASH);
    gretl_mkdir(dirname);

    sprintf(dirname, "%s%cgraph", ppaths->tramodir, SLASH);
    if (gretl_mkdir(dirname)) {
      *ppaths->tramodir = '\0';
      return E_FOPEN;
    }

    sprintf(dirname, "%s%cgraph%cacf", ppaths->tramodir, SLASH, SLASH);
    gretl_mkdir(dirname);
    sprintf(dirname, "%s%cgraph%cfilters", ppaths->tramodir, SLASH, SLASH);
    gretl_mkdir(dirname);
    sprintf(dirname, "%s%cgraph%cforecast", ppaths->tramodir, SLASH, SLASH);
    gretl_mkdir(dirname);
    sprintf(dirname, "%s%cgraph%cseries", ppaths->tramodir, SLASH, SLASH);
    gretl_mkdir(dirname);
    sprintf(dirname, "%s%cgraph%cspectra", ppaths->tramodir, SLASH, SLASH);
    gretl_mkdir(dirname);
# endif

    return err;
}

#endif /* x12a || tramo */

static void copy_paths_to_internal (PATHS *paths)
{
    strcpy(gretl_paths.dotdir,   paths->dotdir);
    strcpy(gretl_paths.workdir,  paths->workdir);
    strcpy(gretl_paths.gnuplot,  paths->gnuplot);
    strcpy(gretl_paths.x12a,     paths->x12a);
    strcpy(gretl_paths.x12adir,  paths->x12adir);
    strcpy(gretl_paths.tramo,    paths->tramo);
    strcpy(gretl_paths.tramodir, paths->tramodir);
    strcpy(gretl_paths.pngfont,  paths->pngfont);

#ifdef USE_RLIB
    if (strcmp(paths->rlibpath, gretl_paths.rlibpath)) {
      strcpy(gretl_paths.rlibpath, paths->rlibpath);
      gretl_R_reset_error();
    }
#endif

    gretl_insert_builtin_string("gretldir", paths->gretldir);
    gretl_insert_builtin_string("dotdir",   paths->dotdir);
    gretl_insert_builtin_string("workdir",  paths->workdir);
    gretl_insert_builtin_string("gnuplot",  paths->gnuplot);
    gretl_insert_builtin_string("x12a",     paths->x12a);
    gretl_insert_builtin_string("x12adir",  paths->x12adir);
    gretl_insert_builtin_string("tramo",    paths->tramo);
    gretl_insert_builtin_string("tramodir", paths->tramodir);

    if (*paths->tramo) {
      char s[MAXLEN];
      int n;

      *s = '\0';
      strncat(s, paths->tramo, MAXLEN - 1);
      n = strlen(s);
#ifdef WIN32
      if (n >= 9 && !strcmp(s + n - 9, "tramo.exe")) {
          strcpy(s + n - 9, "seats.exe");
          gretl_insert_builtin_string("seats", s);
          return;
      }
#endif
      if (n >= 5 && !strcmp(s + n - 5, "tramo")) {
          strcpy(s + n - 5, "seats");
          gretl_insert_builtin_string("seats", s);
      }
    }
}

const char *gretl_lib_path (void)
{
    static int set;

    if (!set) {
      char *epath = getenv("GRETL_PLUGIN_PATH");

      if (epath != NULL) {
          gretl_paths.libpath[0] = '\0';
          strncat(gretl_paths.libpath, epath, MAXLEN - 1);
      }
      set = 1;
    }

    return gretl_paths.libpath;
}

const char *gretl_dot_dir (void)
{
    return gretl_paths.dotdir;
}

const char *gretl_work_dir (void)
{
    return gretl_paths.workdir;
}

#ifdef WIN32

static void correct_blank_dotdir (PATHS *paths)
{
    char *base = appdata_path();

    if (base != NULL) {
      sprintf(paths->dotdir, "%s\\gretl\\", base);
      free(base);
    } 
}

/* if the default workdir is a valid directory, and
   not equal to the current workdir, return the path
   to it
*/

char *gretl_default_workdir (PATHS *paths)
{
    char *base = mydocs_path();
    char *ret = NULL;
    int ok = 0;

    if (base != NULL) {
      ret = g_strdup_printf("%s\\gretl\\", base);
      if (strcmp(ret, paths->workdir)) {
          DIR *dir = win32_opendir(ret);

          if (dir != NULL) {
            closedir(dir);
            ok = 1;
          }
      }
      free(base);
    }

    if (ret && !ok) {
      free(ret);
      ret = NULL;
    }

    return ret;
}

static void correct_blank_workdir (PATHS *paths)
{
    char *base = mydocs_path();

    if (base != NULL) {
      sprintf(paths->workdir, "%s\\gretl\\", base);
      free(base);
    } 
}

#else

static void correct_blank_dotdir (char *path)
{
    char *home = getenv("HOME");

    if (home != NULL) {
      sprintf(path, "%s/.gretl/", home);
    } 
}

char *gretl_default_workdir (PATHS *paths)
{
    char *home = getenv("HOME");
    char *ret = NULL;
    int ok = 0;

    if (home != NULL) {
      ret = g_strdup_printf("%s/gretl/", home);
      if (strcmp(ret, paths->workdir)) {
          DIR *dir = opendir(ret);

          if (dir != NULL) {
            closedir(dir);
            ok = 1;
          }
      }
    }

    if (ret && !ok) {
      free(ret);
      ret = NULL;
    }

    return ret;
}

static void correct_blank_workdir (char *path)
{
    char *home = getenv("HOME");

    if (home != NULL) {
      sprintf(path, "%s/gretl/", home);
    } 
}

#endif

static int validate_writedir (const char *dirname)
{
    int err = 0;

    if (*dirname == '\0') {
      strcpy(gretl_errmsg, _("User directory is not set"));
      return E_DATA;
    }

    err = gretl_mkdir(dirname);
    if (err) {
      sprintf(gretl_errmsg, _("Couldn't create directory '%s'"), dirname);
    }

    if (!err) {
      /* ensure the directory is writable */
      char *testname;
      FILE *fp;

      testname = g_strdup_printf("%s%cwrite.chk", dirname, SLASH);
      if (testname != NULL) {
          fp = gretl_fopen(testname, "w");
          if (fp == NULL) {
            sprintf(gretl_errmsg, _("Couldn't write to '%s': "
                              "gretl will not work properly!"), 
                  dirname);
            err = 1;
          } else {
            fclose(fp);
            gretl_remove(testname);
          }
          g_free(testname);
      }
    }

    return err;
}

int set_gretl_work_dir (const char *path, PATHS *ppaths)
{
    DIR *test;

    errno = 0;

#ifdef WIN32
    test = win32_opendir(path);
#else
    test = opendir(path);
#endif
    if (test == NULL) {
      gretl_errmsg_set_from_errno(path);
      return E_FOPEN;
    } 

    closedir(test);

    if (path != ppaths->workdir) {
      strcpy(ppaths->workdir, path);
      ensure_slash(ppaths->workdir);
      strcpy(gretl_paths.workdir, ppaths->workdir);
      gretl_insert_builtin_string("workdir", ppaths->workdir);
    }

    return 0;
}

const char *gretl_gnuplot_path (void)
{
    return gretl_paths.gnuplot;
}

const char *gretl_plotfile (void)
{
    return gretl_paths.plotfile;
}

char *set_gretl_plotfile (const char *fname)
{
    *gretl_paths.plotfile = 0;
    strncat(gretl_paths.plotfile, fname, MAXLEN - 1);

    return gretl_paths.plotfile;
}

const char *gretl_tramo (void)
{
    return gretl_paths.tramo;
}

const char *gretl_tramo_dir (void)
{
    return gretl_paths.tramodir;
}

const char *gretl_x12_arima (void)
{
    return gretl_paths.x12a;
}

const char *gretl_x12_arima_dir (void)
{
    return gretl_paths.x12adir;
}

const char *gretl_rlib_path (void)
{
    return gretl_paths.rlibpath;
}

const char *gretl_png_font (void)
{
    return gretl_paths.pngfont;
}

void set_gretl_png_font (const char *s, PATHS *ppaths)
{
    strcpy(gretl_paths.pngfont, s);
    strcpy(ppaths->pngfont, s);
}

static char ox_path[MAXLEN];

#ifdef USE_OX
static void set_default_ox_path (char *s)
{
    if (s == NULL) {
      s = ox_path;
    }

# ifdef WIN32
    sprintf(s, "%s\\OxMetrics5\\Ox\\bin\\oxl.exe", program_files_path());
# else
    strcpy(s, "oxl");
# endif
}
#else
static void set_default_ox_path (char *s)
{
    return;
}
#endif

const char *gretl_ox_path (void)
{
    if (*ox_path == '\0') {
      set_default_ox_path(ox_path);
    }
    
    return ox_path;
}

void set_gretl_ox_path (char *path)
{
    if (*path != '\0') {
      *ox_path = '\0';
      strncat(ox_path, path, MAXLEN - 1);
    } else {
      set_default_ox_path(path);
    }
}

void set_string_table_written (void)
{
    gretl_paths.status |= STRING_TABLE_WRITTEN;
}

int gretl_string_table_written (void)
{
    int ret = 0;

    if (gretl_paths.status & STRING_TABLE_WRITTEN) ret = 1;

    gretl_paths.status &= ~STRING_TABLE_WRITTEN;

    return ret;
}

void show_paths (const PATHS *ppaths)
{
    printf(_("gretl: using these basic search paths:\n"));
    printf("gretldir: %s\n", ppaths->gretldir);
    printf("workdir: %s\n", ppaths->workdir);
    printf("dotdir: %s\n", ppaths->dotdir);
    printf("gnuplot: %s\n", ppaths->gnuplot);
}

#ifdef WIN32

int gretl_set_paths (PATHS *ppaths, gretlopt opt)
{
    char envstr[MAXLEN];
    int err = 0;

    if (opt & OPT_D) {
      /* set defaults */
      char *home = getenv("GRETL_HOME");

      if (home != NULL) {
          strcpy(ppaths->gretldir, home);
          ensure_slash(ppaths->gretldir);
      } else {
          strcpy(ppaths->gretldir, "c:\\program files\\gretl\\");
      }

      sprintf(ppaths->binbase, "%sdb\\", ppaths->gretldir);
      strcpy(ppaths->ratsbase, "f:\\"); 

      strcpy(ppaths->x12a, "c:\\program files\\x12arima\\x12a.exe");
      strcpy(ppaths->tramo, "c:\\program files\\tramo\\tramo.exe");
      R_path_from_registry(ppaths->rlibpath, RLIB);

      if (opt & OPT_X) {
          strcpy(ppaths->dbhost, "ricardo.ecn.wfu.edu");
      } else {
          ppaths->dbhost[0] = '\0';
      }

      shelldir_init(NULL);
      ppaths->currdir[0] = '\0';
      ppaths->dotdir[0] = '\0';
      ppaths->workdir[0] = '\0';
      gretl_paths.plotfile[0] = '\0';
      strcpy(ppaths->pngfont, "verdana 8");
      set_default_ox_path(NULL);
    } else {
      /* not defaults: after reading from registry */
      ensure_slash(ppaths->gretldir);
      if (*ppaths->dotdir == '\0') {
          correct_blank_dotdir(ppaths);
      }
      err = validate_writedir(ppaths->dotdir);
      if (*ppaths->workdir == '\0') {
          correct_blank_workdir(ppaths);
      }
      if (strcmp(ppaths->dotdir, ppaths->workdir)) { 
          err += validate_writedir(ppaths->workdir);
      }
      if (!err) {
          err = set_tramo_x12a_dirs(ppaths, err);
      }
    }

    if (opt & OPT_X) {
      /* gui program */
      gretl_set_gui_mode(1);
      if (opt & OPT_N) {
          /* force english */
          sprintf(ppaths->helpfile, "%sgretlgui_hlp.txt", ppaths->gretldir);
          sprintf(ppaths->cmd_helpfile, "%sgretlcmd_hlp.txt", ppaths->gretldir);
          sprintf(ppaths->cli_helpfile, "%sgretlcli_hlp.txt", ppaths->gretldir);
      } else {
          sprintf(ppaths->helpfile, "%s%s", ppaths->gretldir, _("gretlgui_hlp.txt"));
          sprintf(ppaths->cmd_helpfile, "%s%s", ppaths->gretldir, _("gretlcmd_hlp.txt"));
          sprintf(ppaths->cli_helpfile, "%s%s", ppaths->gretldir, _("gretlcli_hlp.txt"));
      }
    } else { 
      sprintf(ppaths->helpfile, "%s%s", ppaths->gretldir, _("gretlcli_hlp.txt"));
      strcpy(ppaths->cli_helpfile, ppaths->helpfile);
    }

    sprintf(ppaths->gnuplot, "%swgnuplot.exe", ppaths->gretldir);

    sprintf(envstr, "%sshare\\gtksourceview-1.0\\language-specs", ppaths->gretldir);
    gretl_setenv("GTKSOURCEVIEW_LANGUAGE_DIR", envstr);

    ensure_slash(ppaths->dotdir);
    ensure_slash(ppaths->workdir);
    set_gretl_libpath(ppaths->gretldir);
    copy_paths_to_internal(ppaths);

    if (!(opt & OPT_D)) {
      shelldir_init(ppaths->workdir);
    }

    set_gretl_tex_preamble();

    return err;
}

#else /* not Windows */

static void check_gretldir (PATHS *ppaths)
{
    char *epath = getenv("GRETL_HOME");
    char buf[FILENAME_MAX];
    FILE *fp;
    int gotit = 0;

    ensure_slash(ppaths->gretldir);

    if (epath != NULL && strcmp(epath, ppaths->gretldir)) {
      /* environment vs rc file: is the env version OK? */
      sprintf(buf, "%sCOPYING", epath);
      fp = gretl_fopen(buf, "r");
      if (fp != NULL) {
          fclose(fp);
          *ppaths->gretldir = '\0';
          strncat(ppaths->gretldir, epath, MAXLEN - 2);
          ensure_slash(ppaths->gretldir);
          gotit = 1;
      }
    } else {
      /* no env setting: check what the rc file says */
      sprintf(buf, "%sCOPYING", ppaths->gretldir);
      fp = gretl_fopen(buf, "r");
      if (fp != NULL) {
          fclose(fp);
          gotit = 1;
      }
    } 

    if (!gotit) {
      /* we're messed up; try to recover */
      gchar *proc_exe;
      const char *s;
      pid_t pid;
      ssize_t nr;

      pid = getpid();
      proc_exe = g_strdup_printf("/proc/%d/exe", pid);
      nr = readlink(proc_exe, buf, FILENAME_MAX - 1);
      if (nr > 0) {
          buf[nr] = '\0';
          fprintf(stderr, "gretl is process %d, '%s'\n", (int) pid, buf);
          /* should be something like /foo/bar/bin/gretl; we
             want the /foo/bar bit to append to
          */
          s = strstr(buf, "bin/gretl");
          if (s != NULL) {
            *ppaths->gretldir = '\0';
            strncat(ppaths->gretldir, buf, s - buf);
            strcat(ppaths->gretldir, "share/gretl/");
            fprintf(stderr, "gretldir is really '%s'?\n", 
                  ppaths->gretldir);
          }
      }
      g_free(proc_exe);
    }
}

int gretl_set_paths (PATHS *ppaths, gretlopt opt)
{
    int err = 0;

    if (opt & OPT_D) {
      /* defaults */
      char *home = getenv("GRETL_HOME");

      if (home != NULL) {
          strcpy(ppaths->gretldir, home);
          ensure_slash(ppaths->gretldir);
      } else {
          strcpy(ppaths->gretldir, GRETL_PREFIX);
          strcat(ppaths->gretldir, "/share/gretl/");
      } 

      sprintf(ppaths->binbase, "%sdb/", ppaths->gretldir);
      strcpy(ppaths->ratsbase, "/mnt/dosc/userdata/rats/oecd/");

      if (opt & OPT_X) {
          strcpy(ppaths->dbhost, "ricardo.ecn.wfu.edu");
      } else {
          ppaths->dbhost[0] = '\0';
      }

#ifdef RLIBPATH
      strcpy(ppaths->rlibpath, RLIBPATH);
#else
      *ppaths->rlibpath = '\0';
#endif

      strcpy(ppaths->gnuplot, "gnuplot");
#ifdef OSX_BUILD
      strcpy(ppaths->pngfont, "Sans 9");
#else
      strcpy(ppaths->pngfont, "Vera 9");
#endif
      ppaths->currdir[0] = '\0';    
      shelldir_init(NULL);

      /* try to set a default userdir */
      home = getenv("HOME");
      if (home != NULL) {
          strcpy(ppaths->dotdir, home);
          strcat(ppaths->dotdir, "/.gretl/");
          strcpy(ppaths->workdir, home);
          strcat(ppaths->workdir, "/gretl/");
      } else {
          *ppaths->dotdir = '\0';
          *ppaths->workdir = '\0';
      }

#ifdef HAVE_X12A   
      strcpy(ppaths->x12a, "x12a");        
#endif       
             
#ifdef HAVE_TRAMO        
      strcpy(ppaths->tramo, "tramo");      
#endif

      set_default_ox_path(NULL);
      *gretl_paths.plotfile = '\0';
    } else {
      /* check validity of main directories */
      check_gretldir(ppaths);
      if (*ppaths->dotdir == '\0') {
          correct_blank_dotdir(ppaths->dotdir);
      }
      if (*ppaths->workdir == '\0') {
          correct_blank_workdir(ppaths->workdir);
      }
      err = validate_writedir(ppaths->dotdir);
      if (strcmp(ppaths->dotdir, ppaths->workdir)) {
          err += validate_writedir(ppaths->workdir);
      }
    }

    if (opt & OPT_X) {
      gretl_set_gui_mode(1);
      if (opt & OPT_N) {
          /* force english */
          sprintf(ppaths->helpfile, "%sgretlgui.hlp", ppaths->gretldir);
          sprintf(ppaths->cli_helpfile, "%sgretlcli.hlp", ppaths->gretldir);
          sprintf(ppaths->cmd_helpfile, "%sgretlcmd.hlp", ppaths->gretldir);
      } else {
          sprintf(ppaths->helpfile, "%s%s", ppaths->gretldir, _("gretlgui.hlp"));
          sprintf(ppaths->cli_helpfile, "%s%s", ppaths->gretldir, _("gretlcli.hlp"));
          sprintf(ppaths->cmd_helpfile, "%s%s", ppaths->gretldir, _("gretlcmd.hlp"));
      }
    } else {
      sprintf(ppaths->helpfile, "%s%s", ppaths->gretldir, _("gretlcli.hlp"));
      strcpy(ppaths->cli_helpfile, ppaths->helpfile);
    }

    if (getenv("GTKSOURCEVIEW_LANGUAGE_DIR") == NULL) {
      /* for the benefit of the bundled gtksourceview library */
      char envstr[MAXLEN];

      sprintf(envstr, "%sgtksourceview", ppaths->gretldir);
      gretl_setenv("GTKSOURCEVIEW_LANGUAGE_DIR", envstr);
    }

    ensure_slash(ppaths->dotdir);
    set_gretl_libpath(ppaths->gretldir);

#if defined(HAVE_X12A) || defined(HAVE_TRAMO)
    if ((!(opt & OPT_D) || !(opt & OPT_X))) {
      err = set_tramo_x12a_dirs(ppaths, err);
    }
#endif

    copy_paths_to_internal(ppaths);

#ifdef OSX_BUILD
    if (!(opt & OPT_D)) {
      shelldir_init(ppaths->workdir);
    }
#endif

    set_gretl_tex_preamble();

    return err;
}

#endif /* win32 versus unix */

/* for writing a file, name given by user: if the path is not
   absolute, switch to the gretl "workdir" (for a plain filename and
   STATE_USE_CWD not set), or to the current "shelldir" (for a filename
   beginning with '.', or if STATE_USE_CWD is set).
*/

const char *gretl_maybe_switch_dir (const char *fname)
{
    if (fname[0] == '~' && fname[1] == '/') {
      char *home = getenv("HOME");
      
      if (home != NULL) {
          chdir(home);
          fname += 2;
      }
    } else if (!g_path_is_absolute(fname)) {
      if (dotpath(fname) || libset_get_bool(USE_CWD)) {
          char *sdir = get_shelldir();

          if (sdir != NULL && *sdir != '\0') {
            gretl_chdir(sdir);
          }
      } else {
          gretl_chdir(gretl_paths.workdir);
      }
    }

    return fname;
}

/* argument should be of length FILENAME_MAX */

char *gretl_maybe_prepend_dir (char *fname)
{
    char tmp[FILENAME_MAX];

    *tmp = '\0';

    if (fname[0] == '~' && fname[1] == '/') {
      char *home = getenv("HOME");
      
      if (home != NULL) {
          build_path(tmp, home, fname + 2, NULL);
      }
    } else if (!g_path_is_absolute(fname)) {
      if (dotpath(fname) || libset_get_bool(USE_CWD)) {
          char *sdir = get_shelldir();

          if (sdir != NULL && *sdir != '\0') {
            build_path(tmp, sdir, fname, NULL);
          }
      } else {
          build_path(tmp, gretl_paths.workdir, fname, NULL);
      }
    }

    if (*tmp != '\0') {
      strcpy(fname, tmp);
    }

    return fname;
}

/* remove '.' and '..' from @path */

int gretl_normalize_path (char *path)
{
    char tmp[FILENAME_MAX];
    char *pcpy, *pbit, *s = path;
    char **S, **P = NULL;
    int i, n = 0;
    int err = 0;

    if (*path == '\0' || strstr(path, SLASHSTR) == NULL) {
      return 0;
    }

    pcpy = gretl_strdup(path);
    if (pcpy == NULL) {
      return E_ALLOC;
    }

    *tmp = '\0';
    s = pcpy;

#ifdef WIN32
    /* may be ok for a filename to start with a double backslash */
    if (!strncmp(path, "\\\\", 2)) {
      strcpy(tmp, SLASHSTR);
      s++;
    } else if (*path && path[1] == ':') {
      strncat(tmp, path, 2);
      s += 2;
    }
#endif

    while ((pbit = strtok(s, SLASHSTR)) != NULL && !err) {
      if (strcmp(pbit, ".")) {
          S = realloc(P, (n+1) * sizeof *P);
          if (S == NULL) {
            err = E_ALLOC;
          } else {
            P = S;
            P[n++] = pbit;
          }
      }
      s = NULL;
    }

    if (!err) {
      int j;

      for (i=n-1; i>0; i--) {
          if (P[i] != NULL && !strcmp(P[i], "..")) {
            for (j=i-1; j>0; j--) {
                if (P[j] != NULL && strcmp(P[j], "..")) {
                  P[j] = NULL;
                  break;
                }
            }
          }
      }
      for (i=0; i<n; i++) {
          if (P[i] != NULL && strcmp(P[i], "..")) {
            strcat(tmp, SLASHSTR);
            strcat(tmp, P[i]);
          }
      }
      strcpy(path, tmp);
      free(P);
    }

    free(pcpy);
    
    return err;
}

void slash_terminate (char *path)
{
    if (path == NULL || *path == '\0') return;

    if (path[strlen(path) - 1] != SLASH) {
      strcat(path, SLASHSTR);
    }
}

#ifndef WIN32

static void rc_set_gp_colors (const char *gpcolors)
{
    char cstr[N_GP_COLORS][8];
    int i, nc;

    *cstr[0] = *cstr[1] = *cstr[2] = *cstr[3] = '\0';

    nc = sscanf(gpcolors, "%7s %7s %7s %7s", 
            cstr[0], cstr[1], cstr[2], cstr[3]);

    for (i=0; i<nc; i++) {
      set_graph_palette_from_string(i, cstr[i]);
    }
}

static int rc_bool (const char *s)
{
    if (!strcmp(s, "true") || !strcmp(s, "1")) {
      return 1;
    } else {
      return 0;
    } 
}

int cli_read_rc (PATHS *paths) 
{
    FILE *fp;
    char rcfile[FILENAME_MAX];
    char line[MAXLEN], key[32], val[MAXLEN];
    char dbproxy[21] = {0};
    char *home;
    int usecwd = 0;
    int use_proxy = 0;
    int err = 0;

    home = getenv("HOME");
    if (home == NULL) {
      return 1;
    }

    sprintf(rcfile, "%s/.gretl2rc", home);
    fp = gretl_fopen(rcfile, "r");
    if (fp == NULL) {
      return 1;
    }

    while (fgets(line, MAXLEN, fp) != NULL) {
      if (*line == '#') {
          continue;
      }
      if (!strncmp(line, "recent", 6)) {
          break;
      }
      if (sscanf(line, "%s", key) == 1) {
          strcpy(val, line + strlen(key) + 3); 
          chopstr(val); 
          if (!strcmp(key, "gretldir")) {
            *paths->gretldir = '\0';
            strncat(paths->gretldir, val, MAXLEN - 1);
          } else if (!strcmp(key, "userdir")) {
            *paths->workdir = '\0';
            strncat(paths->workdir, val, MAXLEN - 1);
          } else if (!strcmp(key, "shellok")) {
            libset_set_bool(SHELL_OK, rc_bool(val));
          } else if (!strcmp(key, "usecwd")) {
            usecwd = rc_bool(val);
            libset_set_bool(USE_CWD, usecwd);
          } else if (!strcmp(key, "binbase")) {
            *paths->binbase = '\0';
            strncat(paths->binbase, val, MAXLEN - 1);
          } else if (!strcmp(key, "ratsbase")) {
            *paths->ratsbase = '\0';
            strncat(paths->ratsbase, val, MAXLEN - 1);
          } else if (!strcmp(key, "dbhost")) {
            *paths->dbhost = '\0';
            strncat(paths->dbhost, val, 32 - 1);
          } else if (!strcmp(key, "dbproxy")) {
            strncat(dbproxy, val, 21 - 1);
          } else if (!strcmp(key, "useproxy")) {
            use_proxy = rc_bool(val);
          } else if (!strcmp(key, "x12a")) {
            *paths->x12a = '\0';
            strncat(paths->x12a, val, FILENAME_MAX - 1);
          } else if (!strcmp(key, "Gp_colors")) {
            rc_set_gp_colors(val);
          } 
      }
    }

    fclose(fp);

    if (usecwd) {
      char *s, cwd[MAXLEN];

      s = getcwd(cwd, MAXLEN);
      if (s != NULL) {
          *paths->workdir = '\0';
          strncat(paths->workdir, s, MAXLEN - 2);
          ensure_slash(paths->workdir);
      }
    }

    err = gretl_set_paths(paths, OPT_NONE);
    gretl_www_init(paths->dbhost, dbproxy, use_proxy);

    return err;
}

#endif

Generated by  Doxygen 1.6.0   Back to index