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

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