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

1.7     ! millert     1: /*     $OpenBSD: rdist.c,v 1.6 1998/07/16 20:43:56 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.7     ! millert    42: "$OpenBSD: rdist.c,v 1.6 1998/07/16 20:43:56 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: #ifdef __STDC__
                     63: void           docmdargs(int, char **);
                     64: void           usage(void);
                     65: #else
                     66: void           docmdargs();
                     67: void           usage();
                     68: #endif
1.1       dm         69:
                     70: char                  *distfile = NULL;                /* Name of distfile to use */
                     71: int            maxchildren = MAXCHILDREN;      /* Max no of concurrent PIDs */
                     72: int            nflag = 0;                      /* Say without doing */
                     73: long           min_freespace = 0;              /* Min filesys free space */
                     74: long           min_freefiles = 0;              /* Min filesys free # files */
                     75: FILE                  *fin = NULL;                     /* Input file pointer */
                     76: struct group   *gr = NULL;                     /* Static area for getgrent */
                     77: char           localmsglist[] = "stdout=all:notify=all:syslog=nerror,ferror";
                     78: char                  *remotemsglist = NULL;
                     79: char           optchars[] = "A:a:bcd:DFf:hil:L:M:m:NnOo:p:P:qRrst:Vvwxy";
                     80: FILE                  *opendist();
                     81: char          *path_rdistd = _PATH_RDISTD;
1.4       millert    82: char          *path_remsh = NULL;
1.1       dm         83:
                     84: /*
                     85:  * Add a hostname to the host list
                     86:  */
                     87: static void addhostlist(name, hostlist)
                     88:        char *name;
                     89:        struct namelist **hostlist;
                     90: {
                     91:        register struct namelist *ptr, *new;
                     92:
                     93:        if (!name || !hostlist)
                     94:                return;
                     95:
                     96:        new = (struct namelist *) xmalloc(sizeof(struct namelist));
1.7     ! millert    97:        new->n_name = xstrdup(name);
1.1       dm         98:        new->n_next = NULL;
                     99:
                    100:        if (*hostlist) {
                    101:                for (ptr = *hostlist; ptr && ptr->n_next; ptr = ptr->n_next)
                    102:                        ;
                    103:                ptr->n_next = new;
                    104:        } else
                    105:                *hostlist = new;
                    106: }
                    107:
