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