125326Sserge #ifndef lint
2*25372Sserge static char *sccsid="@(#)showtc.c 1.9 (Berkeley) 11/01/85";
312044Slayer #endif
412044Slayer
512031Slayer /*
612031Slayer ** show termcap entries
712031Slayer **
812031Slayer ** where:
912458Slayer ** -D look for duplicate names and print termcap file
1012031Slayer ** -S sort entries before display
1112458Slayer ** -T trace (-DDEBUG only)
1213250Slayer ** -U print unknown capabilities
1312044Slayer ** -b show bare entries
1412458Slayer ** -d -D and stop
1512044Slayer ** -f following arg is FULL PATHNAME of termcap file
1612044Slayer ** -g sort on generic names
1712044Slayer ** -s don't print two char name at the front of every line
1812044Slayer ** -x expand tc= capabilities
1912031Slayer ** [ent] display specific entry. tc= will be expanded.
2012031Slayer **
2112031Slayer ** David L. Wasley, U.C.Berkeley
2212446Slayer ** Kevin Layer: modified for 4.1c and misc changes.
2312446Slayer ** Kevin Layer: added the printing of terminal capabilities
2412446Slayer ** in `human' readable form (like that in "man 5 termcap").
2512031Slayer */
2612031Slayer
2712031Slayer #include <stdio.h>
2812031Slayer #include <sys/file.h>
2912031Slayer #include <ctype.h>
30*25372Sserge #include <sys/param.h>
3112031Slayer #include <sys/stat.h>
3212031Slayer
3312031Slayer #define NO 0
3412031Slayer #define YES 1
3512031Slayer #define CNULL '\0'
3612031Slayer #define NOENTRIES 1024
3712044Slayer #define USAGE "usage: %s [-Sxdngb] [-f termcapfile] [entry] ...\n"
3812031Slayer
39*25372Sserge #ifndef MAXPATHLEN
40*25372Sserge #define MAXPATHLEN 1024
41*25372Sserge #endif
42*25372Sserge
4312031Slayer struct TcName {
4412031Slayer char name_buf[124];
4512031Slayer long file_pos;
4612031Slayer } tcNames[NOENTRIES];
4712031Slayer
4812446Slayer struct Caps {
4912446Slayer char *cap;
5012446Slayer char *desc;
5125326Sserge } capList[] =
5212446Slayer {
5325326Sserge "AL", "Add N new blank lines",
5425326Sserge "CC", "Command char in prototype if settable",
5525326Sserge "DC", "Delete N characters",
5625326Sserge "DL", "Delete N lines",
5725326Sserge "DO", "Move cursor down N lines",
5825326Sserge "IC", "Insert N blank characters",
5925326Sserge "LE", "Move cursor left N positions",
6025326Sserge "RI", "Move cursor right N positions",
6125326Sserge "UP", "Move cursor up N lines",
6212446Slayer "ae", "End alternate character set",
6312446Slayer "al", "Add new blank line",
6412446Slayer "am", "Has automatic margins",
6512446Slayer "as", "Start alternate character set",
6612446Slayer "bc", "Backspace if not ^H",
6725326Sserge "bl", "Audible Bell (default ^G)",
6812446Slayer "bs", "Can backspace with ^H",
6912446Slayer "bt", "Back tab",
7012446Slayer "bw", "Backspace wraps from col 0 to last col",
7112446Slayer "cd", "Clear to end of display",
7212446Slayer "ce", "Clear to end of line",
7312446Slayer "ch", "Like cm, but horizontal motion only",
7412446Slayer "cl", "Clear screen",
7512446Slayer "cm", "Cursor motion",
7612446Slayer "co", "Number of columns in a line",
7725326Sserge "cr", "Carriage return (default ^M)",
7812446Slayer "cs", "Change scrolling region (vt100), like cm",
7925326Sserge "ct", "Clear all tab stops",
8012446Slayer "cv", "Like ch but vertical only.",
8125326Sserge "dB", "Number of millisec of bs delay needed",
8225326Sserge "dC", "Number of millisec of cr delay needed",
8325326Sserge "dF", "Number of millisec of ff delay needed",
8425326Sserge "dN", "Number of millisec of nl delay needed",
8525326Sserge "dT", "Number of millisec of tab delay needed",
8612446Slayer "da", "Display may be retained above",
8712446Slayer "db", "Display may be retained below",
8812446Slayer "dc", "Delete character",
8912446Slayer "dl", "Delete line",
9012446Slayer "dm", "Start Delete mode",
9112446Slayer "do", "Down one line",
9212461Slayer "ds", "Disable status display",
9312446Slayer "ed", "End delete mode",
9412446Slayer "ei", "End insert mode;give \":ei=:\" if ic",
9512446Slayer "eo", "Can erase overstrikes with a blank",
9612461Slayer "es", "Escape seq's ok on status line",
9712446Slayer "ff", "Hardcopy page eject (default ^L)",
9812446Slayer "fs", "From status line sequence",
9912446Slayer "hc", "Hardcopy terminal",
10012446Slayer "hd", "Half-line down (forward 1/2 lf)",
10112446Slayer "ho", "Home cursor (if no cm)",
10225326Sserge "hs", "Has status line",
10312446Slayer "hu", "Half-line up (reverse 1/2 lf)",
10412446Slayer "hz", "Hazeltine; can't print ~'s",
10525326Sserge "i2", "Initialization string (used by sysline(1))",
10612446Slayer "ic", "Insert character",
10712446Slayer "if", "Name of file containing is",
10812446Slayer "im", "Start insert mode;give \":im=:\" if ic",
10912446Slayer "in", "Insert mode distinguishes nulls on display",
11012446Slayer "ip", "Insert pad after character inserted",
11112446Slayer "is", "Initialization string",
11225326Sserge "k0", "Sent by function key 0",
11325326Sserge "k1", "Sent by function key 1",
11425326Sserge "k2", "Sent by function key 2",
11525326Sserge "k3", "Sent by function key 3",
11625326Sserge "k4", "Sent by function key 4",
11725326Sserge "k5", "Sent by function key 5",
11825326Sserge "k6", "Sent by function key 6",
11925326Sserge "k7", "Sent by function key 7",
12025326Sserge "k8", "Sent by function key 8",
12125326Sserge "k9", "Sent by function key 9",
12212446Slayer "kb", "Sent by backspace key",
12325326Sserge "kd", "Sent by down arrow key",
12412446Slayer "ke", "Out of \"keypad transmit\" mode",
12512446Slayer "kh", "Sent by home key",
12612446Slayer "kl", "Sent by left arrow key",
12725326Sserge "km", "Has a \"meta\" key (shift, sets parity bit)",
12812446Slayer "kn", "Number of \"other\" keys",
12912446Slayer "ko", "Tc entries for other non-function keys",
13012446Slayer "kr", "Sent by right arrow key",
13112446Slayer "ks", "Put in \"keypad transmit\" mode",
13212446Slayer "ku", "Sent by up arrow key",
13325326Sserge "l0", "Label on function key 0 (if not \"0\")",
13425326Sserge "l1", "Label on function key 1 (if not \"1\")",
13525326Sserge "l2", "Label on function key 2 (if not \"2\")",
13625326Sserge "l3", "Label on function key 3 (if not \"3\")",
13725326Sserge "l4", "Label on function key 4 (if not \"4\")",
13825326Sserge "l5", "Label on function key 5 (if not \"5\")",
13925326Sserge "l6", "Label on function key 6 (if not \"6\")",
14025326Sserge "l7", "Label on function key 7 (if not \"7\")",
14125326Sserge "l8", "Label on function key 8 (if not \"8\")",
14225326Sserge "l9", "Label on function key 9 (if not \"9\")",
14313250Slayer "le", "Move left",
14412446Slayer "li", "Number of lines on screen or page",
14512446Slayer "ll", "Last line, first column (if no cm)",
14612446Slayer "ma", "Arrow key map, used by vi V2 only",
14713250Slayer "mb", "Enter blinking mode",
14813250Slayer "md", "Enter bold mode",
14913250Slayer "me", "Reset video attributes",
15013250Slayer "mh", "Enter halfbright mode",
15112446Slayer "mi", "Safe to move while in insert mode",
15213250Slayer "mk", "Enter protected mode",
15312446Slayer "ml", "Memory lock on above cursor.",
15425326Sserge "mp", "Turn on protected attribute",
15513250Slayer "mr", "Enter reverse video mode",
15612446Slayer "ms", "Ok to move while in standout/underline mode",
15712446Slayer "mu", "Memory unlock (turn off memory lock).",
15812446Slayer "nc", "No working CR (DM2500,H2000)",
15912446Slayer "nd", "Non-destructive space (cursor right)",
16012446Slayer "nl", "Newline character (default \\n)",
16112446Slayer "ns", "Is a CRT but doesn't scroll.",
16212446Slayer "os", "Terminal overstrikes",
16325326Sserge "pb", "Lowest baud where delays are required",
16412446Slayer "pc", "Pad character (rather than null)",
16525326Sserge "pl", "Program function key N to execute string S (terminfo only)",
16612446Slayer "pt", "Has hardware tabs (may need to use is)",
16725326Sserge "rc", "Restore cursor to position of last sc",
16825326Sserge "rf", "Name of file containing reset codes",
16925326Sserge "rs", "Reset terminal completely to sane modes",
17025326Sserge "sc", "Save cursor position",
17112446Slayer "se", "End stand out mode",
17212446Slayer "sf", "Scroll forwards",
17312446Slayer "sg", "Number of blank chars left by so/se",
17412446Slayer "so", "Begin stand out mode",
17512446Slayer "sr", "Scroll reverse (backwards)",
17625326Sserge "st", "Set a tab in all rows, current column",
17712446Slayer "ta", "Tab (other than ^I or with padding)",
17812446Slayer "tc", "Entry of similar terminal - must be last",
17912446Slayer "te", "String to end programs that use cm",
18012446Slayer "ti", "String to begin programs that use cm",
18112446Slayer "ts", "To status line sequence",
18212446Slayer "uc", "Underscore one char and move past it",
18312446Slayer "ue", "End underscore mode",
18412446Slayer "ug", "Number of blank chars left by us or ue",
18512446Slayer "ul", "Underlines, though no overstrike",
18612446Slayer "up", "Upline (cursor up)",
18712446Slayer "us", "Start underscore mode",
18812446Slayer "vb", "Visible bell (may not move cursor)",
18912446Slayer "ve", "Sequence to end open/visual mode",
19012446Slayer "vs", "Sequence to start open/visual mode",
19125326Sserge "vt", "Virtual terminal number (not supported on all systems)",
19212446Slayer "xb", "Beehive (f1=escape, f2=ctrl C)",
19312446Slayer "xn", "A newline is ignored after a wrap (Concept)",
19412446Slayer "xr", "Return acts like ce \\r \\n (Delta Data)",
19512446Slayer "xs", "Standout not erased by writing over it (HP 264?)",
19612446Slayer "xt", "Destructive tabs, magic so char (Teleray 1061)"
19712446Slayer };
19812446Slayer
19925326Sserge #define NOCAPS (sizeof capList / sizeof *capList)
20025326Sserge
20112031Slayer #ifdef DEBUG
20212031Slayer int Dflag = NO;
20312031Slayer #endif
20412031Slayer int xflag = NO;
20512044Slayer int Sflag = YES;
20612044Slayer int sflag = NO;
20712031Slayer int dflag = NO;
20812031Slayer int nflag = NO;
20912031Slayer int gflag = NO;
21012031Slayer int bflag = NO;
21113250Slayer int Uflag = NO;
21212031Slayer int tc_loopc; /* loop counter */
21312031Slayer char *tcfile; /* termcap database pathname */
214*25372Sserge char cwd[MAXPATHLEN]; /* current working directory */
21515192Slayer char tcbuf[2048]; /* buffer for termcap description */
21612031Slayer char *lastchar();
21712031Slayer int name_cmp();
21812031Slayer int ent_cmp();
21912031Slayer struct TcName *find_name();
22012031Slayer char *getenv();
22112031Slayer char *ctime();
22212031Slayer char *strncpy();
22312031Slayer long ftell();
22412031Slayer
main(argc,argv,envp)22512031Slayer main(argc, argv, envp)
22612031Slayer int argc;
22712031Slayer char **argv;
22812031Slayer char **envp;
22912031Slayer {
23012031Slayer char *av;
23112031Slayer struct TcName *tn;
23212031Slayer register char *bp;
23312031Slayer long pos;
23412031Slayer int n;
23512031Slayer struct stat st;
23612031Slayer char envbuf[256];
23712031Slayer FILE *tcfp;
23812031Slayer
23912031Slayer if ((bp = getenv("TERMCAP")) && *bp == '/')
24012031Slayer tcfile = bp;
24112031Slayer else
24212031Slayer tcfile = "/etc/termcap";
24312031Slayer
24412031Slayer while (--argc > 0)
24512031Slayer {
24612031Slayer if (*(av = *++argv) == '-')
24712031Slayer {
24812031Slayer while (*++av)
24912031Slayer {
25012031Slayer switch (*av)
25112031Slayer {
25212031Slayer /* use alternate termcap file */
25312031Slayer case 'f':
25412031Slayer if (argc-- <= 0)
25512031Slayer {
25612031Slayer fprintf(stderr,
25712031Slayer "-f needs a filename\n");
25812031Slayer exit(1);
25912031Slayer }
26012031Slayer tcfile = *++argv;
26112031Slayer break;
26212031Slayer
26312031Slayer /* only check for dup names */
26412458Slayer case 'd':
26512031Slayer nflag = YES;
26612031Slayer /* fall thru */
26712031Slayer
26812031Slayer /* look for duplicated names */
26912458Slayer case 'D':
27012031Slayer dflag = YES;
27112031Slayer continue;
27212031Slayer
27313250Slayer case 'U':
27413250Slayer Uflag = YES;
27513250Slayer continue;
27613250Slayer
27712044Slayer /* strip the two name off */
27812044Slayer case 's':
27912044Slayer sflag = YES;
28012044Slayer continue;
28112044Slayer
28212031Slayer /* sort the name array */
28312031Slayer case 'S':
28412044Slayer Sflag = NO;
28512031Slayer continue;
28612031Slayer
28712031Slayer #ifdef DEBUG
28812458Slayer case 'T':
28912031Slayer Dflag = YES;
29012031Slayer continue;
29112031Slayer #endif
29212031Slayer
29312031Slayer /* sort on generic names */
29412031Slayer case 'g':
29512031Slayer gflag = YES;
29612031Slayer continue;
29712031Slayer
29812031Slayer /* expand entries in 'full mode' */
29912031Slayer case 'x':
30012031Slayer xflag = YES;
30112031Slayer continue;
30212031Slayer
30312031Slayer /* show bare entry */
30412031Slayer case 'b':
30512031Slayer bflag = YES;
30612031Slayer continue;
30712031Slayer
30812031Slayer default:
30912031Slayer fprintf(stderr, "showtc: unknown flag: -%c\n", *av);
31012031Slayer fprintf(stderr, USAGE, argv[0]);
31112031Slayer exit(1);
31212031Slayer }
31312031Slayer }
31412031Slayer }
31512031Slayer else
31612031Slayer break;
31712031Slayer }
31812031Slayer
31912031Slayer /*
32012031Slayer * insert the specified TERMCAP file into the environment
32112031Slayer */
322*25372Sserge if (*tcfile != '/') {
323*25372Sserge char *getwd();
324*25372Sserge
325*25372Sserge if (getwd(cwd) == NULL) {
326*25372Sserge fprintf(stderr, "showtc: %s\n", cwd);
327*25372Sserge exit(1);
328*25372Sserge } else if (strlen(cwd) + strlen(tcfile) + 2 > sizeof cwd) {
329*25372Sserge fprintf(stderr, "showtc: %s\n",
330*25372Sserge "Current working directory name too long");
331*25372Sserge exit(1);
332*25372Sserge } else {
333*25372Sserge if (cwd[strlen(cwd) - 1] != '/')
334*25372Sserge strcat(cwd, "/");
335*25372Sserge strcat(cwd, tcfile);
336*25372Sserge tcfile = cwd;
337*25372Sserge }
338*25372Sserge }
33912031Slayer (void) sprintf(envbuf, "TERMCAP=%s", tcfile);
34012031Slayer while (*envp)
34112031Slayer {
34212031Slayer if (strncmp(*envp, "TERMCAP=", 8) == 0)
34312031Slayer {
34412031Slayer *envp = envbuf;
34512031Slayer break;
34612031Slayer }
34712031Slayer envp++;
34812031Slayer }
34912031Slayer if (! *envp)
35012031Slayer *envp = envbuf; /* this may be dangerous */
35112031Slayer
35212031Slayer /*
35312031Slayer ** if user specified type(s), do only those
35412031Slayer */
35512031Slayer if (argc > 0)
35612031Slayer {
35712031Slayer /*
35812031Slayer ** look for the users specified term types
35912031Slayer */
36012031Slayer while (argc > 0)
36112031Slayer {
36212031Slayer switch (n = tgetent(tcbuf, *argv))
36312031Slayer {
36412031Slayer case 1:
36512031Slayer if (bflag)
36612031Slayer (void) prnt_raw(tcbuf);
36712031Slayer else
36812031Slayer (void) prnt_ent(tcbuf);
36912031Slayer break;
37012031Slayer
37112031Slayer case 0:
37212031Slayer fprintf(stderr,
37312031Slayer "showtc: bad entry: %s\n", *argv);
37412031Slayer break;
37512031Slayer
37612031Slayer case -1:
37712031Slayer fputs("showtc: ", stderr);
37812031Slayer perror(tcfile);
37912031Slayer exit(1);
38012031Slayer
38112031Slayer default:
38212031Slayer fprintf(stderr, "bad return from tgetent: %d\n", n);
38312031Slayer exit(1);
38412031Slayer }
38512031Slayer argc--;
38612031Slayer argv++;
38712031Slayer }
38812031Slayer exit(0);
38912031Slayer }
39012031Slayer
39112031Slayer if (bflag)
39212031Slayer {
39312031Slayer fprintf(stderr, "showtc: -b flag with no entries makes no sense.\n");
39412031Slayer exit(1);
39512031Slayer }
39612031Slayer
39712031Slayer
39812031Slayer /*
39912031Slayer ** if no type was specified, do the whole file
40012031Slayer */
40112031Slayer if ((tcfp = fopen(tcfile, "r")) == NULL)
40212031Slayer {
40312031Slayer perror(tcfile);
40412031Slayer exit(1);
40512031Slayer }
40612031Slayer
40712031Slayer /*
40812031Slayer ** identify database, for the record
40912031Slayer */
41012031Slayer if (stat(tcfile, &st))
41112031Slayer {
41212031Slayer perror(tcfile);
41312031Slayer exit(1);
41412031Slayer }
41512031Slayer printf("File: %s, last modified: %s\n", tcfile, ctime(&st.st_mtime));
41612031Slayer
41712031Slayer
41812031Slayer /*
41912031Slayer ** build termcap entry table
42012031Slayer */
42112031Slayer tn = tcNames;
42212031Slayer pos = ftell(tcfp);
42312031Slayer bp = tcbuf;
42412031Slayer while (fgets(bp, sizeof (tcbuf), tcfp) != NULL)
42512031Slayer {
42612031Slayer if (tcbuf[0] == '#')
42712031Slayer {
42812031Slayer pos = ftell(tcfp);
42912031Slayer bp = tcbuf;
43012031Slayer continue;
43112031Slayer }
43212031Slayer
43312031Slayer tn->file_pos = pos;
43412031Slayer
43512031Slayer /*
43612031Slayer ** get full entry
43712031Slayer */
43812031Slayer while (*(bp = lastchar(bp)) == '\\' && fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp))
43912031Slayer ;
44012031Slayer /*
44112031Slayer ** save the names
44212031Slayer */
44312031Slayer for (bp = tcbuf; *bp && *bp != ':'; bp++)
44412031Slayer ;
44512031Slayer *bp = '\0';
44612031Slayer (void) strncpy(tn->name_buf, tcbuf,
44712031Slayer sizeof tcNames[0].name_buf);
44812031Slayer
44912031Slayer pos = ftell(tcfp);
45012031Slayer bp = tcbuf;
45112031Slayer tn++;
45212031Slayer }
45312031Slayer tn->file_pos = -1;
45412031Slayer
45512031Slayer /*
45612031Slayer ** Look for duplicate names
45712031Slayer */
45812031Slayer if (dflag)
45912031Slayer check_dup();
46012031Slayer if (nflag)
46112031Slayer exit(0);
46212031Slayer
46312031Slayer #ifdef DEBUG
46412031Slayer if (Dflag)
46512031Slayer {
46612031Slayer for (tn = tcNames; tn->file_pos >= 0; tn++)
46712031Slayer {
46812031Slayer printf("Entry #%d:\n\t%s\n\tfile_pos = %ld\n",
46912031Slayer tn - tcNames, tn->name_buf, tn->file_pos);
47012031Slayer }
47112031Slayer exit(0);
47212031Slayer }
47312031Slayer #endif
47412031Slayer
47512031Slayer /*
47612031Slayer ** Order the list
47712031Slayer */
47812044Slayer if (Sflag)
47912031Slayer qsort((char *)tcNames, tn - tcNames,
48012031Slayer sizeof (struct TcName), name_cmp);
48112031Slayer
48212031Slayer /*
48312031Slayer ** List termcap entry for each name in table
48412031Slayer */
48512031Slayer for (tn = tcNames; tn->file_pos >= 0; tn++)
48612031Slayer {
48712031Slayer tc_loopc = 0;
48812031Slayer /*** working toward this ...
48912031Slayer (void) prnt_ent(tn);
49012031Slayer ***/
49112031Slayer (void) fseek(tcfp, tn->file_pos, 0);
49212031Slayer bp = tcbuf;
49312031Slayer while (fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp)
49412031Slayer && *(bp = lastchar(bp)) == '\\')
49512031Slayer ;
49612031Slayer (void) prnt_ent(tcbuf);
49712031Slayer }
49812031Slayer }
49912031Slayer
50012031Slayer char *
lastchar(b)50112031Slayer lastchar(b)
50212031Slayer char *b;
50312031Slayer {
50412031Slayer register char *p;
50512031Slayer
50612031Slayer p = b + strlen(b) - 1;
50712031Slayer while (*p == '\n' || *p == ' ')
50812031Slayer p--;
50912031Slayer return(p);
51012031Slayer }
51112031Slayer
name_cmp(a,b)51212031Slayer name_cmp(a, b)
51312031Slayer char *a, *b;
51412031Slayer {
51512031Slayer if (gflag) /* sort on generic names */
51612031Slayer {
51712031Slayer a += 3;
51812031Slayer b += 3;
51912031Slayer while (*a && *b && *a != '|' && *a == *b)
52012031Slayer {
52112031Slayer a++;
52212031Slayer b++;
52312031Slayer }
52412031Slayer if (*a == '|' || *a == CNULL)
52512031Slayer return((*b == '|' || *b == CNULL)? 0:-1);
52612031Slayer if (*b == '|' || *b == CNULL)
52712031Slayer return(1);
52812031Slayer return(*a - *b);
52912031Slayer }
53012031Slayer return(strncmp(a, b, 2));
53112031Slayer }
53212031Slayer
prnt_ent(buf)53312031Slayer prnt_ent(buf)
53412031Slayer register char *buf;
53512031Slayer {
53612031Slayer register char *name;
53712446Slayer char *getdesc();
53812031Slayer char *caps[256];
53912031Slayer register char **cp;
54012031Slayer register char **tp;
54112031Slayer char tname[3];
54212031Slayer
54312031Slayer cp = caps;
54412031Slayer name = buf;
54512031Slayer tname[3] = '\0';
54612031Slayer
54712031Slayer while (*buf)
54812031Slayer {
54912031Slayer switch (*buf)
55012031Slayer {
55112031Slayer case ':':
55212031Slayer *buf++ = '\0';
55312031Slayer while (*buf && !isalnum(*buf))
55412031Slayer buf++;
55512031Slayer if (*buf)
55612031Slayer {
55712031Slayer /*
55812031Slayer * ignore duplicate cap entries
55912031Slayer */
56012031Slayer for (tp = caps; tp < cp; tp++)
56112031Slayer if (strncmp(buf, *tp, 2) == 0)
56212031Slayer goto skip;
56312031Slayer *cp++ = buf;
56412031Slayer skip:
56512031Slayer /*
56612031Slayer * does user want tc= expanded?
56712031Slayer */
56812031Slayer if (xflag && strncmp(buf, "tc=", 3) == 0)
56912031Slayer {
57012031Slayer /*
57112031Slayer * find end of tc=
57212031Slayer */
57312031Slayer while (*buf != ':')
57412031Slayer buf++;
57512031Slayer *buf = '\0';
57612031Slayer /*
57712031Slayer * save term name
57812031Slayer */
57912031Slayer tname[0] = name[0];
58012031Slayer tname[1] = name[1];
58112031Slayer printf("%s: expanding %s\n",
58212031Slayer tname, cp[-1]);
58312031Slayer /*
58412031Slayer * let tgetent do the work
58512031Slayer */
58612031Slayer tgetent(tcbuf, tname);
58712031Slayer prnt_ent(tcbuf);
58812031Slayer return;
58912031Slayer }
59012031Slayer }
59112031Slayer continue;
59212031Slayer
59312031Slayer case '|':
59412031Slayer *buf++ = ',';
59512031Slayer continue;
59612031Slayer
59712031Slayer default:
59812031Slayer buf++;
59912031Slayer }
60012031Slayer }
60112031Slayer *cp = CNULL; /* was (char *)0 */
60212031Slayer
60312044Slayer if (Sflag)
60412031Slayer qsort((char *) caps, cp - caps, sizeof (char *), ent_cmp);
60512031Slayer
60612031Slayer printf("%s\n", name);
60712031Slayer for (cp = caps; *cp; cp++)
60813250Slayer if (Uflag) {
60913250Slayer if (unknowncap(*cp)) {
61013250Slayer printf("%3.3s\n", *cp);
61113250Slayer }
61213250Slayer } else if (sflag) {
61312446Slayer printf("%-45s %s\n", getdesc(*cp), *cp);
61413250Slayer } else {
61512446Slayer printf("%2.2s %-45s %s\n", name, getdesc(*cp), *cp);
61612446Slayer }
61712031Slayer (void) putchar('\n');
61812031Slayer }
61912031Slayer
prnt_raw(buf)62012031Slayer prnt_raw(buf)
62112031Slayer char *buf;
62212031Slayer {
62312031Slayer register char *b;
62412031Slayer register int len;
62512031Slayer register int n;
62612031Slayer char *index();
62712031Slayer
62812031Slayer len = 0;
62912031Slayer b = buf;
63012031Slayer while (*b)
63112031Slayer {
63212031Slayer if ((n = index(b, ':') - b + 1) <= 0)
63312031Slayer n = strlen(b);
63412031Slayer if (len == 0) /* first part */
63512031Slayer {
63612031Slayer printf("%.*s\\\n\t:", n, b);
63712031Slayer len = 9 - n;
63812031Slayer }
63912031Slayer else
64012031Slayer {
64112031Slayer if ((len + n) >= 75)
64212031Slayer {
64312031Slayer printf("\\\n\t:");
64412031Slayer len = 9;
64512031Slayer }
64612031Slayer printf("%.*s", n, b);
64712031Slayer }
64812031Slayer len += n;
64912031Slayer b += n;
65012031Slayer while (*b && index(" \t:\n", *b))
65112031Slayer b++;
65212031Slayer }
65312031Slayer if (b[-1] != ':')
65412031Slayer (void) putchar(':');
65512031Slayer (void) putchar('\n');
65612031Slayer }
65712031Slayer
ent_cmp(a,b)65812031Slayer ent_cmp(a, b)
65912031Slayer char **a, **b;
66012031Slayer {
66112031Slayer return(strncmp(*a, *b, 2));
66212031Slayer }
66312031Slayer
check_dup()66412031Slayer check_dup()
66512031Slayer {
66612031Slayer /*
66712031Slayer ** Look for duplicated names
66812031Slayer */
66912031Slayer register char *p;
67012031Slayer register char *q;
67112031Slayer register struct TcName *tn;
67212031Slayer register struct TcName *tm;
67312031Slayer
67412031Slayer tn = tcNames;
67512031Slayer while (tn->file_pos >= 0)
67612031Slayer {
67712031Slayer p = q = tn->name_buf;
67812031Slayer while (*q)
67912031Slayer {
68012031Slayer while (*p && *p != '|')
68112031Slayer p++;
68212031Slayer if (p != q && (tm = find_name(q, tn + 1, p - q)))
68312031Slayer {
68412031Slayer fputs("Duplicate name: ", stdout);
68512031Slayer while (q != p)
68612031Slayer (void) putchar(*q++);
68712031Slayer (void) putchar('\n');
68812031Slayer puts(tn->name_buf);
68912031Slayer puts(tm->name_buf);
69012031Slayer puts("---\n");
69112031Slayer }
69212031Slayer if (*p == '|')
69312031Slayer p++;
69412031Slayer q = p;
69512031Slayer }
69612031Slayer tn++;
69712031Slayer }
69812031Slayer }
69912031Slayer
70012031Slayer struct TcName *
find_name(name,tn,len)70112031Slayer find_name(name, tn, len)
70212031Slayer register char *name;
70312031Slayer register struct TcName *tn;
70412031Slayer register int len;
70512031Slayer {
70612031Slayer /*
70712031Slayer ** find name of length len in tcname structure buffers.
70812031Slayer */
70912031Slayer register char *p;
71012031Slayer register char *buf;
71112031Slayer register int n;
71212031Slayer
71312031Slayer while (tn->file_pos >= 0)
71412031Slayer {
71512031Slayer buf = tn->name_buf;
71612031Slayer while (*buf)
71712031Slayer {
71812031Slayer p = name;
71912031Slayer n = len;
72012031Slayer if (*buf == '|')
72112031Slayer buf++;
72212031Slayer
72312031Slayer while (*buf && *buf != '|')
72412031Slayer {
72512031Slayer if (*p != *buf)
72612031Slayer {
72712031Slayer while (*buf && *buf != '|')
72812031Slayer buf++;
72912031Slayer break;
73012031Slayer }
73112031Slayer
73212031Slayer if (--n <= 0)
73312031Slayer {
73412031Slayer buf++;
73512031Slayer if (*buf == '|' || *buf == '\0')
73612031Slayer return(tn);
73712031Slayer while (*buf && *buf != '|')
73812031Slayer buf++;
73912031Slayer break;
74012031Slayer }
74112031Slayer buf++;
74212031Slayer p++;
74312031Slayer }
74412031Slayer }
74512031Slayer tn++;
74612031Slayer }
74712031Slayer return((struct TcName *)0);
74812031Slayer }
74912446Slayer
75012446Slayer char *
getdesc(key)75112446Slayer getdesc(key)
75212446Slayer char *key;
75312446Slayer {
75412446Slayer register int i;
75512446Slayer
756*25372Sserge for (i = 0; i < NOCAPS; i++)
75712446Slayer if (strncmp(key, capList[i].cap, 2) == 0)
75812446Slayer return (capList[i].desc);
75912458Slayer return("");
76012446Slayer }
76113250Slayer
unknowncap(key)76213250Slayer unknowncap(key)
76313250Slayer char *key;
76413250Slayer {
76513250Slayer register int i;
76613250Slayer
767*25372Sserge for (i = 0; i < NOCAPS; i++)
76813250Slayer if (strncmp(key, capList[i].cap, 2) == 0)
76913250Slayer return (0);
77013250Slayer return(1);
77113250Slayer }
772