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