1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate /* 29*7c478bd9Sstevel@tonic-gate stoa - convert string to address 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate If a string begins in \o or \O, the following address is octal 32*7c478bd9Sstevel@tonic-gate " " " " " \x or \X, the following address is hex 33*7c478bd9Sstevel@tonic-gate Otherwise, a string is considered text. Text may be quoted 34*7c478bd9Sstevel@tonic-gate with double quotes and the C-like escapes \n, \b, \t, \v, \r, and \nnn 35*7c478bd9Sstevel@tonic-gate (nnn = octal char) are recognized. 36*7c478bd9Sstevel@tonic-gate A \ followed by a newline causes the newline 37*7c478bd9Sstevel@tonic-gate to vanish. A \ followed by any other char causes any "magic" of 38*7c478bd9Sstevel@tonic-gate any other char to disappear. 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate Other escape sequences recognized are: 41*7c478bd9Sstevel@tonic-gate \!cmd args [ \! || EOL ] 42*7c478bd9Sstevel@tonic-gate which is replaced by the raw output of the execution of cmd. 43*7c478bd9Sstevel@tonic-gate This may only be used in a string. 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate \$cmd args [ \$ || EOL ] 46*7c478bd9Sstevel@tonic-gate which is replaced by the output of the execution of cmd and 47*7c478bd9Sstevel@tonic-gate is then reprocessed. 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate A NULL is returned on any error(s). 50*7c478bd9Sstevel@tonic-gate */ 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #include <stdio.h> 53*7c478bd9Sstevel@tonic-gate #include <memory.h> 54*7c478bd9Sstevel@tonic-gate #include <ctype.h> 55*7c478bd9Sstevel@tonic-gate #include "nsaddr.h" 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #define toupper(c) (islower(c) ? _toupper(c) : (c)) 59*7c478bd9Sstevel@tonic-gate #define todigit(c) ((int)((c) - '0')) /* char to digit */ 60*7c478bd9Sstevel@tonic-gate #define toxdigit(c) ((isdigit(c))?todigit(c):(toupper(c)-(int)'A'+10)) 61*7c478bd9Sstevel@tonic-gate #define isodigit(c) (isdigit(c) && ((c) != '9') && ((c) != '8')) 62*7c478bd9Sstevel@tonic-gate #define itoac(i) (((i) > 9) ? ((char)((i)-10) + 'A'):((char)(i) + '0')) 63*7c478bd9Sstevel@tonic-gate #define MASK(n) ((1 << (n)) - 1) 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #define MAXRLEVEL 10 /* maximum recursion level */ 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate #define TRUE 1; 68*7c478bd9Sstevel@tonic-gate #define FALSE 0; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate char scanbuf[SBUFSIZE]; 71*7c478bd9Sstevel@tonic-gate int sbp = 0; 72*7c478bd9Sstevel@tonic-gate int rec = 0; /* Recursion level */ 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate char sbuf[SBUFSIZE]; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate extern void free(); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate struct netbuf * 79*7c478bd9Sstevel@tonic-gate stoa(str, addr) /* Return 0 for success, -1 for error */ 80*7c478bd9Sstevel@tonic-gate char *str; 81*7c478bd9Sstevel@tonic-gate struct netbuf *addr; 82*7c478bd9Sstevel@tonic-gate { 83*7c478bd9Sstevel@tonic-gate char *xfer(), *prescan(); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate int myadr; /* was netbuf struct allocated here ? */ 86*7c478bd9Sstevel@tonic-gate int quote; /* quoted string ? */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate myadr = FALSE; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate if (!str) 91*7c478bd9Sstevel@tonic-gate return NULL; 92*7c478bd9Sstevel@tonic-gate while (*str && isspace(*str)) /* leading whites are OK */ 93*7c478bd9Sstevel@tonic-gate ++str; 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate str = prescan(str); /* Do all \$ ... \$ */ 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate if (!str || !*str) return NULL; /* Nothing to convert */ 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate if (!addr) { 100*7c478bd9Sstevel@tonic-gate if ((addr = (struct netbuf *)malloc(sizeof(struct netbuf))) == NULL) 101*7c478bd9Sstevel@tonic-gate return NULL; 102*7c478bd9Sstevel@tonic-gate myadr = TRUE; 103*7c478bd9Sstevel@tonic-gate addr->buf = NULL; 104*7c478bd9Sstevel@tonic-gate addr->maxlen = 0; 105*7c478bd9Sstevel@tonic-gate addr->len = 0; 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* Now process the address */ 109*7c478bd9Sstevel@tonic-gate quote = 0; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate if (*str == '\\') { 112*7c478bd9Sstevel@tonic-gate ++str; 113*7c478bd9Sstevel@tonic-gate switch (*str) { 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate case 'X': /* hex */ 116*7c478bd9Sstevel@tonic-gate case 'x': 117*7c478bd9Sstevel@tonic-gate addr->len = dobase(++str, sbuf, HEX); 118*7c478bd9Sstevel@tonic-gate break; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate case 'o': /* octal */ 121*7c478bd9Sstevel@tonic-gate case 'O': 122*7c478bd9Sstevel@tonic-gate addr->len = dobase(++str, sbuf, OCT); 123*7c478bd9Sstevel@tonic-gate break; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate case '\0': /* No address given!, length is 0 */ 126*7c478bd9Sstevel@tonic-gate addr->len = dostring(str, sbuf, 0); 127*7c478bd9Sstevel@tonic-gate break; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate default: /* \ is handled by dostring */ 130*7c478bd9Sstevel@tonic-gate addr->len = dostring(--str, sbuf, quote); 131*7c478bd9Sstevel@tonic-gate break; 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate else { 135*7c478bd9Sstevel@tonic-gate if (*str == '"') { /* quoted string */ 136*7c478bd9Sstevel@tonic-gate quote = 1; 137*7c478bd9Sstevel@tonic-gate ++str; 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate addr->len = dostring(str, sbuf, quote); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate if (addr->len == 0) { /* Error in conversion */ 143*7c478bd9Sstevel@tonic-gate if (myadr) 144*7c478bd9Sstevel@tonic-gate free(addr); 145*7c478bd9Sstevel@tonic-gate return NULL; 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate if ((addr->buf = xfer(addr->buf, sbuf, addr->len, addr->maxlen)) == NULL) 148*7c478bd9Sstevel@tonic-gate return NULL; 149*7c478bd9Sstevel@tonic-gate else 150*7c478bd9Sstevel@tonic-gate return addr; 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate /* 155*7c478bd9Sstevel@tonic-gate dostring: Copy string at s to buf translating 156*7c478bd9Sstevel@tonic-gate escaped characters and shell escapes. 157*7c478bd9Sstevel@tonic-gate return length of string. 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate int 161*7c478bd9Sstevel@tonic-gate dostring(s, buf, quote) /* read in a raw address */ 162*7c478bd9Sstevel@tonic-gate char *s, *buf; 163*7c478bd9Sstevel@tonic-gate int quote; 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate char *xcmd(); 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate int oc, ch, len = 0; 168*7c478bd9Sstevel@tonic-gate int l = 0; 169*7c478bd9Sstevel@tonic-gate char *rout; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate while (*s) { 172*7c478bd9Sstevel@tonic-gate if (len >= SBUFSIZE) { 173*7c478bd9Sstevel@tonic-gate fprintf(stderr, "dostring: string too long\n"); 174*7c478bd9Sstevel@tonic-gate break; 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate else if (*s == '\\') 177*7c478bd9Sstevel@tonic-gate switch(*++s) { 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate case '!': /* raw shell escape */ 180*7c478bd9Sstevel@tonic-gate if (rout = xcmd(s+1, '!', &s, &l)) { 181*7c478bd9Sstevel@tonic-gate if (len + l < SBUFSIZE) 182*7c478bd9Sstevel@tonic-gate memcpy(buf+len, rout, l); 183*7c478bd9Sstevel@tonic-gate len += l; 184*7c478bd9Sstevel@tonic-gate free(rout); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate break; 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate case '\n': /* ignore newline */ 189*7c478bd9Sstevel@tonic-gate ++s; 190*7c478bd9Sstevel@tonic-gate break; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate case 'b': /* backspace */ 193*7c478bd9Sstevel@tonic-gate buf[len++] = '\b'; s++; 194*7c478bd9Sstevel@tonic-gate break; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate case 'n': /* newline */ 197*7c478bd9Sstevel@tonic-gate buf[len++] = '\n'; s++; 198*7c478bd9Sstevel@tonic-gate break; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate case 'r': /* return */ 201*7c478bd9Sstevel@tonic-gate buf[len++] = '\r'; s++; 202*7c478bd9Sstevel@tonic-gate break; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate case 't': /* horiz. tab */ 205*7c478bd9Sstevel@tonic-gate buf[len++] = '\t'; s++; 206*7c478bd9Sstevel@tonic-gate break; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate case 'v': /* vert. tab */ 209*7c478bd9Sstevel@tonic-gate buf[len++] = '\v'; s++; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate case '0': 212*7c478bd9Sstevel@tonic-gate case '1': 213*7c478bd9Sstevel@tonic-gate case '2': 214*7c478bd9Sstevel@tonic-gate case '3': 215*7c478bd9Sstevel@tonic-gate for(oc=ch=0; (*s >= '0' && *s <= '7') && oc++ < 3; ++s) 216*7c478bd9Sstevel@tonic-gate ch = (ch << 3) | (*s - '0'); 217*7c478bd9Sstevel@tonic-gate buf[len++] = ch; 218*7c478bd9Sstevel@tonic-gate break; 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate case 0: /* end of string -- terminate */ 221*7c478bd9Sstevel@tonic-gate break; 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate default: /* take the character blindly */ 224*7c478bd9Sstevel@tonic-gate buf[len++] = *s++; 225*7c478bd9Sstevel@tonic-gate break; 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate else if ((quote && (*s == '"')) || (!quote && isspace(*s))) 228*7c478bd9Sstevel@tonic-gate break; 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate else 231*7c478bd9Sstevel@tonic-gate buf[len++] = *s++; 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate return (len >= SBUFSIZE) ? 0 : len; 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate /* 238*7c478bd9Sstevel@tonic-gate dobase : converts a hex or octal ASCII string 239*7c478bd9Sstevel@tonic-gate to a binary address. Only HEX or OCT may be used 240*7c478bd9Sstevel@tonic-gate for type. 241*7c478bd9Sstevel@tonic-gate return length of binary string (in bytes), 0 if error. 242*7c478bd9Sstevel@tonic-gate The binary result is placed at buf. 243*7c478bd9Sstevel@tonic-gate */ 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate int 246*7c478bd9Sstevel@tonic-gate dobase(s, buf, type) /* read in an address */ 247*7c478bd9Sstevel@tonic-gate char *s, *buf; /* source ASCII, result binary string */ 248*7c478bd9Sstevel@tonic-gate int type; 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate void memcp(); 251*7c478bd9Sstevel@tonic-gate int bp = SBUFSIZE - 1; 252*7c478bd9Sstevel@tonic-gate int shift = 0; 253*7c478bd9Sstevel@tonic-gate char *end; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate for (end = s; *end && ((type == OCT) ? isodigit(*end) : 256*7c478bd9Sstevel@tonic-gate isxdigit(*end)); ++end) ; 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate /* any non-white, non-digits cause address to be rejected, 259*7c478bd9Sstevel@tonic-gate other fields are ignored */ 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate if ((*s == 0) || (end == s) || (!isspace(*end) && *end)) { 262*7c478bd9Sstevel@tonic-gate fprintf(stderr, "dobase: Illegal trailer on address string\n"); 263*7c478bd9Sstevel@tonic-gate buf[0] = '\0'; 264*7c478bd9Sstevel@tonic-gate return 0; 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate --end; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate buf[bp] = '\0'; 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate while (bp > 0 && end >= s) { 271*7c478bd9Sstevel@tonic-gate buf[bp] |= toxdigit(*end) << shift; 272*7c478bd9Sstevel@tonic-gate if (type == OCT) { 273*7c478bd9Sstevel@tonic-gate if (shift > 5) { 274*7c478bd9Sstevel@tonic-gate buf[--bp] = (todigit(*end) >> (8 - shift)) 275*7c478bd9Sstevel@tonic-gate & MASK(shift-5); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate if ((shift = (shift + 3) % 8) == 0) 278*7c478bd9Sstevel@tonic-gate buf[--bp] = 0; 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate else /* hex */ 281*7c478bd9Sstevel@tonic-gate if ((shift = (shift) ? 0 : 4) == 0) 282*7c478bd9Sstevel@tonic-gate buf[--bp] = 0;; 283*7c478bd9Sstevel@tonic-gate --end; 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate if (bp == 0) { 286*7c478bd9Sstevel@tonic-gate fprintf(stderr, "stoa: dobase: number to long\n"); 287*7c478bd9Sstevel@tonic-gate return 0; 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate /* need to catch end case to avoid extra 0's in front */ 291*7c478bd9Sstevel@tonic-gate if (!shift) 292*7c478bd9Sstevel@tonic-gate bp++; 293*7c478bd9Sstevel@tonic-gate memcp(buf, &buf[bp], (SBUFSIZE - bp)); 294*7c478bd9Sstevel@tonic-gate return (SBUFSIZE - bp); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate #ifdef NOTUSED 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate atos(str, addr, type) 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate convert address to ASCII form with address in hex, octal, 305*7c478bd9Sstevel@tonic-gate or character form. 306*7c478bd9Sstevel@tonic-gate return pointer to buffer (NULL on failure). 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate char * 311*7c478bd9Sstevel@tonic-gate atos(str, addr, type) 312*7c478bd9Sstevel@tonic-gate char *str; 313*7c478bd9Sstevel@tonic-gate struct netbuf *addr; 314*7c478bd9Sstevel@tonic-gate int type; 315*7c478bd9Sstevel@tonic-gate { 316*7c478bd9Sstevel@tonic-gate char *xfer(); 317*7c478bd9Sstevel@tonic-gate int mystr = 0; /* was str allocated here ? */ 318*7c478bd9Sstevel@tonic-gate unsigned x_atos(), o_atos(); 319*7c478bd9Sstevel@tonic-gate void memcp(); 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate char *base; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate if (addr == NULL) 324*7c478bd9Sstevel@tonic-gate return NULL; 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate if (str == NULL) 327*7c478bd9Sstevel@tonic-gate if ((str = malloc(SBUFSIZE)) == NULL) 328*7c478bd9Sstevel@tonic-gate return NULL; 329*7c478bd9Sstevel@tonic-gate else 330*7c478bd9Sstevel@tonic-gate mystr = 1; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate switch (type) { 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate case OCT: 335*7c478bd9Sstevel@tonic-gate /* first add \o */ 336*7c478bd9Sstevel@tonic-gate sbuf[0] = '\\'; 337*7c478bd9Sstevel@tonic-gate sbuf[1] = 'o'; 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate return xfer(str, sbuf, o_atos(sbuf+2, addr->buf, addr->len) + 2, 340*7c478bd9Sstevel@tonic-gate mystr ? SBUFSIZE : 0); 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate case HEX: 343*7c478bd9Sstevel@tonic-gate /* first add \x */ 344*7c478bd9Sstevel@tonic-gate sbuf[0] = '\\'; 345*7c478bd9Sstevel@tonic-gate sbuf[1] = 'x'; 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate return xfer(str, sbuf, x_atos(sbuf+2, addr->buf, addr->len) + 2, 348*7c478bd9Sstevel@tonic-gate mystr ? SBUFSIZE : 0); 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate case RAW: 351*7c478bd9Sstevel@tonic-gate base = xfer(str, addr->buf, 352*7c478bd9Sstevel@tonic-gate addr->len + 1, mystr ? SBUFSIZE : 0); 353*7c478bd9Sstevel@tonic-gate if (base) 354*7c478bd9Sstevel@tonic-gate base[addr->len] = '\0'; /* terminate*/ 355*7c478bd9Sstevel@tonic-gate return base; 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate default: 358*7c478bd9Sstevel@tonic-gate return NULL; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate /* 364*7c478bd9Sstevel@tonic-gate x_atos, o_atos 365*7c478bd9Sstevel@tonic-gate return the number of bytes occupied by string + NULL*/ 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate /* 368*7c478bd9Sstevel@tonic-gate x_atos : convert an address string a, length s 369*7c478bd9Sstevel@tonic-gate to hex ASCII in s */ 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate unsigned 373*7c478bd9Sstevel@tonic-gate x_atos(s, a, l) 374*7c478bd9Sstevel@tonic-gate char *s, *a; 375*7c478bd9Sstevel@tonic-gate unsigned l; 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate char *b; 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate b = s; 380*7c478bd9Sstevel@tonic-gate while (l--) { 381*7c478bd9Sstevel@tonic-gate *s++ = itoac(((*a >> 4) & MASK (4))); 382*7c478bd9Sstevel@tonic-gate *s++ = itoac((*a & MASK(4))); 383*7c478bd9Sstevel@tonic-gate ++a; 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate *s = '\0'; 386*7c478bd9Sstevel@tonic-gate return (s - b + 1); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate /* 391*7c478bd9Sstevel@tonic-gate o_atos : convert an address a, length l 392*7c478bd9Sstevel@tonic-gate to octal ASCII in s */ 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate unsigned 396*7c478bd9Sstevel@tonic-gate o_atos(s, a, l) 397*7c478bd9Sstevel@tonic-gate char *s, *a; 398*7c478bd9Sstevel@tonic-gate unsigned l; 399*7c478bd9Sstevel@tonic-gate { 400*7c478bd9Sstevel@tonic-gate int i, shift; 401*7c478bd9Sstevel@tonic-gate char *b; 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate b = s; 404*7c478bd9Sstevel@tonic-gate if (l == 0) { 405*7c478bd9Sstevel@tonic-gate *s = '\0'; 406*7c478bd9Sstevel@tonic-gate return 0; 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate /* take care of partial bits and set shift factor for next 3 */ 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate i = l % 3; 412*7c478bd9Sstevel@tonic-gate *s++ = itoac((*a>>(i+5)) & MASK(3-i)); 413*7c478bd9Sstevel@tonic-gate shift = 2 + i; 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate while (l) 416*7c478bd9Sstevel@tonic-gate if (shift <= 5) { 417*7c478bd9Sstevel@tonic-gate *s++ = itoac((*a >> shift) & MASK(3)); 418*7c478bd9Sstevel@tonic-gate if (shift == 0) { 419*7c478bd9Sstevel@tonic-gate ++a; 420*7c478bd9Sstevel@tonic-gate --l; 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate shift += (shift < 3) ? 5 : -3; 423*7c478bd9Sstevel@tonic-gate } 424*7c478bd9Sstevel@tonic-gate else { 425*7c478bd9Sstevel@tonic-gate i = (*a & MASK(shift-5)) << (8-shift); 426*7c478bd9Sstevel@tonic-gate i |= (*++a >> shift) & MASK(8-shift); 427*7c478bd9Sstevel@tonic-gate *s++ = itoac(i); 428*7c478bd9Sstevel@tonic-gate shift -= 3; 429*7c478bd9Sstevel@tonic-gate --l; 430*7c478bd9Sstevel@tonic-gate } 431*7c478bd9Sstevel@tonic-gate *s++ = '\0'; 432*7c478bd9Sstevel@tonic-gate return (s - b + 1); 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate #endif /* NOTUSED */ 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate void 438*7c478bd9Sstevel@tonic-gate memcp(d, s, n) /* safe memcpy for overlapping regions */ 439*7c478bd9Sstevel@tonic-gate char *d, *s; 440*7c478bd9Sstevel@tonic-gate int n; 441*7c478bd9Sstevel@tonic-gate { 442*7c478bd9Sstevel@tonic-gate while (n--) 443*7c478bd9Sstevel@tonic-gate *d++ = *s++; 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate /* transfer block to a given destination or allocate one of the 448*7c478bd9Sstevel@tonic-gate right size 449*7c478bd9Sstevel@tonic-gate if max = 0 : ignore max 450*7c478bd9Sstevel@tonic-gate */ 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate char * 453*7c478bd9Sstevel@tonic-gate xfer(dest, src, len, max) 454*7c478bd9Sstevel@tonic-gate char *dest, *src; 455*7c478bd9Sstevel@tonic-gate unsigned len, max; 456*7c478bd9Sstevel@tonic-gate { 457*7c478bd9Sstevel@tonic-gate if (max && dest && max < len) { /* No room */ 458*7c478bd9Sstevel@tonic-gate fprintf(stderr, "xfer: destination not long enough\n"); 459*7c478bd9Sstevel@tonic-gate return NULL; 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate if (!dest) 462*7c478bd9Sstevel@tonic-gate if ((dest = (char *)malloc(len)) == NULL) { 463*7c478bd9Sstevel@tonic-gate fprintf(stderr, "xfer: malloc failed\n"); 464*7c478bd9Sstevel@tonic-gate return NULL; 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate memcpy(dest, src, (int)len); 468*7c478bd9Sstevel@tonic-gate return dest; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate /* 472*7c478bd9Sstevel@tonic-gate prescan: scan through string s, expanding all \$...\$ 473*7c478bd9Sstevel@tonic-gate as shell escapes. 474*7c478bd9Sstevel@tonic-gate Return pointer to string of expanded text. 475*7c478bd9Sstevel@tonic-gate */ 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate char * 478*7c478bd9Sstevel@tonic-gate prescan(s) 479*7c478bd9Sstevel@tonic-gate char *s; 480*7c478bd9Sstevel@tonic-gate { 481*7c478bd9Sstevel@tonic-gate int scan(); 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate rec = sbp = 0; 484*7c478bd9Sstevel@tonic-gate if (!s || !*s || !scan(s)) 485*7c478bd9Sstevel@tonic-gate return NULL; 486*7c478bd9Sstevel@tonic-gate scanbuf[sbp] = '\0'; 487*7c478bd9Sstevel@tonic-gate return scanbuf; 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate /* 492*7c478bd9Sstevel@tonic-gate scan: scan through string s, expanding all \$...\$. 493*7c478bd9Sstevel@tonic-gate (Part II of prescan) 494*7c478bd9Sstevel@tonic-gate Return 0 if anything failed, else 1. 495*7c478bd9Sstevel@tonic-gate */ 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate scan(s) 498*7c478bd9Sstevel@tonic-gate char *s; 499*7c478bd9Sstevel@tonic-gate { 500*7c478bd9Sstevel@tonic-gate char *xcmd(); 501*7c478bd9Sstevel@tonic-gate char *cmd; 502*7c478bd9Sstevel@tonic-gate int len; 503*7c478bd9Sstevel@tonic-gate int esc = 0; /* Keep lookout for \\$ */ 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate while (*s) { 506*7c478bd9Sstevel@tonic-gate if (!esc && (*s == '\\' && *(s+1) == '$')) { 507*7c478bd9Sstevel@tonic-gate if (rec++ == MAXRLEVEL) { 508*7c478bd9Sstevel@tonic-gate fprintf(stderr, "scan: Recursion \ 509*7c478bd9Sstevel@tonic-gate level past %d on shell escape\n", rec); 510*7c478bd9Sstevel@tonic-gate return 0; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate if ((cmd = xcmd(s+2, '$', &s, &len)) != NULL) { 513*7c478bd9Sstevel@tonic-gate cmd[len] = '\0'; 514*7c478bd9Sstevel@tonic-gate if (*cmd != '\0') 515*7c478bd9Sstevel@tonic-gate scan(cmd); 516*7c478bd9Sstevel@tonic-gate free(cmd); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate else 519*7c478bd9Sstevel@tonic-gate return 0; 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate else if (sbp == SBUFSIZE) { 523*7c478bd9Sstevel@tonic-gate fprintf(stderr, "Overflow on shell esc expansion\n"); 524*7c478bd9Sstevel@tonic-gate return 0; 525*7c478bd9Sstevel@tonic-gate } 526*7c478bd9Sstevel@tonic-gate else if (sbp < SBUFSIZE) 527*7c478bd9Sstevel@tonic-gate esc = ((scanbuf[sbp++] = *s++) == '\\'); 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate return 1; 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate /* 534*7c478bd9Sstevel@tonic-gate xcmd : extract command line for shell escape and execute it 535*7c478bd9Sstevel@tonic-gate return pointer to output of command 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate char * 539*7c478bd9Sstevel@tonic-gate xcmd(s, ec, ps, len) 540*7c478bd9Sstevel@tonic-gate char *s; /* input string */ 541*7c478bd9Sstevel@tonic-gate char ec; /* escape char ( $ or ! ) */ 542*7c478bd9Sstevel@tonic-gate char **ps; /* address of input string pointer */ 543*7c478bd9Sstevel@tonic-gate int *len; /* Number of bytes of output from command */ 544*7c478bd9Sstevel@tonic-gate { 545*7c478bd9Sstevel@tonic-gate FILE *popen(); 546*7c478bd9Sstevel@tonic-gate int pclose(); 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate FILE *pfp; /* pipe for process */ 549*7c478bd9Sstevel@tonic-gate char *cmd; /* command buffer */ 550*7c478bd9Sstevel@tonic-gate char *cmdp; /* pointer along cmd */ 551*7c478bd9Sstevel@tonic-gate char *ocmd; /* output of command buffer */ 552*7c478bd9Sstevel@tonic-gate int esc = 0; /* escaped escape shell */ 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate *len = 0; 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate if ((cmd = cmdp = (char *)malloc(SBUFSIZE)) == NULL) { 557*7c478bd9Sstevel@tonic-gate fprintf(stderr, "xcmd: malloc failed\n"); 558*7c478bd9Sstevel@tonic-gate return NULL; 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate if ((ocmd = (char *)malloc(SBUFSIZE)) == NULL) { 562*7c478bd9Sstevel@tonic-gate fprintf(stderr, "xcmd: malloc failed\n"); 563*7c478bd9Sstevel@tonic-gate free(cmd); 564*7c478bd9Sstevel@tonic-gate return NULL; 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate while (*s) { 567*7c478bd9Sstevel@tonic-gate if (!esc && *s == '\\' && *(s+1) == ec) { 568*7c478bd9Sstevel@tonic-gate s += 2; 569*7c478bd9Sstevel@tonic-gate break; 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate else 572*7c478bd9Sstevel@tonic-gate esc = (*cmdp++ = *s++) == '\\'; 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate *cmdp = '\0'; 575*7c478bd9Sstevel@tonic-gate *ps = s; 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate if ((pfp = popen(cmd, "r")) == NULL) 578*7c478bd9Sstevel@tonic-gate fprintf(stderr, "xcmd: popen failed\n"); 579*7c478bd9Sstevel@tonic-gate while (fread(&ocmd[*len], 1, 1, pfp)) 580*7c478bd9Sstevel@tonic-gate if ((*len += 1) >= SBUFSIZE) { 581*7c478bd9Sstevel@tonic-gate fprintf(stderr, "xcmd: command output too long\n"); 582*7c478bd9Sstevel@tonic-gate break; 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate pclose(pfp); 585*7c478bd9Sstevel@tonic-gate free(cmd); 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate return ocmd; 588*7c478bd9Sstevel@tonic-gate } 589