/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#ident "%Z%%M% %I% %E% SMI" /* from SVR4 bnu:stoa.c 1.4 */
#include "uucp.h"
#ifdef TLI
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#include <sys/tiuser.h>
#include <ctype.h>
#define OCT 0
#define HEX 1
/* #include <nsaddr.h>
*/
#define toupper(c) (islower(c) ? _toupper(c) : (c))
#define todigit(c) ((int)((c) - '0')) /* char to digit */
#define toxdigit(c) ((isdigit(c))?todigit(c):(toupper(c)-(int)'A'+10))
#define isodigit(c) (isdigit(c) && ((c) != '9') && ((c) != '8'))
#define itoac(i) (((i) > 9) ? ((char)((i)-10) + 'A'):((char)(i) + '0'))
#define MASK(n) ((1 << (n)) - 1)
#define SBUFSIZE 128
/* #define TRUE 1;
* #define FALSE 0;
*/
GLOBAL char sbuf[SBUFSIZE];
/* local static functions */
static int dobase();
static void memcp();
static char *xfer();
/*
stoa - convert string to address
If a string begins in \o or \O, the following address is octal
" " " " " \x or \X, the following address is hex
If ok, return pointer to netbuf structure.
A NULL is returned on any error(s).
*/
GLOBAL struct netbuf *
stoa(str, addr) /* Return netbuf ptr if success */
char *str; /* Return NULL if error */
struct netbuf *addr;
{
int myadr; /* was netbuf struct allocated here ? */
myadr = FALSE;
if (!str)
return NULL;
while (*str && isspace(*str)) /* leading whites are OK */
++str;
if (!str || !*str) return NULL; /* Nothing to convert */
if (!addr) {
if ((addr = (struct netbuf *)malloc(sizeof(struct netbuf))) == NULL)
return NULL;
myadr = TRUE;
addr->buf = NULL;
addr->maxlen = 0;
addr->len = 0;
}
/* Now process the address */
if (*str == '\\') {
++str;
switch (*str) {
case 'X': /* hex */
case 'x':
addr->len = dobase(++str, sbuf, HEX);
break;
case 'o': /* octal */
case 'O':
addr->len = dobase(++str, sbuf, OCT);
break;
default: /* error */
addr->len = 0;
break;
}
}
if (addr->len == 0) { /* Error in conversion */
if (myadr)
free(addr);
return NULL;
}
if ((addr->buf = xfer(addr->buf, sbuf, addr->len, addr->maxlen)) == NULL)
return NULL;
else
return addr;
}
/*
dobase : converts a hex or octal ASCII string
to a binary address. Only HEX or OCT may be used
for type.
return length of binary string (in bytes), 0 if error.
The binary result is placed at buf.
*/
static int
dobase(s, buf, type) /* read in an address */
char *s, *buf; /* source ASCII, result binary string */
int type;
{
int bp = SBUFSIZE - 1;
int shift = 0;
char *end;
for (end = s; *end && ((type == OCT) ? isodigit(*end) :
isxdigit(*end)); ++end) ;
/* any non-white, non-digits cause address to be rejected,
other fields are ignored */
if ((*s == 0) || (end == s) || (!isspace(*end) && *end)) {
fprintf(stderr, "dobase: Illegal trailer on address string\n");
buf[0] = '\0';
return 0;
}
--end;
buf[bp] = '\0';
while (bp > 0 && end >= s) {
buf[bp] |= toxdigit(*end) << shift;
if (type == OCT) {
if (shift > 5) {
buf[--bp] = (todigit(*end) >> (8 - shift))
& MASK(shift-5);
}
if ((shift = (shift + 3) % 8) == 0)
buf[--bp] = 0;
}
else /* hex */
if ((shift = (shift) ? 0 : 4) == 0)
buf[--bp] = 0;;
--end;
}
if (bp == 0) {
fprintf(stderr, "stoa: dobase: number to long\n");
return 0;
}
/* need to catch end case to avoid extra 0's in front */
if (!shift)
bp++;
memcp(buf, &buf[bp], (SBUFSIZE - bp));
return (SBUFSIZE - bp);
}
static void
memcp(d, s, n) /* safe memcpy for overlapping regions */
char *d, *s;
int n;
{
while (n--)
*d++ = *s++;
return;
}
/* transfer block to a given destination or allocate one of the
right size
if max = 0 : ignore max
*/
static char *
xfer(dest, src, len, max)
char *dest, *src;
unsigned len, max;
{
if (max && dest && max < len) { /* No room */
fprintf(stderr, "xfer: destination not long enough\n");
return NULL;
}
if (!dest)
if ((dest = malloc(len)) == NULL) {
fprintf(stderr, "xfer: malloc failed\n");
return NULL;
}
memcpy(dest, src, (int)len);
return dest;
}
#endif /* TLI */