|
|
1.1 root 1: #include "stdio.h"
2: #include "sys/param.h"
3: #include "sys/stat.h"
4: #include "sys/neta.h"
5: #include "errno.h"
6: #include "sys/ioctl.h"
7: #include "signal.h"
8: #include "setjmp.h"
9:
10: #define RMFSTYP 1 /* file system type for remote file system */
11:
12: struct friend {
13: char *who;
14: char *mount;
15: int dev;
16: int silent;
17: int status;
18: int chan;
19: } friends[NOFILE];
20: int nfriends;
21: #define DEAD 0
22: #define OK 1
23: #define PROBE 2
24: #define KILL 3
25:
26: char *states[] = { "dead", "ok", "probe", "kill", "?"};
27:
28: struct senda x;
29: struct rcva y;
30: extern int errno;
31: extern char *ctime();
32: extern char *malloc();
33: struct stat stb;
34: long looked;
35: jmp_buf jmpbuf;
36:
37: main()
38: { int i;
39: /* any signal but SIGALRM (14) will start it over. SIGALRM is used to
40: * interrupt hung reads. SIGCHLD is ignored too */
41: sigalrm(0);
42: if(setjmp(jmpbuf) == 1)
43: rdfile();
44: else
45: sigcatch();
46: probe();
47: }
48: sigalrm(n)
49: {
50: fprintf(stderr, "sigalrm %d\n", n);
51: fflush(stderr);
52: if(n == SIGALRM || n == 0) /* otherwise might get SIGCHLD in sleep */
53: signal(SIGALRM, sigalrm);
54: signal(SIGCHLD, sigalrm);
55: }
56: sigcatch(n)
57: { int i;
58: for(i = 1; i < NSIG; i++)
59: if(i != SIGALRM && i != SIGCHLD) /* alarm and tdkdial */
60: (void) signal(i, sigcatch);
61: fprintf(stderr, "sigcatch %d\n", n);
62: fflush(stderr);
63: switch(i) {
64: case SIGILL: case SIGBUS: case SIGSEGV:
65: restart();
66: }
67: longjmp(jmpbuf, 1);
68: }
69: restart()
70: {
71: fprintf(stderr, "execing\n");
72: fflush(stderr);
73: execl("/etc/net/setup", "setup", 0);
74: execl("/usr/net/setup", "setup", 0);
75: /* if that doesn't work */
76: fprintf(stderr, "oops, calling main\n");
77: fflush(stderr);
78: main(); /* ho ho */
79: }
80: probe()
81: { int i;
82: static int lastdone;
83: long now;
84: loop:
85: if(lastdone >= nfriends) {
86: lastdone = 0;
87: sleep(30);
88: if(stat("/etc/net/friends", &stb) == 0 && stb.st_mtime > looked)
89: rdfile();
90: if(stat("/usr/net/friends", &stb) == 0 && stb.st_mtime > looked)
91: rdfile();
92: if(time((long *)0) > looked + 1200)
93: rdfile();
94: }
95: i = lastdone++;
96: switch(friends[i].status) {
97: default:
98: break;
99: case PROBE:
100: case OK:
101: friends[i].status++;
102: doprobe(friends + i);
103: if(friends[i].status != OK) {
104: now = time(0);
105: fprintf(stderr, "hmm %s %s %s\n", friends[i].who,
106: states[friends[i].status], ctime(&now));
107: }
108: break;
109: case KILL: /* over the limit */
110: now = time(0);
111: fprintf(stderr, "%s timed out %s 0x%x %s", friends[i].who,
112: states[friends[i].status], friends[i].chan, ctime(&now));
113: errno = 0;
114: gmount(RMFSTYP, friends[i].dev, 1, 0, 0);
115: if(errno == 0 || errno == EINVAL) {
116: friends[i].status = DEAD;
117: fprintf(stderr, "dead now\n");
118: }
119: else
120: perror("xmount");
121: break;
122: }
123: goto loop;
124: }
125: doprobe(x)
126: struct friend *x;
127: { struct stat stb;
128: if(stat(x->mount, &stb) == 0 && stb.st_dev == x->dev)
129: x->status = OK;
130: }
131: startup(p)
132: struct friend *p;
133: { int fd, i;
134: char version;
135: fd = callfs(p->who);
136: if(fd < 0) {
137: fprintf(stderr, "callfs %s failed\n", p->who);
138: return;
139: }
140: (void) fstat(fd, &stb);
141: fprintf(stderr, "starting %s (0x%x)", p->who, stb.st_rdev);
142: gmount(RMFSTYP, p->dev, 1, 0, 0); /* just in case */
143: perror("xunmount");
144: x.trannum = 0;
145: version = x.version = NETVERSION;
146: x.cmd = NSTART;
147: x.uid = p->silent;
148: x.dev = p->dev;
149: alarm(30);
150: x.ta = time(0);
151: if((write(fd, &version, 1) != 1) || write(fd, (char *)&x, sizeof(x))
152: != sizeof(x)) {
153: perror("write in setup");
154: fprintf(stderr, "%s\n", p->who);
155: close(fd);
156: alarm(0);
157: return;
158: }
159: if((i = read(fd, (char *)&y, sizeof(y))) != sizeof(y)) {
160: if(y.trannum == -1)
161: fprintf(stderr, "version mismatch %s\n", p->who);
162: else {
163: fprintf(stderr, "read %d chars for %s\n", i, p->who);
164: perror((char *)&y);
165: }
166: close(fd);
167: return;
168: }
169: alarm(0);
170: if(y.errno != 0) {
171: errno = y.errno;
172: perror("nak in setup");
173: close(fd);
174: return;
175: }
176: if(gmount(RMFSTYP, p->dev, 0, fd, p->mount) != 0) {
177: perror("xmount");
178: fprintf(stderr, "unmounting it\n"); /* garbage collection*/
179: gmount(RMFSTYP, p->dev, 1, 0, 0);
180: perror("xunmount");
181: close(fd);
182: /* and try again later */
183: return;
184: }
185: p->status = OK;
186: fprintf(stderr, "started %s on %s dev %d silent %d chan 0x%x\n", p->who,
187: p->mount, p->dev/256, p->silent, p->chan = stb.st_rdev);
188: close(fd);
189: }
190:
191: #define skip for(; *p == ' ' || *p == '\t'; p++)
192: #define note for(s = p; *p != ' ' && *p != '\t' && *p != '\n'; p++)
193: struct friend *
194: cnvt(s)
195: char *s;
196: { static struct friend x;
197: char *p;
198: s[strlen(s)] = '\n';
199: p = s;
200: skip;
201: if(*p == '\n') {
202: x.who = "#";
203: return(&x);
204: }
205: note;
206: if(*p == '\n')
207: return(0);
208: *p++ = 0;
209: x.who = malloc(strlen(s) + 1);
210: strcpy(x.who, s);
211: s = p;
212: skip;
213: note;
214: if(*p == '\n')
215: return(0);
216: *p++ = 0;
217: x.mount = malloc(strlen(s) + 1);
218: strcpy(x.mount, s);
219: s = p;
220: skip;
221: note;
222: if(*p == '\n')
223: return(0);
224: *p++ = 0;
225: x.dev = 256 * atoi(s);
226: s = p;
227: skip;
228: note;
229: *p++ = 0;
230: x.silent = atoi(s);
231: x.status = DEAD;
232: return(&x);
233: }
234:
235: rdfile()
236: { FILE *fd;
237: int i;
238: char line[128];
239: struct friend *p;
240: alarm(0); /* disable the sleep in probe */
241: fd = fopen("/etc/net/friends", "r");
242: if(fd == NULL) {
243: fd = fopen("/usr/net/friends","r");
244: if(fd == NULL) {
245: perror("friends");
246: exit(1);
247: }
248: }
249: for(;;) {
250: onward:
251: (void) fgets(line, sizeof(line), fd);
252: if(feof(fd))
253: break;
254: p = cnvt(line);
255: if(p == 0) {
256: fprintf(stderr, "weird friends line %s\n", line);
257: continue;
258: }
259: if(p->who[0] == '#')
260: continue;
261: for(i = 0; i < nfriends; i++) {
262: if(strcmp(p->who, friends[i].who))
263: continue;
264: if(friends[i].status != OK) {
265: looked = time(0);
266: fprintf(stderr, "\nrdfile %s (%s) %s",
267: states[friends[i].status],
268: friends[i].who, ctime(&looked));
269: /* off the mother */
270: if(friends[i].status != DEAD) {
271: friends[i].status = KILL;
272: fprintf(stderr, "bye %s\n", friends[i].who);
273: }
274: }
275: if(friends[i].status != DEAD)
276: goto onward;
277: /* one could free the space */
278: fprintf(stderr, "new friend %s\n", p->who);
279: friends[i] = *p;
280: startup(friends + i);
281: goto onward;
282: }
283: for(i = 0; i < nfriends; i++)
284: if(friends[i].status == DEAD) {
285: friends[i] = *p;
286: fprintf(stderr, "new friend %s\n", p->who);
287: startup(friends + i);
288: goto onward;
289: }
290: if(i < nfriends)
291: continue;
292: if(nfriends >= NOFILE) {
293: fprintf(stderr, "friends overflow\n");
294: abort();
295: }
296: fprintf(stderr, "new friend %s\n", p->who);
297: friends[nfriends++] = *p;
298: startup(friends + nfriends - 1);
299: }
300: fclose(fd);
301: looked = time(0);
302: fprintf(stderr, "ok %s", ctime(&looked));
303: }
304:
305: callfs(srvr)
306: char *srvr;
307: {
308: int rem, v;
309: extern int pk_ld, dkp_ld;
310: long x;
311:
312: alarm(30);
313: x = time(0);
314: fprintf(stderr, "%d tdkdial %s %s", getpid(), srvr, ctime(&x));
315: fflush(stderr);
316: rem = _tdkdial(3, 2, srvr);
317: x = time(0);
318: alarm(0);
319: if (rem < 0) {
320: fprintf(stderr, " %d can't rexec err = %d\n", getpid(), errno);
321: fflush(stderr);
322: return(-1);
323: }
324: else
325: fprintf(stderr, "tdkdial ok %s", ctime(&x));
326: /* v = ioctl(rem, FIOPUSHLD, &dkp_ld); /* should be dkproto */
327: v = dkproto(rem, dkp_ld);
328: x = time(0);
329: if (v < 0) {
330: perror("can't start protocol");
331: fprintf(stderr, "\t%s", ctime(&x));
332: close(rem);
333: return(-1);
334: }
335: else
336: fprintf(stderr, "protocol started\n");
337: return(rem);
338: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.