1.5       millert   108: int
1.1       dm        109: main(argc, argv, envp)
                    110:        int argc;
                    111:        char *argv[];
                    112:        char **envp;
                    113: {
                    114:        struct namelist *hostlist = NULL;
                    115:        register int x;
                    116:        register char *cp;
                    117:        int cmdargs = 0;
                    118:        int c;
                    119:
                    120:        /*
                    121:         * We initialize progname here instead of init() because
                    122:         * things in msgparseopts() need progname set.
                    123:         */
                    124:        setprogname(argv);
                    125:
1.5       millert   126:        if ((cp = msgparseopts(localmsglist, TRUE))) {
1.1       dm        127:                error("Bad builtin log option (%s): %s.",
                    128:                      localmsglist, cp);
                    129:                usage();
                    130:        }
                    131:
                    132:        if (init(argc, argv, envp) < 0)
                    133:                exit(1);
                    134:
                    135:        /*
                    136:         * Be backwards compatible.
                    137:         */
                    138:        for (x = 1; x <= argc && argv[x]; x++) {
                    139:                if (strcmp(argv[x], "-Server") != 0)
                    140:                        continue;
                    141: #if    defined(_PATH_OLDRDIST)
                    142:                message(MT_SYSLOG,
                    143:                        "Old rdist (-Server) requested; running %s",
                    144:                        _PATH_OLDRDIST);
                    145:                (void) execl(_PATH_OLDRDIST, xbasename(_PATH_OLDRDIST),
1.5       millert   146:                             "-Server", NULL);
1.1       dm        147:                fatalerr("Exec old rdist failed: %s: %s.",
                    148:                         _PATH_OLDRDIST, SYSERR);
                    149: #else  /* !_PATH_OLDRDIST */
                    150:                fatalerr("Old rdist not available.");
                    151: #endif /* _PATH_OLDRDIST */
                    152:                exit(1);
                    153:        }
                    154:
                    155: #if    defined(DIRECT_RCMD)
                    156:        if (becomeuser() != 0)
                    157:                exit(1);
                    158: #else  /* !DIRECT_RCMD */
                    159:        /*
                    160:         * Perform check to make sure we are not incorrectly installed
                    161:         * setuid to root or anybody else.
                    162:         */
                    163:        if (getuid() != geteuid())
                    164:                fatalerr("This version of rdist should not be installed setuid.");
                    165: #endif /* DIRECT_RCMD */
                    166:
                    167:        while ((c = getopt(argc, argv, optchars)) != -1)
                    168:                switch (c) {
                    169:                case 'l':
1.5       millert   170:                        if ((cp = msgparseopts(optarg, TRUE))) {
1.1       dm        171:                                error("Bad log option \"%s\": %s.", optarg,cp);
                    172:                                usage();
                    173:                        }
                    174:                        break;
                    175:
                    176:                case 'L':
1.7     ! millert   177:                        remotemsglist = xstrdup(optarg);
1.1       dm        178:                        break;
                    179:
                    180:                case 'A':
                    181:                case 'a':
                    182:                case 'M':
                    183:                case 't':
                    184:                        if (!isdigit(*optarg)) {
                    185:                                error("\"%s\" is not a number.", optarg);
                    186:                                usage();
                    187:                        }
                    188:                        if (c == 'a')
                    189:                                min_freespace = atoi(optarg);
                    190:                        else if (c == 'A')
                    191:                                min_freefiles = atoi(optarg);
                    192:                        else if (c == 'M')
                    193:                                maxchildren = atoi(optarg);
                    194:                        else if (c == 't')
                    195:                                rtimeout = atoi(optarg);
                    196:                        break;
                    197:
                    198:                case 'F':
                    199:                        do_fork = FALSE;
                    200:                        break;
                    201:
                    202:                case 'f':
1.7     ! millert   203:                        distfile = xstrdup(optarg);
1.1       dm        204:                        if (distfile[0] == '-' && distfile[1] == CNULL)
                    205:                                fin = stdin;
                    206:                        break;
                    207:
                    208:                case 'm':
                    209:                        addhostlist(optarg, &hostlist);
                    210:                        break;
                    211:
                    212:                case 'd':
                    213:                        define(optarg);
                    214:                        break;
                    215:
                    216:                case 'D':
                    217:                        debug = DM_ALL;
1.5       millert   218:                        if ((cp = msgparseopts("stdout=all,debug", TRUE))) {
1.1       dm        219:                                error("Enable debug messages failed: %s.", cp);
                    220:                                usage();
                    221:                        }
                    222:                        break;
                    223:
                    224:                case 'c':
                    225:                        cmdargs++;
                    226:                        break;
                    227:
                    228:                case 'n':
                    229:                        nflag++;
                    230:                        break;
                    231:
                    232:                case 'V':
                    233:                        printf("%s\n", getversion());
                    234:                        exit(0);
                    235:
                    236:                case 'o':
                    237:                        if (parsedistopts(optarg, &options, TRUE)) {
                    238:                                error("Bad dist option string \"%s\".",
                    239:                                      optarg);
                    240:                                usage();
                    241:                        }
                    242:                        break;
                    243:
                    244:                case 'p':
                    245:                        if (!optarg) {
                    246:                                error("No path specified to \"-p\".");
                    247:                                usage();
                    248:                        }
1.7     ! millert   249:                        path_rdistd = xstrdup(optarg);
1.1       dm        250:                        break;
                    251:
                    252:                case 'P':
                    253:                        if (!optarg) {
                    254:                                error("No path specified to \"-P\".");
                    255:                                usage();
                    256:                        }
1.5       millert   257:                        if ((cp = searchpath(optarg)))
1.7     ! millert   258:                                path_remsh = xstrdup(cp);
1.1       dm        259:                        else {
                    260:                                error("No component of path \"%s\" exists.",
                    261:                                      optarg);
                    262:                                usage();
                    263:                        }
                    264:                        break;
                    265:
                    266:                        /*
                    267:                         * These options are obsoleted by -o.  They are
                    268:                         * provided only for backwards compatibility
                    269:                         */
                    270:                case 'v':       FLAG_ON(options, DO_VERIFY);            break;
                    271:                case 'N':       FLAG_ON(options, DO_CHKNFS);            break;
                    272:                case 'O':       FLAG_ON(options, DO_CHKREADONLY);       break;
                    273:                case 'q':       FLAG_ON(options, DO_QUIET);             break;
                    274:                case 'b':       FLAG_ON(options, DO_COMPARE);           break;
                    275:                case 'r':       FLAG_ON(options, DO_NODESCEND);         break;
                    276:                case 'R':       FLAG_ON(options, DO_REMOVE);            break;
                    277:                case 's':       FLAG_ON(options, DO_SAVETARGETS);       break;
                    278:                case 'w':       FLAG_ON(options, DO_WHOLE);             break;
                    279:                case 'y':       FLAG_ON(options, DO_YOUNGER);           break;
                    280:                case 'h':       FLAG_ON(options, DO_FOLLOW);            break;
                    281:                case 'i':       FLAG_ON(options, DO_IGNLNKS);           break;
                    282:                case 'x':       FLAG_ON(options, DO_NOEXEC);            break;
                    283:
                    284:                case '?':
                    285:                default:
                    286:                        usage();
                    287:                }
                    288:
                    289:        if (debug) {
                    290:                printf("%s\n", getversion());
                    291:                msgprconfig();
                    292:        }
                    293:
                    294:        if (nflag && IS_ON(options, DO_VERIFY))
                    295:                fatalerr(
                    296:                 "The -n flag and \"verify\" mode may not both be used.");
1.4       millert   297:
                    298:        if (path_remsh == NULL)
                    299:                path_remsh = getenv("RSH");
1.1       dm        300:
                    301:        /*
                    302:         * Don't fork children for nflag
                    303:         */
                    304:        if (nflag)
                    305:                do_fork = 0;
                    306:
                    307:        if (cmdargs)
                    308:                docmdargs(realargc - optind, &realargv[optind]);
                    309:        else {
                    310:                if (fin == NULL)
                    311:                        fin = opendist(distfile);
                    312:                (void) yyparse();
                    313:                /*
                    314:                 * Need to keep stdin open for child processing later
                    315:                 */
                    316:                if (fin != stdin)
                    317:                        (void) fclose(fin);
                    318:                if (nerrs == 0)
                    319:                        docmds(hostlist, realargc-optind, &realargv[optind]);
                    320:        }
                    321:
                    322:        exit(nerrs != 0);
                    323: }
                    324:
                    325: /*
                    326:  * Open a distfile
                    327:  */
                    328: FILE *opendist(distfile)
                    329:        char *distfile;
                    330: {
                    331:        char *file = NULL;
                    332:        FILE *fp;
                    333:
                    334:        if (distfile == NULL) {
                    335:                if (access("distfile", R_OK) == 0)
                    336:                        file = "distfile";
                    337:                else if (access("Distfile", R_OK) == 0)
                    338:                        file = "Distfile";
                    339:        } else {
                    340:                /*
                    341:                 * Try to test to see if file is readable before running m4.
                    342:                 */
                    343:                if (access(distfile, R_OK) != 0)
                    344:                        fatalerr("%s: Cannot access file: %s.",
                    345:                                 distfile, SYSERR);
                    346:                file = distfile;
                    347:        }
                    348:
                    349:        if (file == NULL)
                    350:                fatalerr("No distfile found.");
                    351:
                    352:        fp = fopen(file, "r");
                    353:
                    354:        if (fp == NULL)
                    355:                fatalerr("%s: open failed: %s.", file, SYSERR);
                    356:
                    357:        return(fp);
                    358: }
                    359:
                    360: /*
                    361:  * Print usage message and exit.
                    362:  */
