/* * Make a database-root if it doesn't exist. */ static int make_db_root(const char *path) { int rc; char fullpath[PATH_MAX]; if ((rc = make_db_path(fullpath, path, sizeof(fullpath))) == 0) { #if USE_HASHED_DB DB *capdbp; if ((capdbp = _nc_db_open(fullpath, TRUE)) == NULL) rc = -1; else if (_nc_db_close(capdbp) < 0) rc = -1; #else struct stat statbuf; if ((rc = stat(path, &statbuf)) < 0) { rc = mkdir(path, 0777); } else if (_nc_access(path, R_OK | W_OK | X_OK) < 0) { rc = -1; /* permission denied */ } else if (!(S_ISDIR(statbuf.st_mode))) { rc = -1; /* not a directory */ } #endif } return rc; }
_nc_write_entry(TERMTYPE *const tp) { #if USE_HASHED_DB char buffer[MAX_ENTRY_SIZE + 1]; unsigned limit = sizeof(buffer); unsigned offset = 0; #else /* !USE_HASHED_DB */ struct stat statbuf; char filename[PATH_MAX]; char linkname[PATH_MAX]; #if USE_SYMLINKS char symlinkname[PATH_MAX]; #if !HAVE_LINK #undef HAVE_LINK #define HAVE_LINK 1 #endif #endif /* USE_SYMLINKS */ static int call_count; static time_t start_time; /* time at start of writes */ #endif /* USE_HASHED_DB */ char name_list[MAX_TERMINFO_LENGTH]; char *first_name, *other_names; char *ptr; assert(strlen(tp->term_names) != 0); assert(strlen(tp->term_names) < sizeof(name_list)); (void) strlcpy(name_list, tp->term_names, sizeof(name_list)); DEBUG(7, ("Name list = '%s'", name_list)); first_name = name_list; ptr = &name_list[strlen(name_list) - 1]; other_names = ptr + 1; while (ptr > name_list && *ptr != '|') ptr--; if (ptr != name_list) { *ptr = '\0'; for (ptr = name_list; *ptr != '\0' && *ptr != '|'; ptr++) continue; if (*ptr == '\0') other_names = ptr; else { *ptr = '\0'; other_names = ptr + 1; } } DEBUG(7, ("First name = '%s'", first_name)); DEBUG(7, ("Other names = '%s'", other_names)); _nc_set_type(first_name); #if USE_HASHED_DB if (write_object(tp, buffer + 1, &offset, limit - 1) != ERR) { DB *capdb = _nc_db_open(_nc_tic_dir(0), TRUE); DBT key, data; if (capdb != 0) { buffer[0] = 0; memset(&key, 0, sizeof(key)); key.data = tp->term_names; key.size = strlen(tp->term_names); memset(&data, 0, sizeof(data)); data.data = buffer; data.size = offset + 1; _nc_db_put(capdb, &key, &data); buffer[0] = 2; key.data = name_list; key.size = strlen(name_list); strlcpy(buffer + 1, tp->term_names, sizeof(buffer) - 1); data.size = strlen(tp->term_names) + 1; _nc_db_put(capdb, &key, &data); while (*other_names != '\0') { ptr = other_names++; while (*other_names != '|' && *other_names != '\0') other_names++; if (*other_names != '\0') *(other_names++) = '\0'; key.data = ptr; key.size = strlen(ptr); _nc_db_put(capdb, &key, &data); } _nc_db_close(capdb); } } #else /* !USE_HASHED_DB */ if (call_count++ == 0) { start_time = 0; } if (strlen(first_name) >= sizeof(filename) - 3) _nc_warning("terminal name too long."); snprintf(filename, sizeof(filename), LEAF_FMT "/%s", first_name[0], first_name); /* * Has this primary name been written since the first call to * write_entry()? If so, the newer write will step on the older, * so warn the user. */ if (start_time > 0 && stat(filename, &statbuf) >= 0 && statbuf.st_mtime >= start_time) { _nc_warning("name multiply defined."); } check_writeable(first_name[0]); write_file(filename, tp); if (start_time == 0) { if (stat(filename, &statbuf) < 0 || (start_time = statbuf.st_mtime) == 0) { _nc_syserr_abort("error obtaining time from %s/%s", _nc_tic_dir(0), filename); } } while (*other_names != '\0') { ptr = other_names++; assert(ptr < buffer + sizeof(buffer) - 1); while (*other_names != '|' && *other_names != '\0') other_names++; if (*other_names != '\0') *(other_names++) = '\0'; if (strlen(ptr) > sizeof(linkname) - 3) { _nc_warning("terminal alias %s too long.", ptr); continue; } if (strchr(ptr, '/') != 0) { _nc_warning("cannot link alias %s.", ptr); continue; } check_writeable(ptr[0]); snprintf(linkname, sizeof(linkname), LEAF_FMT "/%s", ptr[0], ptr); if (strcmp(filename, linkname) == 0) { _nc_warning("self-synonym ignored"); } else if (stat(linkname, &statbuf) >= 0 && statbuf.st_mtime < start_time) { _nc_warning("alias %s multiply defined.", ptr); } else if (_nc_access(linkname, W_OK) == 0) #if HAVE_LINK { int code; #if USE_SYMLINKS strlcpy(symlinkname, "../", sizeof(symlinkname)); strlcat(symlinkname, filename, sizeof(symlinkname)); #endif /* USE_SYMLINKS */ #if HAVE_REMOVE code = remove(linkname); #else code = unlink(linkname); #endif if (code != 0 && errno == ENOENT) code = 0; #if USE_SYMLINKS if (symlink(symlinkname, linkname) < 0) #else if (link(filename, linkname) < 0) #endif /* USE_SYMLINKS */ { /* * If there wasn't anything there, and we cannot * link to the target because it is the same as the * target, then the source must be on a filesystem * that uses caseless filenames, such as Win32, etc. */ if (code == 0 && errno == EEXIST) _nc_warning("can't link %s to %s", filename, linkname); else if (code == 0 && (errno == EPERM || errno == ENOENT)) write_file(linkname, tp); else { #if MIXEDCASE_FILENAMES _nc_syserr_abort("can't link %s to %s", filename, linkname); #else _nc_warning("can't link %s to %s (errno=%d)", filename, linkname, errno); #endif } } else { DEBUG(1, ("Linked %s", linkname)); } } #else /* just make copies */ write_file(linkname, tp); #endif /* HAVE_LINK */ } #endif /* USE_HASHED_DB */ }
static int typelist(int eargc, char *eargv[], bool verbosity, void (*hook) (const char *, TERMTYPE *tp)) /* apply a function to each entry in given terminfo directories */ { int i; for (i = 0; i < eargc; i++) { #if USE_DATABASE if (_nc_is_dir_path(eargv[i])) { char *cwd_buf = 0; DIR *termdir; DIRENT *subdir; if ((termdir = opendir(eargv[i])) == 0) { (void) fflush(stdout); (void) fprintf(stderr, "%s: can't open terminfo directory %s\n", _nc_progname, eargv[i]); return (EXIT_FAILURE); } else if (verbosity) (void) printf("#\n#%s:\n#\n", eargv[i]); while ((subdir = readdir(termdir)) != 0) { size_t len = NAMLEN(subdir); size_t cwd_len = len + strlen(eargv[i]) + 3; char name_1[PATH_MAX]; DIR *entrydir; DIRENT *entry; cwd_buf = typeRealloc(char, cwd_len, cwd_buf); if (cwd_buf == 0) failed("realloc cwd_buf"); assert(cwd_buf != 0); strncpy(name_1, subdir->d_name, len)[len] = '\0'; if (isDotname(name_1)) continue; (void) sprintf(cwd_buf, "%s/%.*s/", eargv[i], (int) len, name_1); if (chdir(cwd_buf) != 0) continue; entrydir = opendir("."); if (entrydir == 0) { perror(cwd_buf); continue; } while ((entry = readdir(entrydir)) != 0) { char name_2[PATH_MAX]; TERMTYPE lterm; char *cn; int status; len = NAMLEN(entry); strncpy(name_2, entry->d_name, len)[len] = '\0'; if (isDotname(name_2) || !_nc_is_file_path(name_2)) continue; status = _nc_read_file_entry(name_2, <erm); if (status <= 0) { (void) fflush(stdout); (void) fprintf(stderr, "%s: couldn't open terminfo file %s.\n", _nc_progname, name_2); return (EXIT_FAILURE); } /* only visit things once, by primary name */ cn = _nc_first_name(lterm.term_names); if (!strcmp(cn, name_2)) { /* apply the selected hook function */ (*hook) (cn, <erm); } _nc_free_termtype(<erm); } closedir(entrydir); } closedir(termdir); if (cwd_buf != 0) free(cwd_buf); } #if USE_HASHED_DB else { DB *capdbp; char filename[PATH_MAX]; if (make_db_name(filename, eargv[i], sizeof(filename))) { if ((capdbp = _nc_db_open(filename, FALSE)) != 0) { DBT key, data; int code; code = _nc_db_first(capdbp, &key, &data); while (code == 0) { TERMTYPE lterm; int used; char *have; char *cn; if (_nc_db_have_data(&key, &data, &have, &used)) { if (_nc_read_termtype(<erm, have, used) > 0) { /* only visit things once, by primary name */ cn = _nc_first_name(lterm.term_names); /* apply the selected hook function */ (*hook) (cn, <erm); _nc_free_termtype(<erm); } } code = _nc_db_next(capdbp, &key, &data); } _nc_db_close(capdbp); } } } #endif #endif #if USE_TERMCAP #if HAVE_BSD_CGETENT char *db_array[2]; char *buffer = 0; if (verbosity) (void) printf("#\n#%s:\n#\n", eargv[i]); db_array[0] = eargv[i]; db_array[1] = 0; if (cgetfirst(&buffer, db_array)) { show_termcap(buffer, hook); free(buffer); while (cgetnext(&buffer, db_array)) { show_termcap(buffer, hook); free(buffer); } } cgetclose(); #else /* scan termcap text-file only */ if (_nc_is_file_path(eargv[i])) { char buffer[2048]; FILE *fp; if ((fp = fopen(eargv[i], "r")) != 0) { while (fgets(buffer, sizeof(buffer), fp) != 0) { if (*buffer == '#') continue; if (isspace(*buffer)) continue; show_termcap(buffer, hook); } fclose(fp); } } #endif #endif }