#include "rcv.h"
#include "configdefs.h"
#include <locale.h>
static char *arpafix(char name[], char from[]);
static char *lasthost(char *addr);
static char *makeremote(char name[], char from[]);
static int mstash(char name[], int attnet);
static int mtype(int mid);
static int netlook(char machine[], int attnet);
static int nettype(int mid);
static int ntype(register int nc);
static void stradd(register char *str, int n, register int c);
static char *tackon(char *sys, char *rest);
static struct xtrahash *xlocate(char name[]);
#ifdef OPTIM
static char best(int src, int dest);
static char *mlook(int mid);
static int netkind(register int nt);
static void optiboth(char net[]);
static void optim(char net[], char name[]);
static void optim1(char netstr[], char name[]);
static int optimex(char net[], char name[]);
static int optimimp(char net[], char name[]);
static void prefer(char name[]);
static char *rpair(char str[], int mach);
#endif
char *
netmap(char name[], char from[])
{
char nbuf[BUFSIZ], ret[BUFSIZ];
register char *cp, *oname;
if (debug) fprintf(stderr, "netmap(name '%s', from '%s')\n", name, from);
if (strlen(from) == 0)
return(name);
if (strcmp(from, name) == 0)
return(name);
if (any('@', name) || any('%', name))
return(arpafix(name, from));
if (any('@', from) || any('%', from))
return(unuucp(makeremote(name, from)));
if (value("onehop") && (cp = strchr(name, '!')) && cp > name) {
nstrcpy(nbuf, sizeof (nbuf), name);
} else {
from = tackon(host, from);
*strrchr(from, '!') = 0;
name = tackon(lasthost(from), name);
while (((cp = lasthost(from)) != 0) && ishost(cp, name)) {
oname = name;
name = strchr(name, '!') + 1;
if (cp == from) {
from[strlen(from)] = '!';
if (value("mustbang") && !strchr(name, '!'))
name = oname;
return(unuucp(name));
}
*--cp = 0;
}
from[strlen(from)] = '!';
from = strchr(from, '!') + 1;
snprintf(nbuf, sizeof (nbuf), "%s!%s", from, name);
}
if (debug) fprintf(stderr, "before optim, nbuf '%s'\n", name);
#ifdef OPTIM
if ((cp = value("conv"))==NOSTR || strcmp(cp, "optimize") != 0)
nstrcpy(ret, sizeof (ret), nbuf);
else
optim(nbuf, ret);
#else
nstrcpy(ret, sizeof (ret), nbuf);
#endif
if (debug) fprintf(stderr, "after optim, nbuf '%s', ret '%s'\n", nbuf, ret);
cp = ret;
if (debug) fprintf(stderr, "wind up with '%s'\n", name);
if (!icequal(name, cp))
return(unuucp((char *) savestr(cp)));
return(unuucp(name));
}
static char *
tackon(char *sys, char *rest)
{
while (*rest == '!')
rest++;
if (!ishost(sys, rest)) {
char *r = (char *)salloc(strlen(sys) + strlen(rest) + 2);
sprintf(r, "%s!%s", sys, rest);
rest = r;
}
return rest;
}
int
ishost(char *sys, char *rest)
{
while (*sys && *sys == *rest)
sys++, rest++;
return(*sys == 0 && *rest == '!');
}
static char *
lasthost(char *addr)
{
char *r = strrchr(addr, '!');
return r ? ++r : addr;
}
char *
unuucp(char *name)
{
register char *np, *hp, *cp;
char result[100];
char tname[300];
if (UnUUCP==0 &&
((cp = value("conv"))==NOSTR || strcmp(cp, "internet")))
return name;
if (debug) fprintf(stderr, "unuucp(%s)\n", name);
nstrcpy(tname, sizeof (tname), name);
np = strrchr(tname, '!');
if (np == NOSTR)
return name;
*np++ = 0;
hp = strrchr(tname, '!');
if (hp == NOSTR)
hp = tname;
else
*hp++ = 0;
cp = strchr(np, '@');
if (cp == NOSTR)
cp = strchr(np, '%');
if (cp)
*cp = 0;
if (debug) fprintf(stderr, "host %s, name %s\n", hp, np);
snprintf(result, sizeof (result), "%s@%s.UUCP", np, hp);
if (debug) fprintf(stderr, "unuucp returns %s\n", result);
return savestr(result);
}
static int
netlook(char machine[], int attnet)
{
register struct netmach *np;
register char *cp, *cp2;
char nbuf[BUFSIZ];
for (cp = machine, cp2 = nbuf;
*cp && cp2 < &nbuf[BUFSIZ-1];
*cp2++ = tolower(*cp++))
;
*cp2 = 0;
if (strlen(nbuf) == 1)
for (np = netmach; np->nt_mid != 0; np++)
if (np->nt_mid == nbuf[0])
return(nbuf[0]);
for (np = netmach; np->nt_mid != 0; np++)
if (strcmp(np->nt_machine, nbuf) == 0)
return(np->nt_mid);
return(mstash(nbuf, attnet));
}
#ifdef OPTIM
static char *
netname(int mid)
{
register struct netmach *np;
if (mid & 0200)
return(mlook(mid));
for (np = netmach; np->nt_mid != 0; np++)
if (np->nt_mid == mid)
return(np->nt_machine);
return(NOSTR);
}
#endif
static char *
arpafix(char name[], char from[])
{
register char *cp;
register int arpamach;
char newname[BUFSIZ];
if (debug) {
fprintf(stderr, "arpafix(%s, %s)\n", name, from);
}
cp = strrchr(name, '@');
if (cp == NOSTR)
cp = strrchr(name, '%');
if (cp == NOSTR) {
fprintf(stderr,
gettext("Something's amiss -- no @ or %% in arpafix\n"));
return(name);
}
cp++;
arpamach = netlook(cp, '@');
if (debug)
fprintf(stderr,
"cp '%s', arpamach %o, nettypes arpamach %o LOCAL %o\n",
cp, arpamach, nettype(arpamach), nettype(LOCAL));
if (arpamach == 0) {
if (debug)
fprintf(stderr, "machine %s unknown, uses: %s\n",
cp, name);
return(name);
}
if (((nettype(arpamach) & nettype(LOCAL)) & ~AN) == 0) {
if (debug)
fprintf(stderr, "machine %s known but remote, uses: %s\n",
cp, name);
return(name);
}
nstrcpy(newname, sizeof (newname), name);
cp = strrchr(newname, '@');
if (cp == NOSTR)
cp = strrchr(newname, '%');
*cp = 0;
if (debug) fprintf(stderr, "local address, return '%s'\n", newname);
return(savestr(newname));
}
static char *
makeremote(char name[], char from[])
{
register char *cp;
char rbuf[BUFSIZ];
if (!value("makeremote"))
return(name);
if (debug) fprintf(stderr, "makeremote(%s, %s) returns ", name, from);
cp = strrchr(from, '@');
if (cp == NOSTR)
cp = strrchr(from, '%');
snprintf(rbuf, sizeof (rbuf), "%s%s", name, cp);
if (debug) fprintf(stderr, "%s\n", rbuf);
return(savestr(rbuf));
}
static int
nettype(int mid)
{
register struct netmach *np;
if (mid & 0200)
return(mtype(mid));
for (np = netmach; np->nt_mid != 0; np++)
if (np->nt_mid == mid)
return(np->nt_type);
return(0);
}
#define XHSIZE 97
#define NXMID (XHSIZE*3/4)
struct xtrahash {
char *xh_name;
short xh_mid;
short xh_attnet;
} xtrahash[XHSIZE];
static struct xtrahash *xtab[XHSIZE];
static short midfree;
void
minit(void)
{
register struct xtrahash *xp, **tp;
midfree = 0;
tp = &xtab[0];
for (xp = &xtrahash[0]; xp < &xtrahash[XHSIZE]; xp++) {
xp->xh_name = NOSTR;
xp->xh_mid = 0;
xp->xh_attnet = 0;
*tp++ = (struct xtrahash *) 0;
}
}
static int
mstash(char name[], int attnet)
{
register struct xtrahash *xp;
int x;
xp = xlocate(name);
if (xp == (struct xtrahash *) 0) {
printf(gettext("Ran out of machine id spots\n"));
return(0);
}
if (xp->xh_name == NOSTR) {
if (midfree >= XHSIZE) {
printf(gettext("Out of machine ids\n"));
return(0);
}
xtab[midfree] = xp;
xp->xh_name = savestr(name);
xp->xh_mid = 0200 + midfree++;
}
x = ntype(attnet);
if (x == 0)
xp->xh_attnet |= AN;
else
xp->xh_attnet |= x;
return(xp->xh_mid);
}
static struct xtrahash *
xlocate(char name[])
{
register int h, q, i;
register char *cp;
register struct xtrahash *xp;
for (h = 0, cp = name; *cp; h = (h << 2) + *cp++)
;
if (h < 0 && (h = -h) < 0)
h = 0;
h = h % XHSIZE;
cp = name;
for (i = 0, q = 0; q < XHSIZE; i++, q = i * i) {
xp = &xtrahash[(h + q) % XHSIZE];
if (xp->xh_name == NOSTR)
return(xp);
if (strcmp(cp, xp->xh_name) == 0)
return(xp);
if (h - q < 0)
h += XHSIZE;
xp = &xtrahash[(h - q) % XHSIZE];
if (xp->xh_name == NOSTR)
return(xp);
if (strcmp(cp, xp->xh_name) == 0)
return(xp);
}
return((struct xtrahash *) 0);
}
#ifdef OPTIM
static char *
mlook(int mid)
{
register int m;
if ((mid & 0200) == 0)
return(NOSTR);
m = mid & 0177;
if (m >= midfree) {
printf(gettext("Use made of undefined machine id\n"));
return(NOSTR);
}
return(xtab[m]->xh_name);
}
#endif
static int
mtype(int mid)
{
register int m;
if ((mid & 0200) == 0)
return(0);
m = mid & 0177;
if (m >= midfree) {
printf(gettext("Use made of undefined machine id\n"));
return(0);
}
return(xtab[m]->xh_attnet);
}
#ifdef OPTIM
static void
optim(char net[], char name[])
{
char netcomp[BUFSIZ], netstr[STSIZ], xfstr[STSIZ];
register char *cp, *cp2;
register int c;
if (debug) fprintf(stderr, "optim(%s, %s) called\n", net, name);
*netstr = '\0';
cp = net;
for (;;) {
cp2 = netcomp;
while (*cp && !any(*cp, metanet))
*cp2++ = *cp++;
*cp2 = 0;
if (*cp == 0)
break;
if ((c = netlook(netcomp, *cp)) == 0) {
printf(gettext("No host named \"%s\"\n"), netcomp);
err:
nstrcpy(name, BUFSIZ, net);
return;
}
stradd(name, BUFSIZ, c);
stradd(name, BUFSIZ, *cp++);
while (any(*cp, metanet))
cp++;
}
if (strlen(netcomp) == 0) {
printf(gettext("net name syntax\n"));
goto err;
}
if (debug) fprintf(stderr, "optim1(%s,%s) called\n", netstr, xfstr);
optim1(netstr, xfstr);
if (debug) fprintf(stderr, "optim1(%s,%s) returns\n", netstr, xfstr);
cp = xfstr;
*name = '\0';
while (*cp) {
if ((cp2 = netname(*cp++)) == NOSTR) {
printf(gettext("Made up bad net name\n"));
printf(gettext("Machine code %c (0%o)\n"), cp[-1],
cp[-1]);
printf(gettext("Sorry.\n"));
goto err;
}
nstrcat(name, BUFSIZ, cp2);
stradd(name, BUFSIZ, *cp++);
}
nstrcat(name, BUFSIZ, netcomp);
if (debug) fprintf(stderr, "optim returns %s in name\n", name);
}
static void
optim1(char netstr[], char name[])
{
char path[STSIZ], rpath[STSIZ];
register char *cp, *cp2;
register int tp, nc;
cp = netstr;
prefer(cp);
*name = '\0';
if ((int)strlen(cp) > 1 && cp[strlen(cp) - 2] == LOCAL)
return;
while (*cp != 0) {
*path = '\0';
tp = ntype(cp[1]);
nc = cp[1];
while (*cp && tp == ntype(cp[1])) {
stradd(path, sizeof (path), *cp++);
cp++;
}
switch (netkind(tp)) {
default:
nstrcpy(rpath, sizeof (rpath), path);
break;
case IMPLICIT:
optimimp(path, rpath);
break;
case EXPLICIT:
optimex(path, rpath);
break;
}
for (cp2 = rpath; *cp2 != 0; cp2++) {
stradd(name, BUFSIZ, *cp2);
stradd(name, BUFSIZ, nc);
}
}
optiboth(name);
prefer(name);
}
#endif
static int
ntype(register int nc)
{
register struct ntypetab *np;
for (np = ntypetab; np->nt_char != 0; np++)
if (np->nt_char == nc)
return(np->nt_bcode);
return(0);
}
#ifdef OPTIM
static int
netkind(register int nt)
{
register struct nkindtab *np;
for (np = nkindtab; np->nk_type != 0; np++)
if (np->nk_type == nt)
return(np->nk_kind);
return(0);
}
static int
optimex(char net[], char name[])
{
register char *cp, *rp;
register int m;
nstrcpy(name, STSIZ, net);
cp = name;
if (strlen(cp) == 0)
return(-1);
if (cp[strlen(cp)-1] == LOCAL) {
name[0] = 0;
return(0);
}
for (cp = name; *cp; cp++) {
m = *cp;
rp = strrchr(cp+1, m);
if (rp != NOSTR)
strcpy(cp, rp);
}
return(0);
}
static int
optimimp(char net[], char name[])
{
register char *cp;
register char m;
cp = net;
if (strlen(cp) == 0)
return(-1);
m = cp[strlen(cp) - 1];
if (m == LOCAL) {
*name = '\0';
return(0);
}
name[0] = m;
name[1] = 0;
return(0);
}
static void
optiboth(char net[])
{
register char *cp, *cp2;
cp = net;
if (strlen(cp) == 0)
return;
if (((int)strlen(cp) % 2) != 0) {
printf(gettext("Strange arg to optiboth\n"));
return;
}
while (*cp) {
cp2 = rpair(cp+2, *cp);
if (cp2 != NOSTR)
strcpy(cp, cp2);
cp += 2;
}
}
static char *
rpair(char str[], int mach)
{
register char *cp, *last;
cp = str;
last = NOSTR;
while (*cp) {
if (*cp == mach)
last = cp;
cp += 2;
}
return(last);
}
static void
prefer(char name[])
{
register char *cp, n;
register int state;
state = LOCAL;
for (cp = name; *cp; cp += 2) {
n = best(state, *cp);
if (n)
cp[1] = n;
state = *cp;
}
}
static char
best(int src, int dest)
{
register int dtype, stype;
register struct netorder *np;
stype = nettype(src);
dtype = nettype(dest);
fflush(stdout);
if (stype == 0 || dtype == 0) {
printf(gettext("ERROR: unknown internal machine id\n"));
return(0);
}
if ((stype & dtype) == 0)
return(0);
np = &netorder[0];
while ((np->no_stat & stype & dtype) == 0)
np++;
return(np->no_char);
}
#endif
#ifdef notdef
#define WORD 257
static char netbuf[256];
static char *yylval;
char *
revarpa(char str[])
{
if (yyinit(str) < 0)
return(NOSTR);
if (name())
return(NOSTR);
if (strcmp(str, netbuf) == 0)
return(str);
return(savestr(netbuf));
}
static int
name(void)
{
register int t;
register char *cp;
for (;;) {
t = yylex();
if (t != WORD)
return(-1);
cp = yylval;
t = yylex();
switch (t) {
case 0:
nstrcat(netbuf, sizeof (netbuf), cp);
return(0);
case '@':
case '%':
if (name())
return(-1);
stradd(netbuf, sizeof (netbuf), '@');
nstrcat(netbuf, sizeof (netbuf), cp);
return(0);
case WORD:
return(-1);
default:
nstrcat(netbuf, sizeof (netbuf), cp);
stradd(netbuf, sizeof (netbuf), t);
}
}
}
static char *charp;
static int nexttok;
int
yyinit(char str[])
{
static char lexbuf[BUFSIZ];
netbuf[0] = 0;
if (strlen(str) >= sizeof lexbuf - 1)
return(-1);
nexttok = 0;
nstrcpy(lexbuf, sizeof (lexbuf), str);
charp = lexbuf;
return(0);
}
int
yylex(void)
{
register char *cp, *dotp;
register int s;
if (nexttok) {
s = nexttok;
nexttok = 0;
return(s);
}
cp = charp;
while (*cp && isspace(*cp))
cp++;
if (*cp == 0)
return(0);
if (any(*cp, metanet)) {
charp = cp+1;
return(*cp);
}
dotp = cp;
while (*cp && !any(*cp, metanet) && !any(*cp, " \t"))
cp++;
if (any(*cp, metanet))
nexttok = *cp;
if (*cp == 0)
charp = cp;
else
charp = cp+1;
*cp = 0;
yylval = dotp;
return(WORD);
}
#endif
static void
stradd(register char *dst, int dstsize, register int c)
{
while (*dst != '\0') {
dst++;
dstsize--;
}
if (--dstsize > 0)
*dst++ = (char)c;
*dst = '\0';
}