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

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