home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / smail-3.1.28 / pd / pathalias / printit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-03  |  6.8 KB  |  329 lines

  1. /* Smail SCCS ID: @(#)pd/pathalias/printit.c    1.3 %G 00:43:43 */
  2. /* pathalias -- by steve bellovin, as told to peter honeyman */
  3. #ifndef lint
  4. static char    *sccsid = "@(#)printit.c    9.4 89/02/07";
  5. #endif
  6.  
  7. #include "def.h"
  8.  
  9. /*
  10.  * print the routes by traversing the shortest path tree in preorder.
  11.  * use lots of char bufs -- profiling indicates this costs about 5 kbytes
  12.  */
  13.  
  14. /* exports */
  15. extern void printit();
  16.  
  17. /* imports */
  18. extern int Cflag, Vflag, Dflag, Fflag;
  19. extern node *Home;
  20. extern char *Netchars;
  21. extern void die();
  22. #ifndef SMAIL_3
  23. extern int strlen();
  24. #endif
  25.  
  26. /* privates */
  27. static link *Ancestor;    /* for -f option */
  28. STATIC void preorder(), setpath(), printhost(), printdomain();
  29. STATIC char *hostpath();
  30. STATIC int printable();
  31.  
  32. /* in practice, even the longest paths are < 100 bytes */
  33. #define PATHSIZE 512
  34.  
  35. void
  36. printit()
  37. {    link *l;
  38.     char pbuf[PATHSIZE];
  39.  
  40.     /* print home */
  41.     if (Cflag)
  42.         printf("%ld\t", (long) Home->n_cost);
  43.     printf("%s\t%%s\n", Home->n_name);
  44.     
  45.     strcpy(pbuf, "%s");
  46.     for (l = Home->n_link; l; l = l->l_next) {
  47.         if (l->l_flag & LTREE) {
  48.             l->l_flag &= ~LTREE;
  49.             Ancestor = l;
  50.             preorder(l, pbuf);
  51.             strcpy(pbuf, "%s");
  52.         }
  53.     }
  54.     fflush(stdout);
  55.     fflush(stderr);
  56. }
  57.  
  58. /*
  59.  * preorder traversal of shortest path tree.
  60.  */
  61. STATIC void
  62. preorder(l, ppath)
  63.     register link *l;
  64.     char *ppath;
  65. {    register node *n;
  66.     node *ncp;        /* circular copy list */
  67.     Cost cost;
  68.     char npath[PATHSIZE];
  69.     short p_dir;        /* DIR bits of parent (for nets) */
  70.     char p_op;        /* net op of parent (for nets) */
  71.  
  72.     setpath(l, ppath, npath);
  73.     n = l->l_to;
  74.     if (printable(n)) {
  75.         if (Fflag)
  76.             cost = Ancestor->l_to->n_cost;
  77.         else
  78.             cost = n->n_cost;
  79.         if (ISADOMAIN(n))
  80.             printdomain(n, npath, cost);
  81.         else if (!(n->n_flag & NNET)) {
  82.             printhost(n, npath, cost);
  83.         }
  84.         n->n_flag |= PRINTED;
  85.         for (ncp = n->n_copy; ncp != n; ncp = ncp->n_copy)
  86.             ncp->n_flag |= PRINTED;
  87.     }
  88.  
  89.     /* prepare routing bits for domain members */
  90.     p_dir = l->l_flag & LDIR;
  91.     p_op = l->l_netop;
  92.  
  93.     /* recursion */
  94.     for (l = n->n_link; l; l = l->l_next) {
  95.         if (!(l->l_flag & LTREE))
  96.             continue;
  97.         /* network member inherits the routing syntax of its gateway */
  98.         if (ISANET(n)) {
  99.             l->l_flag = (l->l_flag & ~LDIR) | p_dir;
  100.             l->l_netop = p_op;
  101.         }
  102.         l->l_flag &= ~LTREE;
  103.         preorder(l, npath);
  104.     }
  105. }
  106.  
  107. STATIC int
  108. printable(n)
  109.     register node *n;
  110. {    node *ncp;
  111.     link *l;
  112.  
  113.     if (n->n_flag & PRINTED)
  114.         return 0;
  115.  
  116.     /* is there a cheaper copy? */
  117.     for (ncp = n->n_copy; n != ncp; ncp = ncp->n_copy) {
  118.         if (!(ncp->n_flag & MAPPED))
  119.             continue;    /* unmapped copy */
  120.  
  121.         if (n->n_cost > ncp->n_cost)
  122.             return 0;    /* cheaper copy */
  123.  
  124.         if (n->n_cost == ncp->n_cost && !(ncp->n_flag & NTERMINAL))
  125.             return 0;    /* synthetic copy */
  126.     }
  127.  
  128.     /* will a domain route suffice? */
  129.     if (Dflag && !ISANET(n) && ISADOMAIN(n->n_parent)) {
  130.         /*
  131.          * are there any interesting links?  a link
  132.          * is interesting if it doesn't point back
  133.          * to the parent, and is not an alias.
  134.          */
  135.  
  136.         /* check n */
  137.         for (l = n->n_link; l; l = l->l_next) {
  138.             if (l->l_to == n->n_parent)
  139.                 continue;
  140.             if (!(l->l_flag & LALIAS))
  141.                 return 1;
  142.         }
  143.  
  144.         /* check copies of n */
  145.         for (ncp = n->n_copy; ncp != n; ncp = ncp->n_copy) {
  146.             for (l = ncp->n_link; l; l = l->l_next) {
  147.                 if (l->l_to == n->n_parent)
  148.                     continue;
  149.                 if (!(l->l_flag & LALIAS))
  150.                     return 1;
  151.             }
  152.         }
  153.  
  154.         /* domain route suffices */
  155.         return 0;
  156.     }
  157.     return 1;
  158. }
  159.  
  160. STATIC void
  161. setpath(l, ppath, npath) 
  162.     link *l;
  163.     register char *ppath, *npath;
  164. {    register node *next, *parent;
  165.     char netchar;
  166.  
  167.     next = l->l_to;
  168.     parent = next->n_parent;
  169.     netchar = NETCHAR(l);
  170.  
  171.     /* for magic @->% conversion */
  172.     if (parent->n_flag & ATSIGN)
  173.         next->n_flag |= ATSIGN;
  174.  
  175.     /*
  176.      * i've noticed that distant gateways to domains frequently get
  177.      * ...!gateway!user@dom.ain wrong.  ...!gateway!user%dom.ain
  178.      * seems to work, so if next is a domain and the parent is
  179.      * not the local host, force a magic %->@ conversion.  in this
  180.      * context, "parent" is the nearest ancestor that is not a net.
  181.      */
  182.     while (ISANET(parent))
  183.         parent = parent->n_parent;
  184.     if (ISADOMAIN(next) && parent != Home)
  185.         next->n_flag |= ATSIGN;
  186.  
  187.     /*
  188.      * special handling for nets (including domains) and aliases.
  189.      * part of the trick is to treat aliases to domains as 0 cost
  190.      * links.  (the author believes they should be declared as such
  191.      * in the input, but the world disagrees).
  192.      */
  193.     if (ISANET(next) || ((l->l_flag & LALIAS) && !ISADOMAIN(parent))) {
  194.         strcpy(npath, ppath);
  195.         return;
  196.     }
  197.         
  198.     if (netchar == '@')
  199.         if (next->n_flag & ATSIGN)
  200.             netchar = '%';    /* shazam?  shaman? */
  201.         else
  202.             next->n_flag |= ATSIGN;
  203.  
  204.     /* remainder should be a sprintf -- foo on '%' as an operator */
  205.     for ( ; (*npath = *ppath) != 0; ppath++) {
  206.         if (*ppath == '%') {
  207.             switch(ppath[1]) {
  208.             case 's':
  209.                 ppath++;
  210.                 npath = hostpath(npath, l, netchar);
  211.                 break;
  212.  
  213.             case '%':
  214.                 *++npath = *++ppath;
  215.                 npath++;
  216.                 break;
  217.  
  218.             default:
  219.                 die("unknown escape in setpath");
  220.                 break;
  221.             }
  222.         } else
  223.             npath++;
  224.     }
  225. }
  226.  
  227. STATIC char *
  228. hostpath(path, l, netchar)
  229.     register char *path;
  230.     register link *l;
  231.     char netchar;
  232. {    register node *prev;
  233.  
  234.     prev = l->l_to->n_parent;
  235.     if (NETDIR(l) == LLEFT) {
  236.         /* host!%s */
  237.         strcpy(path, l->l_to->n_name);
  238.         path += strlen(path);
  239.         while (ISADOMAIN(prev)) {
  240.             strcpy(path, prev->n_name);
  241.             path += strlen(path);
  242.             prev = prev->n_parent;
  243.         }
  244.         *path++ = netchar;
  245.         if (netchar == '%')
  246.             *path++ = '%';
  247.         *path++ = '%';
  248.         *path++ = 's';
  249.     } else {
  250.         /* %s@host */
  251.         *path++ = '%';
  252.         *path++ = 's';
  253.         *path++ = netchar;
  254.         if (netchar == '%')
  255.             *path++ = '%';
  256.         strcpy(path, l->l_to->n_name);
  257.         path += strlen(path);
  258.         while (ISADOMAIN(prev)) {
  259.             strcpy(path, prev->n_name);
  260.             path += strlen(path);
  261.             prev = prev->n_parent;
  262.         }
  263.     }
  264.     return path;
  265. }
  266.  
  267. STATIC void
  268. printhost(n, path, cost)
  269.     register node *n;
  270.     char *path;
  271.     Cost cost;
  272. {
  273.     if (n->n_flag & PRINTED)
  274.         die("printhost called twice");
  275.     n->n_flag |= PRINTED;
  276.     /* skip private hosts */
  277.     if ((n->n_flag & ISPRIVATE) == 0) {
  278.         if (Cflag)
  279.             printf("%ld\t", (long) cost);
  280.         fputs(n->n_name, stdout);
  281.         putchar('\t');
  282.         puts(path);
  283.     }
  284. }
  285.  
  286. STATIC void
  287. printdomain(n, path, cost)
  288.     register node *n;
  289.     char *path;
  290.     Cost cost;
  291. {    node *p;
  292.  
  293.     if (n->n_flag & PRINTED)
  294.         die("printdomain called twice");
  295.     n->n_flag |= PRINTED;
  296.  
  297.     /*
  298.      * print a route for dom.ain if it is a top-level domain, unless
  299.      * it is private.
  300.      *
  301.      * print a route for sub.dom.ain only if all its ancestor dom.ains
  302.      * are private and sub.dom.ain is not private.
  303.      */
  304.     if (!ISADOMAIN(n->n_parent)) {
  305.         /* top-level domain */
  306.         if (n->n_flag & ISPRIVATE) {
  307.             vprintf(stderr, "ignoring private top-level domain %s\n", n->n_name);
  308.             return;
  309.         }
  310.     } else {
  311.         /* subdomain */
  312.         for (p = n->n_parent; ISADOMAIN(p); p = p->n_parent)
  313.             if (!(p->n_flag & ISPRIVATE))
  314.                 return;
  315.         if (n->n_flag & ISPRIVATE)
  316.             return;
  317.     }
  318.  
  319.     /* print it (at last!) */
  320.     if (Cflag)
  321.         printf("%ld\t", (long) cost);
  322.     do {
  323.         fputs(n->n_name, stdout);
  324.         n = n->n_parent;
  325.     } while (ISADOMAIN(n));
  326.     putchar('\t');
  327.     puts(path);
  328. }
  329.