|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 10735 (0x29ef)
Types: TextFile
Names: »pathto.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦2fafebccf⟧ »EurOpenD3/mail/smail3.1.19.tar.Z«
└─⟦bcd2bc73f⟧
└─⟦this⟧ »src/pathto.c«
/* @(#)pathto.c 3.17 2/20/89 14:59:59 */
/*
* Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
*
* See the file COPYING, distributed with smail, for restriction
* and warranty information.
*/
/*
* main.c:
* process arguments, configure environment and process
* messages.
*
* external functions: main, initialize_state, process_args,
* deliver_mail
*/
#include <stdio.h>
#include "defs.h"
#include "smail.h"
#include "main.h"
#include "transport.h"
#include "addr.h"
#include "exitcodes.h"
#ifndef DEPEND
# include "error.h"
# include "extern.h"
#endif
/* variables local to this file */
static int bang_paths_only;
static int disable_smarthost;
static int direct_and_route;
static int show_transport;
/* functions local to this file */
static void print_pathto_addr();
static void pathto_direct_and_route();
static char **pathto_setup();
static struct addr *pathto_route();
static void pathto_usage();
static void uupath_usage();
/*
* pathto - return paths to the given addresses.
*/
void
pathto(argv)
char **argv; /* generally, argv from main */
{
struct addr *addr;
char *error;
argv = pathto_setup(argv, "vdnst", pathto_usage);
if (direct_and_route) {
struct addr *okay; /* list of routed addrs */
struct addr *defer; /* list of temp failed addrs */
struct addr *fail; /* list of failed addrs */
pathto_direct_and_route(argv, &okay, &defer, &fail);
while (defer) {
if (defer->error->info&ERR_CONFERR) {
(void) fprintf(stderr, "%s: %s ... config error: %s\n",
program, defer->in_addr,
defer->error->message);
} else {
(void) fprintf(stderr, "%s: %s ... temp error: %s\n",
program, defer->in_addr,
defer->error->message);
}
defer = defer->succ;
}
while (fail) {
(void) fprintf(stderr, "%s: %s ... failed: %s\n",
program, fail->in_addr, fail->error->message);
fail = fail->succ;
}
while (okay) {
print_pathto_addr(okay);
okay = okay->succ;
}
} else {
for (; *argv; argv++) {
if ((addr = pathto_route(*argv, &error)) == NULL) {
if (error) {
(void) fprintf(stderr, "%s: %s: %s\n",
program, *argv, error);
}
continue;
} else {
if (addr->next_host == NULL) {
addr->next_addr = addr->remainder;
}
print_pathto_addr(addr);
}
}
}
exit(EX_OK);
}
/*
* pathto_direct_and_route - take an array of address strings and
* return a list of resolved addresses
*/
static void
pathto_direct_and_route(addr_strings, okay, defer, fail)
char **addr_strings; /* input address strings */
struct addr **okay; /* successfully routed addrs */
struct addr **defer; /* temp routing failures */
struct addr **fail; /* unresolvable addrs */
{
register struct addr *addr = NULL;
*okay = NULL;
*defer = NULL;
*fail = NULL;
while (*addr_strings) {
register struct addr *new = alloc_addr();
char *error;
new->in_addr = *addr_strings;
new->work_addr = preparse_address(new->in_addr, &error);
if (new->work_addr == NULL) {
new->error = note_error(ERR_111,
xprintf("parse error: %s", error));
new->succ = *fail;
*fail = new;
} else {
if (disable_smarthost) {
new->flags |= ADDR_SMARTUSER|ADDR_SMARTHOST;
}
new->succ = addr;
addr = new;
}
addr_strings++;
}
/* resolve all of the addresses, removing duplicates */
resolve_addr_list(addr, okay, defer, fail, TRUE);
}
/*
* print_pathto_addr - output the given addr structure as an address
*/
static void
print_pathto_addr(addr)
register struct addr *addr;
{
if (addr->next_host == NULL) {
if (direct_and_route) {
(void) printf("%s", addr->next_addr);
} else if (bang_paths_only) {
(void) printf("%s!%s", uucp_name, addr->next_addr);
} else {
(void) printf("%s@%s", addr->next_addr, primary_name);
}
} else if (bang_paths_only) {
char *error;
char *path = build_uucp_route(addr->next_addr, &error);
if (path == NULL) {
(void) fprintf(stderr, "%s: %s: %s\n",
program, addr->in_addr, error);
return;
} else {
(void) printf("%s!%s", addr->next_host, path);
}
} else {
char *target;
char *remainder;
switch (parse_address(addr->next_addr, &target, &remainder)) {
case FAIL:
case PARSE_ERROR:
(void) fprintf(stderr, "%s: %s: %s",
program, addr->in_addr, remainder);
break;
case RFC_ROUTE:
(void) printf("@%s,@%s,%s",
addr->next_host, target, remainder);
break;
case RFC_ENDROUTE:
(void) printf("@%s,@%s:%s",
addr->next_host, target, remainder);
break;
case MAILBOX:
(void) printf("@%s:%s@%s",
addr->next_host, remainder, target);
break;
case UUCP_ROUTE:
(void) printf("%s!%s!%s",
addr->next_host, target, remainder);
break;
case BERKENET:
(void) printf("%s:%s@%s",
target, remainder, addr->next_host);
break;
case DECNET:
(void) printf("%s::%s@%s",
target, remainder, addr->next_host);
break;
case PCT_MAILBOX:
(void) printf("%s%%%s@%s",
remainder, target, addr->next_host);
break;
case LOCAL:
(void) printf("%s@%s", remainder, addr->next_host);
break;
}
}
if (show_transport && addr->transport) {
printf("\tusing %s", addr->transport->name);
}
putchar('\n');
}
/*
* optto - return more optimal paths to the given addresses.
*/
/*ARGSUSED*/
void
optto(argv)
char **argv; /* generally, argv from main */
{
(void) fprintf(stderr, "%s: optto not currently supported\n", program);
exit(EX_UNAVAILABLE);
}
/*
* uupath - return paths to the given host.
*/
void
uupath(argv)
char **argv; /* generally, argv from main */
{
struct addr *addr;
char *error;
for (argv = pathto_setup(argv, "vst", uupath_usage); *argv; argv++) {
char *host_path = build_uucp_route(*argv, &error);
char *in_addr;
if (host_path == NULL) {
(void) fprintf(stderr, "%s: %s: %s\n", program, *argv, error);
continue;
}
in_addr = xmalloc(strlen(host_path) + sizeof("!~~user~~"));
(void) sprintf(in_addr, "%s!~~user~~", host_path);
if ((addr = pathto_route(in_addr, &error)) == NULL) {
if (error) {
(void) fprintf(stderr, "%s: %s: %s\n", program, *argv, error);
}
continue;
}
if (addr->next_host == NULL) {
(void) printf("%%s\n");
} else {
char *last_part;
char *path = build_uucp_route(addr->next_addr, &error);
if (path == NULL) {
(void) fprintf(stderr, "%s: %s: %s\n",
program, *argv, error);
} else {
last_part = rindex(path, '!');
if (last_part == NULL) {
(void) printf("%s", addr->next_host);
} else {
*last_part = '\0'; /* chop off the ~~user~~ */
(void) printf("%s!%s", addr->next_host, path);
}
if (show_transport && addr->transport) {
printf("\tusing %s", addr->transport->name);
}
putchar('\n');
}
}
}
exit(EX_OK);
}
/*
* pathto_setup - standard setup for the various pathto routines
*/
static char **
pathto_setup(argv, oargs, usage)
char **argv;
char *oargs;
void (*usage)();
{
char *error;
int argc;
extern char *optarg;
extern int optind, opterr;
int c;
/* handle relative configuration file names */
config_file = make_lib_fn(config_file);
/* read in the config and secondary config files */
if ((error = read_config_file(config_file)) ||
(second_config_file &&
(error = read_config_file(make_lib_fn(second_config_file)))))
{
panic(EX_OSFILE, "%s", error);
}
/* do the same thing with other variables */
director_file = make_lib_fn(director_file);
router_file = make_lib_fn(router_file);
transport_file = make_lib_fn(transport_file);
method_dir = make_lib_fn(method_dir);
copying_file = make_lib_fn(copying_file);
smail = make_lib_fn(smail);
/* read the other configuration files */
if ((error = read_transport_file()) ||
(error = read_router_file()) ||
(error = read_director_file()))
{
panic(EX_OSFILE, "%s", error);
}
/* All errors go to the terminal */
error_processing = TERMINAL;
--argv; /* go back to program name */
initialize_state();
/* count arguments, why does getopt really need this? */
for (argc = 0; argv[argc]; argc++) ;
disable_smarthost = TRUE;
bang_paths_only = TRUE;
direct_and_route = FALSE;
show_transport = FALSE;
while ((c = getopt(argc, argv, oargs)) != EOF) {
switch (c) {
case 'd':
direct_and_route = TRUE;
break;
case 'n':
bang_paths_only = FALSE;
break;
case 't':
show_transport = TRUE;
break;
case 's':
disable_smarthost = FALSE;
break;
case 'v':
debug = 1; /* turn on debugging */
break;
default:
(*usage)();
exit(EX_USAGE);
}
}
if (argv[optind] == NULL) {
(*usage)();
exit(EX_USAGE);
}
/* setup all of the hostname information */
build_host_strings();
return &argv[optind];
}
static struct addr *
pathto_route(in_addr, error)
char *in_addr;
char **error;
{
struct addr *cur = alloc_addr();
struct addr *defer = NULL;
struct addr *fail = NULL;
struct addr *done = NULL;
int form;
cur->in_addr = in_addr;
if (disable_smarthost) {
/*
* state we have already used the smarthost router to
* prevent its being used at all
*/
cur->flags |= ADDR_SMARTHOST;
}
if ((cur->work_addr = preparse_address(in_addr, error)) == NULL) {
return NULL;
}
while (cur &&
(form = parse_address(cur->work_addr, &cur->target,
&cur->remainder)
) != FAIL && form != PARSE_ERROR && form != LOCAL)
{
struct addr *retry;
cur->flags &= ~ADDR_FORM_MASK;
cur->flags |= form;
if (islocalhost(cur->target)) {
cur->work_addr = cur->remainder;
continue;
}
done = NULL;
defer = NULL;
fail = NULL;
retry = NULL;
route_remote_addrs(cur, &done, &retry, &defer, &fail);
cur = retry;
}
/* note if route_remote_addrs returned an error */
if (defer) {
*error = defer->error->message;
return NULL;
}
if (fail) {
*error = fail->error->message;
return NULL;
}
/* nope, no error from route_remote_addrs */
switch (form) {
case PARSE_ERROR:
case FAIL:
*error = cur->remainder;
return NULL;
break;
case LOCAL:
cur->next_host = NULL;
break;
default:
if (done) {
cur = done;
} else {
*error = NULL;
return NULL;
}
break;
}
return cur;
}
static void
pathto_usage()
{
(void) fprintf(stderr, "usage: %s [-vdsnt] addr ...\n", program);
}
static void
uupath_usage()
{
(void) fprintf(stderr, "usage: %s [-vst] addr ...\n", program);
}