|
|
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.