xref: /illumos-gate/usr/src/cmd/bnu/stoa.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
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
7  * with the License.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 #ident	"%Z%%M%	%I%	%E% SMI"	/* from SVR4 bnu:stoa.c 1.4 */
27 
28 #include	"uucp.h"
29 
30 #ifdef TLI
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <memory.h>
35 #include <malloc.h>
36 #include <sys/tiuser.h>
37 #include <ctype.h>
38 #define OCT	0
39 #define HEX	1
40 /* #include <nsaddr.h>
41 */
42 #define	toupper(c)	(islower(c) ? _toupper(c) : (c))
43 #define	todigit(c)	((int)((c) - '0'))	/* char to digit */
44 #define	toxdigit(c)	((isdigit(c))?todigit(c):(toupper(c)-(int)'A'+10))
45 #define	isodigit(c)	(isdigit(c) && ((c) != '9') && ((c) != '8'))
46 #define	itoac(i)	(((i) > 9) ? ((char)((i)-10) + 'A'):((char)(i) + '0'))
47 #define	MASK(n)		((1 << (n)) - 1)
48 
49 #define	SBUFSIZE	128
50 
51 /* #define	TRUE	1;
52  * #define	FALSE	0;
53  */
54 
55 GLOBAL char	sbuf[SBUFSIZE];
56 
57 /*	local static functions	*/
58 static int dobase();
59 static void memcp();
60 static char *xfer();
61 
62 /*
63 	stoa - convert string to address
64 
65 	If a string begins in \o or \O, the following address is octal
66 	"  "   "       "    " \x or \X, the following address is hex
67 
68 	If ok, return pointer to netbuf structure.
69 	A  NULL is returned on any error(s).
70 */
71 
72 GLOBAL struct netbuf *
73 stoa(str, addr)			/* Return netbuf ptr if success */
74 char	*str;			/* Return NULL if error		*/
75 struct netbuf	*addr;
76 {
77 	int	myadr;		/* was netbuf struct allocated here ? */
78 
79 	myadr = FALSE;
80 
81 	if (!str)
82 		return NULL;
83 	while (*str && isspace(*str))	/* leading whites are OK */
84 		++str;
85 
86 	if (!str || !*str) return NULL;		/* Nothing to convert */
87 
88 	if (!addr) {
89 		if ((addr = (struct netbuf *)malloc(sizeof(struct netbuf))) == NULL)
90 			return NULL;
91 		myadr = TRUE;
92 		addr->buf = NULL;
93 		addr->maxlen = 0;
94 		addr->len = 0;
95 	}
96 
97 	/* Now process the address */
98 	if (*str == '\\') {
99 		++str;
100 		switch (*str) {
101 
102 		case 'X':	/* hex */
103 		case 'x':
104 			addr->len = dobase(++str, sbuf, HEX);
105 			break;
106 
107 		case 'o':	/* octal */
108 		case 'O':
109 			addr->len = dobase(++str, sbuf, OCT);
110 			break;
111 
112 		default:	/* error */
113 			addr->len = 0;
114 			break;
115 		}
116 	}
117 
118 	if (addr->len == 0) {	/* Error in conversion */
119 		if (myadr)
120 			free(addr);
121 		return NULL;
122 	}
123 	if ((addr->buf = xfer(addr->buf, sbuf, addr->len, addr->maxlen)) == NULL)
124 		return NULL;
125 	else
126 		return addr;
127 }
128 
129 /*
130 	dobase :	converts a hex or octal ASCII string
131 		to a binary address. Only HEX or OCT may be used
132 		for type.
133 	return length of binary string (in bytes), 0 if error.
134 	The binary result is placed at buf.
135 */
136 
137 static int
138 dobase(s, buf, type)	/* read in an address */
139 char	*s, *buf;	/* source ASCII, result binary string */
140 int	type;
141 {
142 	int	bp = SBUFSIZE - 1;
143 	int	shift = 0;
144 	char	*end;
145 
146 	for (end = s; *end && ((type == OCT) ? isodigit(*end) :
147 		isxdigit(*end)); ++end) ;
148 
149 	/* any non-white, non-digits cause address to be rejected,
150 	   other fields are ignored */
151 
152 	if ((*s == 0) || (end == s) || (!isspace(*end) && *end)) {
153 		fprintf(stderr, "dobase: Illegal trailer on address string\n");
154 		buf[0] = '\0';
155 		return 0;
156 	}
157 	--end;
158 
159 	buf[bp] = '\0';
160 
161 	while (bp > 0 && end >= s) {
162 		buf[bp] |= toxdigit(*end) << shift;
163 		if (type == OCT) {
164 			if (shift > 5) {
165 				buf[--bp] = (todigit(*end) >> (8 - shift))
166 					& MASK(shift-5);
167 			}
168 			if ((shift = (shift + 3) % 8) == 0)
169 				buf[--bp] = 0;
170 		}
171 		else	/* hex */
172 			if ((shift = (shift) ? 0 : 4) == 0)
173 				buf[--bp] = 0;;
174 		--end;
175 	}
176 	if (bp == 0) {
177 		fprintf(stderr, "stoa: dobase: number to long\n");
178 		return 0;
179 	}
180 
181 	/* need to catch end case to avoid extra 0's in front	*/
182 	if (!shift)
183 		bp++;
184 	memcp(buf, &buf[bp], (SBUFSIZE - bp));
185 	return (SBUFSIZE - bp);
186 }
187 
188 static void
189 memcp(d, s, n)	/* safe memcpy for overlapping regions */
190 char	*d, *s;
191 int	n;
192 {
193 	while (n--)
194 		*d++ = *s++;
195 	return;
196 }
197 
198 /* transfer block to a given destination or allocate one of the
199     right size
200     if max = 0 : ignore max
201 */
202 
203 static char *
204 xfer(dest, src, len, max)
205 char	*dest, *src;
206 unsigned	len, max;
207 {
208 	if (max && dest && max < len) {		/* No room */
209 		fprintf(stderr, "xfer: destination not long enough\n");
210 		return NULL;
211 	}
212 	if (!dest)
213 		if ((dest = malloc(len)) == NULL) {
214 			fprintf(stderr, "xfer: malloc failed\n");
215 			return NULL;
216 		}
217 
218 	memcpy(dest, src, (int)len);
219 	return dest;
220 }
221 
222 #endif /* TLI */
223