1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 1997 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 18*7c478bd9Sstevel@tonic-gate 19*7c478bd9Sstevel@tonic-gate #if 0 20*7c478bd9Sstevel@tonic-gate static char 21*7c478bd9Sstevel@tonic-gate sccsid[] = "@(#)termcap.c 1.11 88/02/08 SMI"; /* from UCB 5.1 6/5/85 */ 22*7c478bd9Sstevel@tonic-gate #endif 23*7c478bd9Sstevel@tonic-gate 24*7c478bd9Sstevel@tonic-gate #define BUFSIZ 1024 25*7c478bd9Sstevel@tonic-gate #define MAXHOP 32 /* max number of tc= indirections */ 26*7c478bd9Sstevel@tonic-gate #define E_TERMCAP "/etc/termcap" 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 29*7c478bd9Sstevel@tonic-gate #include <unistd.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <stddef.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <strings.h> 34*7c478bd9Sstevel@tonic-gate #include <ctype.h> 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate /* 37*7c478bd9Sstevel@tonic-gate * termcap - routines for dealing with the terminal capability data base 38*7c478bd9Sstevel@tonic-gate * 39*7c478bd9Sstevel@tonic-gate * BUG: Should use a "last" pointer in tbuf, so that searching 40*7c478bd9Sstevel@tonic-gate * for capabilities alphabetically would not be a n**2/2 41*7c478bd9Sstevel@tonic-gate * process when large numbers of capabilities are given. 42*7c478bd9Sstevel@tonic-gate * Note: If we add a last pointer now we will screw up the 43*7c478bd9Sstevel@tonic-gate * tc capability. We really should compile termcap. 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * Essentially all the work here is scanning and decoding escapes 46*7c478bd9Sstevel@tonic-gate * in string capabilities. We don't use stdio because the editor 47*7c478bd9Sstevel@tonic-gate * doesn't, and because living w/o it is not hard. 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate static char *tbuf; 51*7c478bd9Sstevel@tonic-gate static int hopcount; /* detect infinite loops in termcap, init 0 */ 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate /* forward declarations */ 54*7c478bd9Sstevel@tonic-gate static char *tdecode(char *, char **); 55*7c478bd9Sstevel@tonic-gate static void tngetsize(char *); 56*7c478bd9Sstevel@tonic-gate static char *tskip(char *bp); 57*7c478bd9Sstevel@tonic-gate static char *appendsmalldec(char *, int); 58*7c478bd9Sstevel@tonic-gate int tnamatch(char *); 59*7c478bd9Sstevel@tonic-gate int tnchktc(void); 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate /* 62*7c478bd9Sstevel@tonic-gate * Get an entry for terminal name in buffer bp, 63*7c478bd9Sstevel@tonic-gate * from the termcap file. Parse is very rudimentary; 64*7c478bd9Sstevel@tonic-gate * we just notice escaped newlines. 65*7c478bd9Sstevel@tonic-gate */ 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate int 68*7c478bd9Sstevel@tonic-gate tgetent(char *bp, char *name) 69*7c478bd9Sstevel@tonic-gate { 70*7c478bd9Sstevel@tonic-gate char *cp; 71*7c478bd9Sstevel@tonic-gate int c; 72*7c478bd9Sstevel@tonic-gate int i = 0; 73*7c478bd9Sstevel@tonic-gate ssize_t cnt = 0; 74*7c478bd9Sstevel@tonic-gate char ibuf[BUFSIZ]; 75*7c478bd9Sstevel@tonic-gate int tf; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate tbuf = bp; 78*7c478bd9Sstevel@tonic-gate tf = -1; 79*7c478bd9Sstevel@tonic-gate #ifndef V6 80*7c478bd9Sstevel@tonic-gate cp = getenv("TERMCAP"); 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * TERMCAP can have one of two things in it. It can be the 83*7c478bd9Sstevel@tonic-gate * name of a file to use instead of /etc/termcap. In this 84*7c478bd9Sstevel@tonic-gate * case it better start with a "/". Or it can be an entry to 85*7c478bd9Sstevel@tonic-gate * use so we don't have to read the file. In this case it 86*7c478bd9Sstevel@tonic-gate * has to already have the newlines crunched out. 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate if (cp && *cp) { 89*7c478bd9Sstevel@tonic-gate if (*cp == '/') { 90*7c478bd9Sstevel@tonic-gate tf = open(cp, 0); 91*7c478bd9Sstevel@tonic-gate } else { 92*7c478bd9Sstevel@tonic-gate tbuf = cp; 93*7c478bd9Sstevel@tonic-gate c = tnamatch(name); 94*7c478bd9Sstevel@tonic-gate tbuf = bp; 95*7c478bd9Sstevel@tonic-gate if (c) { 96*7c478bd9Sstevel@tonic-gate (void) strcpy(bp, cp); 97*7c478bd9Sstevel@tonic-gate return (tnchktc()); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate if (tf < 0) 102*7c478bd9Sstevel@tonic-gate tf = open(E_TERMCAP, 0); 103*7c478bd9Sstevel@tonic-gate #else 104*7c478bd9Sstevel@tonic-gate tf = open(E_TERMCAP, 0); 105*7c478bd9Sstevel@tonic-gate #endif 106*7c478bd9Sstevel@tonic-gate if (tf < 0) 107*7c478bd9Sstevel@tonic-gate return (-1); 108*7c478bd9Sstevel@tonic-gate for (;;) { 109*7c478bd9Sstevel@tonic-gate cp = bp; 110*7c478bd9Sstevel@tonic-gate for (;;) { 111*7c478bd9Sstevel@tonic-gate if (i == cnt) { 112*7c478bd9Sstevel@tonic-gate cnt = read(tf, ibuf, BUFSIZ); 113*7c478bd9Sstevel@tonic-gate if (cnt <= 0) { 114*7c478bd9Sstevel@tonic-gate (void) close(tf); 115*7c478bd9Sstevel@tonic-gate return (0); 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate i = 0; 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate c = ibuf[i++]; 120*7c478bd9Sstevel@tonic-gate if (c == '\n') { 121*7c478bd9Sstevel@tonic-gate if (cp > bp && cp[-1] == '\\') { 122*7c478bd9Sstevel@tonic-gate cp--; 123*7c478bd9Sstevel@tonic-gate continue; 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate break; 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate if (cp >= bp+BUFSIZ) { 128*7c478bd9Sstevel@tonic-gate (void) write(2, "Termcap entry too long\n", 23); 129*7c478bd9Sstevel@tonic-gate break; 130*7c478bd9Sstevel@tonic-gate } else 131*7c478bd9Sstevel@tonic-gate *cp++ = (char) c; 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate *cp = 0; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* 136*7c478bd9Sstevel@tonic-gate * The real work for the match. 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate if (tnamatch(name)) { 139*7c478bd9Sstevel@tonic-gate (void) close(tf); 140*7c478bd9Sstevel@tonic-gate return (tnchktc()); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * tnchktc: check the last entry, see if it's tc=xxx. If so, 147*7c478bd9Sstevel@tonic-gate * recursively find xxx and append that entry (minus the names) 148*7c478bd9Sstevel@tonic-gate * to take the place of the tc=xxx entry. This allows termcap 149*7c478bd9Sstevel@tonic-gate * entries to say "like an HP2621 but doesn't turn on the labels". 150*7c478bd9Sstevel@tonic-gate * Note that this works because of the left to right scan. 151*7c478bd9Sstevel@tonic-gate */ 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate int 154*7c478bd9Sstevel@tonic-gate tnchktc(void) 155*7c478bd9Sstevel@tonic-gate { 156*7c478bd9Sstevel@tonic-gate char *p, *q; 157*7c478bd9Sstevel@tonic-gate char tcname[16]; /* name of similar terminal */ 158*7c478bd9Sstevel@tonic-gate char tcbuf[BUFSIZ]; 159*7c478bd9Sstevel@tonic-gate char *holdtbuf = tbuf; 160*7c478bd9Sstevel@tonic-gate ptrdiff_t l; 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate p = tbuf + strlen(tbuf) - 2; /* before the last colon */ 163*7c478bd9Sstevel@tonic-gate while (*--p != ':') 164*7c478bd9Sstevel@tonic-gate if (p < tbuf) { 165*7c478bd9Sstevel@tonic-gate (void) write(2, "Bad termcap entry\n", 18); 166*7c478bd9Sstevel@tonic-gate return (0); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate p++; 169*7c478bd9Sstevel@tonic-gate /* p now points to beginning of last field */ 170*7c478bd9Sstevel@tonic-gate if (p[0] != 't' || p[1] != 'c') { 171*7c478bd9Sstevel@tonic-gate tngetsize(tbuf); 172*7c478bd9Sstevel@tonic-gate return (1); 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate (void) strcpy(tcname, p+3); 175*7c478bd9Sstevel@tonic-gate q = tcname; 176*7c478bd9Sstevel@tonic-gate while (*q && *q != ':') 177*7c478bd9Sstevel@tonic-gate q++; 178*7c478bd9Sstevel@tonic-gate *q = 0; 179*7c478bd9Sstevel@tonic-gate if (++hopcount > MAXHOP) { 180*7c478bd9Sstevel@tonic-gate (void) write(2, "Infinite tc= loop\n", 18); 181*7c478bd9Sstevel@tonic-gate return (0); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate if (tgetent(tcbuf, tcname) != 1) { 184*7c478bd9Sstevel@tonic-gate hopcount = 0; /* unwind recursion */ 185*7c478bd9Sstevel@tonic-gate return (0); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate for (q = tcbuf; *q != ':'; q++) 188*7c478bd9Sstevel@tonic-gate ; 189*7c478bd9Sstevel@tonic-gate l = p - holdtbuf + strlen(q); 190*7c478bd9Sstevel@tonic-gate if (l > BUFSIZ) { 191*7c478bd9Sstevel@tonic-gate (void) write(2, "Termcap entry too long\n", 23); 192*7c478bd9Sstevel@tonic-gate q[BUFSIZ - (p-tbuf)] = 0; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate (void) strcpy(p, q+1); 195*7c478bd9Sstevel@tonic-gate tbuf = holdtbuf; 196*7c478bd9Sstevel@tonic-gate hopcount = 0; /* unwind recursion */ 197*7c478bd9Sstevel@tonic-gate tngetsize(tbuf); 198*7c478bd9Sstevel@tonic-gate return (1); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* 202*7c478bd9Sstevel@tonic-gate * Tnamatch deals with name matching. The first field of the termcap 203*7c478bd9Sstevel@tonic-gate * entry is a sequence of names separated by |'s, so we compare 204*7c478bd9Sstevel@tonic-gate * against each such name. The normal : terminator after the last 205*7c478bd9Sstevel@tonic-gate * name (before the first field) stops us. 206*7c478bd9Sstevel@tonic-gate */ 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate int 209*7c478bd9Sstevel@tonic-gate tnamatch(char *np) 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate char *Np, *Bp; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate Bp = tbuf; 214*7c478bd9Sstevel@tonic-gate if (*Bp == '#') 215*7c478bd9Sstevel@tonic-gate return (0); 216*7c478bd9Sstevel@tonic-gate for (;;) { 217*7c478bd9Sstevel@tonic-gate for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 218*7c478bd9Sstevel@tonic-gate continue; 219*7c478bd9Sstevel@tonic-gate if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 220*7c478bd9Sstevel@tonic-gate return (1); 221*7c478bd9Sstevel@tonic-gate while (*Bp && *Bp != ':' && *Bp != '|') 222*7c478bd9Sstevel@tonic-gate Bp++; 223*7c478bd9Sstevel@tonic-gate if (*Bp == 0 || *Bp == ':') 224*7c478bd9Sstevel@tonic-gate return (0); 225*7c478bd9Sstevel@tonic-gate Bp++; 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate /* 230*7c478bd9Sstevel@tonic-gate * Skip to the next field. Notice that this is very dumb, not 231*7c478bd9Sstevel@tonic-gate * knowing about \: escapes or any such. If necessary, :'s can be put 232*7c478bd9Sstevel@tonic-gate * into the termcap file in octal. 233*7c478bd9Sstevel@tonic-gate */ 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate static char * 236*7c478bd9Sstevel@tonic-gate tskip(char *bp) 237*7c478bd9Sstevel@tonic-gate { 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate while (*bp && *bp != ':') 240*7c478bd9Sstevel@tonic-gate bp++; 241*7c478bd9Sstevel@tonic-gate if (*bp == ':') { 242*7c478bd9Sstevel@tonic-gate do { 243*7c478bd9Sstevel@tonic-gate bp++; 244*7c478bd9Sstevel@tonic-gate while (isspace(*bp)) 245*7c478bd9Sstevel@tonic-gate bp++; 246*7c478bd9Sstevel@tonic-gate } while (*bp == ':'); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate return (bp); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* 252*7c478bd9Sstevel@tonic-gate * Return the (numeric) option id. 253*7c478bd9Sstevel@tonic-gate * Numeric options look like 254*7c478bd9Sstevel@tonic-gate * li#80 255*7c478bd9Sstevel@tonic-gate * i.e. the option string is separated from the numeric value by 256*7c478bd9Sstevel@tonic-gate * a # character. If the option is not found we return -1. 257*7c478bd9Sstevel@tonic-gate * Note that we handle octal numbers beginning with 0. 258*7c478bd9Sstevel@tonic-gate */ 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate int 261*7c478bd9Sstevel@tonic-gate tgetnum(char *id) 262*7c478bd9Sstevel@tonic-gate { 263*7c478bd9Sstevel@tonic-gate int i, base; 264*7c478bd9Sstevel@tonic-gate char *bp = tbuf; 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate for (;;) { 267*7c478bd9Sstevel@tonic-gate bp = tskip(bp); 268*7c478bd9Sstevel@tonic-gate if (*bp == 0) 269*7c478bd9Sstevel@tonic-gate return (-1); 270*7c478bd9Sstevel@tonic-gate if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 271*7c478bd9Sstevel@tonic-gate continue; 272*7c478bd9Sstevel@tonic-gate if (*bp == '@') 273*7c478bd9Sstevel@tonic-gate return (-1); 274*7c478bd9Sstevel@tonic-gate if (*bp != '#') 275*7c478bd9Sstevel@tonic-gate continue; 276*7c478bd9Sstevel@tonic-gate bp++; 277*7c478bd9Sstevel@tonic-gate base = 10; 278*7c478bd9Sstevel@tonic-gate if (*bp == '0') 279*7c478bd9Sstevel@tonic-gate base = 8; 280*7c478bd9Sstevel@tonic-gate i = 0; 281*7c478bd9Sstevel@tonic-gate while (isdigit(*bp)) 282*7c478bd9Sstevel@tonic-gate i *= base, i += *bp++ - '0'; 283*7c478bd9Sstevel@tonic-gate return (i); 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* 288*7c478bd9Sstevel@tonic-gate * Handle a flag option. 289*7c478bd9Sstevel@tonic-gate * Flag options are given "naked", i.e. followed by a : or the end 290*7c478bd9Sstevel@tonic-gate * of the buffer. Return 1 if we find the option, or 0 if it is 291*7c478bd9Sstevel@tonic-gate * not given. 292*7c478bd9Sstevel@tonic-gate */ 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate int 295*7c478bd9Sstevel@tonic-gate tgetflag(char *id) 296*7c478bd9Sstevel@tonic-gate { 297*7c478bd9Sstevel@tonic-gate char *bp = tbuf; 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate for (;;) { 300*7c478bd9Sstevel@tonic-gate bp = tskip(bp); 301*7c478bd9Sstevel@tonic-gate if (!*bp) 302*7c478bd9Sstevel@tonic-gate return (0); 303*7c478bd9Sstevel@tonic-gate if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { 304*7c478bd9Sstevel@tonic-gate if (!*bp || *bp == ':') 305*7c478bd9Sstevel@tonic-gate return (1); 306*7c478bd9Sstevel@tonic-gate else if (*bp == '@') 307*7c478bd9Sstevel@tonic-gate return (0); 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate /* 313*7c478bd9Sstevel@tonic-gate * Get a string valued option. 314*7c478bd9Sstevel@tonic-gate * These are given as 315*7c478bd9Sstevel@tonic-gate * cl=^Z 316*7c478bd9Sstevel@tonic-gate * Much decoding is done on the strings, and the strings are 317*7c478bd9Sstevel@tonic-gate * placed in area, which is a ref parameter which is updated. 318*7c478bd9Sstevel@tonic-gate * No checking on area overflow. 319*7c478bd9Sstevel@tonic-gate */ 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate char * 322*7c478bd9Sstevel@tonic-gate tgetstr(char *id, char **area) 323*7c478bd9Sstevel@tonic-gate { 324*7c478bd9Sstevel@tonic-gate char *bp = tbuf; 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate for (;;) { 327*7c478bd9Sstevel@tonic-gate bp = tskip(bp); 328*7c478bd9Sstevel@tonic-gate if (!*bp) 329*7c478bd9Sstevel@tonic-gate return (0); 330*7c478bd9Sstevel@tonic-gate if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 331*7c478bd9Sstevel@tonic-gate continue; 332*7c478bd9Sstevel@tonic-gate if (*bp == '@') 333*7c478bd9Sstevel@tonic-gate return (0); 334*7c478bd9Sstevel@tonic-gate if (*bp != '=') 335*7c478bd9Sstevel@tonic-gate continue; 336*7c478bd9Sstevel@tonic-gate bp++; 337*7c478bd9Sstevel@tonic-gate return (tdecode(bp, area)); 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate /* 342*7c478bd9Sstevel@tonic-gate * Tdecode does the grung work to decode the 343*7c478bd9Sstevel@tonic-gate * string capability escapes. 344*7c478bd9Sstevel@tonic-gate */ 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate static char * 347*7c478bd9Sstevel@tonic-gate tdecode(char *str, char **area) 348*7c478bd9Sstevel@tonic-gate { 349*7c478bd9Sstevel@tonic-gate char *cp; 350*7c478bd9Sstevel@tonic-gate int c; 351*7c478bd9Sstevel@tonic-gate char *dp; 352*7c478bd9Sstevel@tonic-gate int i; 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate cp = *area; 355*7c478bd9Sstevel@tonic-gate while (((c = *str++) != 0) && c != ':') { 356*7c478bd9Sstevel@tonic-gate switch (c) { 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate case '^': 359*7c478bd9Sstevel@tonic-gate c = *str++ & 037; 360*7c478bd9Sstevel@tonic-gate break; 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate case '\\': 363*7c478bd9Sstevel@tonic-gate dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 364*7c478bd9Sstevel@tonic-gate c = *str++; 365*7c478bd9Sstevel@tonic-gate nextc: 366*7c478bd9Sstevel@tonic-gate if (*dp++ == c) { 367*7c478bd9Sstevel@tonic-gate c = *dp++; 368*7c478bd9Sstevel@tonic-gate break; 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate dp++; 371*7c478bd9Sstevel@tonic-gate if (*dp) 372*7c478bd9Sstevel@tonic-gate goto nextc; 373*7c478bd9Sstevel@tonic-gate if (isdigit(c)) { 374*7c478bd9Sstevel@tonic-gate c -= '0', i = 2; 375*7c478bd9Sstevel@tonic-gate do 376*7c478bd9Sstevel@tonic-gate c <<= 3, c |= *str++ - '0'; 377*7c478bd9Sstevel@tonic-gate while (--i && isdigit(*str)); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate break; 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate *cp++ = (char) c; 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate *cp++ = 0; 384*7c478bd9Sstevel@tonic-gate str = *area; 385*7c478bd9Sstevel@tonic-gate *area = cp; 386*7c478bd9Sstevel@tonic-gate return (str); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate static void 392*7c478bd9Sstevel@tonic-gate tngetsize(char *bp) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate struct winsize ws; 395*7c478bd9Sstevel@tonic-gate char *np, *cp; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate if (ioctl(1, TIOCGWINSZ, (char *)&ws) < 0) 398*7c478bd9Sstevel@tonic-gate return; 399*7c478bd9Sstevel@tonic-gate if (ws.ws_row == 0 || ws.ws_col == 0 || 400*7c478bd9Sstevel@tonic-gate ws.ws_row > 999 || ws.ws_col > 999) 401*7c478bd9Sstevel@tonic-gate return; 402*7c478bd9Sstevel@tonic-gate cp = index(bp, ':'); /* find start of description */ 403*7c478bd9Sstevel@tonic-gate bp = rindex(bp, 0); /* find end of description */ 404*7c478bd9Sstevel@tonic-gate np = bp + 15; /* allow enough room for stuff below */ 405*7c478bd9Sstevel@tonic-gate while (bp >= cp) /* move description right 15 chars */ 406*7c478bd9Sstevel@tonic-gate *np-- = *bp--; 407*7c478bd9Sstevel@tonic-gate bp++; /* bp now points to where ':' used to be */ 408*7c478bd9Sstevel@tonic-gate *bp++ = ':'; 409*7c478bd9Sstevel@tonic-gate *bp++ = 'l'; 410*7c478bd9Sstevel@tonic-gate *bp++ = 'i'; 411*7c478bd9Sstevel@tonic-gate *bp++ = '#'; 412*7c478bd9Sstevel@tonic-gate bp = appendsmalldec(bp, ws.ws_row); 413*7c478bd9Sstevel@tonic-gate *bp++ = ':'; 414*7c478bd9Sstevel@tonic-gate *bp++ = 'c'; 415*7c478bd9Sstevel@tonic-gate *bp++ = 'o'; 416*7c478bd9Sstevel@tonic-gate *bp++ = '#'; 417*7c478bd9Sstevel@tonic-gate bp = appendsmalldec(bp, ws.ws_col); 418*7c478bd9Sstevel@tonic-gate *bp++ = ':'; 419*7c478bd9Sstevel@tonic-gate while (bp <= np) /* space fill to start of orig description */ 420*7c478bd9Sstevel@tonic-gate *bp++ = ' '; 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate static char * 424*7c478bd9Sstevel@tonic-gate appendsmalldec(char *bp, int val) 425*7c478bd9Sstevel@tonic-gate { 426*7c478bd9Sstevel@tonic-gate int i; 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate if ((i = val / 100) != 0) { 429*7c478bd9Sstevel@tonic-gate *bp++ = '0' + i; 430*7c478bd9Sstevel@tonic-gate val %= 100; 431*7c478bd9Sstevel@tonic-gate if (0 == val / 10) 432*7c478bd9Sstevel@tonic-gate *bp++ = '0'; /* place holder because next test fails */ 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate if ((i = val / 10) != 0) 435*7c478bd9Sstevel@tonic-gate *bp++ = '0' + i; 436*7c478bd9Sstevel@tonic-gate *bp++ = '0' + val % 10; 437*7c478bd9Sstevel@tonic-gate return (bp); 438*7c478bd9Sstevel@tonic-gate } 439