[BACK]Return to rdist.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rdist

Annotation of src/usr.bin/rdist/rdist.c, Revision 1.14

1.14    ! deraadt     1: /*     $OpenBSD: rdist.c,v 1.13 2002/05/09 19:19:33 millert Exp $      */
1.3       deraadt     2:
1.1       dm          3: /*
                      4:  * Copyright (c) 1983 Regents of the University of California.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
                     36: #ifndef lint
1.5       millert    37: #if 0
1.1       dm         38: static char RCSid[] =
1.5       millert    39: "$From: rdist.c,v 6.65 1995/12/12 00:20:39 mcooper Exp $";
                     40: #else
                     41: static char RCSid[] =
1.14    ! deraadt    42: "$OpenBSD: rdist.c,v 1.13 2002/05/09 19:19:33 millert Exp $";
1.5       millert    43: #endif
1.1       dm         44:
                     45: static char sccsid[] = "@(#)main.c     5.1 (Berkeley) 6/6/85";
                     46:
                     47: static char copyright[] =
                     48: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
                     49:  All rights reserved.\n";
                     50: #endif /* not lint */
                     51:
                     52:
                     53: #include "defs.h"
                     54: #include "y.tab.h"
                     55: #include <netdb.h>
                     56: #include <sys/ioctl.h>
                     57:
                     58: /*
                     59:  * Remote distribution program.
                     60:  */
1.6       millert    61:
                     62: void           docmdargs(int, char **);
                     63: void           usage(void);
1.1       dm         64:
                     65: char                  *distfile = NULL;                /* Name of distfile to use */
                     66: int            maxchildren = MAXCHILDREN;      /* Max no of concurrent PIDs */
                     67: int            nflag = 0;                      /* Say without doing */
                     68: long           min_freespace = 0;              /* Min filesys free space */
                     69: long           min_freefiles = 0;              /* Min filesys free # files */
                     70: FILE                  *fin = NULL;                     /* Input file pointer */
                     71: struct group   *gr = NULL;                     /* Static area for getgrent */
                     72: char           localmsglist[] = "stdout=all:notify=all:syslog=nerror,ferror";
                     73: char                  *remotemsglist = NULL;
                     74: char           optchars[] = "A:a:bcd:DFf:hil:L:M:m:NnOo:p:P:qRrst:Vvwxy";
                     75: FILE                  *opendist();
                     76: char          *path_rdistd = _PATH_RDISTD;
1.4       millert    77: char          *path_remsh = NULL;
1.1       dm         78:
                     79: /*
                     80:  * Add a hostname to the host list
                     81:  */
                     82: static void addhostlist(name, hostlist)
                     83:        char *name;
                     84:        struct namelist **hostlist;
                     85: {
1.9       mpech      86:        struct namelist *ptr, *new;
1.1       dm         87:
                     88:        if (!name || !hostlist)
                     89:                return;
                     90:
                     91:        new = (struct namelist *) xmalloc(sizeof(struct namelist));
1.7       millert    92:        new->n_name = xstrdup(name);
1.1       dm         93:        new->n_next = NULL;
                     94:
                     95:        if (*hostlist) {
                     96:                for (ptr = *hostlist; ptr && ptr->n_next; ptr = ptr->n_next)
                     97:                        ;
                     98:                ptr->n_next = new;
                     99:        } else
                    100:                *hostlist = new;
                    101: }
                    102:
