_nc_set_writedir(char *dir) /* set the write directory for compiled entries */ { const char *destination; char actual[PATH_MAX]; if (dir == 0 && use_terminfo_vars()) dir = getenv("TERMINFO"); if (dir != 0) (void) _nc_tic_dir(dir); destination = _nc_tic_dir(0); if (make_directory(destination) < 0) { char *home = _nc_home_terminfo(); if (home != 0) { destination = home; if (make_directory(destination) < 0) _nc_err_abort("%s: permission denied (errno %d)", destination, errno); } } /* * Note: because of this code, this logic should be exercised * *once only* per run. */ if (chdir(_nc_tic_dir(destination)) < 0 || getcwd(actual, sizeof(actual)) == 0) _nc_err_abort("%s: not a directory", destination); _nc_keep_tic_dir(strdup(actual)); }
_nc_tic_dir(const char *path) { if (!KeepTicDirectory) { if (path != 0) { TicDirectory = path; HaveTicDirectory = TRUE; } else if (!HaveTicDirectory && use_terminfo_vars()) { char *envp; if ((envp = getenv("TERMINFO")) != 0) return _nc_tic_dir(envp); } } return TicDirectory; }
_nc_tic_dir(const char *path) { T(("_nc_tic_dir %s", NonNull(path))); if (!KeepTicDirectory) { if (path != 0) { TicDirectory = path; HaveTicDirectory = TRUE; } else if (HaveTicDirectory == 0) { if (use_terminfo_vars()) { char *envp; if ((envp = getenv("TERMINFO")) != 0) return _nc_tic_dir(envp); } } } return TicDirectory ? TicDirectory : TERMINFO; }
_nc_home_terminfo(void) { char *result = 0; #if USE_HOME_TERMINFO char *home; if (use_terminfo_vars()) { if (MyBuffer == 0) { if ((home = getenv("HOME")) != 0) { size_t want = (strlen(home) + sizeof(PRIVATE_INFO)); TYPE_MALLOC(char, want, MyBuffer); _nc_SPRINTF(MyBuffer, _nc_SLIMIT(want) PRIVATE_INFO, home); } } result = MyBuffer; } #endif return result; }
_nc_set_writedir(char *dir) { const char *destination; char actual[PATH_MAX]; if (dir == 0 #ifndef USE_ROOT_ENVIRON && use_terminfo_vars() #endif ) dir = getenv("TERMINFO"); if (dir != 0) (void) _nc_tic_dir(dir); destination = _nc_tic_dir(0); if (make_db_root(destination) < 0) { char *home = _nc_home_terminfo(); if (home != 0) { destination = home; if (make_db_root(destination) < 0) _nc_err_abort("%s: permission denied (errno %d)", destination, errno); } } /* * Note: because of this code, this logic should be exercised * *once only* per run. */ #if USE_HASHED_DB make_db_path(actual, destination, sizeof(actual)); #else if (chdir(_nc_tic_dir(destination)) < 0 || getcwd(actual, sizeof(actual)) == 0) _nc_err_abort("%s: not a directory", destination); #endif _nc_keep_tic_dir(strdup(actual)); }
_nc_first_db(DBDIRS * state, int *offset) { bool cache_has_expired = FALSE; *state = dbdTIC; *offset = 0; T(("_nc_first_db")); /* build a blob containing all of the strings we will use for a lookup * table. */ 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; /* * This is the first item in the list, and is used only when tic is * writing to the database, as a performance improvement. */ values[dbdTIC] = TicDirectory; #if NCURSES_USE_DATABASE #ifdef TERMINFO_DIRS values[dbdCfgList] = TERMINFO_DIRS; #endif #ifdef TERMINFO values[dbdCfgOnce] = TERMINFO; #endif #endif #if NCURSES_USE_TERMCAP values[dbdCfgList2] = TERMPATH; #endif if (use_terminfo_vars()) { #if NCURSES_USE_DATABASE values[dbdEnvOnce] = cache_getenv("TERMINFO", dbdEnvOnce); values[dbdHome] = _nc_home_terminfo(); (void) cache_getenv("HOME", dbdHome); values[dbdEnvList] = cache_getenv("TERMINFO_DIRS", dbdEnvList); #endif #if NCURSES_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 /* NCURSES_USE_TERMCAP */ } for (j = 0; j < dbdLAST; ++j) { if (values[j] == 0) values[j] = ""; blobsize += 2 + strlen(values[j]); } my_blob = malloc(blobsize); if (my_blob != 0) { *my_blob = '\0'; for (j = 0; j < dbdLAST; ++j) { add_to_blob(values[j], blobsize); } /* Now, build an array which will be pointers to the distinct * strings in the blob. */ blobsize = 2; for (j = 0; my_blob[j] != '\0'; ++j) { if (my_blob[j] == NCURSES_PATHSEP) ++blobsize; } my_list = typeCalloc(char *, blobsize); my_stat = typeCalloc(struct stat, blobsize); if (my_list != 0 && my_stat != 0) { k = 0; my_list[k++] = my_blob; for (j = 0; my_blob[j] != '\0'; ++j) { if (my_blob[j] == NCURSES_PATHSEP) { my_blob[j] = '\0'; my_list[k++] = &my_blob[j + 1]; } } /* * Eliminate duplicates from the list. */ for (j = 0; my_list[j] != 0; ++j) { #ifdef TERMINFO if (*my_list[j] == '\0') my_list[j] = strdup(TERMINFO); #endif for (k = 0; k < j; ++k) { if (!strcmp(my_list[j], my_list[k])) { k = j - 1; while ((my_list[j] = my_list[j + 1]) != 0) { ++j; } j = k; break; } } } /* * Eliminate non-existent databases, and those that happen to * be symlinked to another location. */ for (j = 0; my_list[j] != 0; ++j) { bool found = check_existence(my_list[j], &my_stat[j]); #if HAVE_LINK if (found) { for (k = 0; k < j; ++k) { if (my_stat[j].st_dev == my_stat[k].st_dev && my_stat[j].st_ino == my_stat[k].st_ino) { found = FALSE; break; } } } #endif if (!found) { k = j; while ((my_list[k] = my_list[k + 1]) != 0) { ++k; } --j; } } my_size = j; my_time = time((time_t *) 0); } else { FreeAndNull(my_blob); } free(my_stat); }
_nc_next_db(DBDIRS * state, int *offset) { const char *result; char *envp; while (*state < dbdLAST) { DBDIRS next = (DBDIRS) ((int) (*state) + 1); result = 0; switch (*state) { case dbdTIC: if (HaveTicDirectory) result = _nc_tic_dir(0); break; #if USE_DATABASE case dbdEnvOnce: if (use_terminfo_vars()) { if ((envp = getenv("TERMINFO")) != 0) result = _nc_tic_dir(envp); } break; case dbdHome: if (use_terminfo_vars()) { result = _nc_home_terminfo(); } break; case dbdEnvList: if (use_terminfo_vars()) { if ((result = NEXT_DBD(getenv("TERMINFO_DIRS"), offset)) != 0) next = *state; } break; case dbdCfgList: #ifdef TERMINFO_DIRS if ((result = NEXT_DBD(TERMINFO_DIRS, offset)) != 0) next = *state; #endif break; case dbdCfgOnce: #ifndef TERMINFO_DIRS result = TERMINFO; #endif break; #endif /* USE_DATABASE */ #if USE_TERMCAP case dbdEnvOnce2: if (use_terminfo_vars()) { if ((envp = getenv("TERMCAP")) != 0) result = _nc_tic_dir(envp); } break; case dbdEnvList2: if (use_terminfo_vars()) { if ((result = NEXT_DBD(getenv("TERMPATH"), offset)) != 0) next = *state; } break; case dbdCfgList2: if ((result = NEXT_DBD(TERMPATH, offset)) != 0) next = *state; break; #endif /* USE_TERMCAP */ case dbdLAST: break; } if (*state != next) { *state = next; *offset = 0; _nc_last_db(); } if (result != 0) { return result; } } return 0; }