#include "mt.h"
#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
#define toupper(c) (islower(c) ? _toupper(c) : (c))
#define todigit(c) ((int)((c) - '0'))
#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
static int dobase(char *, char *, int);
static void memcp(char *, char *, int);
static char *xfer(char *, char *, unsigned, unsigned);
static struct netbuf *
stoa(char *str, struct netbuf *addr)
{
int myadr;
static char *sbuf;
myadr = FALSE;
if (!str)
return (NULL);
while (*str && isspace(*str))
++str;
if (!str || !*str)
return (NULL);
if (!addr) {
if ((addr = malloc(sizeof (struct netbuf))) == NULL)
return (NULL);
myadr = TRUE;
addr->buf = NULL;
addr->maxlen = 0;
addr->len = 0;
}
if (sbuf == NULL) {
sbuf = malloc(SBUFSIZE);
if (sbuf == NULL)
return (NULL);
}
if (*str == '\\') {
++str;
switch (*str) {
case 'X':
case 'x':
addr->len = dobase(++str, sbuf, HEX);
break;
case 'o':
case 'O':
addr->len = dobase(++str, sbuf, OCT);
break;
default:
addr->len = 0;
break;
}
}
if (addr->len == 0) {
if (myadr)
free(addr);
return (NULL);
}
if ((addr->buf = xfer(addr->buf, sbuf, addr->len, addr->maxlen)) ==
NULL)
return (NULL);
return (addr);
}
static int
dobase(char *s, char *buf, int type)
{
int bp = SBUFSIZE - 1;
int shift = 0;
char *end;
for (end = s; *end && ((type == OCT) ? isodigit(*end) :
isxdigit(*end)); ++end)
;
if ((*s == 0) || (end == s) || (!isspace(*end) && *end)) {
(void) 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
if ((shift = (shift) ? 0 : 4) == 0)
buf[--bp] = 0;
--end;
}
if (bp == 0) {
(void) fprintf(stderr, "stoa: dobase: number to long\n");
return (0);
}
if (!shift)
bp++;
memcp(buf, &buf[bp], (SBUFSIZE - bp));
return (SBUFSIZE - bp);
}
static void
memcp(char *d, char *s, int n)
{
while (n--)
*d++ = *s++;
}
static char *
xfer(char *dest, char *src, unsigned len, unsigned max)
{
if (max && dest && max < len) {
(void) fprintf(stderr, "xfer: destination not long enough\n");
return (NULL);
}
if (!dest)
if ((dest = malloc(len)) == NULL) {
(void) fprintf(stderr, "xfer: malloc failed\n");
return (NULL);
}
(void) memcpy(dest, src, (size_t)len);
return (dest);
}
#endif