1.5       millert   103: int
1.1       dm        104: main(argc, argv, envp)
                    105:        int argc;
                    106:        char *argv[];
                    107:        char **envp;
                    108: {
                    109:        struct namelist *hostlist = NULL;
1.9       mpech     110:        int x;
                    111:        char *cp;
1.1       dm        112:        int cmdargs = 0;
                    113:        int c;
                    114:
                    115:        /*
                    116:         * We initialize progname here instead of init() because
                    117:         * things in msgparseopts() need progname set.
                    118:         */
                    119:        setprogname(argv);
                    120:
1.5       millert   121:        if ((cp = msgparseopts(localmsglist, TRUE))) {
1.1       dm        122:                error("Bad builtin log option (%s): %s.",
                    123:                      localmsglist, cp);
                    124:                usage();
                    125:        }
                    126:
                    127:        if (init(argc, argv, envp) < 0)
                    128:                exit(1);
                    129:
                    130:        /*
                    131:         * Be backwards compatible.
                    132:         */
                    133:        for (x = 1; x <= argc && argv[x]; x++) {
                    134:                if (strcmp(argv[x], "-Server") != 0)
                    135:                        continue;
                    136: #if    defined(_PATH_OLDRDIST)
                    137:                message(MT_SYSLOG,
                    138:                        "Old rdist (-Server) requested; running %s",
                    139:                        _PATH_OLDRDIST);
                    140:                (void) execl(_PATH_OLDRDIST, xbasename(_PATH_OLDRDIST),
1.8       deraadt   141:                             "-Server", (char *)NULL);
1.1       dm        142:                fatalerr("Exec old rdist failed: %s: %s.",
                    143:                         _PATH_OLDRDIST, SYSERR);
                    144: #else  /* !_PATH_OLDRDIST */
                    145:                fatalerr("Old rdist not available.");
                    146: #endif /* _PATH_OLDRDIST */
                    147:                exit(1);
                    148:        }
                    149:
                    150: #if    defined(DIRECT_RCMD)
                    151:        if (becomeuser() != 0)
                    152:                exit(1);
                    153: #else  /* !DIRECT_RCMD */
                    154:        /*
                    155:         * Perform check to make sure we are not incorrectly installed
                    156:         * setuid to root or anybody else.
                    157:         */
                    158:        if (getuid() != geteuid())
                    159:                fatalerr("This version of rdist should not be installed setuid.");
                    160: #endif /* DIRECT_RCMD */
                    161:
                    162:        while ((c = getopt(argc, argv, optchars)) != -1)
                    163:                switch (c) {
                    164:                case 'l':
1.5       millert   165:                        if ((cp = msgparseopts(optarg, TRUE))) {
1.1       dm        166:                                error("Bad log option \"%s\": %s.", optarg,cp);
                    167:                                usage();
                    168:                        }
                    169:                        break;
                    170:
                    171:                case 'L':
1.7       millert   172:                        remotemsglist = xstrdup(optarg);
1.1       dm        173:                        break;
                    174:
                    175:                case 'A':
                    176:                case 'a':
                    177:                case 'M':
                    178:                case 't':
                    179:                        if (!isdigit(*optarg)) {
                    180:                                error("\"%s\" is not a number.", optarg);
                    181:                                usage();
                    182:                        }
                    183:                        if (c == 'a')
                    184:                                min_freespace = atoi(optarg);
                    185:                        else if (c == 'A')
                    186:                                min_freefiles = atoi(optarg);
                    187:                        else if (c == 'M')
                    188:                                maxchildren = atoi(optarg);
                    189:                        else if (c == 't')
                    190:                                rtimeout = atoi(optarg);
                    191:                        break;
                    192:
                    193:                case 'F':
                    194:                        do_fork = FALSE;
                    195:                        break;
                    196:
                    197:                case 'f':
1.7       millert   198:                        distfile = xstrdup(optarg);
1.1       dm        199:                        if (distfile[0] == '-' && distfile[1] == CNULL)
                    200:                                fin = stdin;
                    201:                        break;
                    202:
                    203:                case 'm':
                    204:                        addhostlist(optarg, &hostlist);
                    205:                        break;
                    206:
                    207:                case 'd':
                    208:                        define(optarg);
                    209:                        break;
                    210:
                    211:                case 'D':
                    212:                        debug = DM_ALL;
1.5       millert   213:                        if ((cp = msgparseopts("stdout=all,debug", TRUE))) {
1.1       dm        214:                                error("Enable debug messages failed: %s.", cp);
                    215:                                usage();
                    216:                        }
                    217:                        break;
                    218:
                    219:                case 'c':
                    220:                        cmdargs++;
                    221:                        break;
                    222:
                    223:                case 'n':
                    224:                        nflag++;
                    225:                        break;
                    226:
                    227:                case 'V':
                    228:                        printf("%s\n", getversion());
                    229:                        exit(0);
                    230:
                    231:                case 'o':
                    232:                        if (parsedistopts(optarg, &options, TRUE)) {
                    233:                                error("Bad dist option string \"%s\".",
                    234:                                      optarg);
                    235:                                usage();
                    236:                        }
                    237:                        break;
                    238:
                    239:                case 'p':
                    240:                        if (!optarg) {
                    241:                                error("No path specified to \"-p\".");
                    242:                                usage();
                    243:                        }
1.7       millert   244:                        path_rdistd = xstrdup(optarg);
1.1       dm        245:                        break;
                    246:
                    247:                case 'P':
                    248:                        if (!optarg) {
                    249:                                error("No path specified to \"-P\".");
                    250:                                usage();
                    251:                        }
1.5       millert   252:                        if ((cp = searchpath(optarg)))
1.7       millert   253:                                path_remsh = xstrdup(cp);
1.1       dm        254:                        else {
                    255:                                error("No component of path \"%s\" exists.",
                    256:                                      optarg);
                    257:                                usage();
                    258:                        }
                    259:                        break;
                    260:
                    261:                        /*
                    262:                         * These options are obsoleted by -o.  They are
                    263:                         * provided only for backwards compatibility
                    264:                         */
                    265:                case 'v':       FLAG_ON(options, DO_VERIFY);            break;
                    266:                case 'N':       FLAG_ON(options, DO_CHKNFS);            break;
                    267:                case 'O':       FLAG_ON(options, DO_CHKREADONLY);       break;
                    268:                case 'q':       FLAG_ON(options, DO_QUIET);             break;
                    269:                case 'b':       FLAG_ON(options, DO_COMPARE);           break;
                    270:                case 'r':       FLAG_ON(options, DO_NODESCEND);         break;
                    271:                case 'R':       FLAG_ON(options, DO_REMOVE);            break;
                    272:                case 's':       FLAG_ON(options, DO_SAVETARGETS);       break;
                    273:                case 'w':       FLAG_ON(options, DO_WHOLE);             break;
                    274:                case 'y':       FLAG_ON(options, DO_YOUNGER);           break;
                    275:                case 'h':       FLAG_ON(options, DO_FOLLOW);            break;
                    276:                case 'i':       FLAG_ON(options, DO_IGNLNKS);           break;
                    277:                case 'x':       FLAG_ON(options, DO_NOEXEC);            break;
                    278:
                    279:                case '?':
                    280:                default:
                    281:                        usage();
                    282:                }
                    283:
                    284:        if (debug) {
                    285:                printf("%s\n", getversion());
                    286:                msgprconfig();
                    287:        }
                    288:
                    289:        if (nflag && IS_ON(options, DO_VERIFY))
                    290:                fatalerr(
                    291:                 "The -n flag and \"verify\" mode may not both be used.");
1.4       millert   292:
1.13      millert   293:        if (path_remsh == NULL) {
                    294:                if ((cp = getenv("RSH")) != NULL && *cp != '\0')
                    295:                        path_remsh = cp;
                    296:                else
                    297:                        path_remsh = _PATH_SSH;
                    298:        }
1.1       dm        299:
                    300:        /*
                    301:         * Don't fork children for nflag
                    302:         */
                    303:        if (nflag)
                    304:                do_fork = 0;
                    305:
                    306:        if (cmdargs)
                    307:                docmdargs(realargc - optind, &realargv[optind]);
                    308:        else {
                    309:                if (fin == NULL)
                    310:                        fin = opendist(distfile);
                    311:                (void) yyparse();
                    312:                /*
                    313:                 * Need to keep stdin open for child processing later
                    314:                 */
                    315:                if (fin != stdin)
                    316:                        (void) fclose(fin);
                    317:                if (nerrs == 0)
                    318:                        docmds(hostlist, realargc-optind, &realargv[optind]);
                    319:        }
                    320:
                    321:        exit(nerrs != 0);
                    322: }
                    323:
                    324: /*
                    325:  * Open a distfile
                    326:  */
                    327: FILE *opendist(distfile)
                    328:        char *distfile;
                    329: {
                    330:        char *file = NULL;
                    331:        FILE *fp;
                    332:
                    333:        if (distfile == NULL) {
                    334:                if (access("distfile", R_OK) == 0)
                    335:                        file = "distfile";
                    336:                else if (access("Distfile", R_OK) == 0)
                    337:                        file = "Distfile";
                    338:        } else {
                    339:                /*
                    340:                 * Try to test to see if file is readable before running m4.
                    341:                 */
                    342:                if (access(distfile, R_OK) != 0)
                    343:                        fatalerr("%s: Cannot access file: %s.",
                    344:                                 distfile, SYSERR);
                    345:                file = distfile;
                    346:        }
                    347:
                    348:        if (file == NULL)
                    349:                fatalerr("No distfile found.");
                    350:
                    351:        fp = fopen(file, "r");
                    352:
                    353:        if (fp == NULL)
                    354:                fatalerr("%s: open failed: %s.", file, SYSERR);
                    355:
                    356:        return(fp);
                    357: }
                    358:
                    359: /*
                    360:  * Print usage message and exit.
                    361:  */
