|
|
1.1 root 1: /* pathalias -- by steve bellovin, as told to peter honeyman */
2: #ifndef lint
3: static char *sccsid = "@(#)mapaux.c 8.2 (down!honey) 86/01/26";
4: #endif lint
5:
6: #include "def.h"
7:
8: void pack();
9:
10: void
11: pack()
12: {
13: long hole, next;
14:
15: /* find first "hole " */
16: for (hole = Tabsize - 1; hole >= 0 && Table[hole] != 0; --hole)
17: ;
18:
19: /* repeatedly move next filled entry into last hole */
20: for (next = hole - 1; next >= 0; --next) {
21: if (Table[next] != 0) {
22: Table[hole] = Table[next];
23: Table[hole]->n_tloc = hole;
24: Table[next] = 0;
25: while (Table[--hole] != 0) /* find next hole */
26: ;
27: }
28: }
29: Hashpart = hole + 1;
30: }
31:
32: FILE *Gstream;
33:
34: dumpgraph()
35: {
36: long i;
37: node *n;
38:
39: if ((Gstream = fopen(Graphout, "w")) == NULL) {
40: fprintf(stderr, "%s: ", ProgName);
41: perror(Graphout);
42: }
43:
44: untangle(); /* untangle net cycles for proper output */
45:
46: for (i = Hashpart; i < Tabsize; i++) {
47: n = Table[i];
48: if (n == 0)
49: continue; /* impossible, but ... */
50: /* a minor optimization ... */
51: if (n->n_link == 0)
52: continue;
53: /* pathparse doesn't need these */
54: if (n->n_flag & NNET)
55: continue;
56: dumpnode(n);
57: }
58: }
59:
60: dumpnode(from)
61: node *from;
62: {
63: node *to;
64: link *l;
65: char netbuf[BUFSIZ], *nptr = netbuf;
66:
67: for (l = from->n_link ; l; l = l->l_next) {
68: to = l->l_to;
69: if (from == to)
70: continue; /* oops -- it's me! */
71:
72: if ((to->n_flag & NNET) == 0) {
73: /* host -> host -- print host>host */
74: if (l->l_cost == INF)
75: continue; /* phoney link */
76: fputs(from->n_name, Gstream);
77: putc('>', Gstream);
78: fputs(to->n_name, Gstream);
79: putc('\n', Gstream);
80: } else {
81: /* host -> net -- just cache it for now */
82: while (to->n_root && to != to->n_root)
83: to = to->n_root;
84: *nptr++ = ',';
85: strcpy(nptr, to->n_name);
86: nptr += strlen(nptr);
87: }
88: }
89:
90: /* dump nets */
91: if (nptr != netbuf) {
92: /* nets -- print host@\tnet,net, ... */
93: *nptr = 0;
94: fputs(from->n_name, Gstream);
95: putc('@', Gstream);
96: *netbuf = '\t'; /* insert tab by killing initial ',' */
97: fputs(netbuf, Gstream); /* skip initial ',' */
98: putc('\n', Gstream);
99: }
100: }
101:
102: /*
103: * remove cycles in net definitions.
104: *
105: * depth-first search
106: *
107: * for each net, run dfs on its neighbors (nets only). if we return to
108: * a visited node, that's a net cycle. mark the cycle with a pointer
109: * in the n_root field (which gets us closer to the root of this
110: * portion of the dfs tree).
111: */
112: untangle()
113: {
114: long i;
115: node *n;
116:
117: for (i = Hashpart; i < Tabsize; i++) {
118: n = Table[i];
119: if (n == 0 || (n->n_flag & NNET) == 0 || n->n_root)
120: continue;
121: dfs(n);
122: }
123: }
124:
125: dfs(n)
126: node *n;
127: {
128: link *l;
129: node *next;
130:
131: n->n_flag |= INDFS;
132: n->n_root = n;
133: for (l = n->n_link; l; l = l->l_next) {
134: next = l->l_to;
135: if ((next->n_flag & NNET) == 0)
136: continue;
137: if ((next->n_flag & INDFS) == 0) {
138: dfs(next);
139: if (next->n_root != next)
140: n->n_root = next->n_root;
141: } else
142: n->n_root = next->n_root;
143: }
144: n->n_flag &= ~INDFS;
145: }
146:
147: showlinks()
148: {
149: link *l;
150: node *n;
151: long i;
152: FILE *estream;
153:
154: if ((estream = fopen(Linkout, "w")) == 0)
155: return;
156:
157: for (i = Hashpart; i < Tabsize; i++) {
158: n = Table[i];
159: if (n == 0) /* impossible, but ... */
160: continue;
161: if (l = n->n_link) {
162: fprintf(estream, "%s\t%s(%d)", n->n_name,
163: l->l_to->n_name,
164: l->l_cost ? l->l_cost : DEFCOST);
165: for (l = l->l_next; l; l = l->l_next)
166: fprintf(estream, ",\n\t%s(%d)", l->l_to->n_name,
167: l->l_cost ? l->l_cost : DEFCOST);
168: fputc('\n', estream);
169: }
170: }
171: (void) fclose(estream);
172: }
173:
174: /*
175: * n is node in heap, newp is candidate for new parent.
176: * choose between newp and n->n_parent for parent.
177: * return 0 to use newp, non-zero o.w.
178: */
179: #define NEWP 0
180: #define OLDP 1
181: tiebreaker(n, newp)
182: node *n, *newp;
183: {
184: register char *opname, *npname, *name;
185: node *oldp;
186: int metric;
187:
188: oldp = n->n_parent;
189:
190: /*
191: * given the choice, avoid gatewayed nets,
192: * thereby placating the FCC or some such.
193: */
194: if (GATEWAYED(newp) && !GATEWAYED(oldp))
195: return(OLDP);
196: if (!GATEWAYED(newp) && GATEWAYED(oldp))
197: return(NEWP);
198:
199: /* look at real parents, not nets */
200: while (oldp->n_flag & NNET)
201: oldp = oldp->n_parent;
202: while (newp->n_flag & NNET)
203: newp = newp->n_parent;
204:
205: /* use fewer hops, if possible */
206: metric = height(oldp) - height(newp);
207: if (metric < 0)
208: return(OLDP);
209: if (metric > 0)
210: return(NEWP);
211:
212: /* compare names */
213: opname = oldp->n_name;
214: npname = newp->n_name;
215: name = n->n_name;
216:
217: /* find point of departure */
218: while (*opname == *npname && *npname == *name) {
219: if (*name == 0) {
220: fprintf(stderr, "%s: error in tie breaker\n", ProgName);
221: badmagic(1);
222: }
223: opname++;
224: npname++;
225: name++;
226: }
227:
228: /* use longest match, if appl. */
229: if (*opname == *name || *opname == 0)
230: return(OLDP);
231: if (*npname == *name || *npname == 0)
232: return(NEWP);
233:
234: /* use shorter host name, if appl. */
235: metric = strlen(opname) - strlen(npname);
236: if (metric < 0)
237: return(OLDP);
238: if (metric > 0)
239: return(NEWP);
240:
241: /* use larger lexicographically (no reason) */
242: metric = strcmp(opname, npname);
243: if (metric < 0)
244: return(NEWP);
245: return(OLDP);
246: }
247:
248: height(n)
249: register node *n;
250: {
251: register int i = 0;
252:
253: while ((n = n->n_parent) != 0)
254: if ((n->n_flag & NNET) == 0)
255: i++; /* should count domains too ... */
256: return(i);
257: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.