+#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, size_t limit)
+{
+ (void) limit;
+
+ if (*text != '\0') {
+ char *last = my_blob + strlen(my_blob);
+ if (last != my_blob)
+ *last++ = NCURSES_PATHSEP;
+ _nc_STRCPY(last, text, limit);
+ }
+}
+
+static bool
+check_existence(const char *name, struct stat *sb)
+{
+ bool result = FALSE;
+
+ if (quick_prefix(name)) {
+ result = TRUE;
+ } else if (stat(name, sb) == 0
+ && (S_ISDIR(sb->st_mode)
+ || (S_ISREG(sb->st_mode) && sb->st_size))) {
+ result = TRUE;
+ }
+#if USE_HASHED_DB
+ else if (strlen(name) < PATH_MAX - sizeof(DBM_SUFFIX)) {
+ char temp[PATH_MAX];
+ _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "%s%s", name, DBM_SUFFIX);
+ if (stat(temp, sb) == 0 && S_ISREG(sb->st_mode) && sb->st_size) {
+ result = TRUE;
+ }
+ }
+#endif
+ return result;
+}
+
+/*
+ * Trim newlines (and backslashes preceding those) and tab characters to
+ * help simplify scripting of the quick-dump feature. Leave spaces and
+ * other backslashes alone.
+ */
+static void
+trim_formatting(char *source)
+{
+ char *target = source;
+ char ch;
+
+ while ((ch = *source++) != '\0') {
+ if (ch == '\\' && *source == '\n')
+ continue;
+ if (ch == '\n' || ch == '\t')
+ continue;
+ *target++ = ch;
+ }
+ *target = '\0';
+}
+
+/*
+ * Store the latest value of an environment variable in my_vars[] so we can
+ * detect if one changes, invalidating the cached search-list.
+ */
+static bool
+update_getenv(const char *name, DBDIRS which)
+{
+ bool result = FALSE;
+
+ if (which < dbdLAST) {
+ char *value;
+ char *cached_value = my_vars[which].value;
+ bool same_value;
+
+ if ((value = getenv(name)) != 0) {
+ value = strdup(value);
+ }
+ same_value = ((value == 0 && cached_value == 0) ||
+ (value != 0 &&
+ cached_value != 0 &&
+ strcmp(value, cached_value) == 0));
+
+ /* Set variable name to enable checks in cache_expired(). */
+ my_vars[which].name = name;
+
+ if (!same_value) {
+ FreeIfNeeded(my_vars[which].value);
+ my_vars[which].value = value;
+ result = TRUE;
+ } else {
+ free(value);
+ }
+ }
+ return result;
+}
+
+#if NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP
+static char *
+cache_getenv(const char *name, DBDIRS which)
+{
+ char *result = 0;
+
+ (void) update_getenv(name, which);
+ if (which < dbdLAST) {
+ result = my_vars[which].value;
+ }
+ return result;
+}
+#endif
+
+/*
+ * The cache expires if at least a second has passed since the initial lookup,
+ * or if one of the environment variables changed.
+ *
+ * Only a few applications use multiple lookups of terminal entries, seems that
+ * aside from bulk I/O such as tic and toe, that leaves interactive programs
+ * which should not be modifying the terminal databases in a way that would
+ * invalidate the search-list.
+ *
+ * The "1-second" is to allow for user-directed changes outside the program.
+ */
+static bool
+cache_expired(void)
+{
+ bool result = FALSE;
+ time_t now = time((time_t *) 0);
+
+ if (now > my_time) {
+ result = TRUE;
+ } else {
+ DBDIRS n;
+ for (n = (DBDIRS) 0; n < dbdLAST; ++n) {
+ if (my_vars[n].name != 0
+ && update_getenv(my_vars[n].name, n)) {
+ result = TRUE;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+static void
+free_cache(void)
+{
+ FreeAndNull(my_blob);
+ FreeAndNull(my_list);
+}
+
+static void
+update_tic_dir(const char *update)
+{
+ free((char *) TicDirectory);
+ TicDirectory = update;
+}