4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 #pragma ident "%Z%%M% %I% %E% SMI"
35 stoa - convert string to address
37 If a string begins in \o or \O, the following address is octal
38 " " " " " \x or \X, the following address is hex
39 Otherwise, a string is considered text. Text may be quoted
40 with double quotes and the C-like escapes \n, \b, \t, \v, \r, and \nnn
41 (nnn = octal char) are recognized.
42 A \ followed by a newline causes the newline
43 to vanish. A \ followed by any other char causes any "magic" of
44 any other char to disappear.
46 Other escape sequences recognized are:
47 \!cmd args [ \! || EOL ]
48 which is replaced by the raw output of the execution of cmd.
49 This may only be used in a string.
51 \$cmd args [ \$ || EOL ]
52 which is replaced by the output of the execution of cmd and
55 A NULL is returned on any error(s).
64 #define toupper(c) (islower(c) ? _toupper(c) : (c))
65 #define todigit(c) ((int)((c) - '0')) /* char to digit */
66 #define toxdigit(c) ((isdigit(c))?todigit(c):(toupper(c)-(int)'A'+10))
67 #define isodigit(c) (isdigit(c) && ((c) != '9') && ((c) != '8'))
68 #define itoac(i) (((i) > 9) ? ((char)((i)-10) + 'A'):((char)(i) + '0'))
69 #define MASK(n) ((1 << (n)) - 1)
71 #define MAXRLEVEL 10 /* maximum recursion level */
76 char scanbuf
[SBUFSIZE
];
78 int rec
= 0; /* Recursion level */
85 stoa(str
, addr
) /* Return 0 for success, -1 for error */
89 char *xfer(), *prescan();
91 int myadr
; /* was netbuf struct allocated here ? */
92 int quote
; /* quoted string ? */
98 while (*str
&& isspace(*str
)) /* leading whites are OK */
101 str
= prescan(str
); /* Do all \$ ... \$ */
103 if (!str
|| !*str
) return NULL
; /* Nothing to convert */
106 if ((addr
= (struct netbuf
*)malloc(sizeof(struct netbuf
))) == NULL
)
114 /* Now process the address */
123 addr
->len
= dobase(++str
, sbuf
, HEX
);
126 case 'o': /* octal */
128 addr
->len
= dobase(++str
, sbuf
, OCT
);
131 case '\0': /* No address given!, length is 0 */
132 addr
->len
= dostring(str
, sbuf
, 0);
135 default: /* \ is handled by dostring */
136 addr
->len
= dostring(--str
, sbuf
, quote
);
141 if (*str
== '"') { /* quoted string */
145 addr
->len
= dostring(str
, sbuf
, quote
);
148 if (addr
->len
== 0) { /* Error in conversion */
153 if ((addr
->buf
= xfer(addr
->buf
, sbuf
, addr
->len
, addr
->maxlen
)) == NULL
)
161 dostring: Copy string at s to buf translating
162 escaped characters and shell escapes.
163 return length of string.
167 dostring(s
, buf
, quote
) /* read in a raw address */
178 if (len
>= SBUFSIZE
) {
179 fprintf(stderr
, "dostring: string too long\n");
185 case '!': /* raw shell escape */
186 if (rout
= xcmd(s
+1, '!', &s
, &l
)) {
187 if (len
+ l
< SBUFSIZE
)
188 memcpy(buf
+len
, rout
, l
);
194 case '\n': /* ignore newline */
198 case 'b': /* backspace */
199 buf
[len
++] = '\b'; s
++;
202 case 'n': /* newline */
203 buf
[len
++] = '\n'; s
++;
206 case 'r': /* return */
207 buf
[len
++] = '\r'; s
++;
210 case 't': /* horiz. tab */
211 buf
[len
++] = '\t'; s
++;
214 case 'v': /* vert. tab */
215 buf
[len
++] = '\v'; s
++;
221 for(oc
=ch
=0; (*s
>= '0' && *s
<= '7') && oc
++ < 3; ++s
)
222 ch
= (ch
<< 3) | (*s
- '0');
226 case 0: /* end of string -- terminate */
229 default: /* take the character blindly */
233 else if ((quote
&& (*s
== '"')) || (!quote
&& isspace(*s
)))
239 return (len
>= SBUFSIZE
) ? 0 : len
;
244 dobase : converts a hex or octal ASCII string
245 to a binary address. Only HEX or OCT may be used
247 return length of binary string (in bytes), 0 if error.
248 The binary result is placed at buf.
252 dobase(s
, buf
, type
) /* read in an address */
253 char *s
, *buf
; /* source ASCII, result binary string */
257 int bp
= SBUFSIZE
- 1;
261 for (end
= s
; *end
&& ((type
== OCT
) ? isodigit(*end
) :
262 isxdigit(*end
)); ++end
) ;
264 /* any non-white, non-digits cause address to be rejected,
265 other fields are ignored */
267 if ((*s
== 0) || (end
== s
) || (!isspace(*end
) && *end
)) {
268 fprintf(stderr
, "dobase: Illegal trailer on address string\n");
276 while (bp
> 0 && end
>= s
) {
277 buf
[bp
] |= toxdigit(*end
) << shift
;
280 buf
[--bp
] = (todigit(*end
) >> (8 - shift
))
283 if ((shift
= (shift
+ 3) % 8) == 0)
287 if ((shift
= (shift
) ? 0 : 4) == 0)
292 fprintf(stderr
, "stoa: dobase: number to long\n");
296 /* need to catch end case to avoid extra 0's in front */
299 memcp(buf
, &buf
[bp
], (SBUFSIZE
- bp
));
300 return (SBUFSIZE
- bp
);
308 atos(str, addr, type)
310 convert address to ASCII form with address in hex, octal,
312 return pointer to buffer (NULL on failure).
317 atos(str
, addr
, type
)
323 int mystr
= 0; /* was str allocated here ? */
324 unsigned x_atos(), o_atos();
333 if ((str
= malloc(SBUFSIZE
)) == NULL
)
345 return xfer(str
, sbuf
, o_atos(sbuf
+2, addr
->buf
, addr
->len
) + 2,
346 mystr
? SBUFSIZE
: 0);
353 return xfer(str
, sbuf
, x_atos(sbuf
+2, addr
->buf
, addr
->len
) + 2,
354 mystr
? SBUFSIZE
: 0);
357 base
= xfer(str
, addr
->buf
,
358 addr
->len
+ 1, mystr
? SBUFSIZE
: 0);
360 base
[addr
->len
] = '\0'; /* terminate*/
371 return the number of bytes occupied by string + NULL*/
374 x_atos : convert an address string a, length s
387 *s
++ = itoac(((*a
>> 4) & MASK (4)));
388 *s
++ = itoac((*a
& MASK(4)));
397 o_atos : convert an address a, length l
398 to octal ASCII in s */
415 /* take care of partial bits and set shift factor for next 3 */
418 *s
++ = itoac((*a
>>(i
+5)) & MASK(3-i
));
423 *s
++ = itoac((*a
>> shift
) & MASK(3));
428 shift
+= (shift
< 3) ? 5 : -3;
431 i
= (*a
& MASK(shift
-5)) << (8-shift
);
432 i
|= (*++a
>> shift
) & MASK(8-shift
);
444 memcp(d
, s
, n
) /* safe memcpy for overlapping regions */
453 /* transfer block to a given destination or allocate one of the
455 if max = 0 : ignore max
459 xfer(dest
, src
, len
, max
)
463 if (max
&& dest
&& max
< len
) { /* No room */
464 fprintf(stderr
, "xfer: destination not long enough\n");
468 if ((dest
= (char *)malloc(len
)) == NULL
) {
469 fprintf(stderr
, "xfer: malloc failed\n");
473 memcpy(dest
, src
, (int)len
);
478 prescan: scan through string s, expanding all \$...\$
480 Return pointer to string of expanded text.
490 if (!s
|| !*s
|| !scan(s
))
498 scan: scan through string s, expanding all \$...\$.
500 Return 0 if anything failed, else 1.
510 int esc
= 0; /* Keep lookout for \\$ */
513 if (!esc
&& (*s
== '\\' && *(s
+1) == '$')) {
514 if (rec
++ == MAXRLEVEL
) {
515 fprintf(stderr
, "scan: Recursion \
516 level past %d on shell escape\n", rec
);
519 if ((cmd
= xcmd(s
+2, '$', &s
, &len
)) != NULL
) {
529 else if (sbp
== SBUFSIZE
) {
530 fprintf(stderr
, "Overflow on shell esc expansion\n");
533 else if (sbp
< SBUFSIZE
)
534 esc
= ((scanbuf
[sbp
++] = *s
++) == '\\');
541 xcmd : extract command line for shell escape and execute it
542 return pointer to output of command
547 char *s
; /* input string */
548 char ec
; /* escape char ( $ or ! ) */
549 char **ps
; /* address of input string pointer */
550 int *len
; /* Number of bytes of output from command */
555 FILE *pfp
; /* pipe for process */
556 char *cmd
; /* command buffer */
557 char *cmdp
; /* pointer along cmd */
558 char *ocmd
; /* output of command buffer */
559 int esc
= 0; /* escaped escape shell */
563 if ((cmd
= cmdp
= (char *)malloc(SBUFSIZE
)) == NULL
) {
564 fprintf(stderr
, "xcmd: malloc failed\n");
568 if ((ocmd
= (char *)malloc(SBUFSIZE
)) == NULL
) {
569 fprintf(stderr
, "xcmd: malloc failed\n");
574 if (!esc
&& *s
== '\\' && *(s
+1) == ec
) {
579 esc
= (*cmdp
++ = *s
++) == '\\';
584 if ((pfp
= popen(cmd
, "r")) == NULL
)
585 fprintf(stderr
, "xcmd: popen failed\n");
586 while (fread(&ocmd
[*len
], 1, 1, pfp
))
587 if ((*len
+= 1) >= SBUFSIZE
) {
588 fprintf(stderr
, "xcmd: command output too long\n");