📄 sltermin.c
字号:
/* This file contains enough terminfo reading capabilities sufficient for * the slang SLtt interface. *//* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis * This file is part of the S-Lang library. * * You may distribute under the terms of either the GNU General Public * License or the Perl Artistic License. */#include "slinclud.h"#include "slang.h"#include "_slang.h"/* * The majority of the comments found in the file were taken from the * term(4) man page on an SGI. *//* Short integers are stored in two 8-bit bytes. The first byte contains * the least significant 8 bits of the value, and the second byte contains * the most significant 8 bits. (Thus, the value represented is * 256*second+first.) The value -1 is represented by 0377,0377, and the * value -2 is represented by 0376,0377; other negative values are illegal. * The -1 generally means that a capability is missing from this terminal. * The -2 means that the capability has been cancelled in the terminfo * source and also is to be considered missing. */static int make_integer (unsigned char *buf){ register int lo, hi; lo = (int) *buf++; hi = (int) *buf; if (hi == 0377) { if (lo == 0377) return -1; if (lo == 0376) return -2; } return lo + 256 * hi;}/* * The compiled file is created from the source file descriptions of the * terminals (see the -I option of infocmp) by using the terminfo compiler, * tic, and read by the routine setupterm [see curses(3X).] The file is * divided into six parts in the following order: the header, terminal * names, boolean flags, numbers, strings, and string table. * * The header section begins the file. This section contains six short * integers in the format described below. These integers are (1) the magic * number (octal 0432); (2) the size, in bytes, of the names section; (3) * the number of bytes in the boolean section; (4) the number of short * integers in the numbers section; (5) the number of offsets (short * integers) in the strings section; (6) the size, in bytes, of the string * table. */#define MAGIC 0432/* In this structure, all char * fields are malloced EXCEPT if the * structure is SLTERMCAP. In that case, only terminal_names is malloced * and the other fields are pointers into it. */struct _SLterminfo_Type{#define SLTERMINFO 1#define SLTERMCAP 2 unsigned int flags; unsigned int name_section_size; char *terminal_names; unsigned int boolean_section_size; unsigned char *boolean_flags; unsigned int num_numbers; unsigned char *numbers; unsigned int num_string_offsets; unsigned char *string_offsets; unsigned int string_table_size; char *string_table;};static char *tcap_getstr (char *, SLterminfo_Type *);static int tcap_getnum (char *, SLterminfo_Type *);static int tcap_getflag (char *, SLterminfo_Type *);static int tcap_getent (char *, SLterminfo_Type *);static FILE *open_terminfo (char *file, SLterminfo_Type *h){ FILE *fp; unsigned char buf[12]; /* Alan Cox reported a security problem here if the application using the * library is setuid. So, I need to make sure open the file as a normal * user. Unfortunately, there does not appear to be a portable way of * doing this, so I am going to use 'setfsgid' and 'setfsuid', which * are not portable. * * I will also look into the use of setreuid, seteuid and setregid, setegid. * FIXME: Priority=medium */ fp = fopen (file, "rb"); if (fp == NULL) return NULL; if ((12 == fread ((char *) buf, 1, 12, fp) && (MAGIC == make_integer (buf)))) { h->name_section_size = make_integer (buf + 2); h->boolean_section_size = make_integer (buf + 4); h->num_numbers = make_integer (buf + 6); h->num_string_offsets = make_integer (buf + 8); h->string_table_size = make_integer (buf + 10); } else { fclose (fp); fp = NULL; } return fp;}/* * The terminal names section comes next. It contains the first line of the * terminfo description, listing the various names for the terminal, * separated by the bar ( | ) character (see term(5)). The section is * terminated with an ASCII NUL character. *//* returns pointer to malloced space */static unsigned char *read_terminfo_section (FILE *fp, unsigned int size){ char *s; if (NULL == (s = (char *) SLmalloc (size))) return NULL; if (size != fread (s, 1, size, fp)) { SLfree (s); return NULL; } return (unsigned char *) s;}static char *read_terminal_names (FILE *fp, SLterminfo_Type *t){ return t->terminal_names = (char *) read_terminfo_section (fp, t->name_section_size);}/* * The boolean flags have one byte for each flag. This byte is either 0 or * 1 as the flag is present or absent. The value of 2 means that the flag * has been cancelled. The capabilities are in the same order as the file * <term.h>. */static unsigned char *read_boolean_flags (FILE *fp, SLterminfo_Type *t){ /* Between the boolean section and the number section, a null byte is * inserted, if necessary, to ensure that the number section begins on an * even byte offset. All short integers are aligned on a short word * boundary. */ unsigned int size = (t->name_section_size + t->boolean_section_size) % 2; size += t->boolean_section_size; return t->boolean_flags = read_terminfo_section (fp, size);}/* * The numbers section is similar to the boolean flags section. Each * capability takes up two bytes, and is stored as a short integer. If the * value represented is -1 or -2, the capability is taken to be missing. */static unsigned char *read_numbers (FILE *fp, SLterminfo_Type *t){ return t->numbers = read_terminfo_section (fp, 2 * t->num_numbers);}/* The strings section is also similar. Each capability is stored as a * short integer, in the format above. A value of -1 or -2 means the * capability is missing. Otherwise, the value is taken as an offset from * the beginning of the string table. Special characters in ^X or \c * notation are stored in their interpreted form, not the printing * representation. Padding information ($<nn>) and parameter information * (%x) are stored intact in uninterpreted form. */static unsigned char *read_string_offsets (FILE *fp, SLterminfo_Type *t){ return t->string_offsets = (unsigned char *) read_terminfo_section (fp, 2 * t->num_string_offsets);}/* The final section is the string table. It contains all the values of * string capabilities referenced in the string section. Each string is * null terminated. */static char *read_string_table (FILE *fp, SLterminfo_Type *t){ return t->string_table = (char *) read_terminfo_section (fp, t->string_table_size);}/* * Compiled terminfo(4) descriptions are placed under the directory * /usr/share/lib/terminfo. In order to avoid a linear search of a huge * UNIX system directory, a two-level scheme is used: * /usr/share/lib/terminfo/c/name where name is the name of the terminal, * and c is the first character of name. Thus, att4425 can be found in the * file /usr/share/lib/terminfo/a/att4425. Synonyms for the same terminal * are implemented by multiple links to the same compiled file. */static char *Terminfo_Dirs [] ={ NULL, /* $HOME/.terminfo */ NULL, /* $TERMINFO */ "/usr/share/terminfo", "/usr/lib/terminfo", "/usr/share/lib/terminfo", "/etc/terminfo", "/usr/local/lib/terminfo",#ifdef MISC_TERMINFO_DIRS MISC_TERMINFO_DIRS,#endif ""};SLterminfo_Type *_SLtt_tigetent (char *term){ char *tidir; int i; FILE *fp = NULL; char file[1024]; static char home_ti [1024]; char *home; SLterminfo_Type *ti; if ( (term == NULL)#ifdef SLANG_UNTIC && (SLang_Untic_Terminfo_File == NULL)#endif ) return NULL; if (_SLsecure_issetugid () && ((term[0] == '.') || (NULL != strchr (term, '/')))) return NULL; if (NULL == (ti = (SLterminfo_Type *) SLmalloc (sizeof (SLterminfo_Type)))) { return NULL; }#ifdef SLANG_UNTIC if (SLang_Untic_Terminfo_File != NULL) { fp = open_terminfo (SLang_Untic_Terminfo_File, ti); goto fp_open_label; } else#endif /* If we are on a termcap based system, use termcap */ if (0 == tcap_getent (term, ti)) return ti; if (NULL != (home = _SLsecure_getenv ("HOME"))) { strncpy (home_ti, home, sizeof (home_ti) - 11); home_ti [sizeof(home_ti) - 11] = 0; strcat (home_ti, "/.terminfo"); Terminfo_Dirs [0] = home_ti; } Terminfo_Dirs[1] = _SLsecure_getenv ("TERMINFO"); i = 0; while (1) { tidir = Terminfo_Dirs[i]; if (tidir != NULL) { if (*tidir == 0) break; /* last one */ if (sizeof (file) > strlen (tidir) + 2 + strlen (term)) { sprintf (file, "%s/%c/%s", tidir, *term, term); if (NULL != (fp = open_terminfo (file, ti))) break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -