home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / contrib / smail / smail-3.1 / smail-3 / smail-3.1.28 / src / pathto.c < prev    next >
C/C++ Source or Header  |  1992-09-18  |  10KB  |  443 lines

  1. /* @(#)src/pathto.c    1.8 9/18/92 06:49:20 */
  2.  
  3. /*
  4.  *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
  5.  *    Copyright (C) 1992  Ronald S. Karr
  6.  * 
  7.  * See the file COPYING, distributed with smail, for restriction
  8.  * and warranty information.
  9.  */
  10.  
  11. /*
  12.  * main.c:
  13.  *    process arguments, configure environment and process
  14.  *    messages.
  15.  *
  16.  *    external functions: main, initialize_state, process_args,
  17.  *    deliver_mail
  18.  */
  19. #include <stdio.h>
  20. #include "defs.h"
  21. #include "smail.h"
  22. #include "main.h"
  23. #include "transport.h"
  24. #include "addr.h"
  25. #include "exitcodes.h"
  26. #ifndef DEPEND
  27. # include "error.h"
  28. # include "extern.h"
  29. #endif
  30.  
  31. /* variables local to this file */
  32. static int bang_paths_only;
  33. static int disable_smarthost;
  34. static int direct_and_route;
  35. static int show_transport;
  36.  
  37. /* functions local to this file */
  38. static void print_pathto_addr();
  39. static void pathto_direct_and_route();
  40. static char **pathto_setup();
  41. static struct addr *pathto_route();
  42. static void pathto_usage();
  43. static void uupath_usage();
  44.  
  45. /*
  46.  * pathto - return paths to the given addresses.
  47.  */
  48. void
  49. pathto(argv)
  50.     char **argv;            /* generally, argv from main */
  51. {
  52.     struct addr *addr;
  53.     char *error;
  54.  
  55.     argv = pathto_setup(argv, "vdnstD:", pathto_usage);
  56.     if (direct_and_route) {
  57.     struct addr *okay;        /* list of routed addrs */
  58.     struct addr *defer;        /* list of temp failed addrs */
  59.     struct addr *fail;        /* list of failed addrs */
  60.  
  61.     pathto_direct_and_route(argv, &okay, &defer, &fail);
  62.     while (defer) {
  63.         if (defer->error->info&ERR_CONFERR) {
  64.         (void) fprintf(stderr, "%s: %s ... config error: %s\n",
  65.                    program, defer->in_addr,
  66.                    defer->error->message);
  67.         } else {
  68.         (void) fprintf(stderr, "%s: %s ... temp error: %s\n",
  69.                    program, defer->in_addr,
  70.                    defer->error->message);
  71.         }
  72.         defer = defer->succ;
  73.     }
  74.     while (fail) {
  75.         (void) fprintf(stderr, "%s: %s ... failed: %s\n",
  76.                program, fail->in_addr, fail->error->message);
  77.         fail = fail->succ;
  78.     }
  79.     while (okay) {
  80.         print_pathto_addr(okay);
  81.         okay = okay->succ;
  82.     }
  83.     } else {
  84.     for (; *argv; argv++) {
  85.         if ((addr = pathto_route(*argv, &error)) == NULL) {
  86.         if (error) {
  87.             (void) fprintf(stderr, "%s: %s: %s\n",
  88.                    program, *argv, error);
  89.         }
  90.         continue;
  91.         } else {
  92.         if (addr->next_host == NULL) {
  93.             addr->next_addr = addr->remainder;
  94.         }
  95.         print_pathto_addr(addr);
  96.         }
  97.     }
  98.     }
  99.  
  100.     exit(EX_OK);
  101. }
  102.  
  103. /*
  104.  * pathto_direct_and_route - take an array of address strings and
  105.  *                 return a list of resolved addresses
  106.  */
  107. static void
  108. pathto_direct_and_route(addr_strings, okay, defer, fail)
  109.     char **addr_strings;        /* input address strings */
  110.     struct addr **okay;            /* successfully routed addrs */
  111.     struct addr **defer;        /* temp routing failures */
  112.     struct addr **fail;            /* unresolvable addrs */
  113. {
  114.     register struct addr *addr = NULL;
  115.  
  116.     *okay = NULL;
  117.     *defer = NULL;
  118.     *fail = NULL;
  119.     while (*addr_strings) {
  120.     register struct addr *new = alloc_addr();
  121.     char *error;
  122.  
  123.     new->in_addr = *addr_strings;
  124.     new->work_addr = preparse_address(new->in_addr, &error);
  125.     if (new->work_addr == NULL) {
  126.         new->error = note_error(ERR_111,
  127.                     xprintf("parse error: %s", error));
  128.         new->succ = *fail;
  129.         *fail = new;
  130.     } else {
  131.         if (disable_smarthost) {
  132.         new->flags |= ADDR_SMARTUSER|ADDR_SMARTHOST;
  133.         }
  134.         new->succ = addr;
  135.         addr = new;
  136.     }
  137.     addr_strings++;
  138.     }
  139.  
  140.     /* resolve all of the addresses, removing duplicates */
  141.     resolve_addr_list(addr, okay, defer, fail, TRUE);
  142. }
  143.  
  144. /*
  145.  * print_pathto_addr - output the given addr structure as an address
  146.  */
  147. static void
  148. print_pathto_addr(addr)
  149.     register struct addr *addr;
  150. {
  151.     if (show_transport) {
  152.     printf("%-11s ", addr->transport? addr->transport->name: "local");
  153.     }
  154.     if (addr->next_host == NULL) {
  155.     if (direct_and_route) {
  156.         (void) printf("%s\n", addr->next_addr);
  157.     } else if (bang_paths_only) {
  158.         (void) printf("%s!%s\n", uucp_name, addr->next_addr);
  159.     } else {
  160.         (void) printf("%s@%s\n", addr->next_addr, primary_name);
  161.     }
  162.     } else if (bang_paths_only) {
  163.     char *error;
  164.     char *path = build_uucp_route(addr->next_addr, &error,
  165.                       addr->parseflags);
  166.  
  167.     if (path == NULL) {
  168.         putchar('\n');
  169.         (void) fprintf(stderr, "%s: %s: %s\n",
  170.                program, addr->in_addr, error);
  171.         return;
  172.     } else {
  173.         (void) printf("%s!%s\n", addr->next_host, path);
  174.     }
  175.     } else {
  176.     printf("%s :: %s\n", addr->next_host, addr->next_addr);
  177.     }
  178.     return;
  179. }
  180.  
  181. /*
  182.  * optto - return more optimal paths to the given addresses.
  183.  */
  184. /*ARGSUSED*/
  185. void
  186. optto(argv)
  187.     char **argv;            /* generally, argv from main */
  188. {
  189.     (void) fprintf(stderr, "%s: optto not currently supported\n", program);
  190.     exit(EX_UNAVAILABLE);
  191. }
  192.  
  193. /*
  194.  * uupath - return paths to the given host.
  195.  */
  196. void
  197. uupath(argv)
  198.     char **argv;            /* generally, argv from main */
  199. {
  200.     struct addr *addr;
  201.     char *error;
  202.  
  203.     for (argv = pathto_setup(argv, "vstD:", uupath_usage); *argv; argv++) {
  204.     char *host_path = build_uucp_route(*argv, &error, 0);
  205.     char *in_addr;
  206.  
  207.     if (host_path == NULL) {
  208.         (void) fprintf(stderr, "%s: %s: %s\n", program, *argv, error);
  209.         continue;
  210.     }
  211.     in_addr = xmalloc(strlen(host_path) + sizeof("!~~user~~"));
  212.     (void) sprintf(in_addr, "%s!~~user~~", host_path);
  213.     if ((addr = pathto_route(in_addr, &error)) == NULL) {
  214.         if (error) {
  215.         (void) fprintf(stderr, "%s: %s: %s\n", program, *argv, error);
  216.         }
  217.         continue;
  218.     }
  219.     if (show_transport) {
  220.         printf("%-11s ", addr->transport? addr->transport->name: "local");
  221.     }
  222.     if (addr->next_host == NULL) {
  223.         (void) printf("%%s\n");
  224.     } else {
  225.         char *last_part;
  226.         char *path = build_uucp_route(addr->next_addr, &error,
  227.                       addr->parseflags);
  228.  
  229.         if (path == NULL) {
  230.         (void) fprintf(stderr, "%s: %s: %s\n",
  231.                    program, *argv, error);
  232.         } else {
  233.         last_part = rindex(path, '!');
  234.         if (last_part == NULL) {
  235.             (void) printf("%s\n", addr->next_host);
  236.         } else {
  237.             *last_part = '\0';    /* chop off the ~~user~~ */
  238.             (void) printf("%s!%s\n", addr->next_host, path);
  239.         }
  240.         }
  241.     }
  242.     }
  243.  
  244.     exit(EX_OK);
  245. }
  246.  
  247. /*
  248.  * pathto_setup - standard setup for the various pathto routines
  249.  */
  250. static char **
  251. pathto_setup(argv, oargs, usage)
  252.     char **argv;
  253.     char *oargs;
  254.     void (*usage)();
  255. {
  256.     char *error;
  257.     int argc;
  258.     extern char *optarg;
  259.     extern int optind, opterr;
  260.     int c;
  261.     char **argp;
  262.  
  263.     /* handle relative configuration file names */
  264.     config_file = make_lib_fn(config_file);
  265.  
  266.     /* read in the config and secondary config files */
  267.     if ((error = read_config_file(config_file)) ||
  268.     (second_config_file &&
  269.        (error = read_config_file(make_lib_fn(second_config_file)))))
  270.     {
  271.     panic(EX_OSFILE, "%s", error);
  272.     }
  273.  
  274.     /* do the same thing with other variables */
  275.     director_file = make_lib_fn(director_file);
  276.     router_file = make_lib_fn(router_file);
  277.     transport_file = make_lib_fn(transport_file);
  278.     method_dir = make_lib_fn(method_dir);
  279.     copying_file = make_lib_fn(copying_file);
  280.     smail = make_lib_fn(smail);
  281.  
  282.     /* read the other configuration files */
  283.     if ((error = read_transport_file()) ||
  284.     (error = read_router_file()) ||
  285.     (error = read_director_file()))
  286.     {
  287.     panic(EX_OSFILE, "%s", error);
  288.     }
  289.  
  290.     /* All errors go to the terminal */
  291.     error_processing = TERMINAL;
  292.  
  293.     --argv;                /* go back to program name */
  294.     initialize_state();
  295.  
  296.     /* count arguments, why does getopt really need this? */
  297.     for (argc = 0; argv[argc]; argc++) ;
  298.  
  299.     disable_smarthost = TRUE;
  300.     bang_paths_only = TRUE;
  301.     direct_and_route = FALSE;
  302.     show_transport = FALSE;
  303.  
  304.     while ((c = getopt(argc, argv, oargs)) != EOF) {
  305.     switch (c) {
  306.  
  307.     case 'd':
  308.         direct_and_route = TRUE;
  309.         break;
  310.  
  311.     case 'n':
  312.         bang_paths_only = FALSE;
  313.         break;
  314.  
  315.     case 't':
  316.         show_transport = TRUE;
  317.         break;
  318.  
  319.     case 's':
  320.         disable_smarthost = FALSE;
  321.         break;
  322.  
  323.     case 'v':
  324.         if (! debug)
  325.         debug = 1;        /* turn on debugging */
  326.         break;
  327.  
  328.     case 'D':
  329.         debug = atoi(optarg);    /* set debugging level */
  330.         break;
  331.  
  332.     default:
  333.         (*usage)();
  334.         exit(EX_USAGE);
  335.     }
  336.     }
  337.  
  338.     if (argv[optind] == NULL) {
  339.     (*usage)();
  340.     exit(EX_USAGE);
  341.     }
  342.  
  343.     for (argp = &argv[optind]; *argp; argp++) {
  344.     strip_rfc822_comments(*argp);
  345.     }
  346.  
  347.     /* setup all of the hostname information */
  348.     build_host_strings();
  349.  
  350.     return &argv[optind];
  351. }
  352.  
  353. static struct addr *
  354. pathto_route(in_addr, error)
  355.     char *in_addr;
  356.     char **error;
  357. {
  358.     struct addr *cur = alloc_addr();
  359.     struct addr *defer = NULL;
  360.     struct addr *fail = NULL;
  361.     struct addr *done = NULL;
  362.     int form;
  363.  
  364.     cur->in_addr = in_addr;
  365.     if (disable_smarthost) {
  366.         /*
  367.          * state we have already used the smarthost router to
  368.          * prevent its being used at all
  369.          */
  370.         cur->flags |= ADDR_SMARTHOST;
  371.     }
  372.     if ((cur->work_addr = preparse_address(in_addr, error)) == NULL) {
  373.     return NULL;
  374.     }
  375.  
  376.     while (cur &&
  377.        (form = parse_address(cur->work_addr, &cur->target,
  378.                  &cur->remainder, &cur->parseflags)
  379.         ) != FAIL && form != PARSE_ERROR && form != LOCAL)
  380.     {
  381.     struct addr *retry;
  382.  
  383.     cur->flags &= ~ADDR_FORM_MASK;
  384.     cur->flags |= form;
  385.  
  386.     if (islocalhost(cur->target)) {
  387.         cur->work_addr = cur->remainder;
  388.         continue;
  389.     }
  390.     done = NULL;
  391.     defer = NULL;
  392.     fail = NULL;
  393.     retry = NULL;
  394.     route_remote_addrs(cur, &done, &retry, &defer, &fail);
  395.     cur = retry;
  396.     }
  397.  
  398.     /* note if route_remote_addrs returned an error */
  399.     if (defer) {
  400.     *error = defer->error->message;
  401.     return NULL;
  402.     }
  403.     if (fail) {
  404.     *error = fail->error->message;
  405.     return NULL;
  406.     }
  407.  
  408.     /* nope, no error from route_remote_addrs */
  409.     switch (form) {
  410.     case PARSE_ERROR:
  411.     case FAIL:
  412.     *error = cur->remainder;
  413.     return NULL;
  414.  
  415.     case LOCAL:
  416.     cur->next_host = NULL;
  417.     break;
  418.  
  419.     default:
  420.     if (done) {
  421.         cur = done;
  422.     } else {
  423.         *error = NULL;
  424.         return NULL;
  425.     }
  426.     break;
  427.     }
  428.  
  429.     return cur;
  430. }
  431.  
  432. static void
  433. pathto_usage()
  434. {
  435.     (void) fprintf(stderr, "usage: %s [-vdsnt] addr ...\n", program);
  436. }
  437.  
  438. static void
  439. uupath_usage()
  440. {
  441.     (void) fprintf(stderr, "usage: %s [-vst] addr ...\n", program);
  442. }
  443.