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