Annotation of researchv10no/netfs/libnetb/setup.c, revision 1.1.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.