1.5       millert   363: void
1.1       dm        364: usage()
                    365: {
                    366:        char *sopts = "cDFnv";
                    367:
                    368:        (void) fprintf(stderr,
                    369:                      "Usage: %s [-%s] [-A <num>] [-a <num>] [-d var=value]\n",
                    370:                       progname, sopts);
                    371:        (void) fprintf(stderr,
                    372:        "\t[-f distfile] [-l <msgopt>] [-L <msgopt>] [-M <maxproc>]\n");
                    373:        (void) fprintf(stderr,
                    374:        "\t[-m host] [-o <distopts>] [-p <rdistd-cmd>] [-P <rsh-path>]\n");
                    375:        (void) fprintf(stderr,
                    376:        "\t[-t <timeout>] [target ...]\n");
                    377:
                    378:        (void) fprintf(stderr,
                    379:                      "OR:    %s [-%s] -c source [...] machine[:dest]\n",
                    380:                       progname, sopts);
                    381:
                    382:        (void) fprintf(stderr, "OR:    %s -V\n", progname);
                    383:
                    384:        (void) fprintf(stderr, "\nThe values for <distopts> are:\n\t%s\n",
                    385:                       getdistoptlist());
                    386:
                    387:        msgprusage();
                    388:
                    389:        exit(1);
                    390: }
                    391:
                    392: /*
                    393:  * rcp like interface for distributing files.
                    394:  */