1.5       millert   362: void
1.1       dm        363: usage()
                    364: {
                    365:        char *sopts = "cDFnv";
                    366:
                    367:        (void) fprintf(stderr,
                    368:                      "Usage: %s [-%s] [-A <num>] [-a <num>] [-d var=value]\n",
                    369:                       progname, sopts);
                    370:        (void) fprintf(stderr,
                    371:        "\t[-f distfile] [-l <msgopt>] [-L <msgopt>] [-M <maxproc>]\n");
                    372:        (void) fprintf(stderr,
                    373:        "\t[-m host] [-o <distopts>] [-p <rdistd-cmd>] [-P <rsh-path>]\n");
                    374:        (void) fprintf(stderr,
                    375:        "\t[-t <timeout>] [target ...]\n");
                    376:
                    377:        (void) fprintf(stderr,
                    378:                      "OR:    %s [-%s] -c source [...] machine[:dest]\n",
                    379:                       progname, sopts);
                    380:
                    381:        (void) fprintf(stderr, "OR:    %s -V\n", progname);
                    382:
                    383:        (void) fprintf(stderr, "\nThe values for <distopts> are:\n\t%s\n",
                    384:                       getdistoptlist());
                    385:
                    386:        msgprusage();
                    387:
                    388:        exit(1);
                    389: }
                    390:
                    391: /*
                    392:  * rcp like interface for distributing files.
                    393:  */
