/*
* 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
* 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 1998 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* mailx -- a modified version of a University of California at Berkeley
* mail program
*
* Network name modification routines.
*/
#include "rcv.h"
#include "configdefs.h"
#include <locale.h>
#ifdef OPTIM
#endif
/*
* Map a name into the correct network "view" of the
* name. This is done by prepending the name with the
* network address of the sender, then optimizing away
* nonsense.
*/
char *
{
return(name); /* "from" is empty - can't do anything */
return(name); /* "from" and "name" are the same, do nothing */
/*
* If the name contains an "@" or a "%", remove it and the host
* following it if that host is "known".
*/
/*
* If the sender contains a "@" or a "%", make "name" into an
* address on that host, on the presumption that it should
* really have read "name@from" when we received the message
* rather than just "name".
*/
/*
* "onehop" is set, meaning all machines are one UUCP
* hop away (fat chance, in this day and age), and "name"
* is a UUCP path rather than just a name. Leave it alone.
*/
} else {
}
*--cp = 0;
}
}
#ifdef OPTIM
else
#else
#endif /* OPTIM */
}
/*
* Stick a host on the beginning of a uucp
* address if it isn't there already.
*/
static char *
{
while (*rest == '!')
rest++;
rest = r;
}
return rest;
}
/*
* Check equality of the first host in a uucp address.
*/
int
{
}
/*
* Return last host in a uucp address.
*/
static char *
{
return r ? ++r : addr;
}
/*
* Optionally translate an old format uucp name into a new one, e.g.
* "mach1!mach2!user" becomes "user@mach2.UUCP". This optional because
* some information is necessarily lost (e.g. the route it got here
* via) and if we don't have the host in our routing tables, we lose.
* XXX THIS IS NO LONGER VALID WITH THE NEW UUCP PROJECT PLANS TO
* REGISTER UUCP HOSTS IN THE STANDARD INTERNET NAMESPACE, E.G.
* ihnp4 BECOMES "ihnp4.att.com".
*/
char *
{
if (UnUUCP==0 &&
return name;
return name;
*np++ = 0;
else
*hp++ = 0;
if (cp)
*cp = 0;
}
/*
* Turn a network machine name into a unique character
*/
static int
{
/*
* Make into lower case.
*/
/*nothing*/;
*cp2 = 0;
/*
* If a single letter machine, look through those first.
*/
return(nbuf[0]);
/*
* Look for usual name
*/
/*
* Look in side hash table.
*/
}
#ifdef OPTIM
/*
* Turn a network unique character identifier into a network name.
*/
static char *
{
if (mid & 0200)
return(np->nt_machine);
return(NOSTR);
}
#endif
/*
* Deal with arpa net addresses. The way this is done is strange.
* name contains an "@" or "%". Look up the machine after it in
* the hash table. If it isn't found, return name unmolested.
* If ???, return name unmolested.
* Otherwise, delete the "@" or "%" and the machine after it from
* name, and return the new string.
*/
static char *
{
register char *cp;
register int arpamach;
if (debug) {
}
gettext("Something's amiss -- no @ or %% in arpafix\n"));
return(name);
}
cp++;
if (debug)
"cp '%s', arpamach %o, nettypes arpamach %o LOCAL %o\n",
if (arpamach == 0) {
if (debug)
return(name);
}
if (debug)
return(name);
}
*cp = 0;
}
/*
* We have name with no @'s in it, and from with @'s.
* Assume that name is meaningful only on the site in from,
* and return "name@site_in_from".
*/
static char *
{
register char *cp;
if (!value("makeremote"))
return(name);
}
/*
* Take a network machine descriptor and find the types of connected
* nets and return it.
*/
static int
{
if (mid & 0200)
return(0);
}
/*
* Hashing routines to salt away machines seen scanning
* networks paths that we don't know about.
*/
struct xtrahash {
/*
* Initialize the extra host hash table.
* Called by sreset.
*/
void
minit(void)
{
midfree = 0;
}
}
/*
* Stash a net name in the extra host hash table.
* If a new entry is put in the hash table, deduce what
* net the machine is attached to from the net character.
*
* If the machine is already known, add the given attached
* net to those already known.
*/
static int
{
int x;
return(0);
}
return(0);
}
}
if (x == 0)
else
}
/*
* Search for the given name in the hash table
* and return the pointer to it if found, or to the first
* empty slot if not found.
*
* If no free slots can be found, return 0.
*/
static struct xtrahash *
{
register int h, q, i;
register char *cp;
;
if (h < 0 && (h = -h) < 0)
h = 0;
h = h % XHSIZE;
for (i = 0, q = 0; q < XHSIZE; i++, q = i * i) {
return(xp);
return(xp);
if (h - q < 0)
h += XHSIZE;
return(xp);
return(xp);
}
return((struct xtrahash *) 0);
}
#ifdef OPTIM
/*
* Return the name from the extra host hash table corresponding
* to the passed machine id.
*/
static char *
{
register int m;
if ((mid & 0200) == 0)
return(NOSTR);
m = mid & 0177;
if (m >= midfree) {
return(NOSTR);
}
}
#endif
/*
* Return the bit mask of net's that the given extra host machine
* id has so far.
*/
static int
{
register int m;
if ((mid & 0200) == 0)
return(0);
m = mid & 0177;
if (m >= midfree) {
return(0);
}
}
#ifdef OPTIM
/*
* Take a network name and optimize it. This gloriously messy
* operation takes place as follows: the name with machine names
* in it is tokenized by mapping each machine name into a single
* character machine id (netlook). The separator characters (network
* metacharacters) are left intact. The last component of the network
* name is stripped off and assumed to be the destination user name --
* it does not participate in the optimization. As an example, the
* name "res!vax!res!uvax!bill" becomes, tokenized,
* "r!x!r!v!" and "bill" A low level routine, optim1, fixes up the
* network part (eg, "r!x!r!v!"), then we convert back to network
* machine names and tack the user name on the end.
*
* The result of this is copied into the parameter "name"
*/
static void
{
register int c;
*netstr = '\0';
for (;;) {
/*
* Rip off next path component into netcomp
*/
*cp2 = 0;
/*
* If we hit null byte, then we just scanned
* the destination user name. Go off and optimize
* if its so.
*/
if (*cp == 0)
break;
err:
return;
}
/*
* If multiple network separators given,
* throw away the extras.
*/
cp++;
}
goto err;
}
/*
* Convert back to machine names.
*/
*name = '\0';
while (*cp) {
cp[-1]);
goto err;
}
}
}
/*
* Take a string of network machine id's and separators and
* optimize them. We process these by pulling off maximal
* leading strings of the same type, passing these to the appropriate
* optimizer and concatenating the results.
*/
static void
{
*name = '\0';
/*
* If the address ultimately points back to us,
* just return a null network path.
*/
return;
while (*cp != 0) {
*path = '\0';
cp++;
}
default:
break;
case IMPLICIT:
break;
case EXPLICIT:
break;
}
}
}
}
#endif /* OPTIM */
/*
* Return the network of the separator --
* AN for arpa net
* BN for Bell labs net (e.g. UUCP, NOT Berknet)
* SN for Schmidt net (Berknet)
* 0 if we don't know.
*/
static int
{
return(0);
}
#ifdef OPTIM
/*
* Return the kind of routing used for the particular net
* EXPLICIT means explicitly routed
* IMPLICIT means implicitly routed
* 0 means don't know
*/
static int
{
return(0);
}
/*
* Do name optimization for an explicitly routed network (eg uucp).
*/
static int
{
register int m;
return(-1);
name[0] = 0;
return(0);
}
m = *cp;
}
return(0);
}
/*
* Do name optimization for implicitly routed network (eg, arpanet).
*/
static int
{
register char *cp;
register char m;
return(-1);
if (m == LOCAL) {
*name = '\0';
return(0);
}
name[0] = m;
name[1] = 0;
return(0);
}
/*
* Perform global optimization on the given network path.
* The trick here is to look ahead to see if there are any loops
* in the path and remove them. The interpretation of loops is
* more strict here than in optimex since both the machine and net
* type must match.
*/
static void
{
return;
return;
}
while (*cp) {
cp += 2;
}
}
/*
* Find the rightmost instance of the given (machine, type) pair.
*/
static char *
{
while (*cp) {
cp += 2;
}
return(last);
}
/*
* Change the network separators in the given network path
* to the preferred network transmission means.
*/
static void
{
register char *cp, n;
register int state;
if (n)
cp[1] = n;
}
}
/*
* Return the best network separator for the given machine pair.
*/
static char
{
return(0);
}
return(0);
np++;
}
#endif /* OPTIM */
#ifdef notdef
/*
* Code to twist around arpa net names.
*/
static char *yylval;
/*
* Reverse all of the arpa net addresses in the given name to
* be of the form "host @ user" instead of "user @ host"
* This function is its own inverse.
*/
char *
{
return(NOSTR);
if (name())
return(NOSTR);
return(str);
}
/*
* Parse (by recursive descent) network names, using the following grammar:
* name:
* term {':' term}
* term {'^' term}
* term {'!' term}
* term '@' name
* term '%' name
*
* term:
* string of characters.
*/
static int
name(void)
{
register int t;
register char *cp;
for (;;) {
t = yylex();
if (t != WORD)
return(-1);
t = yylex();
switch (t) {
case 0:
return(0);
case '@':
case '%':
if (name())
return(-1);
return(0);
case WORD:
return(-1);
default:
}
}
}
/*
* Scanner for network names.
*/
/*
* Initialize the network name scanner.
*/
int
{
netbuf[0] = 0;
return(-1);
nexttok = 0;
return(0);
}
/*
* Scan and return a single token.
* yylval is set to point to a scanned string.
*/
int
yylex(void)
{
register int s;
if (nexttok) {
s = nexttok;
nexttok = 0;
return(s);
}
cp++;
if (*cp == 0)
return(0);
return(*cp);
}
cp++;
if (*cp == 0)
else
*cp = 0;
return(WORD);
}
#endif
/*
* Add a single character onto a string. Here dstsize is the size of the
* destnation buffer.
*/
static void
{
while (*dst != '\0') {
dst++;
dstsize--;
}
if (--dstsize > 0)
*dst++ = (char)c;
*dst = '\0';
}