Annotation of 43BSD/ucb/rdist/docmd.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)docmd.c    5.1 (Berkeley) 6/6/85";
                      9: #endif not lint
                     10: 
                     11: #include "defs.h"
                     12: #include <setjmp.h>
                     13: #include <netdb.h>
                     14: 
                     15: #ifndef RDIST
                     16: #define RDIST "/usr/ucb/rdist"
                     17: #endif
                     18: 
                     19: FILE   *lfp;                   /* log file for recording files updated */
                     20: struct subcmd *subcmds;        /* list of sub-commands for current cmd */
                     21: jmp_buf        env;
                     22: 
                     23: int    cleanup();
                     24: int    lostconn();
                     25: 
                     26: /*
                     27:  * Do the commands in cmds (initialized by yyparse).
                     28:  */
                     29: docmds(dhosts, argc, argv)
                     30:        char **dhosts;
                     31:        int argc;
                     32:        char **argv;
                     33: {
                     34:        register struct cmd *c;
                     35:        register struct namelist *f;
                     36:        register char **cpp;
                     37:        extern struct cmd *cmds;
                     38: 
                     39:        signal(SIGHUP, cleanup);
                     40:        signal(SIGINT, cleanup);
                     41:        signal(SIGQUIT, cleanup);
                     42:        signal(SIGTERM, cleanup);
                     43: 
                     44:        for (c = cmds; c != NULL; c = c->c_next) {
                     45:                if (dhosts != NULL && *dhosts != NULL) {
                     46:                        for (cpp = dhosts; *cpp; cpp++)
                     47:                                if (strcmp(c->c_name, *cpp) == 0)
                     48:                                        goto fndhost;
                     49:                        continue;
                     50:                }
                     51:        fndhost:
                     52:                if (argc) {
                     53:                        for (cpp = argv; *cpp; cpp++) {
                     54:                                if (c->c_label != NULL &&
                     55:                                    strcmp(c->c_label, *cpp) == 0) {
                     56:                                        cpp = NULL;
                     57:                                        goto found;
                     58:                                }
                     59:                                for (f = c->c_files; f != NULL; f = f->n_next)
                     60:                                        if (strcmp(f->n_name, *cpp) == 0)
                     61:                                                goto found;
                     62:                        }
                     63:                        continue;
                     64:                } else
                     65:                        cpp = NULL;
                     66:        found:
                     67:                switch (c->c_type) {
                     68:                case ARROW:
                     69:                        doarrow(cpp, c->c_files, c->c_name, c->c_cmds);
                     70:                        break;
                     71:                case DCOLON:
                     72:                        dodcolon(cpp, c->c_files, c->c_name, c->c_cmds);
                     73:                        break;
                     74:                default:
                     75:                        fatal("illegal command type %d\n", c->c_type);
                     76:                }
                     77:        }
                     78:        closeconn();
                     79: }
                     80: 
                     81: /*
                     82:  * Process commands for sending files to other machines.
                     83:  */
                     84: doarrow(filev, files, rhost, cmds)
                     85:        char **filev;
                     86:        struct namelist *files;
                     87:        char *rhost;
                     88:        struct subcmd *cmds;
                     89: {
                     90:        register struct namelist *f;
                     91:        register struct subcmd *sc;
                     92:        register char **cpp;
                     93:        int n, ddir, opts = options;
                     94: 
                     95:        if (debug)
                     96:                printf("doarrow(%x, %s, %x)\n", files, rhost, cmds);
                     97: 
                     98:        if (files == NULL) {
                     99:                error("no files to be updated\n");
                    100:                return;
                    101:        }
                    102: 
                    103:        subcmds = cmds;
                    104:        ddir = files->n_next != NULL;   /* destination is a directory */
                    105:        if (nflag)
                    106:                printf("updating host %s\n", rhost);
                    107:        else {
                    108:                if (setjmp(env))
                    109:                        goto done;
                    110:                signal(SIGPIPE, lostconn);
                    111:                if (!makeconn(rhost))
                    112:                        return;
                    113:                if ((lfp = fopen(tmpfile, "w")) == NULL) {
                    114:                        fatal("cannot open %s\n", tmpfile);
                    115:                        exit(1);
                    116:                }
                    117:        }
                    118:        for (f = files; f != NULL; f = f->n_next) {
                    119:                if (filev) {
                    120:                        for (cpp = filev; *cpp; cpp++)
                    121:                                if (strcmp(f->n_name, *cpp) == 0)
                    122:                                        goto found;
                    123:                        if (!nflag)
                    124:                                (void) fclose(lfp);
                    125:                        continue;
                    126:                }
                    127:        found:
                    128:                n = 0;
                    129:                for (sc = cmds; sc != NULL; sc = sc->sc_next) {
                    130:                        if (sc->sc_type != INSTALL)
                    131:                                continue;
                    132:                        n++;
                    133:                        install(f->n_name, sc->sc_name,
                    134:                                sc->sc_name == NULL ? 0 : ddir, sc->sc_options);
                    135:                        opts = sc->sc_options;
                    136:                }
                    137:                if (n == 0)
                    138:                        install(f->n_name, NULL, 0, options);
                    139:        }
                    140: done:
                    141:        if (!nflag) {
                    142:                (void) signal(SIGPIPE, cleanup);
                    143:                (void) fclose(lfp);
                    144:                lfp = NULL;
                    145:        }
                    146:        for (sc = cmds; sc != NULL; sc = sc->sc_next)
                    147:                if (sc->sc_type == NOTIFY)
                    148:                        notify(tmpfile, rhost, sc->sc_args, 0);
                    149:        if (!nflag) {
                    150:                (void) unlink(tmpfile);
                    151:                for (; ihead != NULL; ihead = ihead->nextp) {
                    152:                        free(ihead);
                    153:                        if ((opts & IGNLNKS) || ihead->count == 0)
                    154:                                continue;
                    155:                        log(lfp, "%s: Warning: missing links\n",
                    156:                                ihead->pathname);
                    157:                }
                    158:        }
                    159: }
                    160: 
                    161: /*
                    162:  * Create a connection to the rdist server on the machine rhost.
                    163:  */
                    164: makeconn(rhost)
                    165:        char *rhost;
                    166: {
                    167:        register char *ruser, *cp;
                    168:        static char *cur_host = NULL;
                    169:        static int port = -1;
                    170:        char tuser[20];
                    171:        int n;
                    172:        extern char user[];
                    173:        extern int userid;
                    174: 
                    175:        if (debug)
                    176:                printf("makeconn(%s)\n", rhost);
                    177: 
                    178:        if (cur_host != NULL && rem >= 0) {
                    179:                if (strcmp(cur_host, rhost) == 0)
                    180:                        return(1);
                    181:                closeconn();
                    182:        }
                    183:        cur_host = rhost;
                    184:        cp = index(rhost, '@');
                    185:        if (cp != NULL) {
                    186:                char c = *cp;
                    187: 
                    188:                *cp = '\0';
                    189:                strncpy(tuser, rhost, sizeof(tuser)-1);
                    190:                *cp = c;
                    191:                rhost = cp + 1;
                    192:                ruser = tuser;
                    193:                if (*ruser == '\0')
                    194:                        ruser = user;
                    195:                else if (!okname(ruser))
                    196:                        return(0);
                    197:        } else
                    198:                ruser = user;
                    199:        if (!qflag)
                    200:                printf("updating host %s\n", rhost);
                    201:        (void) sprintf(buf, "%s -Server%s", RDIST, qflag ? " -q" : "");
                    202:        if (port < 0) {
                    203:                struct servent *sp;
                    204: 
                    205:                if ((sp = getservbyname("shell", "tcp")) == NULL)
                    206:                        fatal("shell/tcp: unknown service");
                    207:                port = sp->s_port;
                    208:        }
                    209: 
                    210:        if (debug) {
                    211:                printf("port = %d, luser = %s, ruser = %s\n", ntohs(port), user, ruser);
                    212:                printf("buf = %s\n", buf);
                    213:        }
                    214: 
                    215:        fflush(stdout);
                    216:        setreuid(userid, 0);
                    217:        rem = rcmd(&rhost, port, user, ruser, buf, 0);
                    218:        setreuid(0, userid);
                    219:        if (rem < 0)
                    220:                return(0);
                    221:        cp = buf;
                    222:        if (read(rem, cp, 1) != 1)
                    223:                lostconn();
                    224:        if (*cp == 'V') {
                    225:                do {
                    226:                        if (read(rem, cp, 1) != 1)
                    227:                                lostconn();
                    228:                } while (*cp++ != '\n' && cp < &buf[BUFSIZ]);
                    229:                *--cp = '\0';
                    230:                cp = buf;
                    231:                n = 0;
                    232:                while (*cp >= '0' && *cp <= '9')
                    233:                        n = (n * 10) + (*cp++ - '0');
                    234:                if (*cp == '\0' && n == VERSION)
                    235:                        return(1);
                    236:                error("connection failed: version numbers don't match (local %d, remote %d)\n", VERSION, n);
                    237:        } else
                    238:                error("connection failed: version numbers don't match\n");
                    239:        closeconn();
                    240:        return(0);
                    241: }
                    242: 
                    243: /*
                    244:  * Signal end of previous connection.
                    245:  */
                    246: closeconn()
                    247: {
                    248:        if (debug)
                    249:                printf("closeconn()\n");
                    250: 
                    251:        if (rem >= 0) {
                    252:                (void) write(rem, "\2\n", 2);
                    253:                (void) close(rem);
                    254:                rem = -1;
                    255:        }
                    256: }
                    257: 
                    258: lostconn()
                    259: {
                    260:        if (iamremote)
                    261:                cleanup();
                    262:        log(lfp, "rdist: lost connection\n");
                    263:        longjmp(env, 1);
                    264: }
                    265: 
                    266: okname(name)
                    267:        register char *name;
                    268: {
                    269:        register char *cp = name;
                    270:        register int c;
                    271: 
                    272:        do {
                    273:                c = *cp;
                    274:                if (c & 0200)
                    275:                        goto bad;
                    276:                if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
                    277:                        goto bad;
                    278:                cp++;
                    279:        } while (*cp);
                    280:        return(1);
                    281: bad:
                    282:        error("invalid user name %s\n", name);
                    283:        return(0);
                    284: }
                    285: 
                    286: time_t lastmod;
                    287: FILE   *tfp;
                    288: extern char target[], *tp;
                    289: 
                    290: /*
                    291:  * Process commands for comparing files to time stamp files.
                    292:  */
                    293: dodcolon(filev, files, stamp, cmds)
                    294:        char **filev;
                    295:        struct namelist *files;
                    296:        char *stamp;
                    297:        struct subcmd *cmds;
                    298: {
                    299:        register struct subcmd *sc;
                    300:        register struct namelist *f;
                    301:        register char **cpp;
                    302:        struct timeval tv[2];
                    303:        struct timezone tz;
                    304:        struct stat stb;
                    305: 
                    306:        if (debug)
                    307:                printf("dodcolon()\n");
                    308: 
                    309:        if (files == NULL) {
                    310:                error("no files to be updated\n");
                    311:                return;
                    312:        }
                    313:        if (stat(stamp, &stb) < 0) {
                    314:                error("%s: %s\n", stamp, sys_errlist[errno]);
                    315:                return;
                    316:        }
                    317:        if (debug)
                    318:                printf("%s: %d\n", stamp, stb.st_mtime);
                    319: 
                    320:        subcmds = cmds;
                    321:        lastmod = stb.st_mtime;
                    322:        if (nflag || (options & VERIFY))
                    323:                tfp = NULL;
                    324:        else {
                    325:                if ((tfp = fopen(tmpfile, "w")) == NULL) {
                    326:                        error("%s: %s\n", stamp, sys_errlist[errno]);
                    327:                        return;
                    328:                }
                    329:                (void) gettimeofday(&tv[0], &tz);
                    330:                tv[1] = tv[0];
                    331:                (void) utimes(stamp, tv);
                    332:        }
                    333: 
                    334:        for (f = files; f != NULL; f = f->n_next) {
                    335:                if (filev) {
                    336:                        for (cpp = filev; *cpp; cpp++)
                    337:                                if (strcmp(f->n_name, *cpp) == 0)
                    338:                                        goto found;
                    339:                        continue;
                    340:                }
                    341:        found:
                    342:                tp = NULL;
                    343:                cmptime(f->n_name);
                    344:        }
                    345: 
                    346:        if (tfp != NULL)
                    347:                (void) fclose(tfp);
                    348:        for (sc = cmds; sc != NULL; sc = sc->sc_next)
                    349:                if (sc->sc_type == NOTIFY)
                    350:                        notify(tmpfile, NULL, sc->sc_args, lastmod);
                    351:        if (!nflag && !(options & VERIFY))
                    352:                (void) unlink(tmpfile);
                    353: }
                    354: 
                    355: /*
                    356:  * Compare the mtime of file to the list of time stamps.
                    357:  */
                    358: cmptime(name)
                    359:        char *name;
                    360: {
                    361:        struct stat stb;
                    362: 
                    363:        if (debug)
                    364:                printf("cmptime(%s)\n", name);
                    365: 
                    366:        if (except(name))
                    367:                return;
                    368: 
                    369:        if (nflag) {
                    370:                printf("comparing dates: %s\n", name);
                    371:                return;
                    372:        }
                    373: 
                    374:        /*
                    375:         * first time cmptime() is called?
                    376:         */
                    377:        if (tp == NULL) {
                    378:                if (exptilde(target, name) == NULL)
                    379:                        return;
                    380:                tp = name = target;
                    381:                while (*tp)
                    382:                        tp++;
                    383:        }
                    384:        if (access(name, 4) < 0 || stat(name, &stb) < 0) {
                    385:                error("%s: %s\n", name, sys_errlist[errno]);
                    386:                return;
                    387:        }
                    388: 
                    389:        switch (stb.st_mode & S_IFMT) {
                    390:        case S_IFREG:
                    391:                break;
                    392: 
                    393:        case S_IFDIR:
                    394:                rcmptime(&stb);
                    395:                return;
                    396: 
                    397:        default:
                    398:                error("%s: not a plain file\n", name);
                    399:                return;
                    400:        }
                    401: 
                    402:        if (stb.st_mtime > lastmod)
                    403:                log(tfp, "new: %s\n", name);
                    404: }
                    405: 
                    406: rcmptime(st)
                    407:        struct stat *st;
                    408: {
                    409:        register DIR *d;
                    410:        register struct direct *dp;
                    411:        register char *cp;
                    412:        char *otp;
                    413:        int len;
                    414: 
                    415:        if (debug)
                    416:                printf("rcmptime(%x)\n", st);
                    417: 
                    418:        if ((d = opendir(target)) == NULL) {
                    419:                error("%s: %s\n", target, sys_errlist[errno]);
                    420:                return;
                    421:        }
                    422:        otp = tp;
                    423:        len = tp - target;
                    424:        while (dp = readdir(d)) {
                    425:                if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
                    426:                        continue;
                    427:                if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
                    428:                        error("%s/%s: Name too long\n", target, dp->d_name);
                    429:                        continue;
                    430:                }
                    431:                tp = otp;
                    432:                *tp++ = '/';
                    433:                cp = dp->d_name;
                    434:                while (*tp++ = *cp++)
                    435:                        ;
                    436:                tp--;
                    437:                cmptime(target);
                    438:        }
                    439:        closedir(d);
                    440:        tp = otp;
                    441:        *tp = '\0';
                    442: }
                    443: 
                    444: /*
                    445:  * Notify the list of people the changes that were made.
                    446:  * rhost == NULL if we are mailing a list of changes compared to at time
                    447:  * stamp file.
                    448:  */
                    449: notify(file, rhost, to, lmod)
                    450:        char *file, *rhost;
                    451:        register struct namelist *to;
                    452:        time_t lmod;
                    453: {
                    454:        register int fd, len;
                    455:        FILE *pf, *popen();
                    456:        struct stat stb;
                    457: 
                    458:        if ((options & VERIFY) || to == NULL)
                    459:                return;
                    460:        if (!qflag) {
                    461:                printf("notify ");
                    462:                if (rhost)
                    463:                        printf("@%s ", rhost);
                    464:                prnames(to);
                    465:        }
                    466:        if (nflag)
                    467:                return;
                    468: 
                    469:        if ((fd = open(file, 0)) < 0) {
                    470:                error("%s: %s\n", file, sys_errlist[errno]);
                    471:                return;
                    472:        }
                    473:        if (fstat(fd, &stb) < 0) {
                    474:                error("%s: %s\n", file, sys_errlist[errno]);
                    475:                (void) close(fd);
                    476:                return;
                    477:        }
                    478:        if (stb.st_size == 0) {
                    479:                (void) close(fd);
                    480:                return;
                    481:        }
                    482:        /*
                    483:         * Create a pipe to mailling program.
                    484:         */
                    485:        pf = popen(MAILCMD, "w");
                    486:        if (pf == NULL) {
                    487:                error("notify: \"%s\" failed\n", MAILCMD);
                    488:                (void) close(fd);
                    489:                return;
                    490:        }
                    491:        /*
                    492:         * Output the proper header information.
                    493:         */
                    494:        fprintf(pf, "From: rdist (Remote distribution program)\n");
                    495:        fprintf(pf, "To:");
                    496:        if (!any('@', to->n_name) && rhost != NULL)
                    497:                fprintf(pf, " %s@%s", to->n_name, rhost);
                    498:        else
                    499:                fprintf(pf, " %s", to->n_name);
                    500:        to = to->n_next;
                    501:        while (to != NULL) {
                    502:                if (!any('@', to->n_name) && rhost != NULL)
                    503:                        fprintf(pf, ", %s@%s", to->n_name, rhost);
                    504:                else
                    505:                        fprintf(pf, ", %s", to->n_name);
                    506:                to = to->n_next;
                    507:        }
                    508:        putc('\n', pf);
                    509:        if (rhost != NULL)
                    510:                fprintf(pf, "Subject: files updated by rdist from %s to %s\n",
                    511:                        host, rhost);
                    512:        else
                    513:                fprintf(pf, "Subject: files updated after %s\n", ctime(&lmod));
                    514:        putc('\n', pf);
                    515: 
                    516:        while ((len = read(fd, buf, BUFSIZ)) > 0)
                    517:                (void) fwrite(buf, 1, len, pf);
                    518:        (void) close(fd);
                    519:        (void) pclose(pf);
                    520: }
                    521: 
                    522: /*
                    523:  * Return true if name is in the list.
                    524:  */
                    525: inlist(list, file)
                    526:        struct namelist *list;
                    527:        char *file;
                    528: {
                    529:        register struct namelist *nl;
                    530: 
                    531:        for (nl = list; nl != NULL; nl = nl->n_next)
                    532:                if (!strcmp(file, nl->n_name))
                    533:                        return(1);
                    534:        return(0);
                    535: }
                    536: 
                    537: /*
                    538:  * Return TRUE if file is in the exception list.
                    539:  */
                    540: except(file)
                    541:        char *file;
                    542: {
                    543:        register struct subcmd *sc;
                    544:        register struct namelist *nl;
                    545: 
                    546:        if (debug)
                    547:                printf("except(%s)\n", file);
                    548: 
                    549:        for (sc = subcmds; sc != NULL; sc = sc->sc_next) {
                    550:                if (sc->sc_type != EXCEPT && sc->sc_type != PATTERN)
                    551:                        continue;
                    552:                for (nl = sc->sc_args; nl != NULL; nl = nl->n_next) {
                    553:                        if (sc->sc_type == EXCEPT) {
                    554:                                if (!strcmp(file, nl->n_name))
                    555:                                        return(1);
                    556:                                continue;
                    557:                        }
                    558:                        re_comp(nl->n_name);
                    559:                        if (re_exec(file) > 0)
                    560:                                return(1);
                    561:                }
                    562:        }
                    563:        return(0);
                    564: }
                    565: 
                    566: char *
                    567: colon(cp)
                    568:        register char *cp;
                    569: {
                    570: 
                    571:        while (*cp) {
                    572:                if (*cp == ':')
                    573:                        return(cp);
                    574:                if (*cp == '/')
                    575:                        return(0);
                    576:                cp++;
                    577:        }
                    578:        return(0);
                    579: }

unix.superglobalmegacorp.com

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