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

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