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