1.5       millert   394: void
1.1       dm        395: docmdargs(nargs, args)
                    396:        int nargs;
                    397:        char *args[];
                    398: {
1.9       mpech     399:        struct namelist *nl, *prev;
                    400:        char *cp;
1.1       dm        401:        struct namelist *files, *hosts;
                    402:        struct subcmd *cmds;
                    403:        char *dest;
                    404:        static struct namelist tnl = { NULL, NULL };
                    405:        int i;
                    406:
                    407:        if (nargs < 2)
                    408:                usage();
                    409:
                    410:        prev = NULL;
                    411:        files = NULL;
                    412:        for (i = 0; i < nargs - 1; i++) {
                    413:                nl = makenl(args[i]);
                    414:                if (prev == NULL)
                    415:                        files = prev = nl;
                    416:                else {
                    417:                        prev->n_next = nl;
                    418:                        prev = nl;
                    419:                }
                    420:        }
                    421:
                    422:        cp = args[i];
                    423:        if ((dest = strchr(cp, ':')) != NULL)
                    424:                *dest++ = '\0';
                    425:        tnl.n_name = cp;
                    426:        hosts = expand(&tnl, E_ALL);
                    427:        if (nerrs)
                    428:                exit(1);
                    429:
                    430:        if (dest == NULL || *dest == '\0')
                    431:                cmds = NULL;
                    432:        else {
                    433:                cmds = makesubcmd(INSTALL);
                    434:                cmds->sc_options = options;
                    435:                cmds->sc_name = dest;
                    436:        }
                    437:
                    438:        debugmsg(DM_MISC, "docmdargs()\nfiles = %s", getnlstr(files));
                    439:        debugmsg(DM_MISC, "host = %s", getnlstr(hosts));
                    440:
1.5       millert   441:        insert(NULL, files, hosts, cmds);
                    442:        docmds(0, NULL, 0, (char **)NULL);
1.1       dm        443: }
                    444:
                    445: /*
                    446:  * Get a list of NAME blocks (mostly for debugging).
                    447:  */
                    448: extern char *getnlstr(nl)
1.9       mpech     449:        struct namelist *nl;
1.1       dm        450: {
                    451:        static char buf[16384];
1.9       mpech     452:        int count = 0, len = 0;
1.1       dm        453:
1.14    ! deraadt   454:        (void) snprintf(buf, sizeof buf, "(");
1.1       dm        455:
                    456:        while (nl != NULL) {
                    457:                if (nl->n_name == NULL)
                    458:                        continue;
                    459:                len += strlen(nl->n_name) + 2;
                    460:                if (len >= sizeof(buf)) {
1.14    ! deraadt   461:                        (void) strlcpy(buf,
        !           462:                            "getnlstr() Buffer not large enough",
        !           463:                            sizeof buf);
1.1       dm        464:                        return(buf);
                    465:                }
                    466:                ++count;
1.14    ! deraadt   467:                (void) strlcat(buf, " ", sizeof buf);
        !           468:                (void) strlcat(buf, nl->n_name, sizeof buf);
1.1       dm        469:                nl = nl->n_next;
                    470:        }
                    471:
1.14    ! deraadt   472:        (void) strlcat(buf, " )", sizeof buf);
1.1       dm        473:
                    474:        return(buf);
                    475: }