| 1 | #ifndef LINT |
| 2 | static char *sccsid="@(#)showtc.c 1.7 (Berkeley) %G%"; |
| 3 | #endif |
| 4 | |
| 5 | /* |
| 6 | ** show termcap entries |
| 7 | ** |
| 8 | ** where: |
| 9 | ** -D look for duplicate names and print termcap file |
| 10 | ** -S sort entries before display |
| 11 | ** -T trace (-DDEBUG only) |
| 12 | ** -U print unknown capabilities |
| 13 | ** -b show bare entries |
| 14 | ** -d -D and stop |
| 15 | ** -f following arg is FULL PATHNAME of termcap file |
| 16 | ** -g sort on generic names |
| 17 | ** -s don't print two char name at the front of every line |
| 18 | ** -x expand tc= capabilities |
| 19 | ** [ent] display specific entry. tc= will be expanded. |
| 20 | ** |
| 21 | ** David L. Wasley, U.C.Berkeley |
| 22 | ** Kevin Layer: modified for 4.1c and misc changes. |
| 23 | ** Kevin Layer: added the printing of terminal capabilities |
| 24 | ** in `human' readable form (like that in "man 5 termcap"). |
| 25 | */ |
| 26 | |
| 27 | #include <stdio.h> |
| 28 | #include <sys/file.h> |
| 29 | #include <ctype.h> |
| 30 | #include <sys/types.h> |
| 31 | #include <sys/stat.h> |
| 32 | |
| 33 | #define NO 0 |
| 34 | #define YES 1 |
| 35 | #define CNULL '\0' |
| 36 | #define NOENTRIES 1024 |
| 37 | #define USAGE "usage: %s [-Sxdngb] [-f termcapfile] [entry] ...\n" |
| 38 | |
| 39 | struct TcName { |
| 40 | char name_buf[124]; |
| 41 | long file_pos; |
| 42 | } tcNames[NOENTRIES]; |
| 43 | |
| 44 | #define NOCAPS 105 |
| 45 | |
| 46 | struct Caps { |
| 47 | char *cap; |
| 48 | char *desc; |
| 49 | } capList[NOCAPS] = |
| 50 | { |
| 51 | "ae", "End alternate character set", |
| 52 | "al", "Add new blank line", |
| 53 | "am", "Has automatic margins", |
| 54 | "as", "Start alternate character set", |
| 55 | "bc", "Backspace if not ^H", |
| 56 | "bl", "Audible Bell", |
| 57 | "bs", "Can backspace with ^H", |
| 58 | "bt", "Back tab", |
| 59 | "bw", "Backspace wraps from col 0 to last col", |
| 60 | "CC", "Command char in prototype if settable", |
| 61 | "cd", "Clear to end of display", |
| 62 | "ce", "Clear to end of line", |
| 63 | "ch", "Like cm, but horizontal motion only", |
| 64 | "cl", "Clear screen", |
| 65 | "cm", "Cursor motion", |
| 66 | "co", "Number of columns in a line", |
| 67 | "cr", "Carriage return, (default ^M)", |
| 68 | "cs", "Change scrolling region (vt100), like cm", |
| 69 | "cv", "Like ch but vertical only.", |
| 70 | "da", "Display may be retained above", |
| 71 | "dB", "Number of millisec of bs delay needed", |
| 72 | "db", "Display may be retained below", |
| 73 | "dC", "Number of millisec of cr delay needed", |
| 74 | "dc", "Delete character", |
| 75 | "dF", "Number of millisec of ff delay needed", |
| 76 | "dl", "Delete line", |
| 77 | "dm", "Start Delete mode", |
| 78 | "dN", "Number of millisec of nl delay needed", |
| 79 | "do", "Down one line", |
| 80 | "ds", "Disable status display", |
| 81 | "dT", "Number of millisec of tab delay needed", |
| 82 | "ed", "End delete mode", |
| 83 | "ei", "End insert mode;give \":ei=:\" if ic", |
| 84 | "eo", "Can erase overstrikes with a blank", |
| 85 | "es", "Escape seq's ok on status line", |
| 86 | "ff", "Hardcopy page eject (default ^L)", |
| 87 | "fs", "From status line sequence", |
| 88 | "hc", "Hardcopy terminal", |
| 89 | "hd", "Half-line down (forward 1/2 lf)", |
| 90 | "ho", "Home cursor (if no cm)", |
| 91 | "hs", "Has 25th status line", |
| 92 | "hu", "Half-line up (reverse 1/2 lf)", |
| 93 | "hz", "Hazeltine; can't print ~'s", |
| 94 | "ic", "Insert character", |
| 95 | "if", "Name of file containing is", |
| 96 | "im", "Start insert mode;give \":im=:\" if ic", |
| 97 | "in", "Insert mode distinguishes nulls on display", |
| 98 | "ip", "Insert pad after character inserted", |
| 99 | "is", "Initialization string", |
| 100 | "i2", "Initialization string (used by sysline(1))", |
| 101 | "kb", "Sent by backspace key", |
| 102 | "kd", "Sent down arrow key", |
| 103 | "ke", "Out of \"keypad transmit\" mode", |
| 104 | "kh", "Sent by home key", |
| 105 | "kl", "Sent by left arrow key", |
| 106 | "kn", "Number of \"other\" keys", |
| 107 | "ko", "Tc entries for other non-function keys", |
| 108 | "kr", "Sent by right arrow key", |
| 109 | "ks", "Put in \"keypad transmit\" mode", |
| 110 | "ku", "Sent by up arrow key", |
| 111 | "le", "Move left", |
| 112 | "li", "Number of lines on screen or page", |
| 113 | "ll", "Last line, first column (if no cm)", |
| 114 | "ma", "Arrow key map, used by vi V2 only", |
| 115 | "mb", "Enter blinking mode", |
| 116 | "md", "Enter bold mode", |
| 117 | "me", "Reset video attributes", |
| 118 | "mh", "Enter halfbright mode", |
| 119 | "mi", "Safe to move while in insert mode", |
| 120 | "mk", "Enter protected mode", |
| 121 | "ml", "Memory lock on above cursor.", |
| 122 | "mr", "Enter reverse video mode", |
| 123 | "ms", "Ok to move while in standout/underline mode", |
| 124 | "mu", "Memory unlock (turn off memory lock).", |
| 125 | "nc", "No working CR (DM2500,H2000)", |
| 126 | "nd", "Non-destructive space (cursor right)", |
| 127 | "nl", "Newline character (default \\n)", |
| 128 | "ns", "Is a CRT but doesn't scroll.", |
| 129 | "os", "Terminal overstrikes", |
| 130 | "pc", "Pad character (rather than null)", |
| 131 | "pt", "Has hardware tabs (may need to use is)", |
| 132 | "se", "End stand out mode", |
| 133 | "sf", "Scroll forwards", |
| 134 | "sg", "Number of blank chars left by so/se", |
| 135 | "so", "Begin stand out mode", |
| 136 | "sr", "Scroll reverse (backwards)", |
| 137 | "ta", "Tab (other than ^I or with padding)", |
| 138 | "tc", "Entry of similar terminal - must be last", |
| 139 | "te", "String to end programs that use cm", |
| 140 | "ti", "String to begin programs that use cm", |
| 141 | "ts", "To status line sequence", |
| 142 | "uc", "Underscore one char and move past it", |
| 143 | "ue", "End underscore mode", |
| 144 | "ug", "Number of blank chars left by us or ue", |
| 145 | "ul", "Underlines, though no overstrike", |
| 146 | "up", "Upline (cursor up)", |
| 147 | "us", "Start underscore mode", |
| 148 | "vb", "Visible bell (may not move cursor)", |
| 149 | "ve", "Sequence to end open/visual mode", |
| 150 | "vs", "Sequence to start open/visual mode", |
| 151 | "xb", "Beehive (f1=escape, f2=ctrl C)", |
| 152 | "xn", "A newline is ignored after a wrap (Concept)", |
| 153 | "xr", "Return acts like ce \\r \\n (Delta Data)", |
| 154 | "xs", "Standout not erased by writing over it (HP 264?)", |
| 155 | "xt", "Destructive tabs, magic so char (Teleray 1061)" |
| 156 | }; |
| 157 | |
| 158 | #ifdef DEBUG |
| 159 | int Dflag = NO; |
| 160 | #endif |
| 161 | int xflag = NO; |
| 162 | int Sflag = YES; |
| 163 | int sflag = NO; |
| 164 | int dflag = NO; |
| 165 | int nflag = NO; |
| 166 | int gflag = NO; |
| 167 | int bflag = NO; |
| 168 | int Uflag = NO; |
| 169 | int tc_loopc; /* loop counter */ |
| 170 | char *tcfile; /* termcap database pathname */ |
| 171 | char tcbuf[2048]; /* buffer for termcap description */ |
| 172 | char *lastchar(); |
| 173 | int name_cmp(); |
| 174 | int ent_cmp(); |
| 175 | struct TcName *find_name(); |
| 176 | char *getenv(); |
| 177 | char *ctime(); |
| 178 | char *strncpy(); |
| 179 | long ftell(); |
| 180 | |
| 181 | main(argc, argv, envp) |
| 182 | int argc; |
| 183 | char **argv; |
| 184 | char **envp; |
| 185 | { |
| 186 | char *av; |
| 187 | struct TcName *tn; |
| 188 | register char *bp; |
| 189 | long pos; |
| 190 | int n; |
| 191 | struct stat st; |
| 192 | char envbuf[256]; |
| 193 | FILE *tcfp; |
| 194 | |
| 195 | if ((bp = getenv("TERMCAP")) && *bp == '/') |
| 196 | tcfile = bp; |
| 197 | else |
| 198 | tcfile = "/etc/termcap"; |
| 199 | |
| 200 | while (--argc > 0) |
| 201 | { |
| 202 | if (*(av = *++argv) == '-') |
| 203 | { |
| 204 | while (*++av) |
| 205 | { |
| 206 | switch (*av) |
| 207 | { |
| 208 | /* use alternate termcap file */ |
| 209 | case 'f': |
| 210 | if (argc-- <= 0) |
| 211 | { |
| 212 | fprintf(stderr, |
| 213 | "-f needs a filename\n"); |
| 214 | exit(1); |
| 215 | } |
| 216 | tcfile = *++argv; |
| 217 | break; |
| 218 | |
| 219 | /* only check for dup names */ |
| 220 | case 'd': |
| 221 | nflag = YES; |
| 222 | /* fall thru */ |
| 223 | |
| 224 | /* look for duplicated names */ |
| 225 | case 'D': |
| 226 | dflag = YES; |
| 227 | continue; |
| 228 | |
| 229 | case 'U': |
| 230 | Uflag = YES; |
| 231 | continue; |
| 232 | |
| 233 | /* strip the two name off */ |
| 234 | case 's': |
| 235 | sflag = YES; |
| 236 | continue; |
| 237 | |
| 238 | /* sort the name array */ |
| 239 | case 'S': |
| 240 | Sflag = NO; |
| 241 | continue; |
| 242 | |
| 243 | #ifdef DEBUG |
| 244 | case 'T': |
| 245 | Dflag = YES; |
| 246 | continue; |
| 247 | #endif |
| 248 | |
| 249 | /* sort on generic names */ |
| 250 | case 'g': |
| 251 | gflag = YES; |
| 252 | continue; |
| 253 | |
| 254 | /* expand entries in 'full mode' */ |
| 255 | case 'x': |
| 256 | xflag = YES; |
| 257 | continue; |
| 258 | |
| 259 | /* show bare entry */ |
| 260 | case 'b': |
| 261 | bflag = YES; |
| 262 | continue; |
| 263 | |
| 264 | default: |
| 265 | fprintf(stderr, "showtc: unknown flag: -%c\n", *av); |
| 266 | fprintf(stderr, USAGE, argv[0]); |
| 267 | exit(1); |
| 268 | } |
| 269 | } |
| 270 | } |
| 271 | else |
| 272 | break; |
| 273 | } |
| 274 | |
| 275 | /* |
| 276 | * insert the specified TERMCAP file into the environment |
| 277 | */ |
| 278 | (void) sprintf(envbuf, "TERMCAP=%s", tcfile); |
| 279 | while (*envp) |
| 280 | { |
| 281 | if (strncmp(*envp, "TERMCAP=", 8) == 0) |
| 282 | { |
| 283 | *envp = envbuf; |
| 284 | break; |
| 285 | } |
| 286 | envp++; |
| 287 | } |
| 288 | if (! *envp) |
| 289 | *envp = envbuf; /* this may be dangerous */ |
| 290 | |
| 291 | /* |
| 292 | ** if user specified type(s), do only those |
| 293 | */ |
| 294 | if (argc > 0) |
| 295 | { |
| 296 | /* |
| 297 | ** look for the users specified term types |
| 298 | */ |
| 299 | while (argc > 0) |
| 300 | { |
| 301 | switch (n = tgetent(tcbuf, *argv)) |
| 302 | { |
| 303 | case 1: |
| 304 | if (bflag) |
| 305 | (void) prnt_raw(tcbuf); |
| 306 | else |
| 307 | (void) prnt_ent(tcbuf); |
| 308 | break; |
| 309 | |
| 310 | case 0: |
| 311 | fprintf(stderr, |
| 312 | "showtc: bad entry: %s\n", *argv); |
| 313 | break; |
| 314 | |
| 315 | case -1: |
| 316 | fputs("showtc: ", stderr); |
| 317 | perror(tcfile); |
| 318 | exit(1); |
| 319 | |
| 320 | default: |
| 321 | fprintf(stderr, "bad return from tgetent: %d\n", n); |
| 322 | exit(1); |
| 323 | } |
| 324 | argc--; |
| 325 | argv++; |
| 326 | } |
| 327 | exit(0); |
| 328 | } |
| 329 | |
| 330 | if (bflag) |
| 331 | { |
| 332 | fprintf(stderr, "showtc: -b flag with no entries makes no sense.\n"); |
| 333 | exit(1); |
| 334 | } |
| 335 | |
| 336 | |
| 337 | /* |
| 338 | ** if no type was specified, do the whole file |
| 339 | */ |
| 340 | if ((tcfp = fopen(tcfile, "r")) == NULL) |
| 341 | { |
| 342 | perror(tcfile); |
| 343 | exit(1); |
| 344 | } |
| 345 | |
| 346 | /* |
| 347 | ** identify database, for the record |
| 348 | */ |
| 349 | if (stat(tcfile, &st)) |
| 350 | { |
| 351 | perror(tcfile); |
| 352 | exit(1); |
| 353 | } |
| 354 | printf("File: %s, last modified: %s\n", tcfile, ctime(&st.st_mtime)); |
| 355 | |
| 356 | |
| 357 | /* |
| 358 | ** build termcap entry table |
| 359 | */ |
| 360 | tn = tcNames; |
| 361 | pos = ftell(tcfp); |
| 362 | bp = tcbuf; |
| 363 | while (fgets(bp, sizeof (tcbuf), tcfp) != NULL) |
| 364 | { |
| 365 | if (tcbuf[0] == '#') |
| 366 | { |
| 367 | pos = ftell(tcfp); |
| 368 | bp = tcbuf; |
| 369 | continue; |
| 370 | } |
| 371 | |
| 372 | tn->file_pos = pos; |
| 373 | |
| 374 | /* |
| 375 | ** get full entry |
| 376 | */ |
| 377 | while (*(bp = lastchar(bp)) == '\\' && fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp)) |
| 378 | ; |
| 379 | /* |
| 380 | ** save the names |
| 381 | */ |
| 382 | for (bp = tcbuf; *bp && *bp != ':'; bp++) |
| 383 | ; |
| 384 | *bp = '\0'; |
| 385 | (void) strncpy(tn->name_buf, tcbuf, |
| 386 | sizeof tcNames[0].name_buf); |
| 387 | |
| 388 | pos = ftell(tcfp); |
| 389 | bp = tcbuf; |
| 390 | tn++; |
| 391 | } |
| 392 | tn->file_pos = -1; |
| 393 | |
| 394 | /* |
| 395 | ** Look for duplicate names |
| 396 | */ |
| 397 | if (dflag) |
| 398 | check_dup(); |
| 399 | if (nflag) |
| 400 | exit(0); |
| 401 | |
| 402 | #ifdef DEBUG |
| 403 | if (Dflag) |
| 404 | { |
| 405 | for (tn = tcNames; tn->file_pos >= 0; tn++) |
| 406 | { |
| 407 | printf("Entry #%d:\n\t%s\n\tfile_pos = %ld\n", |
| 408 | tn - tcNames, tn->name_buf, tn->file_pos); |
| 409 | } |
| 410 | exit(0); |
| 411 | } |
| 412 | #endif |
| 413 | |
| 414 | /* |
| 415 | ** Order the list |
| 416 | */ |
| 417 | if (Sflag) |
| 418 | qsort((char *)tcNames, tn - tcNames, |
| 419 | sizeof (struct TcName), name_cmp); |
| 420 | |
| 421 | /* |
| 422 | ** List termcap entry for each name in table |
| 423 | */ |
| 424 | for (tn = tcNames; tn->file_pos >= 0; tn++) |
| 425 | { |
| 426 | tc_loopc = 0; |
| 427 | /*** working toward this ... |
| 428 | (void) prnt_ent(tn); |
| 429 | ***/ |
| 430 | (void) fseek(tcfp, tn->file_pos, 0); |
| 431 | bp = tcbuf; |
| 432 | while (fgets(bp, (sizeof tcbuf) - (bp - tcbuf), tcfp) |
| 433 | && *(bp = lastchar(bp)) == '\\') |
| 434 | ; |
| 435 | (void) prnt_ent(tcbuf); |
| 436 | } |
| 437 | } |
| 438 | |
| 439 | char * |
| 440 | lastchar(b) |
| 441 | char *b; |
| 442 | { |
| 443 | register char *p; |
| 444 | |
| 445 | p = b + strlen(b) - 1; |
| 446 | while (*p == '\n' || *p == ' ') |
| 447 | p--; |
| 448 | return(p); |
| 449 | } |
| 450 | |
| 451 | name_cmp(a, b) |
| 452 | char *a, *b; |
| 453 | { |
| 454 | if (gflag) /* sort on generic names */ |
| 455 | { |
| 456 | a += 3; |
| 457 | b += 3; |
| 458 | while (*a && *b && *a != '|' && *a == *b) |
| 459 | { |
| 460 | a++; |
| 461 | b++; |
| 462 | } |
| 463 | if (*a == '|' || *a == CNULL) |
| 464 | return((*b == '|' || *b == CNULL)? 0:-1); |
| 465 | if (*b == '|' || *b == CNULL) |
| 466 | return(1); |
| 467 | return(*a - *b); |
| 468 | } |
| 469 | return(strncmp(a, b, 2)); |
| 470 | } |
| 471 | |
| 472 | prnt_ent(buf) |
| 473 | register char *buf; |
| 474 | { |
| 475 | register char *name; |
| 476 | char *getdesc(); |
| 477 | char *caps[256]; |
| 478 | register char **cp; |
| 479 | register char **tp; |
| 480 | char tname[3]; |
| 481 | |
| 482 | cp = caps; |
| 483 | name = buf; |
| 484 | tname[3] = '\0'; |
| 485 | |
| 486 | while (*buf) |
| 487 | { |
| 488 | switch (*buf) |
| 489 | { |
| 490 | case ':': |
| 491 | *buf++ = '\0'; |
| 492 | while (*buf && !isalnum(*buf)) |
| 493 | buf++; |
| 494 | if (*buf) |
| 495 | { |
| 496 | /* |
| 497 | * ignore duplicate cap entries |
| 498 | */ |
| 499 | for (tp = caps; tp < cp; tp++) |
| 500 | if (strncmp(buf, *tp, 2) == 0) |
| 501 | goto skip; |
| 502 | *cp++ = buf; |
| 503 | skip: |
| 504 | /* |
| 505 | * does user want tc= expanded? |
| 506 | */ |
| 507 | if (xflag && strncmp(buf, "tc=", 3) == 0) |
| 508 | { |
| 509 | /* |
| 510 | * find end of tc= |
| 511 | */ |
| 512 | while (*buf != ':') |
| 513 | buf++; |
| 514 | *buf = '\0'; |
| 515 | /* |
| 516 | * save term name |
| 517 | */ |
| 518 | tname[0] = name[0]; |
| 519 | tname[1] = name[1]; |
| 520 | printf("%s: expanding %s\n", |
| 521 | tname, cp[-1]); |
| 522 | /* |
| 523 | * let tgetent do the work |
| 524 | */ |
| 525 | tgetent(tcbuf, tname); |
| 526 | prnt_ent(tcbuf); |
| 527 | return; |
| 528 | } |
| 529 | } |
| 530 | continue; |
| 531 | |
| 532 | case '|': |
| 533 | *buf++ = ','; |
| 534 | continue; |
| 535 | |
| 536 | default: |
| 537 | buf++; |
| 538 | } |
| 539 | } |
| 540 | *cp = CNULL; /* was (char *)0 */ |
| 541 | |
| 542 | if (Sflag) |
| 543 | qsort((char *) caps, cp - caps, sizeof (char *), ent_cmp); |
| 544 | |
| 545 | printf("%s\n", name); |
| 546 | for (cp = caps; *cp; cp++) |
| 547 | if (Uflag) { |
| 548 | if (unknowncap(*cp)) { |
| 549 | printf("%3.3s\n", *cp); |
| 550 | } |
| 551 | } else if (sflag) { |
| 552 | printf("%-45s %s\n", getdesc(*cp), *cp); |
| 553 | } else { |
| 554 | printf("%2.2s %-45s %s\n", name, getdesc(*cp), *cp); |
| 555 | } |
| 556 | (void) putchar('\n'); |
| 557 | } |
| 558 | |
| 559 | prnt_raw(buf) |
| 560 | char *buf; |
| 561 | { |
| 562 | register char *b; |
| 563 | register int len; |
| 564 | register int n; |
| 565 | char *index(); |
| 566 | |
| 567 | len = 0; |
| 568 | b = buf; |
| 569 | while (*b) |
| 570 | { |
| 571 | if ((n = index(b, ':') - b + 1) <= 0) |
| 572 | n = strlen(b); |
| 573 | if (len == 0) /* first part */ |
| 574 | { |
| 575 | printf("%.*s\\\n\t:", n, b); |
| 576 | len = 9 - n; |
| 577 | } |
| 578 | else |
| 579 | { |
| 580 | if ((len + n) >= 75) |
| 581 | { |
| 582 | printf("\\\n\t:"); |
| 583 | len = 9; |
| 584 | } |
| 585 | printf("%.*s", n, b); |
| 586 | } |
| 587 | len += n; |
| 588 | b += n; |
| 589 | while (*b && index(" \t:\n", *b)) |
| 590 | b++; |
| 591 | } |
| 592 | if (b[-1] != ':') |
| 593 | (void) putchar(':'); |
| 594 | (void) putchar('\n'); |
| 595 | } |
| 596 | |
| 597 | ent_cmp(a, b) |
| 598 | char **a, **b; |
| 599 | { |
| 600 | return(strncmp(*a, *b, 2)); |
| 601 | } |
| 602 | |
| 603 | check_dup() |
| 604 | { |
| 605 | /* |
| 606 | ** Look for duplicated names |
| 607 | */ |
| 608 | register char *p; |
| 609 | register char *q; |
| 610 | register struct TcName *tn; |
| 611 | register struct TcName *tm; |
| 612 | |
| 613 | tn = tcNames; |
| 614 | while (tn->file_pos >= 0) |
| 615 | { |
| 616 | p = q = tn->name_buf; |
| 617 | while (*q) |
| 618 | { |
| 619 | while (*p && *p != '|') |
| 620 | p++; |
| 621 | if (p != q && (tm = find_name(q, tn + 1, p - q))) |
| 622 | { |
| 623 | fputs("Duplicate name: ", stdout); |
| 624 | while (q != p) |
| 625 | (void) putchar(*q++); |
| 626 | (void) putchar('\n'); |
| 627 | puts(tn->name_buf); |
| 628 | puts(tm->name_buf); |
| 629 | puts("---\n"); |
| 630 | } |
| 631 | if (*p == '|') |
| 632 | p++; |
| 633 | q = p; |
| 634 | } |
| 635 | tn++; |
| 636 | } |
| 637 | } |
| 638 | |
| 639 | struct TcName * |
| 640 | find_name(name, tn, len) |
| 641 | register char *name; |
| 642 | register struct TcName *tn; |
| 643 | register int len; |
| 644 | { |
| 645 | /* |
| 646 | ** find name of length len in tcname structure buffers. |
| 647 | */ |
| 648 | register char *p; |
| 649 | register char *buf; |
| 650 | register int n; |
| 651 | |
| 652 | while (tn->file_pos >= 0) |
| 653 | { |
| 654 | buf = tn->name_buf; |
| 655 | while (*buf) |
| 656 | { |
| 657 | p = name; |
| 658 | n = len; |
| 659 | if (*buf == '|') |
| 660 | buf++; |
| 661 | |
| 662 | while (*buf && *buf != '|') |
| 663 | { |
| 664 | if (*p != *buf) |
| 665 | { |
| 666 | while (*buf && *buf != '|') |
| 667 | buf++; |
| 668 | break; |
| 669 | } |
| 670 | |
| 671 | if (--n <= 0) |
| 672 | { |
| 673 | buf++; |
| 674 | if (*buf == '|' || *buf == '\0') |
| 675 | return(tn); |
| 676 | while (*buf && *buf != '|') |
| 677 | buf++; |
| 678 | break; |
| 679 | } |
| 680 | buf++; |
| 681 | p++; |
| 682 | } |
| 683 | } |
| 684 | tn++; |
| 685 | } |
| 686 | return((struct TcName *)0); |
| 687 | } |
| 688 | |
| 689 | char * |
| 690 | getdesc(key) |
| 691 | char *key; |
| 692 | { |
| 693 | register int i; |
| 694 | |
| 695 | for (i = 0; i <= NOCAPS; i++) |
| 696 | if (strncmp(key, capList[i].cap, 2) == 0) |
| 697 | return (capList[i].desc); |
| 698 | return(""); |
| 699 | } |
| 700 | |
| 701 | unknowncap(key) |
| 702 | char *key; |
| 703 | { |
| 704 | register int i; |
| 705 | |
| 706 | for (i = 0; i <= NOCAPS; i++) |
| 707 | if (strncmp(key, capList[i].cap, 2) == 0) |
| 708 | return (0); |
| 709 | return(1); |
| 710 | } |