Annotation of researchv10no/netfs/libnetb/setup.c, revision 1.1

1.1     ! root        1: #include <stdio.h>
        !             2: #include <sys/types.h>
        !             3: #include <sys/stat.h>
        !             4: #include <signal.h>
        !             5: #include <ipc.h>
        !             6: #include <errno.h>
        !             7: #include <libc.h>
        !             8: #include <pwd.h>
        !             9: #include <grp.h>
        !            10: 
        !            11: typedef struct {
        !            12:        char *address;
        !            13:        char *arg;
        !            14:        char *mpoint;
        !            15:        char *callusr;
        !            16:        int rootino;
        !            17:        dev_t rootdev;
        !            18:        char proto;
        !            19:        char stat;
        !            20:        char devnum;
        !            21:        char debug;
        !            22:        int retry;
        !            23: } Friend;
        !            24: 
        !            25: #define        SOK     01      /* filesystem running ok */
        !            26: #define        SFOUND  02      /* found in most recent friends pass */
        !            27: 
        !            28: #define        MAXRETRY        60      /* slow down after this many retries */
        !            29: #define        LONGRETRY       20      /* after slowdown, retry after this many cycles */
        !            30: 
        !            31: #define        MAXFRIENDS 128
        !            32: Friend friends[MAXFRIENDS];    /* should probably be dynamic */
        !            33: 
        !            34: #define        MAXMSG  5       /* largest message 5*MSGBLOCK -- known to kernel too */
        !            35: #define        MSGBLOCK 1024
        !            36: 
        !            37: #define        NBFS    4       /* our filesystem type */
        !            38: 
        !            39: char frfile[] = "/usr/netb/friends";   /* should be an argument */
        !            40: 
        !            41: char *estr();
        !            42: Friend *findmpoint();
        !            43: 
        !            44: main(argc, argv)
        !            45: int argc;
        !            46: char **argv;
        !            47: {
        !            48:        Friend f;
        !            49:        int fd;
        !            50: 
        !            51:        if (argc <= 1) {
        !            52:                mkdaemon();
        !            53:                rundaemon();
        !            54:        }
        !            55:        if (argc < 6 || argc > 8) {
        !            56:                fprintf(stderr, "usage: setup netaddr arg mountpoint protocol devnum [debug userid]\n");
        !            57:                exit(1);
        !            58:        }
        !            59:        f.address = argv[1];
        !            60:        f.arg = argv[2];
        !            61:        f.mpoint = argv[3];
        !            62:        f.proto = argv[4][0];
        !            63:        f.devnum = atoi(argv[5]);
        !            64:        if (argc <= 6)
        !            65:                f.debug = 0;
        !            66:        else
        !            67:                f.debug = atoi(argv[6]);
        !            68:        if (argc <= 7)
        !            69:                f.callusr = "daemon";
        !            70:        else
        !            71:                f.callusr = argv[7];
        !            72:        if ((fd = callsys(&f)) < 0) {
        !            73:                fprintf(stderr, "%s %s %c %s: %s\n", f.address, f.arg, f.proto, f.callusr, errstr);
        !            74:                exit(1);
        !            75:        }
        !            76:        if (setup(fd, &f) < 0)
        !            77:                exit(1);
        !            78:        exit(0);
        !            79: }
        !            80: 
        !            81: nulltrap(s)
        !            82: {
        !            83:        signal(s, nulltrap);
        !            84: }
        !            85: 
        !            86: /*
        !            87:  * prepare to be a daemon
        !            88:  */
        !            89: 
        !            90: mkdaemon()
        !            91: {
        !            92:        switch (fork()) {
        !            93:        case -1:
        !            94:                perror("fork");
        !            95:                exit(1);
        !            96:        default:        /* parent */
        !            97:                exit(0);
        !            98:        case 0:         /* child */
        !            99:                break;
        !           100:        }
        !           101:        signal(SIGINT, SIG_IGN);
        !           102:        signal(SIGQUIT, SIG_IGN);
        !           103:        signal(SIGHUP, SIG_IGN);
        !           104:        signal(SIGPIPE, SIG_IGN);       /* needed? */
        !           105:        signal(SIGALRM, nulltrap);      /* miscellaneous alarms */
        !           106: }
        !           107: 
        !           108: /*
        !           109:  * the daemon:
        !           110:  * once a minute,
        !           111:  *     see if the filesystems we've already mounted are ok
        !           112:  *     see if the friends file has changed, and read it if so
        !           113:  *     try to mount any filesystem that isn't
        !           114:  */
        !           115: 
        !           116: rundaemon()
        !           117: {
        !           118:        static time_t fmtime;
        !           119:        struct stat st;
        !           120:        register Friend *fp;
        !           121:        int fd;
        !           122: 
        !           123:        for (;; sleep(60)) {
        !           124:                for (fp = friends; fp < &friends[MAXFRIENDS]; fp++) {
        !           125:                        if (fp->address == NULL || (fp->stat & SOK) == 0)
        !           126:                                continue;
        !           127:                        alarm(60);
        !           128:                        if (stat(fp->mpoint, &st) < 0) {
        !           129:                                plog("stat %s: %s\n", fp->mpoint, estr());
        !           130:                                fp->stat &=~ SOK;
        !           131:                        } else if (st.st_dev != fp->rootdev
        !           132:                               ||  st.st_ino != fp->rootino) {
        !           133:                                plog("%s: not root: want 0x%x:%d, have 0x%x:%d\n",
        !           134:                                  fp->mpoint, fp->rootdev, fp->rootino,
        !           135:                                  st.st_dev, st.st_ino);
        !           136:                                fp->stat &=~ SOK;
        !           137:                        }
        !           138:                        alarm(0);
        !           139:                }
        !           140:                if (stat(frfile, &st) < 0)
        !           141:                        plog("stat %s: %s\n", frfile, estr());
        !           142:                else if (fmtime != st.st_mtime) {
        !           143:                        fmtime = st.st_mtime;
        !           144:                        newfriends();
        !           145:                }
        !           146:                for (fp = friends; fp < &friends[MAXFRIENDS]; fp++) {
        !           147:                        if (fp->address == NULL || fp->stat & SOK)
        !           148:                                continue;
        !           149:                        if (fp->retry > MAXRETRY) {
        !           150:                                if (fp->retry < MAXRETRY+LONGRETRY) {
        !           151:                                        fp->retry++;
        !           152:                                        continue;       /* skip this time */
        !           153:                                }
        !           154:                                fp->retry = MAXRETRY;   /* do this one, then skip */
        !           155:                        }
        !           156:                        plog("%s: calling %s %s %c %s\n",
        !           157:                                fp->mpoint, fp->address, fp->arg, fp->proto, fp->callusr);
        !           158:                        if ((fd = callsys(fp)) < 0) {
        !           159:                                plog("%s: %s\n", fp->address, errstr);
        !           160:                                fp->retry++;
        !           161:                                continue;
        !           162:                        }
        !           163:                        if (setup(fd, fp) < 0) {
        !           164:                                plog("%s: setup failed\n", fp->mpoint);
        !           165:                                alarm(30);
        !           166:                                close(fd);
        !           167:                                alarm(0);
        !           168:                                fp->retry++;
        !           169:                                continue;
        !           170:                        }
        !           171:                        close(fd);
        !           172:                        plog("%s started\n", fp->mpoint);
        !           173:                        fp->stat |= SOK;
        !           174:                        fp->retry = 0;
        !           175:                }
        !           176:        }
        !           177: }
        !           178: 
        !           179: /*
        !           180:  * reread the friends file
        !           181:  * the algorithm is quadratic,
        !           182:  * but we don't do it often
        !           183:  */
        !           184: 
        !           185: #define        ASIZE   8
        !           186: newfriends()
        !           187: {
        !           188:        FILE *f;
        !           189:        char line[512];         /* huge */
        !           190:        char *args[ASIZE];
        !           191:        char proto, devnum, debug;
        !           192:        char *callusr;
        !           193:        register Friend *fp;
        !           194: 
        !           195:        if ((f = fopen(frfile, "r")) == NULL) {
        !           196:                plog("can't open %s: %s\n", frfile, estr());
        !           197:                return;
        !           198:        }
        !           199:        setfields(" \t\n");
        !           200:        for (fp = friends; fp < &friends[MAXFRIENDS]; fp++)
        !           201:                fp->stat &=~ SFOUND;
        !           202:        while (fgets(line, sizeof(line), f)) {
        !           203:                if (line[0] == '#')
        !           204:                        continue;
        !           205:                /*
        !           206:                 * backward compatibility:
        !           207:                 * login name may be omitted
        !           208:                 */
        !           209:                switch (getmfields(line, args, ASIZE)) {
        !           210:                default:
        !           211:                        continue;
        !           212: 
        !           213:                case 6:
        !           214:                        callusr = "daemon";
        !           215:                        break;
        !           216: 
        !           217:                case 7:
        !           218:                        callusr = args[6];
        !           219:                        break;
        !           220:                }
        !           221:                proto = args[3][0];
        !           222:                devnum = atoi(args[4]);
        !           223:                debug = atoi(args[5]);
        !           224:                fp = findmpoint(args[2]);
        !           225:                if (fp->address                 /* didn't return an empty */
        !           226:                &&  strcmp(fp->address, args[0]) == 0
        !           227:                &&  strcmp(fp->arg, args[1]) == 0
        !           228:                /* mount point already checked */
        !           229:                &&  strcmp(fp->callusr, callusr) == 0
        !           230:                &&  fp->proto == proto
        !           231:                &&  fp->devnum == devnum
        !           232:                &&  fp->debug == debug) {
        !           233:                        fp->stat |= SFOUND;
        !           234:                        fp->retry = 0;
        !           235:                        continue;               /* it hasn't changed */
        !           236:                }
        !           237:                if (fp->address) {              /* was already there, clear it */
        !           238:                        plog("changing %s\n", fp->mpoint);
        !           239:                        free(fp->address);
        !           240:                        free(fp->arg);
        !           241:                        free(fp->mpoint);
        !           242:                        free(fp->callusr);
        !           243:                }
        !           244:                fp->address = strdup(args[0]);
        !           245:                fp->arg = strdup(args[1]);
        !           246:                fp->mpoint = strdup(args[2]);
        !           247:                fp->callusr = strdup(callusr);
        !           248:                fp->proto = proto;
        !           249:                fp->devnum = devnum;
        !           250:                fp->debug = debug;
        !           251:                fp->stat = SFOUND;      /* nb OK not set yet */
        !           252:                fp->retry = 0;
        !           253:        }
        !           254:        fclose(f);
        !           255:        for (fp = friends; fp < &friends[MAXFRIENDS]; fp++) {
        !           256:                if (fp->address == NULL || fp->stat & SFOUND)
        !           257:                        continue;
        !           258:                plog("dropping %s\n", fp->mpoint);
        !           259:                free(fp->address);
        !           260:                free(fp->arg);
        !           261:                free(fp->mpoint);
        !           262:                fp->address = NULL;
        !           263:        }
        !           264: }
        !           265: 
        !           266: Friend *
        !           267: findmpoint(mp)
        !           268: char *mp;
        !           269: {
        !           270:        register Friend *fp, *ep;
        !           271:        static Friend junkfriend;
        !           272: 
        !           273:        ep = NULL;
        !           274:        for (fp = friends; fp < &friends[MAXFRIENDS]; fp++) {
        !           275:                if (fp->address == NULL) {
        !           276:                        if (ep == NULL)
        !           277:                                ep = fp;
        !           278:                        continue;
        !           279:                }
        !           280:                if (strcmp(fp->mpoint, mp) == 0)
        !           281:                        return (fp);
        !           282:        }
        !           283:        if (ep)
        !           284:                return (ep);
        !           285:        plog("too many friends; no room for %s\n", mp);
        !           286:        return (&junkfriend);
        !           287: }
        !           288: 
        !           289: /*
        !           290:  * call a server
        !           291:  * according to network protocol
        !           292:  */
        !           293: 
        !           294: callsys(fp)
        !           295: register Friend *fp;
        !           296: {
        !           297:        register int fd;
        !           298: 
        !           299:        alarm(120);
        !           300:        setlogname(fp->callusr);        /* who the network thinks we are */
        !           301:        switch (fp->proto) {
        !           302:        case 'd':       /* `datakit' -- general connection */
        !           303:                fd = ipcopen(ipcpath(fp->address, "dk", "fsb"), "heavy hup");
        !           304:                break;
        !           305: 
        !           306:        case 'e':       /* same, but use rexec -- why bother? */
        !           307:                fd = ipcexec(ipcpath(fp->address, "dk", "exec"), "heavy hup", fp->arg);
        !           308:                break;
        !           309: 
        !           310:        case 't':
        !           311:                fd = ipcrexec(fp->address, "heavy hup", fp->arg);
        !           312:                break;
        !           313: 
        !           314:        default:
        !           315:                errstr = "unknown setup protocol";
        !           316:                fd = -1;
        !           317:                break;
        !           318:        }
        !           319:        alarm(0);
        !           320:        return (fd);
        !           321: }
        !           322: 
        !           323: /*
        !           324:  * initial protocol with server:
        !           325:  * client sends 16 bytes:
        !           326:  *     max buffer size in 1024-byte units
        !           327:  *     device number in use
        !           328:  *     protocol letter
        !           329:  *     debugging flag
        !           330:  *     12 unused
        !           331:  * server sends one byte: 1
        !           332:  * client sends a list of userids: maxsize bytes
        !           333:  *     if list won't fit in one buffer, last username is `:'
        !           334:  *     server acks with one byte 012; client sends more
        !           335:  * server sends one byte: 2
        !           336:  * client sends a list of groupids: maxsize bytes
        !           337:  *     if list won't fit in one buffer, last groupname is `:'
        !           338:  *     server acks with one byte 013; client sends more
        !           339:  * server sends one byte: 3
        !           340:  * then we mount it, and further messages come from the kernel
        !           341:  */
        !           342: 
        !           343: #define        M1LEN   16
        !           344: 
        !           345: setup(fd, fp)
        !           346: int fd;
        !           347: register Friend *fp;
        !           348: {
        !           349:        char m[M1LEN];
        !           350:        register int n;
        !           351:        struct stat st;
        !           352: 
        !           353:        memset(m, 0, M1LEN);
        !           354:        m[0] = MAXMSG;
        !           355:        m[1] = fp->devnum;
        !           356:        m[2] = fp->proto;
        !           357:        if (m[2] == 'e')
        !           358:                m[2] = 'd';     /* hack */
        !           359:        m[3] = fp->debug;
        !           360:        alarm(600);
        !           361:        if ((n = write(fd, m, M1LEN)) != M1LEN) {
        !           362:                plog("%s setup 1: write returned %d; %s\n", fp->mpoint, n, estr());
        !           363:                alarm(0);
        !           364:                return (-1);
        !           365:        }
        !           366:        if (getresp(fd, 1, fp->mpoint) == 0)
        !           367:                return (-1);
        !           368:        alarm(600);
        !           369:        if (senduid(fd, fp->mpoint) < 0) {
        !           370:                alarm(0);
        !           371:                return (-1);
        !           372:        }
        !           373:        alarm(600);
        !           374:        if (sendgid(fd, fp->mpoint) < 0) {
        !           375:                alarm(0);
        !           376:                return (-1);
        !           377:        }
        !           378:        alarm(60);
        !           379:        funmount(fp->mpoint);   /* bad -- might unmount wrong fs */
        !           380:        if (fmount(NBFS, fd, fp->mpoint, makedev(fp->devnum, 0)) < 0) {
        !           381:                plog("%s: fmount: %s\n", fp->mpoint, estr());
        !           382:                alarm(0);
        !           383:                return (-1);
        !           384:        }
        !           385:        alarm(60);
        !           386:        if (stat(fp->mpoint, &st) < 0) {
        !           387:                plog("%s: initial root stat: %s\n", fp->mpoint, estr());
        !           388:                alarm(0);
        !           389:                return (-1);
        !           390:        }
        !           391:        alarm(0);
        !           392:        fp->rootino = st.st_ino;
        !           393:        fp->rootdev = st.st_dev;
        !           394:        return (0);
        !           395: }
        !           396: 
        !           397: /*
        !           398:  * get a single-byte response from server
        !           399:  * try to cope with unexpected noise,
        !           400:  * usually something like /etc/motd or `You have mail.'
        !           401:  * fortunately server responses are all characters
        !           402:  * unlikely to appear in ordinary ASCII text (viz. octal 1 2 3).
        !           403:  * it is more important to copy the junk to the logfile
        !           404:  * (so someone can get rid of it) than to survive it
        !           405:  */
        !           406: 
        !           407: getresp(fd, id, fs)
        !           408: int fd, id;
        !           409: char *fs;
        !           410: {
        !           411:        register int i, n;
        !           412:        char m[400];
        !           413:        int tries, tmo;
        !           414: 
        !           415:        tmo = 600;              /* timeout */
        !           416:        for (tries = 0; tries < 5 && tmo > 0; tries++) {
        !           417:                alarm(tmo);
        !           418:                n = read(fd, m, sizeof(m)-1);
        !           419:                tmo = alarm(0);         /* assume errno untouched */
        !           420:                m[n] = 0;
        !           421:                if (n <= 0) {
        !           422:                        plog("%s setup %d: read returned %d: %s\n", fs, id, n, estr());
        !           423:                        return (0);
        !           424:                }
        !           425:                for (i = 0; i < n; i++)
        !           426:                        if (m[i] == id)
        !           427:                                break;
        !           428:                if (i) {
        !           429:                        m[i] = 0;
        !           430:                        plog("%s setup %d: read junk: %s\n", fs, id, m);
        !           431:                }
        !           432:                if (i < n)              /* found it */
        !           433:                        return (1);
        !           434:        }
        !           435:        plog("%s setup %d: no response\n", fs, id);
        !           436:        return (0);
        !           437: }
        !           438: 
        !           439: #define        SLOP    50
        !           440: 
        !           441: senduid(fd, mpoint)
        !           442: int fd;
        !           443: char *mpoint;
        !           444: {
        !           445:        char idbuf[MAXMSG*MSGBLOCK+SLOP];
        !           446:        char onebuf[SLOP];
        !           447:        register char *p;
        !           448:        register struct passwd *pw;
        !           449:        register int n, wn;
        !           450: 
        !           451:        setpwent();
        !           452:        p = idbuf;
        !           453:        while ((pw = getpwent()) != NULL) {
        !           454:                sprintf(onebuf, "%s %d\n", pw->pw_name, pw->pw_uid);
        !           455:                n = strlen(onebuf);
        !           456:                if (n > &idbuf[MAXMSG*MSGBLOCK] - p - 4) { /* room for ": 1\n" */
        !           457:                        strcpy(p, ": 1\n");     /* `more coming' */
        !           458:                        if ((wn = write(fd, idbuf, MAXMSG*MSGBLOCK)) != MAXMSG*MSGBLOCK) {
        !           459:                                plog("%s: write uid: %d; %s\n", mpoint, wn, estr());
        !           460:                                return (-1);
        !           461:                        }
        !           462:                        if (getresp(fd, 012, mpoint) == 0)
        !           463:                                return (-1);
        !           464:                        p = idbuf;
        !           465:                }
        !           466:                strcpy(p, onebuf);
        !           467:                p += n;
        !           468:        }
        !           469:        endpwent();
        !           470:        if ((wn = write(fd, idbuf, MAXMSG*MSGBLOCK)) != MAXMSG*MSGBLOCK) {
        !           471:                plog("%s: write uid: %d; %s\n", mpoint, wn, estr());
        !           472:                return (-1);
        !           473:        }
        !           474:        if (getresp(fd, 2, mpoint) == 0)
        !           475:                return (-1);
        !           476:        return (0);
        !           477: }
        !           478: 
        !           479: sendgid(fd, mpoint)
        !           480: int fd;
        !           481: char *mpoint;
        !           482: {
        !           483:        char idbuf[MAXMSG*MSGBLOCK+SLOP];
        !           484:        char onebuf[SLOP];
        !           485:        register char *p;
        !           486:        register struct group *gr;
        !           487:        register int n, wn;
        !           488: 
        !           489:        setgrent();
        !           490:        p = idbuf;
        !           491:        while ((gr = getgrent()) != NULL) {
        !           492:                sprintf(onebuf, "%s %d\n", gr->gr_name, gr->gr_gid);
        !           493:                n = strlen(onebuf);
        !           494:                if (n > &idbuf[MAXMSG*MSGBLOCK] - p - 4) { /* room for ": 1\n" */
        !           495:                        strcpy(p, ": 1\n");     /* `more coming' */
        !           496:                        if ((wn = write(fd, idbuf, MAXMSG*MSGBLOCK)) != MAXMSG*MSGBLOCK) {
        !           497:                                plog("%s: write gid: %d; %s\n", mpoint, wn, estr());
        !           498:                                return (-1);
        !           499:                        }
        !           500:                        if (getresp(fd, 013, mpoint) == 0)
        !           501:                                return (-1);
        !           502:                        p = idbuf;
        !           503:                }
        !           504:                strcpy(p, onebuf);
        !           505:                p += n;
        !           506:        }
        !           507:        endgrent();
        !           508:        if ((wn = write(fd, idbuf, MAXMSG*MSGBLOCK)) != MAXMSG*MSGBLOCK) {
        !           509:                plog("%s: write gid: %d; %s\n", mpoint, wn, estr());
        !           510:                return (-1);
        !           511:        }
        !           512:        if (getresp(fd, 3, mpoint) == 0)
        !           513:                return (-1);
        !           514:        return (0);
        !           515: }
        !           516: 
        !           517: /*
        !           518:  * error logging stuff
        !           519:  * just print to stderr for now
        !           520:  */
        !           521: 
        !           522: /* PRINTFLIKE1 */
        !           523: plog(s, a, b, c, d, e, f)
        !           524: char *s;
        !           525: {
        !           526:        long now;
        !           527: 
        !           528:        time(&now);
        !           529:        fseek(stderr, 0L, 2);
        !           530:        fprintf(stderr, "%.15s ", ctime(&now)+4);       /* trim day of week, year */
        !           531:        fprintf(stderr, s, a, b, c, d, e, f);
        !           532:        fflush(stderr);
        !           533: }
        !           534: 
        !           535: char *
        !           536: estr()
        !           537: {
        !           538:        static char buf[] = "Error -2147483648";
        !           539: 
        !           540:        if (errno < 0 || errno >= sys_nerr) {
        !           541:                sprintf(buf, "Error %d", errno);
        !           542:                return (buf);
        !           543:        }
        !           544:        return (sys_errlist[errno]);
        !           545: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.