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 *
stoa(char * str,struct netbuf * addr)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
dobase(char * s,char * buf,int type)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
memcp(char * d,char * s,int n)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 *
xfer(char * dest,char * src,unsigned len,unsigned max)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