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

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