1*3694Sroot /* remcap.c 4.1 81/05/09 */ 2*3694Sroot /* Copyright (c) 1979 Regents of the University of California */ 3*3694Sroot #define BUFSIZ 512 4*3694Sroot 5*3694Sroot #include <ctype.h> 6*3694Sroot /* 7*3694Sroot * remcap - routines for dealing with the remote host description 8*3694Sroot * data base 9*3694Sroot * 10*3694Sroot * BUG: Should use a "last" pointer in tbuf, so that searching 11*3694Sroot * for capabilities alphabetically would not be a n**2/2 12*3694Sroot * process when large numbers of capabilities are given. 13*3694Sroot * 14*3694Sroot * Essentially all the work here is scanning and decoding escapes 15*3694Sroot * in string capabilities.*/ 16*3694Sroot 17*3694Sroot static char *rbuf; 18*3694Sroot char *rskip(); 19*3694Sroot char *rgetstr(); 20*3694Sroot char *rdecode(); 21*3694Sroot char *getenv(); 22*3694Sroot char *RM; /* remote file */ 23*3694Sroot 24*3694Sroot /* 25*3694Sroot * Get an entry for host name in buffer bp, 26*3694Sroot * from the remcap file. Parse is very rudimentary; 27*3694Sroot * we just notice escaped newlines. 28*3694Sroot */ 29*3694Sroot rgetent(bp, name) 30*3694Sroot char *bp, *name; 31*3694Sroot { 32*3694Sroot register char *cp; 33*3694Sroot register int c; 34*3694Sroot register int i = 0, cnt = 0; 35*3694Sroot char ibuf[BUFSIZ]; 36*3694Sroot int tf; 37*3694Sroot 38*3694Sroot rbuf = bp; 39*3694Sroot if ((RM = getenv("REMOTE")) == (char *)0) 40*3694Sroot RM = "/etc/remote"; 41*3694Sroot if ((tf = open(RM, 0)) < 0) 42*3694Sroot return (-1); 43*3694Sroot for (;;) { 44*3694Sroot cp = bp; 45*3694Sroot for (;;) { 46*3694Sroot if (i == cnt) { 47*3694Sroot cnt = read(tf, ibuf, BUFSIZ); 48*3694Sroot if (cnt <= 0) { 49*3694Sroot close(tf); 50*3694Sroot return (0); 51*3694Sroot } 52*3694Sroot i = 0; 53*3694Sroot } 54*3694Sroot c = ibuf[i++]; 55*3694Sroot if (c == '\n') { 56*3694Sroot if (cp > bp && cp[-1] == '\\'){ 57*3694Sroot cp--; 58*3694Sroot continue; 59*3694Sroot } 60*3694Sroot break; 61*3694Sroot } 62*3694Sroot *cp++ = c; 63*3694Sroot } 64*3694Sroot *cp = 0; 65*3694Sroot 66*3694Sroot /* 67*3694Sroot * The real work for the match. 68*3694Sroot */ 69*3694Sroot if (rnamatch(name)) { 70*3694Sroot close(tf); 71*3694Sroot return (1); 72*3694Sroot } 73*3694Sroot } 74*3694Sroot } 75*3694Sroot 76*3694Sroot /* 77*3694Sroot * Rnamatch deals with name matching. The first field of the remcap 78*3694Sroot * entry is a sequence of names separated by |'s, so we compare 79*3694Sroot * against each such name. The normal : terminator after the last 80*3694Sroot * name (before the first field) stops us. 81*3694Sroot */ 82*3694Sroot rnamatch(np) 83*3694Sroot char *np; 84*3694Sroot { 85*3694Sroot register char *Np, *Bp; 86*3694Sroot 87*3694Sroot Bp = rbuf; 88*3694Sroot for (;;) { 89*3694Sroot for (Np = np; *Np && *Bp == *Np; Bp++, Np++) 90*3694Sroot continue; 91*3694Sroot if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) 92*3694Sroot return (1); 93*3694Sroot while (*Bp && *Bp != ':' && *Bp != '|') 94*3694Sroot Bp++; 95*3694Sroot if (*Bp == 0 || *Bp == ':') 96*3694Sroot return (0); 97*3694Sroot Bp++; 98*3694Sroot } 99*3694Sroot } 100*3694Sroot 101*3694Sroot /* 102*3694Sroot * Skip to the next field. Notice that this is very dumb, not 103*3694Sroot * knowing about \: escapes or any such. If necessary, :'s can be put 104*3694Sroot * into the printcap file in octal. 105*3694Sroot */ 106*3694Sroot static char * 107*3694Sroot rskip(bp) 108*3694Sroot register char *bp; 109*3694Sroot { 110*3694Sroot 111*3694Sroot while (*bp && *bp != ':') 112*3694Sroot bp++; 113*3694Sroot if (*bp == ':') 114*3694Sroot bp++; 115*3694Sroot return (bp); 116*3694Sroot } 117*3694Sroot 118*3694Sroot /* 119*3694Sroot * Return the (numeric) option id. 120*3694Sroot * Numeric options look like 121*3694Sroot * li#80 122*3694Sroot * i.e. the option string is separated from the numeric value by 123*3694Sroot * a # character. If the option is not found we return -1. 124*3694Sroot * Note that we handle octal numbers beginning with 0. 125*3694Sroot */ 126*3694Sroot rgetnum(id) 127*3694Sroot char *id; 128*3694Sroot { 129*3694Sroot register int i, base; 130*3694Sroot register char *bp = rbuf; 131*3694Sroot 132*3694Sroot for (;;) { 133*3694Sroot bp = rskip(bp); 134*3694Sroot if (*bp == 0) 135*3694Sroot return (-1); 136*3694Sroot if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 137*3694Sroot continue; 138*3694Sroot if (*bp != '#') 139*3694Sroot continue; 140*3694Sroot bp++; 141*3694Sroot base = 10; 142*3694Sroot if (*bp == '0') 143*3694Sroot base = 8; 144*3694Sroot i = 0; 145*3694Sroot while (isdigit(*bp)) 146*3694Sroot i *= base, i += *bp++ - '0'; 147*3694Sroot return (i); 148*3694Sroot } 149*3694Sroot } 150*3694Sroot 151*3694Sroot /* 152*3694Sroot * Handle a flag option. 153*3694Sroot * Flag options are given "naked", i.e. followed by a : or the end 154*3694Sroot * of the buffer. Return 1 if we find the option, or 0 if it is 155*3694Sroot * not given. 156*3694Sroot */ 157*3694Sroot rgetflag(id) 158*3694Sroot char *id; 159*3694Sroot { 160*3694Sroot register char *bp = rbuf; 161*3694Sroot 162*3694Sroot for (;;) { 163*3694Sroot bp = rskip(bp); 164*3694Sroot if (!*bp) 165*3694Sroot return (0); 166*3694Sroot if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1] && (!*bp || *bp == ':')) 167*3694Sroot return (1); 168*3694Sroot } 169*3694Sroot } 170*3694Sroot 171*3694Sroot /* 172*3694Sroot * Get a string valued option. 173*3694Sroot * These are given as 174*3694Sroot * cl=^Z 175*3694Sroot * Much decoding is done on the strings, and the strings are 176*3694Sroot * placed in area, which is a ref parameter which is updated. 177*3694Sroot * No checking on area overflow. 178*3694Sroot */ 179*3694Sroot char * 180*3694Sroot rgetstr(id, area) 181*3694Sroot char *id, **area; 182*3694Sroot { 183*3694Sroot register char *bp = rbuf; 184*3694Sroot 185*3694Sroot for (;;) { 186*3694Sroot bp = rskip(bp); 187*3694Sroot if (!*bp) 188*3694Sroot return (0); 189*3694Sroot if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) 190*3694Sroot continue; 191*3694Sroot if (*bp != '=') 192*3694Sroot continue; 193*3694Sroot bp++; 194*3694Sroot return (rdecode(bp, area)); 195*3694Sroot } 196*3694Sroot } 197*3694Sroot 198*3694Sroot /* 199*3694Sroot * Tdecode does the grung work to decode the 200*3694Sroot * string capability escapes. 201*3694Sroot */ 202*3694Sroot char * 203*3694Sroot rdecode(str, area) 204*3694Sroot register char *str; 205*3694Sroot char **area; 206*3694Sroot { 207*3694Sroot register char *cp; 208*3694Sroot register int c; 209*3694Sroot register char *dp; 210*3694Sroot int i; 211*3694Sroot 212*3694Sroot cp = *area; 213*3694Sroot while ((c = *str++) && c != ':') { 214*3694Sroot switch (c) { 215*3694Sroot 216*3694Sroot case '^': 217*3694Sroot c = *str++ & 037; 218*3694Sroot break; 219*3694Sroot 220*3694Sroot case '\\': 221*3694Sroot dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; 222*3694Sroot c = *str++; 223*3694Sroot nextc: 224*3694Sroot if (*dp++ == c) { 225*3694Sroot c = *dp++; 226*3694Sroot break; 227*3694Sroot } 228*3694Sroot dp++; 229*3694Sroot if (*dp) 230*3694Sroot goto nextc; 231*3694Sroot if (isdigit(c)) { 232*3694Sroot c -= '0', i = 2; 233*3694Sroot do 234*3694Sroot c <<= 3, c |= *str++ - '0'; 235*3694Sroot while (--i && isdigit(*str)); 236*3694Sroot } 237*3694Sroot break; 238*3694Sroot } 239*3694Sroot *cp++ = c; 240*3694Sroot } 241*3694Sroot *cp++ = 0; 242*3694Sroot str = *area; 243*3694Sroot *area = cp; 244*3694Sroot return (str); 245*3694Sroot } 246