1247aff56Sserge #ifndef lint
2*f1fb777fSserge static char *sccsid="@(#)showtc.c 1.9 (Berkeley) 11/01/85";
3d7112359Slayer #endif
4d7112359Slayer
53a84db2eSlayer /*
63a84db2eSlayer ** show termcap entries
73a84db2eSlayer **
83a84db2eSlayer ** where:
9c11c5bf6Slayer ** -D look for duplicate names and print termcap file
103a84db2eSlayer ** -S sort entries before display
11c11c5bf6Slayer ** -T trace (-DDEBUG only)
124ec13c9bSlayer ** -U print unknown capabilities
133a84db2eSlayer ** -b show bare entries
14c11c5bf6Slayer ** -d -D and stop
153a84db2eSlayer ** -f following arg is FULL PATHNAME of termcap file
16d7112359Slayer ** -g sort on generic names
17d7112359Slayer ** -s don't print two char name at the front of every line
18d7112359Slayer ** -x expand tc= capabilities
193a84db2eSlayer ** [ent] display specific entry. tc= will be expanded.
203a84db2eSlayer **
213a84db2eSlayer ** David L. Wasley, U.C.Berkeley
226b6d913cSlayer ** Kevin Layer: modified for 4.1c and misc changes.
236b6d913cSlayer ** Kevin Layer: added the printing of terminal capabilities
246b6d913cSlayer ** in `human' readable form (like that in "man 5 termcap").
253a84db2eSlayer */
263a84db2eSlayer
273a84db2eSlayer #include <stdio.h>
283a84db2eSlayer #include <sys/file.h>
293a84db2eSlayer #include <ctype.h>
30*f1fb777fSserge #include <sys/param.h>
313a84db2eSlayer #include <sys/stat.h>
323a84db2eSlayer
333a84db2eSlayer #define NO 0
343a84db2eSlayer #define YES 1
353a84db2eSlayer #define CNULL '\0'
363a84db2eSlayer #define NOENTRIES 1024
37d7112359Slayer #define USAGE "usage: %s [-Sxdngb] [-f termcapfile] [entry] ...\n"
383a84db2eSlayer
39*f1fb777fSserge #ifndef MAXPATHLEN
40*f1fb777fSserge #define MAXPATHLEN 1024
41*f1fb777fSserge #endif
42*f1fb777fSserge
433a84db2eSlayer struct TcName {
443a84db2eSlayer char name_buf[124];
453a84db2eSlayer long file_pos;
463a84db2eSlayer } tcNames[NOENTRIES];
473a84db2eSlayer
486b6d913cSlayer struct Caps {
496b6d913cSlayer char *cap;
506b6d913cSlayer char *desc;
51247aff56Sserge } capList[] =
526b6d913cSlayer {
53247aff56Sserge "AL", "Add N new blank lines",
54247aff56Sserge "CC", "Command char in prototype if settable",
55247aff56Sserge "DC", "Delete N characters",
56247aff56Sserge "DL", "Delete N lines",
57247aff56Sserge "DO", "Move cursor down N lines",
58247aff56Sserge "IC", "Insert N blank characters",
59247aff56Sserge "LE", "Move cursor left N positions",
60247aff56Sserge "RI", "Move cursor right N positions",
61247aff56Sserge "UP", "Move cursor up N lines",
626b6d913cSlayer "ae", "End alternate character set",
636b6d913cSlayer "al", "Add new blank line",
646b6d913cSlayer "am", "Has automatic margins",
656b6d913cSlayer "as", "Start alternate character set",
666b6d913cSlayer "bc", "Backspace if not ^H",
67247aff56Sserge "bl", "Audible Bell (default ^G)",
686b6d913cSlayer "bs", "Can backspace with ^H",
696b6d913cSlayer "bt", "Back tab",
706b6d913cSlayer "bw", "Backspace wraps from col 0 to last col",
716b6d913cSlayer "cd", "Clear to end of display",
726b6d913cSlayer "ce", "Clear to end of line",
736b6d913cSlayer "ch", "Like cm, but horizontal motion only",
746b6d913cSlayer "cl", "Clear screen",
756b6d913cSlayer "cm", "Cursor motion",
766b6d913cSlayer "co", "Number of columns in a line",
77247aff56Sserge "cr", "Carriage return (default ^M)",
786b6d913cSlayer "cs", "Change scrolling region (vt100), like cm",
79247aff56Sserge "ct", "Clear all tab stops",
806b6d913cSlayer "cv", "Like ch but vertical only.",
816b6d913cSlayer "dB", "Number of millisec of bs delay needed",
826b6d913cSlayer "dC", "Number of millisec of cr delay needed",
836b6d913cSlayer "dF", "Number of millisec of ff delay needed",
84247aff56Sserge "dN", "Number of millisec of nl delay needed",
85247aff56Sserge "dT", "Number of millisec of tab delay needed",
86247aff56Sserge "da", "Display may be retained above",
87247aff56Sserge "db", "Display may be retained below",
88247aff56Sserge "dc", "Delete character",
896b6d913cSlayer "dl", "Delete line",
906b6d913cSlayer "dm", "Start Delete mode",
916b6d913cSlayer "do", "Down one line",
92c87a32d3Slayer "ds", "Disable status display",
936b6d913cSlayer "ed", "End delete mode",
946b6d913cSlayer "ei", "End insert mode;give \":ei=:\" if ic",
956b6d913cSlayer "eo", "Can erase overstrikes with a blank",
96c87a32d3Slayer "es", "Escape seq's ok on status line",
976b6d913cSlayer "ff", "Hardcopy page eject (default ^L)",
986b6d913cSlayer "fs", "From status line sequence",
996b6d913cSlayer "hc", "Hardcopy terminal",
1006b6d913cSlayer "hd", "Half-line down (forward 1/2 lf)",
1016b6d913cSlayer "ho", "Home cursor (if no cm)",
102247aff56Sserge "hs", "Has status line",
1036b6d913cSlayer "hu", "Half-line up (reverse 1/2 lf)",
1046b6d913cSlayer "hz", "Hazeltine; can't print ~'s",
105247aff56Sserge "i2", "Initialization string (used by sysline(1))",
1066b6d913cSlayer "ic", "Insert character",
1076b6d913cSlayer "if", "Name of file containing is",
1086b6d913cSlayer "im", "Start insert mode;give \":im=:\" if ic",
1096b6d913cSlayer "in", "Insert mode distinguishes nulls on display",
1106b6d913cSlayer "ip", "Insert pad after character inserted",
1116b6d913cSlayer "is", "Initialization string",
112247aff56Sserge "k0", "Sent by function key 0",
113247aff56Sserge "k1", "Sent by function key 1",
114247aff56Sserge "k2", "Sent by function key 2",
115247aff56Sserge "k3", "Sent by function key 3",
116247aff56Sserge "k4", "Sent by function key 4",
117247aff56Sserge "k5", "Sent by function key 5",
118247aff56Sserge "k6", "Sent by function key 6",
119247aff56Sserge "k7", "Sent by function key 7",
120247aff56Sserge "k8", "Sent by function key 8",
121247aff56Sserge "k9", "Sent by function key 9",
1226b6d913cSlayer "kb", "Sent by backspace key",
123247aff56Sserge "kd", "Sent by down arrow key",
1246b6d913cSlayer "ke", "Out of \"keypad transmit\" mode",
1256b6d913cSlayer "kh", "Sent by home key",
1266b6d913cSlayer "kl", "Sent by left arrow key",
127247aff56Sserge "km", "Has a \"meta\" key (shift, sets parity bit)",
1286b6d913cSlayer "kn", "Number of \"other\" keys",
1296b6d913cSlayer "ko", "Tc entries for other non-function keys",
1306b6d913cSlayer "kr", "Sent by right arrow key",
1316b6d913cSlayer "ks", "Put in \"keypad transmit\" mode",
1326b6d913cSlayer "ku", "Sent by up arrow key",
133247aff56Sserge "l0", "Label on function key 0 (if not \"0\")",
134247aff56Sserge "l1", "Label on function key 1 (if not \"1\")",
135247aff56Sserge "l2", "Label on function key 2 (if not \"2\")",
136247aff56Sserge "l3", "Label on function key 3 (if not \"3\")",
137247aff56Sserge "l4", "Label on function key 4 (if not \"4\")",
138247aff56Sserge "l5", "Label on function key 5 (if not \"5\")",
139247aff56Sserge "l6", "Label on function key 6 (if not \"6\")",
140247aff56Sserge "l7", "Label on function key 7 (if not \"7\")",
141247aff56Sserge "l8", "Label on function key 8 (if not \"8\")",
142247aff56Sserge "l9", "Label on function key 9 (if not \"9\")",
1434ec13c9bSlayer "le", "Move left",
1446b6d913cSlayer "li", "Number of lines on screen or page",
1456b6d913cSlayer "ll", "Last line, first column (if no cm)",
1466b6d913cSlayer "ma", "Arrow key map, used by vi V2 only",
1474ec13c9bSlayer "mb", "Enter blinking mode",
1484ec13c9bSlayer "md", "Enter bold mode",
1494ec13c9bSlayer "me", "Reset video attributes",
1504ec13c9bSlayer "mh", "Enter halfbright mode",
1516b6d913cSlayer "mi", "Safe to move while in insert mode",
1524ec13c9bSlayer "mk", "Enter protected mode",
1536b6d913cSlayer "ml", "Memory lock on above cursor.",
154247aff56Sserge "mp", "Turn on protected attribute",
1554ec13c9bSlayer "mr", "Enter reverse video mode",
1566b6d913cSlayer "ms", "Ok to move while in standout/underline mode",
1576b6d913cSlayer "mu", "Memory unlock (turn off memory lock).",
1586b6d913cSlayer "nc", "No working CR (DM2500,H2000)",
1596b6d913cSlayer "nd", "Non-destructive space (cursor right)",
1606b6d913cSlayer "nl", "Newline character (default \\n)",
1616b6d913cSlayer "ns", "Is a CRT but doesn't scroll.",
1626b6d913cSlayer "os", "Terminal overstrikes",
163247aff56Sserge "pb", "Lowest baud where delays are required",
1646b6d913cSlayer "pc", "Pad character (rather than null)",
165247aff56Sserge "pl", "Program function key N to execute string S (terminfo only)",
1666b6d913cSlayer "pt", "Has hardware tabs (may need to use is)",
167247aff56Sserge "rc", "Restore cursor to position of last sc",
168247aff56Sserge "rf", "Name of file containing reset codes",
169247aff56Sserge "rs", "Reset terminal completely to sane modes",
170247aff56Sserge "sc", "Save cursor position",
1716b6d913cSlayer "se", "End stand out mode",
1726b6d913cSlayer "sf", "Scroll forwards",
1736b6d913cSlayer "sg", "Number of blank chars left by so/se",
1746b6d913cSlayer "so", "Begin stand out mode",
1756b6d913cSlayer "sr", "Scroll reverse (backwards)",
176247aff56Sserge "st", "Set a tab in all rows, current column",
1776b6d913cSlayer "ta", "Tab (other than ^I or with padding)",
1786b6d913cSlayer "tc", "Entry of similar terminal - must be last",
1796b6d913cSlayer "te", "String to end programs that use cm",
1806b6d913cSlayer "ti", "String to begin programs that use cm",
1816b6d913cSlayer "ts", "To status line sequence",
1826b6d913cSlayer "uc", "Underscore one char and move past it",
1836b6d913cSlayer "ue", "End underscore mode",
1846b6d913cSlayer "ug", "Number of blank chars left by us or ue",
1856b6d913cSlayer "ul", "Underlines, though no overstrike",
1866b6d913cSlayer "up", "Upline (cursor up)",
1876b6d913cSlayer "us", "Start underscore mode",
1886b6d913cSlayer "vb", "Visible bell (may not move cursor)",
1896b6d913cSlayer "ve", "Sequence to end open/visual mode",
1906b6d913cSlayer "vs", "Sequence to start open/visual mode",
191247aff56Sserge "vt", "Virtual terminal number (not supported on all systems)",
1926b6d913cSlayer "xb", "Beehive (f1=escape, f2=ctrl C)",
1936b6d913cSlayer "xn", "A newline is ignored after a wrap (Concept)",
1946b6d913cSlayer "xr", "Return acts like ce \\r \\n (Delta Data)",
1956b6d913cSlayer "xs", "Standout not erased by writing over it (HP 264?)",
1966b6d913cSlayer "xt", "Destructive tabs, magic so char (Teleray 1061)"
1976b6d913cSlayer };
1986b6d913cSlayer
199247aff56Sserge #define NOCAPS (sizeof capList / sizeof *capList)
200247aff56Sserge
2013a84db2eSlayer #ifdef DEBUG
2023a84db2eSlayer int Dflag = NO;
2033a84db2eSlayer #endif
2043a84db2eSlayer int xflag = NO;
205d7112359Slayer int Sflag = YES;
206d7112359Slayer int sflag = NO;
2073a84db2eSlayer int dflag = NO;
2083a84db2eSlayer int nflag = NO;
2093a84db2eSlayer int gflag = NO;
2103a84db2eSlayer int bflag = NO;
2114ec13c9bSlayer int Uflag = NO;
2123a84db2eSlayer int tc_loopc; /* loop counter */
2133a84db2eSlayer char *tcfile; /* termcap database pathname */
214*f1fb777fSserge char cwd[MAXPATHLEN]; /* current working directory */
2155c2942c8Slayer char tcbuf[2048]; /* buffer for termcap description */
2163a84db2eSlayer char *lastchar();
2173a84db2eSlayer int name_cmp();
2183a84db2eSlayer int ent_cmp();
2193a84db2eSlayer struct TcName *find_name();
2203a84db2eSlayer char *getenv();
2213a84db2eSlayer char *ctime();
2223a84db2eSlayer char *strncpy();
2233a84db2eSlayer long ftell();
2243a84db2eSlayer
main(argc,argv,envp)2253a84db2eSlayer main(argc, argv, envp)
2263a84db2eSlayer int argc;
2273a84db2eSlayer char **argv;
2283a84db2eSlayer char **envp;
2293a84db2eSlayer {
2303a84db2eSlayer char *av;
2313a84db2eSlayer struct TcName *tn;
2323a84db2eSlayer register char *bp;
2333a84db2eSlayer long pos;
2343a84db2eSlayer int n;
2353a84db2eSlayer struct stat st;
2363a84db2eSlayer char envbuf[256];
2373a84db2eSlayer FILE *tcfp;
2383a84db2eSlayer
2393a84db2eSlayer if ((bp = getenv("TERMCAP")) && *bp == '/')
2403a84db2eSlayer tcfile = bp;
2413a84db2eSlayer else
2423a84db2eSlayer tcfile = "/etc/termcap";
2433a84db2eSlayer
2443a84db2eSlayer while (--argc > 0)
2453a84db2eSlayer {
2463a84db2eSlayer if (*(av = *++argv) == '-')
2473a84db2eSlayer {
2483a84db2eSlayer while (*++av)
2493a84db2eSlayer {
2503a84db2eSlayer switch (*av)
2513a84db2eSlayer {
2523a84db2eSlayer /* use alternate termcap file */
2533a84db2eSlayer case 'f':
2543a84db2eSlayer if (argc-- <= 0)
2553a84db2eSlayer {
2563a84db2eSlayer fprintf(stderr,
2573a84db2eSlayer "-f needs a filename\n");
2583a84db2eSlayer exit(1);
2593a84db2eSlayer }
2603a84db2eSlayer tcfile = *++argv;
2613a84db2eSlayer break;
2623a84db2eSlayer
2633a84db2eSlayer /* only check for dup names */
264c11c5bf6Slayer case 'd':
2653a84db2eSlayer nflag = YES;
2663a84db2eSlayer /* fall thru */
2673a84db2eSlayer
2683a84db2eSlayer /* look for duplicated names */
269c11c5bf6Slayer case 'D':
2703a84db2eSlayer dflag = YES;
2713a84db2eSlayer continue;
2723a84db2eSlayer
2734ec13c9bSlayer case 'U':
2744ec13c9bSlayer Uflag = YES;
2754ec13c9bSlayer continue;
2764ec13c9bSlayer
277d7112359Slayer /* strip the two name off */
278d7112359Slayer case 's':
279d7112359Slayer sflag = YES;
280d7112359Slayer continue;
281d7112359Slayer
2823a84db2eSlayer /* sort the name array */
2833a84db2eSlayer case 'S':
284d7112359Slayer Sflag = NO;
2853a84db2eSlayer continue;
2863a84db2eSlayer
2873a84db2eSlayer #ifdef DEBUG
288c11c5bf6Slayer case 'T':
2893a84db2eSlayer Dflag = YES;
2903a84db2eSlayer continue;
2913a84db2eSlayer #endif
2923a84db2eSlayer
2933a84db2eSlayer /* sort on generic names */
2943a84db2eSlayer case 'g':
2953a84db2eSlayer gflag = YES;
2963a84db2eSlayer continue;
2973a84db2eSlayer
2983a84db2eSlayer /* expand entries in 'full mode' */
2993a84db2eSlayer case 'x':
3003a84db2eSlayer xflag = YES;
3013a84db2eSlayer continue;
3023a84db2eSlayer
3033a84db2eSlayer /* show bare entry */
3043a84db2eSlayer case 'b':
3053a84db2eSlayer bflag = YES;
3063a84db2eSlayer continue;
3073a84db2eSlayer
3083a84db2eSlayer default:
3093a84db2eSlayer fprintf(stderr, "showtc: unknown flag: -%c\n", *av);
3103a84db2eSlayer fprintf(stderr, USAGE, argv[0]);
3113a84db2eSlayer exit(1);
3123a84db2eSlayer }
3133a84db2eSlayer }
3143a84db2eSlayer }
3153a84db2eSlayer else
3163a84db2eSlayer break;
3173a84db2eSlayer }
3183a84db2eSlayer
3193a84db2eSlayer /*
3203a84db2eSlayer * insert the specified TERMCAP file into the environment
3213a84db2eSlayer */
322*f1fb777fSserge if (*tcfile != '/') {
323*f1fb777fSserge char *getwd();
324*f1fb777fSserge
325*f1fb777fSserge if (getwd(cwd) == NULL) {
326*f1fb777fSserge fprintf(stderr, "showtc: %s\n", cwd);
327*f1fb777fSserge exit(1);
328*f1fb777fSserge } else if (strlen(cwd) + strlen(tcfile) + 2 > sizeof cwd) {
329*f1fb777fSserge fprintf(stderr, "showtc: %s\n",
330*f1fb777fSserge "Current working directory name too long");
331*f1fb777fSserge exit(1);
332*f1fb777fSserge } else {
333*f1fb777fSserge if (cwd[strlen(cwd) - 1] != '/')
334*f1fb777fSserge strcat(cwd, "/");
335*f1fb777fSserge strcat(cwd, tcfile);
336*f1fb777fSserge tcfile = cwd;
337*f1fb777fSserge }
338*f1fb777fSserge }
3393a84db2eSlayer (void) sprintf(envbuf, "TERMCAP=%s", tcfile);
3403a84db2eSlayer while (*envp)
3413a84db2eSlayer {
3423a84db2eSlayer if (strncmp(*envp, "TERMCAP=", 8) == 0)
3433a84db2eSlayer {
3443a84db2eSlayer *envp = envbuf;
3453a84db2eSlayer break;
3463a84db2eSlayer }
3473a84db2eSlayer envp++;
3483a84db2eSlayer }
3493a84db2eSlayer if (! *envp)
3503a84db2eSlayer *envp = envbuf; /* this may be dangerous */
3513a84db2eSlayer
3523a84db2eSlayer /*
3533a84db2eSlayer ** if user specified type(s), do only those
3543a84db2eSlayer */
3553a84db2eSlayer if (argc > 0)
3563a84db2eSlayer {
3573a84db2eSlayer /*
3583a84db2eSlayer ** look for the users specified term types
3593a84db2eSlayer */
3603a84db2eSlayer while (argc > 0)
3613a84db2eSlayer {
3623a84db2eSlayer switch (n = tgetent(tcbuf, *argv))
3633a84db2eSlayer {
3643a84db2eSlayer case 1:
3653a84db2eSlayer if (bflag)
3663a84db2eSlayer (void) prnt_raw(tcbuf);
3673a84db2eSlayer else
3683a84db2eSlayer (void) prnt_ent(tcbuf);
3693a84db2eSlayer break;
3703a84db2eSlayer
3713a84db2eSlayer case 0:
3723a84db2eSlayer fprintf(stderr,
3733a84db2eSlayer "showtc: bad entry: %s\n", *argv);
3743a84db2eSlayer break;
3753a84db2eSlayer
3763a84db2eSlayer case -1:
3773a84db2eSlayer fputs("showtc: ", stderr);
3783a84db2eSlayer perror(tcfile);
3793a84db2eSlayer exit(1);
3803a84db2eSlayer
3813a84db2eSlayer default:
3823a84db2eSlayer fprintf(stderr, "bad return from tgetent: %d\n", n);
3833a84db2eSlayer exit(1);
3843a84db2eSlayer }
3853a84db2eSlayer argc--;
3863a84db2eSlayer argv++;
3873a84db2eSlayer }
3883a84db2eSlayer exit(0);
3893a84db2eSlayer }
3903a84db2eSlayer
3913a84db2eSlayer if (bflag)
3923a84db2eSlayer {
3933a84db2eSlayer fprintf(stderr, "showtc: -b flag with no entries makes no sense.\n");
3943a84db2eSlayer exit(1);
3953a84db2eSlayer }
3963a84db2eSlayer
3973a84db2eSlayer
3983a84db2eSlayer /*
3993a84db2eSlayer ** if no type was specified, do the whole file
4003a84db2eSlayer */
4013a84db2eSlayer if ((tcfp = fopen(tcfile, "r")) == NULL)
4023a84db2eSlayer {
4033a84db2eSlayer perror(tcfile);
4043a84db2eSlayer exit(1);
4053a84db2eSlayer }
4063a84db2eSlayer
4073a84db2eSlayer /*
4083a84db2eSlayer ** identify database, for the record
4093a84db2eSlayer */
4103a84db2eSlayer if (stat(tcfile, &st))
4113a84db2eSlayer {
4123a84db2eSlayer perror(tcfile);
4133a84db2eSlayer exit(1);
4143a84db2eSlayer }
4153a84db2eSlayer printf("File: %s, last modified: %s\n", tcfile, ctime(&st.st_mtime));
4163a84db2eSlayer
4173a84db2eSlayer
4183a84db2eSlayer /*
4193a84db2eSlayer ** build termcap entry table
4203a84db2eSlayer */
4213a84db2eSlayer tn = tcNames;
4223a84db2eSlayer pos = ftell(tcfp);
4233a84db2eSlayer bp = tcbuf;
4243a84db2eSlayer while (fgets(bp, sizeof (tcbuf), tcfp) != NULL)
4253a84db2eSlayer {
4263a84db2eSlayer if (tcbuf[0] == '#')
4273a84db2eSlayer {
4283a84db2eSlayer pos = ftell(tcfp);
4293a84db2eSlayer bp = tcbuf;
4303a84db2eSlayer continue;
4313a84db2eSlayer }
4323a84db2eSlayer
4333a84db2eSlayer tn->file_pos = pos;
4343a84db2eSlayer
4353a84db2eSlayer /*
4363a84db2eSlayer ** get full entry
4373a84db2eSlayer */
4383a84db2eSlayer while (*(bp = lastchar(bp)) == '\\' && fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp))
4393a84db2eSlayer ;
4403a84db2eSlayer /*
4413a84db2eSlayer ** save the names
4423a84db2eSlayer */
4433a84db2eSlayer for (bp = tcbuf; *bp && *bp != ':'; bp++)
4443a84db2eSlayer ;
4453a84db2eSlayer *bp = '\0';
4463a84db2eSlayer (void) strncpy(tn->name_buf, tcbuf,
4473a84db2eSlayer sizeof tcNames[0].name_buf);
4483a84db2eSlayer
4493a84db2eSlayer pos = ftell(tcfp);
4503a84db2eSlayer bp = tcbuf;
4513a84db2eSlayer tn++;
4523a84db2eSlayer }
4533a84db2eSlayer tn->file_pos = -1;
4543a84db2eSlayer
4553a84db2eSlayer /*
4563a84db2eSlayer ** Look for duplicate names
4573a84db2eSlayer */
4583a84db2eSlayer if (dflag)
4593a84db2eSlayer check_dup();
4603a84db2eSlayer if (nflag)
4613a84db2eSlayer exit(0);
4623a84db2eSlayer
4633a84db2eSlayer #ifdef DEBUG
4643a84db2eSlayer if (Dflag)
4653a84db2eSlayer {
4663a84db2eSlayer for (tn = tcNames; tn->file_pos >= 0; tn++)
4673a84db2eSlayer {
4683a84db2eSlayer printf("Entry #%d:\n\t%s\n\tfile_pos = %ld\n",
4693a84db2eSlayer tn - tcNames, tn->name_buf, tn->file_pos);
4703a84db2eSlayer }
4713a84db2eSlayer exit(0);
4723a84db2eSlayer }
4733a84db2eSlayer #endif
4743a84db2eSlayer
4753a84db2eSlayer /*
4763a84db2eSlayer ** Order the list
4773a84db2eSlayer */
478d7112359Slayer if (Sflag)
4793a84db2eSlayer qsort((char *)tcNames, tn - tcNames,
4803a84db2eSlayer sizeof (struct TcName), name_cmp);
4813a84db2eSlayer
4823a84db2eSlayer /*
4833a84db2eSlayer ** List termcap entry for each name in table
4843a84db2eSlayer */
4853a84db2eSlayer for (tn = tcNames; tn->file_pos >= 0; tn++)
4863a84db2eSlayer {
4873a84db2eSlayer tc_loopc = 0;
4883a84db2eSlayer /*** working toward this ...
4893a84db2eSlayer (void) prnt_ent(tn);
4903a84db2eSlayer ***/
4913a84db2eSlayer (void) fseek(tcfp, tn->file_pos, 0);
4923a84db2eSlayer bp = tcbuf;
4933a84db2eSlayer while (fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp)
4943a84db2eSlayer && *(bp = lastchar(bp)) == '\\')
4953a84db2eSlayer ;
4963a84db2eSlayer (void) prnt_ent(tcbuf);
4973a84db2eSlayer }
4983a84db2eSlayer }
4993a84db2eSlayer
5003a84db2eSlayer char *
lastchar(b)5013a84db2eSlayer lastchar(b)
5023a84db2eSlayer char *b;
5033a84db2eSlayer {
5043a84db2eSlayer register char *p;
5053a84db2eSlayer
5063a84db2eSlayer p = b + strlen(b) - 1;
5073a84db2eSlayer while (*p == '\n' || *p == ' ')
5083a84db2eSlayer p--;
5093a84db2eSlayer return(p);
5103a84db2eSlayer }
5113a84db2eSlayer
name_cmp(a,b)5123a84db2eSlayer name_cmp(a, b)
5133a84db2eSlayer char *a, *b;
5143a84db2eSlayer {
5153a84db2eSlayer if (gflag) /* sort on generic names */
5163a84db2eSlayer {
5173a84db2eSlayer a += 3;
5183a84db2eSlayer b += 3;
5193a84db2eSlayer while (*a && *b && *a != '|' && *a == *b)
5203a84db2eSlayer {
5213a84db2eSlayer a++;
5223a84db2eSlayer b++;
5233a84db2eSlayer }
5243a84db2eSlayer if (*a == '|' || *a == CNULL)
5253a84db2eSlayer return((*b == '|' || *b == CNULL)? 0:-1);
5263a84db2eSlayer if (*b == '|' || *b == CNULL)
5273a84db2eSlayer return(1);
5283a84db2eSlayer return(*a - *b);
5293a84db2eSlayer }
5303a84db2eSlayer return(strncmp(a, b, 2));
5313a84db2eSlayer }
5323a84db2eSlayer
prnt_ent(buf)5333a84db2eSlayer prnt_ent(buf)
5343a84db2eSlayer register char *buf;
5353a84db2eSlayer {
5363a84db2eSlayer register char *name;
5376b6d913cSlayer char *getdesc();
5383a84db2eSlayer char *caps[256];
5393a84db2eSlayer register char **cp;
5403a84db2eSlayer register char **tp;
5413a84db2eSlayer char tname[3];
5423a84db2eSlayer
5433a84db2eSlayer cp = caps;
5443a84db2eSlayer name = buf;
5453a84db2eSlayer tname[3] = '\0';
5463a84db2eSlayer
5473a84db2eSlayer while (*buf)
5483a84db2eSlayer {
5493a84db2eSlayer switch (*buf)
5503a84db2eSlayer {
5513a84db2eSlayer case ':':
5523a84db2eSlayer *buf++ = '\0';
5533a84db2eSlayer while (*buf && !isalnum(*buf))
5543a84db2eSlayer buf++;
5553a84db2eSlayer if (*buf)
5563a84db2eSlayer {
5573a84db2eSlayer /*
5583a84db2eSlayer * ignore duplicate cap entries
5593a84db2eSlayer */
5603a84db2eSlayer for (tp = caps; tp < cp; tp++)
5613a84db2eSlayer if (strncmp(buf, *tp, 2) == 0)
5623a84db2eSlayer goto skip;
5633a84db2eSlayer *cp++ = buf;
5643a84db2eSlayer skip:
5653a84db2eSlayer /*
5663a84db2eSlayer * does user want tc= expanded?
5673a84db2eSlayer */
5683a84db2eSlayer if (xflag && strncmp(buf, "tc=", 3) == 0)
5693a84db2eSlayer {
5703a84db2eSlayer /*
5713a84db2eSlayer * find end of tc=
5723a84db2eSlayer */
5733a84db2eSlayer while (*buf != ':')
5743a84db2eSlayer buf++;
5753a84db2eSlayer *buf = '\0';
5763a84db2eSlayer /*
5773a84db2eSlayer * save term name
5783a84db2eSlayer */
5793a84db2eSlayer tname[0] = name[0];
5803a84db2eSlayer tname[1] = name[1];
5813a84db2eSlayer printf("%s: expanding %s\n",
5823a84db2eSlayer tname, cp[-1]);
5833a84db2eSlayer /*
5843a84db2eSlayer * let tgetent do the work
5853a84db2eSlayer */
5863a84db2eSlayer tgetent(tcbuf, tname);
5873a84db2eSlayer prnt_ent(tcbuf);
5883a84db2eSlayer return;
5893a84db2eSlayer }
5903a84db2eSlayer }
5913a84db2eSlayer continue;
5923a84db2eSlayer
5933a84db2eSlayer case '|':
5943a84db2eSlayer *buf++ = ',';
5953a84db2eSlayer continue;
5963a84db2eSlayer
5973a84db2eSlayer default:
5983a84db2eSlayer buf++;
5993a84db2eSlayer }
6003a84db2eSlayer }
6013a84db2eSlayer *cp = CNULL; /* was (char *)0 */
6023a84db2eSlayer
603d7112359Slayer if (Sflag)
6043a84db2eSlayer qsort((char *) caps, cp - caps, sizeof (char *), ent_cmp);
6053a84db2eSlayer
6063a84db2eSlayer printf("%s\n", name);
6073a84db2eSlayer for (cp = caps; *cp; cp++)
6084ec13c9bSlayer if (Uflag) {
6094ec13c9bSlayer if (unknowncap(*cp)) {
6104ec13c9bSlayer printf("%3.3s\n", *cp);
6114ec13c9bSlayer }
6124ec13c9bSlayer } else if (sflag) {
6136b6d913cSlayer printf("%-45s %s\n", getdesc(*cp), *cp);
6144ec13c9bSlayer } else {
6156b6d913cSlayer printf("%2.2s %-45s %s\n", name, getdesc(*cp), *cp);
6166b6d913cSlayer }
6173a84db2eSlayer (void) putchar('\n');
6183a84db2eSlayer }
6193a84db2eSlayer
prnt_raw(buf)6203a84db2eSlayer prnt_raw(buf)
6213a84db2eSlayer char *buf;
6223a84db2eSlayer {
6233a84db2eSlayer register char *b;
6243a84db2eSlayer register int len;
6253a84db2eSlayer register int n;
6263a84db2eSlayer char *index();
6273a84db2eSlayer
6283a84db2eSlayer len = 0;
6293a84db2eSlayer b = buf;
6303a84db2eSlayer while (*b)
6313a84db2eSlayer {
6323a84db2eSlayer if ((n = index(b, ':') - b + 1) <= 0)
6333a84db2eSlayer n = strlen(b);
6343a84db2eSlayer if (len == 0) /* first part */
6353a84db2eSlayer {
6363a84db2eSlayer printf("%.*s\\\n\t:", n, b);
6373a84db2eSlayer len = 9 - n;
6383a84db2eSlayer }
6393a84db2eSlayer else
6403a84db2eSlayer {
6413a84db2eSlayer if ((len + n) >= 75)
6423a84db2eSlayer {
6433a84db2eSlayer printf("\\\n\t:");
6443a84db2eSlayer len = 9;
6453a84db2eSlayer }
6463a84db2eSlayer printf("%.*s", n, b);
6473a84db2eSlayer }
6483a84db2eSlayer len += n;
6493a84db2eSlayer b += n;
6503a84db2eSlayer while (*b && index(" \t:\n", *b))
6513a84db2eSlayer b++;
6523a84db2eSlayer }
6533a84db2eSlayer if (b[-1] != ':')
6543a84db2eSlayer (void) putchar(':');
6553a84db2eSlayer (void) putchar('\n');
6563a84db2eSlayer }
6573a84db2eSlayer
ent_cmp(a,b)6583a84db2eSlayer ent_cmp(a, b)
6593a84db2eSlayer char **a, **b;
6603a84db2eSlayer {
6613a84db2eSlayer return(strncmp(*a, *b, 2));
6623a84db2eSlayer }
6633a84db2eSlayer
check_dup()6643a84db2eSlayer check_dup()
6653a84db2eSlayer {
6663a84db2eSlayer /*
6673a84db2eSlayer ** Look for duplicated names
6683a84db2eSlayer */
6693a84db2eSlayer register char *p;
6703a84db2eSlayer register char *q;
6713a84db2eSlayer register struct TcName *tn;
6723a84db2eSlayer register struct TcName *tm;
6733a84db2eSlayer
6743a84db2eSlayer tn = tcNames;
6753a84db2eSlayer while (tn->file_pos >= 0)
6763a84db2eSlayer {
6773a84db2eSlayer p = q = tn->name_buf;
6783a84db2eSlayer while (*q)
6793a84db2eSlayer {
6803a84db2eSlayer while (*p && *p != '|')
6813a84db2eSlayer p++;
6823a84db2eSlayer if (p != q && (tm = find_name(q, tn + 1, p - q)))
6833a84db2eSlayer {
6843a84db2eSlayer fputs("Duplicate name: ", stdout);
6853a84db2eSlayer while (q != p)
6863a84db2eSlayer (void) putchar(*q++);
6873a84db2eSlayer (void) putchar('\n');
6883a84db2eSlayer puts(tn->name_buf);
6893a84db2eSlayer puts(tm->name_buf);
6903a84db2eSlayer puts("---\n");
6913a84db2eSlayer }
6923a84db2eSlayer if (*p == '|')
6933a84db2eSlayer p++;
6943a84db2eSlayer q = p;
6953a84db2eSlayer }
6963a84db2eSlayer tn++;
6973a84db2eSlayer }
6983a84db2eSlayer }
6993a84db2eSlayer
7003a84db2eSlayer struct TcName *
find_name(name,tn,len)7013a84db2eSlayer find_name(name, tn, len)
7023a84db2eSlayer register char *name;
7033a84db2eSlayer register struct TcName *tn;
7043a84db2eSlayer register int len;
7053a84db2eSlayer {
7063a84db2eSlayer /*
7073a84db2eSlayer ** find name of length len in tcname structure buffers.
7083a84db2eSlayer */
7093a84db2eSlayer register char *p;
7103a84db2eSlayer register char *buf;
7113a84db2eSlayer register int n;
7123a84db2eSlayer
7133a84db2eSlayer while (tn->file_pos >= 0)
7143a84db2eSlayer {
7153a84db2eSlayer buf = tn->name_buf;
7163a84db2eSlayer while (*buf)
7173a84db2eSlayer {
7183a84db2eSlayer p = name;
7193a84db2eSlayer n = len;
7203a84db2eSlayer if (*buf == '|')
7213a84db2eSlayer buf++;
7223a84db2eSlayer
7233a84db2eSlayer while (*buf && *buf != '|')
7243a84db2eSlayer {
7253a84db2eSlayer if (*p != *buf)
7263a84db2eSlayer {
7273a84db2eSlayer while (*buf && *buf != '|')
7283a84db2eSlayer buf++;
7293a84db2eSlayer break;
7303a84db2eSlayer }
7313a84db2eSlayer
7323a84db2eSlayer if (--n <= 0)
7333a84db2eSlayer {
7343a84db2eSlayer buf++;
7353a84db2eSlayer if (*buf == '|' || *buf == '\0')
7363a84db2eSlayer return(tn);
7373a84db2eSlayer while (*buf && *buf != '|')
7383a84db2eSlayer buf++;
7393a84db2eSlayer break;
7403a84db2eSlayer }
7413a84db2eSlayer buf++;
7423a84db2eSlayer p++;
7433a84db2eSlayer }
7443a84db2eSlayer }
7453a84db2eSlayer tn++;
7463a84db2eSlayer }
7473a84db2eSlayer return((struct TcName *)0);
7483a84db2eSlayer }
7496b6d913cSlayer
7506b6d913cSlayer char *
getdesc(key)7516b6d913cSlayer getdesc(key)
7526b6d913cSlayer char *key;
7536b6d913cSlayer {
7546b6d913cSlayer register int i;
7556b6d913cSlayer
756*f1fb777fSserge for (i = 0; i < NOCAPS; i++)
7576b6d913cSlayer if (strncmp(key, capList[i].cap, 2) == 0)
7586b6d913cSlayer return (capList[i].desc);
759c11c5bf6Slayer return("");
7606b6d913cSlayer }
7614ec13c9bSlayer
unknowncap(key)7624ec13c9bSlayer unknowncap(key)
7634ec13c9bSlayer char *key;
7644ec13c9bSlayer {
7654ec13c9bSlayer register int i;
7664ec13c9bSlayer
767*f1fb777fSserge for (i = 0; i < NOCAPS; i++)
7684ec13c9bSlayer if (strncmp(key, capList[i].cap, 2) == 0)
7694ec13c9bSlayer return (0);
7704ec13c9bSlayer return(1);
7714ec13c9bSlayer }
772