]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/tinfo/db_iterator.c
ncurses 5.9 - patch 20120622
[ncurses.git] / ncurses / tinfo / db_iterator.c
index f7e4d6064bf30f020e79cee27fc1a3a1bf6324d5..943104c5dc0f6e6c0d10baf4fd67b260e3dbd8d5 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 2006-2010,2011 Free Software Foundation, Inc.              *
+ * Copyright (c) 2006-2011,2012 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
 #include <hashed_db.h>
 #endif
 
-MODULE_ID("$Id: db_iterator.c,v 1.18 2011/09/26 09:52:00 tom Exp $")
+MODULE_ID("$Id: db_iterator.c,v 1.33 2012/06/23 00:16:58 tom Exp $")
 
 #define HaveTicDirectory _nc_globals.have_tic_directory
 #define KeepTicDirectory _nc_globals.keep_tic_directory
 #define TicDirectory     _nc_globals.tic_directory
-
-/*
- * FIXME: need a no-leaks entrypoint.
- */
-static char *my_blob;          /* string-heap for my_list[] */
-static char **my_list;         /* distinct places to look for data */
-static int my_size;            /* length of my_list[] */
-static time_t my_time;         /* cache last updated */
-static struct {
-    const char *name;
-    char *value;
-} my_vars[dbdLAST];
+#define my_blob          _nc_globals.dbd_blob
+#define my_list          _nc_globals.dbd_list
+#define my_size          _nc_globals.dbd_size
+#define my_time          _nc_globals.dbd_time
+#define my_vars          _nc_globals.dbd_vars
 
 static void
-add_to_blob(const char *text)
+add_to_blob(const char *text, size_t limit)
 {
+    (void) limit;
+
     if (*text != '\0') {
        char *last = my_blob + strlen(my_blob);
        if (last != my_blob)
-           *last++ = ':';
-       strcpy(last, text);
+           *last++ = NCURSES_PATHSEP;
+       _nc_STRCPY(last, text, limit);
     }
 }
 
