xref: /csrg-svn/local/local.cmd/showtc.c (revision 12446)
112044Slayer #ifndef LINT
2*12446Slayer static char *sccsid="@(#)showtc.c	1.3	(Berkeley) 05/14/83";
312044Slayer #endif
412044Slayer 
512031Slayer /*
612031Slayer ** show termcap entries
712031Slayer **
812031Slayer ** where:
912031Slayer **	-S	sort entries before display
1012044Slayer **	-b	show bare entries
1112031Slayer **	-d	look for duplicate names
1212044Slayer **	-f	following arg is FULL PATHNAME of termcap file
1312044Slayer **	-g	sort on generic names
1412031Slayer **	-n	-d and stop
1512044Slayer **	-s	don't print two char name at the front of every line
1612044Slayer **	-x	expand tc= capabilities
1712031Slayer **	[ent]	display specific entry. tc= will be expanded.
1812031Slayer **
1912031Slayer ** David L. Wasley, U.C.Berkeley
20*12446Slayer ** Kevin Layer: modified for 4.1c and misc changes.
21*12446Slayer ** Kevin Layer: added the printing of terminal capabilities
22*12446Slayer **	in `human' readable form (like that in "man 5 termcap").
2312031Slayer */
2412031Slayer 
2512031Slayer #include <stdio.h>
2612031Slayer #include <sys/file.h>
2712031Slayer #include <ctype.h>
2812031Slayer #include <sys/types.h>
2912031Slayer #include <sys/stat.h>
3012031Slayer 
3112031Slayer #define NO		0
3212031Slayer #define YES		1
3312031Slayer #define CNULL		'\0'
3412031Slayer #define NOENTRIES	1024
3512044Slayer #define USAGE		"usage: %s [-Sxdngb] [-f termcapfile] [entry] ...\n"
3612031Slayer 
3712031Slayer struct TcName {
3812031Slayer 	char	name_buf[124];
3912031Slayer 	long	file_pos;
4012031Slayer } tcNames[NOENTRIES];
4112031Slayer 
42*12446Slayer #define NOCAPS	94
43*12446Slayer 
44*12446Slayer struct Caps {
45*12446Slayer 	char	*cap;
46*12446Slayer 	char	*desc;
47*12446Slayer } capList[NOCAPS] =
48*12446Slayer {
49*12446Slayer 	"ae",	"End alternate character set",
50*12446Slayer 	"al",	"Add new blank line",
51*12446Slayer 	"am",	"Has automatic margins",
52*12446Slayer 	"as",	"Start alternate character set",
53*12446Slayer 	"bc",	"Backspace if not ^H",
54*12446Slayer 	"bs",	"Can backspace with ^H",
55*12446Slayer 	"bt",	"Back tab",
56*12446Slayer 	"bw",	"Backspace wraps from col 0 to last col",
57*12446Slayer 	"CC",	"Command char in prototype if settable",
58*12446Slayer 	"cd",	"Clear to end of display",
59*12446Slayer 	"ce",	"Clear to end of line",
60*12446Slayer 	"ch",	"Like cm, but horizontal motion only",
61*12446Slayer 	"cl",	"Clear screen",
62*12446Slayer 	"cm",	"Cursor motion",
63*12446Slayer 	"co",	"Number of columns in a line",
64*12446Slayer 	"cr",	"Carriage return, (default ^M)",
65*12446Slayer 	"cs",	"Change scrolling region (vt100), like cm",
66*12446Slayer 	"cv",	"Like ch but vertical only.",
67*12446Slayer 	"da",	"Display may be retained above",
68*12446Slayer 	"dB",	"Number of millisec of bs delay needed",
69*12446Slayer 	"db",	"Display may be retained below",
70*12446Slayer 	"dC",	"Number of millisec of cr delay needed",
71*12446Slayer 	"dc",	"Delete character",
72*12446Slayer 	"dF",	"Number of millisec of ff delay needed",
73*12446Slayer 	"dl",	"Delete line",
74*12446Slayer 	"dm",	"Start Delete mode",
75*12446Slayer 	"dN",	"Number of millisec of nl delay needed",
76*12446Slayer 	"do",	"Down one line",
77*12446Slayer 	"dT",	"Number of millisec of tab delay needed",
78*12446Slayer 	"ed",	"End delete mode",
79*12446Slayer 	"ei",	"End insert mode;give \":ei=:\" if ic",
80*12446Slayer 	"eo",	"Can erase overstrikes with a blank",
81*12446Slayer 	"ff",	"Hardcopy page eject (default ^L)",
82*12446Slayer 	"fs",	"From status line sequence",
83*12446Slayer 	"hc",	"Hardcopy terminal",
84*12446Slayer 	"hd",	"Half-line down (forward 1/2 lf)",
85*12446Slayer 	"ho",	"Home cursor (if no cm)",
86*12446Slayer 	"hs",	"Has 25th status line",
87*12446Slayer 	"hu",	"Half-line up (reverse 1/2 lf)",
88*12446Slayer 	"hz",	"Hazeltine; can't print ~'s",
89*12446Slayer 	"ic",	"Insert character",
90*12446Slayer 	"if",	"Name of file containing is",
91*12446Slayer 	"im",	"Start insert mode;give \":im=:\" if ic",
92*12446Slayer 	"in",	"Insert mode distinguishes nulls on display",
93*12446Slayer 	"ip",	"Insert pad after character inserted",
94*12446Slayer 	"is",	"Initialization string",
95*12446Slayer 	"kb",	"Sent by backspace key",
96*12446Slayer 	"kd",	"Sent down arrow key",
97*12446Slayer 	"ke",	"Out of \"keypad transmit\" mode",
98*12446Slayer 	"kh",	"Sent by home key",
99*12446Slayer 	"kl",	"Sent by left arrow key",
100*12446Slayer 	"kn",	"Number of \"other\" keys",
101*12446Slayer 	"ko",	"Tc entries for other non-function keys",
102*12446Slayer 	"kr",	"Sent by right arrow key",
103*12446Slayer 	"ks",	"Put in \"keypad transmit\" mode",
104*12446Slayer 	"ku",	"Sent by up arrow key",
105*12446Slayer 	"li",	"Number of lines on screen or page",
106*12446Slayer 	"ll",	"Last line, first column (if no cm)",
107*12446Slayer 	"ma",	"Arrow key map, used by vi V2 only",
108*12446Slayer 	"mi",	"Safe to move while in insert mode",
109*12446Slayer 	"ml",	"Memory lock on above cursor.",
110*12446Slayer 	"ms",	"Ok to move while in standout/underline mode",
111*12446Slayer 	"mu",	"Memory unlock (turn off memory lock).",
112*12446Slayer 	"nc",	"No working CR (DM2500,H2000)",
113*12446Slayer 	"nd",	"Non-destructive space (cursor right)",
114*12446Slayer 	"nl",	"Newline character (default \\n)",
115*12446Slayer 	"ns",	"Is a CRT but doesn't scroll.",
116*12446Slayer 	"os",	"Terminal overstrikes",
117*12446Slayer 	"pc",	"Pad character (rather than null)",
118*12446Slayer 	"pt",	"Has hardware tabs (may need to use is)",
119*12446Slayer 	"se",	"End stand out mode",
120*12446Slayer 	"sf",	"Scroll forwards",
121*12446Slayer 	"sg",	"Number of blank chars left by so/se",
122*12446Slayer 	"so",	"Begin stand out mode",
123*12446Slayer 	"sr",	"Scroll reverse (backwards)",
124*12446Slayer 	"ta",	"Tab (other than ^I or with padding)",
125*12446Slayer 	"tc",	"Entry of similar terminal - must be last",
126*12446Slayer 	"te",	"String to end programs that use cm",
127*12446Slayer 	"ti",	"String to begin programs that use cm",
128*12446Slayer 	"ts",	"To status line sequence",
129*12446Slayer 	"uc",	"Underscore one char and move past it",
130*12446Slayer 	"ue",	"End underscore mode",
131*12446Slayer 	"ug",	"Number of blank chars left by us or ue",
132*12446Slayer 	"ul",	"Underlines, though no overstrike",
133*12446Slayer 	"up",	"Upline (cursor up)",
134*12446Slayer 	"us",	"Start underscore mode",
135*12446Slayer 	"vb",	"Visible bell (may not move cursor)",
136*12446Slayer 	"ve",	"Sequence to end open/visual mode",
137*12446Slayer 	"vs",	"Sequence to start open/visual mode",
138*12446Slayer 	"xb",	"Beehive (f1=escape, f2=ctrl C)",
139*12446Slayer 	"xn",	"A newline is ignored after a wrap (Concept)",
140*12446Slayer 	"xr",	"Return acts like ce \\r \\n (Delta Data)",
141*12446Slayer 	"xs",	"Standout not erased by writing over it (HP 264?)",
142*12446Slayer 	"xt",	"Destructive tabs, magic so char (Teleray 1061)"
143*12446Slayer };
144*12446Slayer 
14512031Slayer #ifdef DEBUG
14612031Slayer int		Dflag = NO;
14712031Slayer #endif
14812031Slayer int		xflag = NO;
14912044Slayer int		Sflag = YES;
15012044Slayer int		sflag = NO;
15112031Slayer int		dflag = NO;
15212031Slayer int		nflag = NO;
15312031Slayer int		gflag = NO;
15412031Slayer int		bflag = NO;
15512031Slayer int		tc_loopc;		/* loop counter */
15612031Slayer char		*tcfile;		/* termcap database pathname */
15712031Slayer char		tcbuf[1024];		/* buffer for termcap description */
15812031Slayer char		*lastchar();
15912031Slayer int		name_cmp();
16012031Slayer int		ent_cmp();
16112031Slayer struct TcName	*find_name();
16212031Slayer char		*getenv();
16312031Slayer char		*ctime();
16412031Slayer char		*strncpy();
16512031Slayer long		ftell();
16612031Slayer 
16712031Slayer main(argc, argv, envp)
16812031Slayer 	int		argc;
16912031Slayer 	char		**argv;
17012031Slayer 	char		**envp;
17112031Slayer {
17212031Slayer 	char		*av;
17312031Slayer 	struct TcName	*tn;
17412031Slayer 	register char	*bp;
17512031Slayer 	long		pos;
17612031Slayer 	int		n;
17712031Slayer 	struct stat	st;
17812031Slayer 	char		envbuf[256];
17912031Slayer 	FILE		*tcfp;
18012031Slayer 
18112031Slayer 	if ((bp = getenv("TERMCAP")) && *bp == '/')
18212031Slayer 		tcfile = bp;
18312031Slayer 	else
18412031Slayer 		tcfile = "/etc/termcap";
18512031Slayer 
18612031Slayer 	while (--argc > 0)
18712031Slayer 	{
18812031Slayer 		if (*(av = *++argv) == '-')
18912031Slayer 		{
19012031Slayer 			while (*++av)
19112031Slayer 			{
19212031Slayer 				switch (*av)
19312031Slayer 				{
19412031Slayer 				/* use alternate termcap file */
19512031Slayer 				case 'f':
19612031Slayer 					if (argc-- <= 0)
19712031Slayer 					{
19812031Slayer 						fprintf(stderr,
19912031Slayer 						    "-f needs a filename\n");
20012031Slayer 						exit(1);
20112031Slayer 					}
20212031Slayer 					tcfile = *++argv;
20312031Slayer 					break;
20412031Slayer 
20512031Slayer 				/* only check for dup names */
20612031Slayer 				case 'n':
20712031Slayer 					nflag = YES;
20812031Slayer 					/* fall thru */
20912031Slayer 
21012031Slayer 				/* look for duplicated names */
21112031Slayer 				case 'd':
21212031Slayer 					dflag = YES;
21312031Slayer 					continue;
21412031Slayer 
21512044Slayer 				/* strip the two name off */
21612044Slayer 				case 's':
21712044Slayer 					sflag = YES;
21812044Slayer 					continue;
21912044Slayer 
22012031Slayer 				/* sort the name array */
22112031Slayer 				case 'S':
22212044Slayer 					Sflag = NO;
22312031Slayer 					continue;
22412031Slayer 
22512031Slayer #ifdef DEBUG
22612031Slayer 				case 'D':
22712031Slayer 					Dflag = YES;
22812031Slayer 					continue;
22912031Slayer #endif
23012031Slayer 
23112031Slayer 				/* sort on generic names */
23212031Slayer 				case 'g':
23312031Slayer 					gflag = YES;
23412031Slayer 					continue;
23512031Slayer 
23612031Slayer 				/* expand entries in 'full mode' */
23712031Slayer 				case 'x':
23812031Slayer 					xflag = YES;
23912031Slayer 					continue;
24012031Slayer 
24112031Slayer 				/* show bare entry */
24212031Slayer 				case 'b':
24312031Slayer 					bflag = YES;
24412031Slayer 					continue;
24512031Slayer 
24612031Slayer 				default:
24712031Slayer 					fprintf(stderr, "showtc: unknown flag: -%c\n", *av);
24812031Slayer 					fprintf(stderr, USAGE, argv[0]);
24912031Slayer 					exit(1);
25012031Slayer 				}
25112031Slayer 			}
25212031Slayer 		}
25312031Slayer 		else
25412031Slayer 			break;
25512031Slayer 	}
25612031Slayer 
25712031Slayer 	/*
25812031Slayer 	 * insert the specified TERMCAP file into the environment
25912031Slayer 	 */
26012031Slayer 	(void) sprintf(envbuf, "TERMCAP=%s", tcfile);
26112031Slayer 	while (*envp)
26212031Slayer 	{
26312031Slayer 		if (strncmp(*envp, "TERMCAP=", 8) == 0)
26412031Slayer 		{
26512031Slayer 			*envp = envbuf;
26612031Slayer 			break;
26712031Slayer 		}
26812031Slayer 		envp++;
26912031Slayer 	}
27012031Slayer 	if (! *envp)
27112031Slayer 		*envp = envbuf;	/* this may be dangerous */
27212031Slayer 
27312031Slayer 	/*
27412031Slayer 	** if user specified type(s), do only those
27512031Slayer 	*/
27612031Slayer 	if (argc > 0)
27712031Slayer 	{
27812031Slayer 		/*
27912031Slayer 		** look for the users specified term types
28012031Slayer 		*/
28112031Slayer 		while (argc > 0)
28212031Slayer 		{
28312031Slayer 			switch (n = tgetent(tcbuf, *argv))
28412031Slayer 			{
28512031Slayer 				case 1:
28612031Slayer 					if (bflag)
28712031Slayer 						(void) prnt_raw(tcbuf);
28812031Slayer 					else
28912031Slayer 						(void) prnt_ent(tcbuf);
29012031Slayer 					break;
29112031Slayer 
29212031Slayer 				case 0:
29312031Slayer 					fprintf(stderr,
29412031Slayer 					   "showtc: bad entry: %s\n", *argv);
29512031Slayer 					break;
29612031Slayer 
29712031Slayer 				case -1:
29812031Slayer 					fputs("showtc: ", stderr);
29912031Slayer 					perror(tcfile);
30012031Slayer 					exit(1);
30112031Slayer 
30212031Slayer 				default:
30312031Slayer 					fprintf(stderr, "bad return from tgetent: %d\n", n);
30412031Slayer 					exit(1);
30512031Slayer 			}
30612031Slayer 			argc--;
30712031Slayer 			argv++;
30812031Slayer 		}
30912031Slayer 		exit(0);
31012031Slayer 	}
31112031Slayer 
31212031Slayer 	if (bflag)
31312031Slayer 	{
31412031Slayer  		fprintf(stderr, "showtc: -b flag with no entries makes no sense.\n");
31512031Slayer 		exit(1);
31612031Slayer 	}
31712031Slayer 
31812031Slayer 
31912031Slayer 	/*
32012031Slayer 	** if no type was specified, do the whole file
32112031Slayer 	*/
32212031Slayer 	if ((tcfp = fopen(tcfile, "r")) == NULL)
32312031Slayer 	{
32412031Slayer 		perror(tcfile);
32512031Slayer 		exit(1);
32612031Slayer 	}
32712031Slayer 
32812031Slayer 	/*
32912031Slayer 	** identify database, for the record
33012031Slayer 	*/
33112031Slayer 	if (stat(tcfile, &st))
33212031Slayer 	{
33312031Slayer 		perror(tcfile);
33412031Slayer 		exit(1);
33512031Slayer 	}
33612031Slayer 	printf("File: %s, last modified: %s\n", tcfile, ctime(&st.st_mtime));
33712031Slayer 
33812031Slayer 
33912031Slayer 	/*
34012031Slayer 	** build termcap entry table
34112031Slayer 	*/
34212031Slayer 	tn = tcNames;
34312031Slayer 	pos = ftell(tcfp);
34412031Slayer 	bp = tcbuf;
34512031Slayer 	while (fgets(bp, sizeof (tcbuf), tcfp) != NULL)
34612031Slayer 	{
34712031Slayer 		if (tcbuf[0] == '#')
34812031Slayer 		{
34912031Slayer 			pos = ftell(tcfp);
35012031Slayer 			bp = tcbuf;
35112031Slayer 			continue;
35212031Slayer 		}
35312031Slayer 
35412031Slayer 		tn->file_pos = pos;
35512031Slayer 
35612031Slayer 		/*
35712031Slayer 		** get full entry
35812031Slayer 		*/
35912031Slayer 		while (*(bp = lastchar(bp)) == '\\' && fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp))
36012031Slayer 			;
36112031Slayer 		/*
36212031Slayer 		** save the names
36312031Slayer 		*/
36412031Slayer 		for (bp = tcbuf; *bp && *bp != ':'; bp++)
36512031Slayer 			;
36612031Slayer 		*bp = '\0';
36712031Slayer 		(void) strncpy(tn->name_buf, tcbuf,
36812031Slayer 				sizeof tcNames[0].name_buf);
36912031Slayer 
37012031Slayer 		pos = ftell(tcfp);
37112031Slayer 		bp = tcbuf;
37212031Slayer 		tn++;
37312031Slayer 	}
37412031Slayer 	tn->file_pos = -1;
37512031Slayer 
37612031Slayer 	/*
37712031Slayer 	** Look for duplicate names
37812031Slayer 	*/
37912031Slayer 	if (dflag)
38012031Slayer 		check_dup();
38112031Slayer 	if (nflag)
38212031Slayer 		exit(0);
38312031Slayer 
38412031Slayer #ifdef DEBUG
38512031Slayer 	if (Dflag)
38612031Slayer 	{
38712031Slayer 		for (tn = tcNames; tn->file_pos >= 0; tn++)
38812031Slayer 		{
38912031Slayer 			printf("Entry #%d:\n\t%s\n\tfile_pos = %ld\n",
39012031Slayer 			tn - tcNames, tn->name_buf, tn->file_pos);
39112031Slayer 		}
39212031Slayer 		exit(0);
39312031Slayer 	}
39412031Slayer #endif
39512031Slayer 
39612031Slayer 	/*
39712031Slayer 	** Order the list
39812031Slayer 	*/
39912044Slayer 	if (Sflag)
40012031Slayer 		qsort((char *)tcNames, tn - tcNames,
40112031Slayer 			sizeof (struct TcName), name_cmp);
40212031Slayer 
40312031Slayer 	/*
40412031Slayer 	** List termcap entry for each name in table
40512031Slayer 	*/
40612031Slayer 	for (tn = tcNames; tn->file_pos >= 0; tn++)
40712031Slayer 	{
40812031Slayer 		tc_loopc = 0;
40912031Slayer 		/*** working toward this ...
41012031Slayer 		(void) prnt_ent(tn);
41112031Slayer 		***/
41212031Slayer 		(void) fseek(tcfp, tn->file_pos, 0);
41312031Slayer 		bp = tcbuf;
41412031Slayer 		while (fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp)
41512031Slayer 			&& *(bp = lastchar(bp)) == '\\')
41612031Slayer 			;
41712031Slayer 		(void) prnt_ent(tcbuf);
41812031Slayer 	}
41912031Slayer }
42012031Slayer 
42112031Slayer char *
42212031Slayer lastchar(b)
42312031Slayer 	char	*b;
42412031Slayer {
42512031Slayer 	register char	*p;
42612031Slayer 
42712031Slayer 	p = b + strlen(b) - 1;
42812031Slayer 	while (*p == '\n' || *p == ' ')
42912031Slayer 		p--;
43012031Slayer 	return(p);
43112031Slayer }
43212031Slayer 
43312031Slayer name_cmp(a, b)
43412031Slayer 	char	*a, *b;
43512031Slayer {
43612031Slayer 	if (gflag)	/* sort on generic names */
43712031Slayer 	{
43812031Slayer 		a += 3;
43912031Slayer 		b += 3;
44012031Slayer 		while (*a && *b && *a != '|' && *a == *b)
44112031Slayer 		{
44212031Slayer 			a++;
44312031Slayer 			b++;
44412031Slayer 		}
44512031Slayer 		if (*a == '|' || *a == CNULL)
44612031Slayer 			return((*b == '|' || *b == CNULL)? 0:-1);
44712031Slayer 		if (*b == '|' || *b == CNULL)
44812031Slayer 			return(1);
44912031Slayer 		return(*a - *b);
45012031Slayer 	}
45112031Slayer 	return(strncmp(a, b, 2));
45212031Slayer }
45312031Slayer 
45412031Slayer prnt_ent(buf)
45512031Slayer 	register char	*buf;
45612031Slayer {
45712031Slayer 	register char	*name;
458*12446Slayer 	char		*getdesc();
45912031Slayer 	char		*caps[256];
46012031Slayer 	register char	**cp;
46112031Slayer 	register char	**tp;
46212031Slayer 	char		tname[3];
46312031Slayer 
46412031Slayer 	cp = caps;
46512031Slayer 	name = buf;
46612031Slayer 	tname[3] = '\0';
46712031Slayer 
46812031Slayer 	while (*buf)
46912031Slayer 	{
47012031Slayer 		switch (*buf)
47112031Slayer 		{
47212031Slayer 		case ':':
47312031Slayer 			*buf++ = '\0';
47412031Slayer 			while (*buf && !isalnum(*buf))
47512031Slayer 				buf++;
47612031Slayer 			if (*buf)
47712031Slayer 			{
47812031Slayer 				/*
47912031Slayer 				 * ignore duplicate cap entries
48012031Slayer 				 */
48112031Slayer 				for (tp = caps; tp < cp; tp++)
48212031Slayer 					if (strncmp(buf, *tp, 2) == 0)
48312031Slayer 						goto skip;
48412031Slayer 				*cp++ = buf;
48512031Slayer 			skip:
48612031Slayer 				/*
48712031Slayer 				 * does user want tc= expanded?
48812031Slayer 				 */
48912031Slayer 				if (xflag && strncmp(buf, "tc=", 3) == 0)
49012031Slayer 				{
49112031Slayer 					/*
49212031Slayer 					 * find end of tc=
49312031Slayer 					 */
49412031Slayer 					while (*buf != ':')
49512031Slayer 						buf++;
49612031Slayer 					*buf = '\0';
49712031Slayer 					/*
49812031Slayer 					 * save term name
49912031Slayer 					 */
50012031Slayer 					tname[0] = name[0];
50112031Slayer 					tname[1] = name[1];
50212031Slayer 					printf("%s: expanding %s\n",
50312031Slayer 						tname, cp[-1]);
50412031Slayer 					/*
50512031Slayer 					 * let tgetent do the work
50612031Slayer 					 */
50712031Slayer 					tgetent(tcbuf, tname);
50812031Slayer 					prnt_ent(tcbuf);
50912031Slayer 					return;
51012031Slayer 				}
51112031Slayer 			}
51212031Slayer 			continue;
51312031Slayer 
51412031Slayer 		case '|':
51512031Slayer 			*buf++ = ',';
51612031Slayer 			continue;
51712031Slayer 
51812031Slayer 		default:
51912031Slayer 			buf++;
52012031Slayer 		}
52112031Slayer 	}
52212031Slayer 	*cp = CNULL;		/* was (char *)0 */
52312031Slayer 
52412044Slayer 	if (Sflag)
52512031Slayer 		qsort((char *) caps, cp - caps, sizeof (char *), ent_cmp);
52612031Slayer 
52712031Slayer 	printf("%s\n", name);
52812031Slayer 	for (cp = caps; *cp; cp++)
52912044Slayer 		if (sflag)
530*12446Slayer 			printf("%-45s %s\n", getdesc(*cp), *cp);
53112044Slayer 		else
532*12446Slayer 		{
533*12446Slayer 			printf("%2.2s  %-45s %s\n", name, getdesc(*cp), *cp);
534*12446Slayer 		}
53512031Slayer 	(void) putchar('\n');
53612031Slayer }
53712031Slayer 
53812031Slayer prnt_raw(buf)
53912031Slayer 	char		*buf;
54012031Slayer {
54112031Slayer 	register char	*b;
54212031Slayer 	register int	len;
54312031Slayer 	register int	n;
54412031Slayer 	char		*index();
54512031Slayer 
54612031Slayer 	len = 0;
54712031Slayer 	b = buf;
54812031Slayer 	while (*b)
54912031Slayer 	{
55012031Slayer 		if ((n = index(b, ':') - b + 1) <= 0)
55112031Slayer 			n = strlen(b);
55212031Slayer 		if (len == 0)			/* first part */
55312031Slayer 		{
55412031Slayer 			printf("%.*s\\\n\t:", n, b);
55512031Slayer 			len = 9 - n;
55612031Slayer 		}
55712031Slayer 		else
55812031Slayer 		{
55912031Slayer 			if ((len + n) >= 75)
56012031Slayer 			{
56112031Slayer 				printf("\\\n\t:");
56212031Slayer 				len = 9;
56312031Slayer 			}
56412031Slayer 			printf("%.*s", n, b);
56512031Slayer 		}
56612031Slayer 		len += n;
56712031Slayer 		b += n;
56812031Slayer 		while (*b && index(" \t:\n", *b))
56912031Slayer 			b++;
57012031Slayer 	}
57112031Slayer 	if (b[-1] != ':')
57212031Slayer 		(void) putchar(':');
57312031Slayer 	(void) putchar('\n');
57412031Slayer }
57512031Slayer 
57612031Slayer ent_cmp(a, b)
57712031Slayer 	char **a, **b;
57812031Slayer {
57912031Slayer 	return(strncmp(*a, *b, 2));
58012031Slayer }
58112031Slayer 
58212031Slayer check_dup()
58312031Slayer {
58412031Slayer 	/*
58512031Slayer 	** Look for duplicated names
58612031Slayer 	*/
58712031Slayer 	register char		*p;
58812031Slayer 	register char		*q;
58912031Slayer 	register struct TcName	*tn;
59012031Slayer 	register struct TcName	*tm;
59112031Slayer 
59212031Slayer 	tn = tcNames;
59312031Slayer 	while (tn->file_pos >= 0)
59412031Slayer 	{
59512031Slayer 		p = q = tn->name_buf;
59612031Slayer 		while (*q)
59712031Slayer 		{
59812031Slayer 			while (*p && *p != '|')
59912031Slayer 				p++;
60012031Slayer 			if (p != q && (tm = find_name(q, tn + 1, p - q)))
60112031Slayer 			{
60212031Slayer 				fputs("Duplicate name: ", stdout);
60312031Slayer 				while (q != p)
60412031Slayer 					(void) putchar(*q++);
60512031Slayer 				(void) putchar('\n');
60612031Slayer 				puts(tn->name_buf);
60712031Slayer 				puts(tm->name_buf);
60812031Slayer 				puts("---\n");
60912031Slayer 			}
61012031Slayer 			if (*p == '|')
61112031Slayer 				p++;
61212031Slayer 			q = p;
61312031Slayer 		}
61412031Slayer 		tn++;
61512031Slayer 	}
61612031Slayer }
61712031Slayer 
61812031Slayer struct TcName *
61912031Slayer find_name(name, tn, len)
62012031Slayer 	register char		*name;
62112031Slayer 	register struct TcName	*tn;
62212031Slayer 	register int		len;
62312031Slayer {
62412031Slayer 	/*
62512031Slayer 	** find name of length len in tcname structure buffers.
62612031Slayer 	*/
62712031Slayer 	register char	*p;
62812031Slayer 	register char	*buf;
62912031Slayer 	register int	 n;
63012031Slayer 
63112031Slayer 	while (tn->file_pos >= 0)
63212031Slayer 	{
63312031Slayer 		buf = tn->name_buf;
63412031Slayer 		while (*buf)
63512031Slayer 		{
63612031Slayer 			p = name;
63712031Slayer 			n = len;
63812031Slayer 			if (*buf == '|')
63912031Slayer 				buf++;
64012031Slayer 
64112031Slayer 			while (*buf && *buf != '|')
64212031Slayer 			{
64312031Slayer 				if (*p != *buf)
64412031Slayer 				{
64512031Slayer 					while (*buf && *buf != '|')
64612031Slayer 						buf++;
64712031Slayer 					break;
64812031Slayer 				}
64912031Slayer 
65012031Slayer 				if (--n <= 0)
65112031Slayer 				{
65212031Slayer 					buf++;
65312031Slayer 					if (*buf == '|' || *buf == '\0')
65412031Slayer 						return(tn);
65512031Slayer 					while (*buf && *buf != '|')
65612031Slayer 						buf++;
65712031Slayer 					break;
65812031Slayer 				}
65912031Slayer 				buf++;
66012031Slayer 				p++;
66112031Slayer 			}
66212031Slayer 		}
66312031Slayer 		tn++;
66412031Slayer 	}
66512031Slayer 	return((struct TcName *)0);
66612031Slayer }
667*12446Slayer 
668*12446Slayer char *
669*12446Slayer getdesc(key)
670*12446Slayer 	char		*key;
671*12446Slayer {
672*12446Slayer 	register int	i;
673*12446Slayer 
674*12446Slayer 	for (i = 0; i <= NOCAPS; i++)
675*12446Slayer 		if (strncmp(key, capList[i].cap, 2) == 0)
676*12446Slayer 			return (capList[i].desc);
677*12446Slayer 	return("Unknown capability");
678*12446Slayer }
679