static void dump_string(char *val, char *buf) /* display the value of a string capability */ { if (val == ABSENT_STRING) _nc_STRCPY(buf, s_absent, MAX_STRING); else if (val == CANCELLED_STRING) _nc_STRCPY(buf, s_cancel, MAX_STRING); else { _nc_SPRINTF(buf, _nc_SLIMIT(MAX_STRING) "'%.*s'", MAX_STRING - 3, TIC_EXPAND(val)); } }
static int make_db_path(char *dst, const char *src, size_t limit) { int rc = -1; const char *top = _nc_tic_dir(0); if (src == top || _nc_is_abs_path(src)) { if (strlen(src) + 1 <= limit) { _nc_STRCPY(dst, src, limit); rc = 0; } } else { if (strlen(top) + strlen(src) + 2 <= limit) { _nc_SPRINTF(dst, _nc_SLIMIT(limit) "%s/%s", top, src); rc = 0; } } #if USE_HASHED_DB if (rc == 0) { static const char suffix[] = DBM_SUFFIX; size_t have = strlen(dst); size_t need = strlen(suffix); if (have > need && strcmp(dst + (int) (have - need), suffix)) { if (have + need <= limit) { _nc_STRCAT(dst, suffix, limit); } else { rc = -1; } } else if (_nc_is_dir_path(dst)) { rc = -1; } } #endif return rc; }
static void dump_numeric(int val, char *buf) /* display the value of a boolean capability */ { switch (val) { case ABSENT_NUMERIC: _nc_STRCPY(buf, s_absent, MAX_STRING); break; case CANCELLED_NUMERIC: _nc_STRCPY(buf, s_cancel, MAX_STRING); break; default: _nc_SPRINTF(buf, _nc_SLIMIT(MAX_STRING) "%d", val); break; } }
_tracechtype2(int bufnum, chtype ch) { char *result = _nc_trace_buf(bufnum, (size_t) BUFSIZ); if (result != 0) { const char *found; attr_t attr = ChAttrOf(ch); _nc_STRCPY(result, l_brace, TRACE_BUF_SIZE(bufnum)); if ((found = _nc_altcharset_name(attr, ch)) != 0) { (void) _nc_trace_bufcat(bufnum, found); attr &= ~A_ALTCHARSET; } else (void) _nc_trace_bufcat(bufnum, _nc_tracechar(CURRENT_SCREEN, (int) ChCharOf(ch))); if (attr != A_NORMAL) { (void) _nc_trace_bufcat(bufnum, " | "); (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr)); } result = _nc_trace_bufcat(bufnum, r_brace); } return result; }
static void failed(const char *msg) { char temp[BUFSIZ]; size_t len = strlen(_nc_progname) + 2; if ((int) len < (int) sizeof(temp) - 12) { _nc_STRCPY(temp, _nc_progname, sizeof(temp)); _nc_STRCAT(temp, ": ", sizeof(temp)); } else { _nc_STRCPY(temp, "tset: ", sizeof(temp)); } _nc_STRNCAT(temp, msg, sizeof(temp), sizeof(temp) - strlen(temp) - 2); perror(temp); exit_error(); /* NOTREACHED */ }
static char * strmalloc(char *s) { size_t need = strlen(s) + 1; char *result = malloc(need); if (result == 0) failed("strmalloc"); _nc_STRCPY(result, s, need); return result; }
/* * Convert a character to visible form. */ static char * visichar(int ch) { static char temp[10]; ch = UChar(ch); assert(ch >= 0 && ch < 256); if (ch == '\\') { _nc_STRCPY(temp, "\\\\", sizeof(temp)); } else if (ch == '\033') { _nc_STRCPY(temp, "\\E", sizeof(temp)); } else if (ch < ' ') { _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "\\%03o", ch); } else if (ch >= 127) { _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "\\%03o", ch); } else { _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "%c", ch); } return temp; }
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 char * canonical_name(char *ptr, char *buf) /* extract the terminal type's primary name */ { char *bp; _nc_STRCPY(buf, ptr, NAMESIZE); if ((bp = strchr(buf, '|')) != 0) *bp = '\0'; return (buf); }
_nc_strdup(const char *s) { char *result = 0; if (s != 0) { size_t need = strlen(s); result = malloc(need + 1); if (result != 0) { _nc_STRCPY(result, s, need); } } return result; }
static char * force_bar(char *dst, char *src) { if (strchr(src, '|') == 0) { size_t len = strlen(src); if (len > MAX_NAME_SIZE) len = MAX_NAME_SIZE; (void) strncpy(dst, src, len); _nc_STRCPY(dst + len, "|", MAX_NAME_SIZE); src = dst; } return src; }
static char * save_string(char *d, const char *const s) { size_t have = (size_t) (d - my_string); size_t need = have + strlen(s) + 2; if (need > my_length) { my_string = (char *) _nc_doalloc(my_string, my_length = (need + need)); if (my_string == 0) _nc_err_abort(MSG_NO_MEMORY); d = my_string + have; } _nc_STRCPY(d, s, my_length - have); return d + strlen(d); }
static char * color_of(int c) { if (c != my_cached) { my_cached = c; my_select = !my_select; if (isDefaultColor(c)) _nc_STRCPY(my_buffer[my_select], "default", COLOR_BUF_SIZE(my_select)); else _nc_SPRINTF(my_buffer[my_select], _nc_SLIMIT(COLOR_BUF_SIZE(my_select)) "color%d", c); } return my_buffer[my_select]; }
static char * save_tc_char(char *bufptr, int c1) { char temp[80]; if (is7bits(c1) && isprint(c1)) { if (c1 == ':' || c1 == '\\') bufptr = save_char(bufptr, '\\'); bufptr = save_char(bufptr, c1); } else { if (c1 == (c1 & 0x1f)) /* iscntrl() returns T on 255 */ _nc_STRCPY(temp, unctrl((chtype) c1), sizeof(temp)); else _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "\\%03o", c1); bufptr = save_string(bufptr, temp); } return bufptr; }
/* * Improve similar_sgr a little by moving the attr-string from the beginning * to the end of the s-string. */ static bool rewrite_sgr(char *s, char *attr) { if (s != 0) { if (PRESENT(attr)) { size_t len_s = strlen(s); size_t len_a = strlen(attr); if (len_s > len_a && !strncmp(attr, s, len_a)) { unsigned n; TR(TRACE_DATABASE, ("rewrite:\n\t%s", s)); for (n = 0; n < len_s - len_a; ++n) { s[n] = s[n + len_a]; } _nc_STRCPY(s + n, attr, strlen(s) + 1); TR(TRACE_DATABASE, ("to:\n\t%s", s)); } } return TRUE; } return FALSE; /* oops */ }
_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; char *term_names = tp->term_names; size_t name_size = strlen(term_names); if (name_size == 0) { _nc_syserr_abort("no terminal name found."); } else if (name_size >= sizeof(name_list) - 1) { _nc_syserr_abort("terminal name too long: %s", term_names); } _nc_STRCPY(name_list, term_names, sizeof(name_list)); DEBUG(7, ("Name list = '%s'", name_list)); first_name = name_list; ptr = &name_list[name_size - 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 = term_names; key.size = name_size; 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); _nc_STRCPY(buffer + 1, term_names, sizeof(buffer) - 1); data.size = name_size + 1; _nc_db_put(capdb, &key, &data); 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'; key.data = ptr; key.size = strlen(ptr); _nc_db_put(capdb, &key, &data); } } } #else /* !USE_HASHED_DB */ if (call_count++ == 0) { start_time = 0; } if (strlen(first_name) >= sizeof(filename) - (2 + LEAF_LEN)) _nc_warning("terminal name too long."); _nc_SPRINTF(filename, _nc_SLIMIT(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) { #if HAVE_LINK && !USE_SYMLINKS /* * If the file has more than one link, the reason for the previous * write could be that the current primary name used to be an alias for * the previous entry. In that case, unlink the file so that we will * not modify the previous entry as we write this one. */ if (statbuf.st_nlink > 1) { _nc_warning("name redefined."); unlink(filename); } else { _nc_warning("name multiply defined."); } #else _nc_warning("name multiply defined."); #endif } 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++; while (*other_names != '|' && *other_names != '\0') other_names++; if (*other_names != '\0') *(other_names++) = '\0'; if (strlen(ptr) > sizeof(linkname) - (2 + LEAF_LEN)) { _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]); _nc_SPRINTF(linkname, _nc_SLIMIT(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 if (first_name[0] == linkname[0]) strncpy(symlinkname, first_name, sizeof(symlinkname) - 1); else { _nc_STRCPY(symlinkname, "../", sizeof(suymlinkname)); strncat(symlinkname, filename, sizeof(symlinkname) - 4); } symlinkname[sizeof(symlinkname) - 1] = '\0'; #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 */ }
_tracecchar_t2(int bufnum, const cchar_t *ch) { char *result = _nc_trace_buf(bufnum, (size_t) BUFSIZ); if (result != 0) { _nc_STRCPY(result, l_brace, TRACE_BUF_SIZE(bufnum)); if (ch != 0) { const char *found; attr_t attr = AttrOfD(ch); if ((found = _nc_altcharset_name(attr, (chtype) CharOfD(ch))) != 0) { (void) _nc_trace_bufcat(bufnum, found); attr &= ~A_ALTCHARSET; } else if (isWidecExt(CHDEREF(ch))) { (void) _nc_trace_bufcat(bufnum, "{NAC}"); attr &= ~A_CHARTEXT; } else { PUTC_DATA; int n; (void) _nc_trace_bufcat(bufnum, "{ "); for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { PUTC_ch = ch->chars[PUTC_i]; if (PUTC_ch == L'\0') { if (PUTC_i == 0) (void) _nc_trace_bufcat(bufnum, "\\000"); break; } PUTC_INIT; PUTC_n = (int) wcrtomb(PUTC_buf, ch->chars[PUTC_i], &PUT_st); if (PUTC_n <= 0) { if (PUTC_ch != L'\0') { /* it could not be a multibyte sequence */ (void) _nc_trace_bufcat(bufnum, _nc_tracechar(CURRENT_SCREEN, UChar(ch->chars[PUTC_i]))); } break; } else if (ch->chars[PUTC_i] > 255) { char temp[80]; _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "{%d:\\u%lx}", wcwidth(ch->chars[PUTC_i]), (unsigned long) ch->chars[PUTC_i]); (void) _nc_trace_bufcat(bufnum, temp); break; } for (n = 0; n < PUTC_n; n++) { if (n) (void) _nc_trace_bufcat(bufnum, ", "); (void) _nc_trace_bufcat(bufnum, _nc_tracechar(CURRENT_SCREEN, UChar(PUTC_buf[n]))); } } (void) _nc_trace_bufcat(bufnum, " }"); } if (attr != A_NORMAL) { (void) _nc_trace_bufcat(bufnum, " | "); (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr)); } #if NCURSES_EXT_COLORS /* * Just in case the extended color is different from the chtype * value, trace both. */ if (ch->ext_color != PairNumber(attr)) { char temp[80]; _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) " X_COLOR{%d:%d}", ch->ext_color, PairNumber(attr)); (void) _nc_trace_bufcat(bufnum, temp); } #endif } result = _nc_trace_bufcat(bufnum, r_brace); } return result; }
_traceattr2(int bufnum, chtype newmode) { #define DATA(name) { name, { #name } } static const struct { unsigned int val; const char name[14]; } names[] = { DATA(A_STANDOUT), DATA(A_UNDERLINE), DATA(A_REVERSE), DATA(A_BLINK), DATA(A_DIM), DATA(A_BOLD), DATA(A_ALTCHARSET), DATA(A_INVIS), DATA(A_PROTECT), DATA(A_CHARTEXT), DATA(A_NORMAL), DATA(A_COLOR), #if USE_ITALIC DATA(A_ITALIC), #endif } #ifndef USE_TERMLIB , colors[] = { DATA(COLOR_BLACK), DATA(COLOR_RED), DATA(COLOR_GREEN), DATA(COLOR_YELLOW), DATA(COLOR_BLUE), DATA(COLOR_MAGENTA), DATA(COLOR_CYAN), DATA(COLOR_WHITE), } #endif /* !USE_TERMLIB */ ; #undef DATA char *result = _nc_trace_buf(bufnum, (size_t) BUFSIZ); if (result != 0) { size_t n; unsigned save_nc_tracing = _nc_tracing; _nc_tracing = 0; _nc_STRCPY(result, l_brace, TRACE_BUF_SIZE(bufnum)); for (n = 0; n < SIZEOF(names); n++) { if ((newmode & names[n].val) != 0) { if (result[1] != '\0') (void) _nc_trace_bufcat(bufnum, "|"); result = _nc_trace_bufcat(bufnum, names[n].name); if (names[n].val == A_COLOR) { char temp[80]; short pairnum = (short) PairNumber(newmode); #ifdef USE_TERMLIB /* pair_content lives in libncurses */ _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "{%d}", pairnum); #else NCURSES_COLOR_T fg, bg; if (pair_content(pairnum, &fg, &bg) == OK) { _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "{%d = {%s, %s}}", pairnum, COLOR_OF(fg), COLOR_OF(bg)); } else { _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "{%d}", pairnum); } #endif result = _nc_trace_bufcat(bufnum, temp); } } } if (ChAttrOf(newmode) == A_NORMAL) { if (result != 0 && result[1] != '\0') (void) _nc_trace_bufcat(bufnum, "|"); (void) _nc_trace_bufcat(bufnum, "A_NORMAL"); } _nc_tracing = save_nc_tracing; result = _nc_trace_bufcat(bufnum, r_brace); } return result; }
safe_keyname (SCREEN *sp, int c) { int i; char name[20]; char *p; NCURSES_CONST char *result = 0; if (c == -1) { result = "-1"; } else { for (i = 0; _nc_key_names[i].offset != -1; i++) { if (_nc_key_names[i].code == c) { result = (NCURSES_CONST char *)key_names + _nc_key_names[i].offset; break; } } if (result == 0 && (c >= 0 && c < SIZEOF_TABLE)) { if (MyTable == 0) MyTable = typeCalloc(char *, SIZEOF_TABLE); if (MyTable != 0) { int m_prefix = (sp == 0 || sp->_use_meta); /* if sense of meta() changed, discard cached data */ if (MyInit != (m_prefix + 1)) { MyInit = m_prefix + 1; for (i = 0; i < SIZEOF_TABLE; ++i) { if (MyTable[i]) { FreeAndNull(MyTable[i]); } } } /* create and cache result as needed */ if (MyTable[c] == 0) { int cc = c; p = name; #define P_LIMIT (sizeof(name) - (size_t) (p - name)) if (cc >= 128 && m_prefix) { _nc_STRCPY(p, "M-", P_LIMIT); p += 2; cc -= 128; } if (cc < 32) _nc_SPRINTF(p, _nc_SLIMIT(P_LIMIT) "^%c", cc + '@'); else if (cc == 127) _nc_STRCPY(p, "^?", P_LIMIT); else _nc_SPRINTF(p, _nc_SLIMIT(P_LIMIT) "%c", cc); MyTable[c] = strdup(name); } result = MyTable[c]; } #if NCURSES_EXT_FUNCS && NCURSES_XNAMES } else if (result == 0 && HasTerminal(sp)) { int j, k; char * bound; TERMTYPE *tp = &(TerminalOf(sp)->type); unsigned save_trace = _nc_tracing; _nc_tracing = 0; /* prevent recursion via keybound() */ for (j = 0; (bound = NCURSES_SP_NAME(keybound)(NCURSES_SP_ARGx c, j)) != 0; ++j) { for(k = STRCOUNT; k < (int) NUM_STRINGS(tp); k++) { if (tp->Strings[k] != 0 && !strcmp(bound, tp->Strings[k])) { result = ExtStrname(tp, k, strnames); break; } } free(bound); if (result != 0) break; } _nc_tracing = save_trace; #endif } }
_nc_varargs(const char *fmt, va_list ap) { static char dummy[] = ""; char buffer[BUFSIZ]; const char *param; int n; if (fmt == 0 || *fmt == '\0') return dummy; if (MyLength == 0) MyBuffer = typeMalloc(char, MyLength = BUFSIZ); if (MyBuffer == 0) return dummy; *MyBuffer = '\0'; while (*fmt != '\0') { if (*fmt == '%') { char *pval = 0; /* avoid const-cast */ const char *sval = ""; double fval = 0.0; int done = FALSE; int ival = 0; int type = 0; ARGTYPE parm[MAX_PARMS]; int parms = 0; ARGTYPE used = atUnknown; while (*++fmt != '\0' && !done) { if (*fmt == '*') { VA_INT(int); if (parms < MAX_PARMS) parm[parms++] = atInteger; } else if (isalpha(UChar(*fmt))) { done = TRUE; switch (*fmt) { case 'Z': /* FALLTHRU */ case 'h': /* FALLTHRU */ case 'l': /* FALLTHRU */ done = FALSE; type = *fmt; break; case 'i': /* FALLTHRU */ case 'd': /* FALLTHRU */ case 'u': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ if (type == 'l') VA_INT(long); else if (type == 'Z') VA_INT(size_t); else VA_INT(int); used = atInteger; break; case 'f': /* FALLTHRU */ case 'e': /* FALLTHRU */ case 'E': /* FALLTHRU */ case 'g': /* FALLTHRU */ case 'G': /* FALLTHRU */ VA_FLT(double); used = atFloat; break; case 'c': VA_INT(int); used = atInteger; break; case 's': VA_STR(const char *); used = atString; break; case 'p': VA_PTR(void *); used = atPoint; break; case 'n': VA_PTR(int *); used = atPoint; break; default: break; } } else if (*fmt == '%') { done = TRUE; } if (used != atUnknown && parms < MAX_PARMS) { parm[parms++] = used; for (n = 0; n < parms; ++n) { used = parm[n]; param = buffer; switch (used) { case atInteger: _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) "%d", ival); break; case atFloat: _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) "%f", fval); break; case atPoint: _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) "%p", pval); break; case atString: param = _nc_visbuf2(1, sval); break; case atUnknown: default: _nc_STRCPY(buffer, "?", sizeof(buffer)); break; } MyLength += strlen(param) + 2; MyBuffer = typeRealloc(char, MyLength, MyBuffer); _nc_SPRINTF(MyBuffer + strlen(MyBuffer), _nc_SLIMIT(MyLength - strlen(MyBuffer)) ", %s", param); } } used = atUnknown; } } else {