@@ -77,19 +72,19 @@ check_existence(const char *name, struct stat *sb)
 {
     bool result = FALSE;
 
-    if (stat(name, sb) == 0 && sb->st_size) {
+    if (stat(name, sb) == 0
+       && (S_ISDIR(sb->st_mode) || S_ISREG(sb->st_mode))) {
        result = TRUE;
     }
 #if USE_HASHED_DB
     else if (strlen(name) < PATH_MAX - sizeof(DBM_SUFFIX)) {
        char temp[PATH_MAX];
-       sprintf(temp, "%s%s", name, DBM_SUFFIX);
-       if (stat(temp, sb) == 0 && sb->st_size) {
+       _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "%s%s", name, DBM_SUFFIX);
+       if (stat(temp, sb) == 0 && S_ISREG(sb->st_mode)) {
            result = TRUE;
        }
     }
 #endif
-
     return result;
 }
 
@@ -101,10 +96,13 @@ static bool
 update_getenv(const char *name, DBDIRS which)
 {
     bool result = FALSE;
-    char *value = getenv(name);
 
     if (which < dbdLAST) {
-       if (my_vars[which].name == 0 || strcmp(my_vars[which].name, name)) {
+       char *value = getenv(name);
+
+       if ((value = getenv(name)) == 0 || (value = strdup(value)) == 0) {
+           ;
+       } else if (my_vars[which].name == 0 || strcmp(my_vars[which].name, name)) {
            FreeIfNeeded(my_vars[which].value);
            my_vars[which].name = name;
            my_vars[which].value = value;
@@ -117,6 +115,8 @@ update_getenv(const char *name, DBDIRS which)
            FreeIfNeeded(my_vars[which].value);
            my_vars[which].value = value;
            result = TRUE;
+       } else {
+           free(value);
        }
     }
     return result;
@@ -155,7 +155,7 @@ cache_expired(void)
        result = TRUE;
     } else {
        DBDIRS n;
-       for (n = 0; n < dbdLAST; ++n) {
+       for (n = (DBDIRS) 0; n < dbdLAST; ++n) {
            if (my_vars[n].name != 0
                && update_getenv(my_vars[n].name, n)) {
                result = TRUE;
@@ -191,7 +191,7 @@ _nc_tic_dir(const char *path)
                return _nc_tic_dir(envp);
        }
     }
-    return TicDirectory;
+    return TicDirectory ? TicDirectory : TERMINFO;
 }
 
 /*
@@ -245,6 +245,7 @@ _nc_next_db(DBDIRS * state, int *offset)
 NCURSES_EXPORT(void)
 _nc_first_db(DBDIRS * state, int *offset)
 {
+    bool cache_has_expired = FALSE;
     *state = dbdTIC;
     *offset = 0;
 
@@ -253,12 +254,15 @@ _nc_first_db(DBDIRS * state, int *offset)
     /* build a blob containing all of the strings we will use for a lookup
      * table.
      */
-    if (my_blob == 0) {
+    if (my_blob == 0 || (cache_has_expired = cache_expired())) {
        size_t blobsize = 0;
        const char *values[dbdLAST];
        struct stat *my_stat;
        int j, k;
 
+       if (cache_has_expired)
+           free_cache();
+
        for (j = 0; j < dbdLAST; ++j)
            values[j] = 0;
 
@@ -287,9 +291,15 @@ _nc_first_db(DBDIRS * state, int *offset)
            values[dbdHome] = _nc_home_terminfo();
            (void) cache_getenv("HOME", dbdHome);
            values[dbdEnvList] = cache_getenv("TERMINFO_DIRS", dbdEnvList);
+
 #endif
 #if USE_TERMCAP
            values[dbdEnvOnce2] = cache_getenv("TERMCAP", dbdEnvOnce2);
+           /* only use $TERMCAP if it is an absolute path */
+           if (values[dbdEnvOnce2] != 0
+               && *values[dbdEnvOnce2] != '/') {
+               values[dbdEnvOnce2] = 0;
+           }
            values[dbdEnvList2] = cache_getenv("TERMPATH", dbdEnvList2);
 #endif /* USE_TERMCAP */
        }
@@ -304,7 +314,7 @@ _nc_first_db(DBDIRS * state, int *offset)
        if (my_blob != 0) {
            *my_blob = '\0';
            for (j = 0; j < dbdLAST; ++j) {
-               add_to_blob(values[j]);
+               add_to_blob(values[j], blobsize);
            }
 
            /* Now, build an array which will be pointers to the distinct
@@ -312,7 +322,7 @@ _nc_first_db(DBDIRS * state, int *offset)
             */
            blobsize = 2;
            for (j = 0; my_blob[j] != '\0'; ++j) {
-               if (my_blob[j] == ':')
+               if (my_blob[j] == NCURSES_PATHSEP)
                    ++blobsize;
            }
            my_list = typeCalloc(char *, blobsize);
@@ -321,7 +331,7 @@ _nc_first_db(DBDIRS * state, int *offset)
                k = 0;
                my_list[k++] = my_blob;
                for (j = 0; my_blob[j] != '\0'; ++j) {
-                   if (my_blob[j] == ':') {
+                   if (my_blob[j] == NCURSES_PATHSEP) {
                        my_blob[j] = '\0';
                        my_list[k++] = &my_blob[j + 1];
                    }
@@ -333,11 +343,11 @@ _nc_first_db(DBDIRS * state, int *offset)
                for (j = 0; my_list[j] != 0; ++j) {
 #ifdef TERMINFO
                    if (*my_list[j] == '\0')
-                       my_list[j] = TERMINFO;
+                       my_list[j] = strdup(TERMINFO);
 #endif
                    for (k = 0; k < j; ++k) {
                        if (!strcmp(my_list[j], my_list[k])) {
-                           k = --j;
+                           k = j - 1;
                            while ((my_list[j] = my_list[j + 1]) != 0) {
                                ++j;
                            }
@@ -377,6 +387,25 @@ _nc_first_db(DBDIRS * state, int *offset)
            } else {
                FreeAndNull(my_blob);
            }
+           free(my_stat);
        }
     }
 }
+
+#if NO_LEAKS
+void
+_nc_db_iterator_leaks(void)
+{
+    DBDIRS which;
+
+    if (my_blob != 0)
+       FreeAndNull(my_blob);
+    if (my_list != 0)
+       FreeAndNull(my_list);
+    for (which = 0; which < dbdLAST; ++which) {
+       my_vars[which].name = 0;
+       FreeIfNeeded(my_vars[which].value);
+       my_vars[which].value = 0;
+    }
+}
+#endif