1.5       millert   395: void
1.1       dm        396: docmdargs(nargs, args)
                    397:        int nargs;
                    398:        char *args[];
                    399: {
                    400:        register struct namelist *nl, *prev;
                    401:        register char *cp;
                    402:        struct namelist *files, *hosts;
                    403:        struct subcmd *cmds;
                    404:        char *dest;
                    405:        static struct namelist tnl = { NULL, NULL };
                    406:        int i;
                    407:
                    408:        if (nargs < 2)
                    409:                usage();
                    410:
                    411:        prev = NULL;
                    412:        files = NULL;
                    413:        for (i = 0; i < nargs - 1; i++) {
                    414:                nl = makenl(args[i]);
                    415:                if (prev == NULL)
                    416:                        files = prev = nl;
                    417:                else {
                    418:                        prev->n_next = nl;
                    419:                        prev = nl;
                    420:                }
                    421:        }
                    422:
                    423:        cp = args[i];
                    424:        if ((dest = strchr(cp, ':')) != NULL)
                    425:                *dest++ = '\0';
                    426:        tnl.n_name = cp;
                    427:        hosts = expand(&tnl, E_ALL);
                    428:        if (nerrs)
                    429:                exit(1);
                    430:
                    431:        if (dest == NULL || *dest == '\0')
                    432:                cmds = NULL;
                    433:        else {
                    434:                cmds = makesubcmd(INSTALL);
                    435:                cmds->sc_options = options;
                    436:                cmds->sc_name = dest;
                    437:        }
                    438:
                    439:        debugmsg(DM_MISC, "docmdargs()\nfiles = %s", getnlstr(files));
                    440:        debugmsg(DM_MISC, "host = %s", getnlstr(hosts));
                    441:
1.5       millert   442:        insert(NULL, files, hosts, cmds);
                    443:        docmds(0, NULL, 0, (char **)NULL);
1.1       dm        444: }
                    445:
                    446: /*
                    447:  * Get a list of NAME blocks (mostly for debugging).
                    448:  */
                    449: extern char *getnlstr(nl)
                    450:        register struct namelist *nl;
                    451: {
                    452:        static char buf[16384];
                    453:        register int count = 0, len = 0;
                    454:
                    455:        (void) sprintf(buf, "(");
                    456:
                    457:        while (nl != NULL) {
                    458:                if (nl->n_name == NULL)
                    459:                        continue;
                    460:                len += strlen(nl->n_name) + 2;
                    461:                if (len >= sizeof(buf)) {
                    462:                        (void) strcpy(buf,
                    463:                                      "getnlstr() Buffer not large enough");
                    464:                        return(buf);
                    465:                }
                    466:                ++count;
                    467:                (void) strcat(buf, " ");
                    468:                (void) strcat(buf, nl->n_name);
                    469:                nl = nl->n_next;
                    470:        }
                    471:
                    472:        (void) strcat(buf, " )");
                    473:
                    474:        return(buf);
                    475: }