[BACK]Return to main.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rsync

Annotation of src/usr.bin/rsync/main.c, Revision 1.42

1.42    ! schwarze    1: /*     $Id: main.c,v 1.41 2019/03/31 08:47:46 naddy Exp $ */
1.1       benno       2: /*
                      3:  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: #include <sys/stat.h>
                     18: #include <sys/socket.h>
                     19: #include <sys/wait.h>
                     20:
                     21: #include <assert.h>
                     22: #include <err.h>
                     23: #include <getopt.h>
                     24: #include <stdint.h>
                     25: #include <stdio.h>
                     26: #include <stdlib.h>
                     27: #include <string.h>
                     28: #include <unistd.h>
                     29:
                     30: #include "extern.h"
                     31:
                     32: /*
                     33:  * A remote host is has a colon before the first path separator.
                     34:  * This works for rsh remote hosts (host:/foo/bar), implicit rsync
                     35:  * remote hosts (host::/foo/bar), and explicit (rsync://host/foo).
                     36:  * Return zero if local, non-zero if remote.
                     37:  */
                     38: static int
                     39: fargs_is_remote(const char *v)
                     40: {
                     41:        size_t   pos;
                     42:
                     43:        pos = strcspn(v, ":/");
1.6       deraadt    44:        return v[pos] == ':';
1.1       benno      45: }
                     46:
                     47: /*
                     48:  * Test whether a remote host is specifically an rsync daemon.
                     49:  * Return zero if not, non-zero if so.
                     50:  */
                     51: static int
                     52: fargs_is_daemon(const char *v)
                     53: {
                     54:        size_t   pos;
                     55:
1.6       deraadt    56:        if (strncasecmp(v, "rsync://", 8) == 0)
1.1       benno      57:                return 1;
                     58:
                     59:        pos = strcspn(v, ":/");
1.6       deraadt    60:        return v[pos] == ':' && v[pos + 1] == ':';
1.1       benno      61: }
                     62:
                     63: /*
                     64:  * Take the command-line filenames (e.g., rsync foo/ bar/ baz/) and
                     65:  * determine our operating mode.
                     66:  * For example, if the first argument is a remote file, this means that
                     67:  * we're going to transfer from the remote to the local.
                     68:  * We also make sure that the arguments are consistent, that is, if
                     69:  * we're going to transfer from the local to the remote, that no
                     70:  * filenames for the local transfer indicate remote hosts.
                     71:  * Always returns the parsed and sanitised options.
                     72:  */
                     73: static struct fargs *
1.26      deraadt    74: fargs_parse(size_t argc, char *argv[], struct opts *opts)
1.1       benno      75: {
                     76:        struct fargs    *f = NULL;
1.26      deraadt    77:        char            *cp, *ccp;
1.1       benno      78:        size_t           i, j, len = 0;
                     79:
                     80:        /* Allocations. */
                     81:
1.6       deraadt    82:        if ((f = calloc(1, sizeof(struct fargs))) == NULL)
1.29      benno      83:                err(1, "calloc");
1.1       benno      84:
                     85:        f->sourcesz = argc - 1;
1.6       deraadt    86:        if ((f->sources = calloc(f->sourcesz, sizeof(char *))) == NULL)
1.29      benno      87:                err(1, "calloc");
1.1       benno      88:
                     89:        for (i = 0; i < argc - 1; i++)
1.6       deraadt    90:                if ((f->sources[i] = strdup(argv[i])) == NULL)
1.29      benno      91:                        err(1, "strdup");
1.1       benno      92:
1.6       deraadt    93:        if ((f->sink = strdup(argv[i])) == NULL)
1.29      benno      94:                err(1, "strdup");
1.1       benno      95:
                     96:        /*
                     97:         * Test files for its locality.
                     98:         * If the last is a remote host, then we're sending from the
                     99:         * local to the remote host ("sender" mode).
                    100:         * If the first, remote to local ("receiver" mode).
                    101:         * If neither, a local transfer in sender style.
                    102:         */
                    103:
                    104:        f->mode = FARGS_SENDER;
                    105:
                    106:        if (fargs_is_remote(f->sink)) {
                    107:                f->mode = FARGS_SENDER;
1.6       deraadt   108:                if ((f->host = strdup(f->sink)) == NULL)
1.29      benno     109:                        err(1, "strdup");
1.1       benno     110:        }
                    111:
                    112:        if (fargs_is_remote(f->sources[0])) {
1.6       deraadt   113:                if (f->host != NULL)
1.35      deraadt   114:                        errx(1, "both source and destination cannot be remote files");
1.1       benno     115:                f->mode = FARGS_RECEIVER;
1.6       deraadt   116:                if ((f->host = strdup(f->sources[0])) == NULL)
1.29      benno     117:                        err(1, "strdup");
1.1       benno     118:        }
                    119:
1.6       deraadt   120:        if (f->host != NULL) {
                    121:                if (strncasecmp(f->host, "rsync://", 8) == 0) {
1.30      benno     122:                        /* rsync://host[:port]/module[/path] */
1.1       benno     123:                        f->remote = 1;
                    124:                        len = strlen(f->host) - 8 + 1;
                    125:                        memmove(f->host, f->host + 8, len);
1.6       deraadt   126:                        if ((cp = strchr(f->host, '/')) == NULL)
1.35      deraadt   127:                                errx(1, "rsync protocol requires a module name");
1.1       benno     128:                        *cp++ = '\0';
                    129:                        f->module = cp;
1.6       deraadt   130:                        if ((cp = strchr(f->module, '/')) != NULL)
1.1       benno     131:                                *cp = '\0';
1.29      benno     132:                        if ((cp = strchr(f->host, ':'))) {
1.26      deraadt   133:                                /* host:port --> extract port */
                    134:                                *cp++ = '\0';
                    135:                                opts->port = cp;
                    136:                        }
1.1       benno     137:                } else {
                    138:                        /* host:[/path] */
                    139:                        cp = strchr(f->host, ':');
1.6       deraadt   140:                        assert(cp != NULL);
1.1       benno     141:                        *cp++ = '\0';
1.6       deraadt   142:                        if (*cp == ':') {
1.1       benno     143:                                /* host::module[/path] */
                    144:                                f->remote = 1;
                    145:                                f->module = ++cp;
                    146:                                cp = strchr(f->module, '/');
1.6       deraadt   147:                                if (cp != NULL)
1.1       benno     148:                                        *cp = '\0';
                    149:                        }
                    150:                }
1.6       deraadt   151:                if ((len = strlen(f->host)) == 0)
1.29      benno     152:                        errx(1, "empty remote host");
1.6       deraadt   153:                if (f->remote && strlen(f->module) == 0)
1.29      benno     154:                        errx(1, "empty remote module");
1.1       benno     155:        }
                    156:
                    157:        /* Make sure we have the same "hostspec" for all files. */
                    158:
1.4       deraadt   159:        if (!f->remote) {
1.6       deraadt   160:                if (f->mode == FARGS_SENDER)
1.1       benno     161:                        for (i = 0; i < f->sourcesz; i++) {
1.4       deraadt   162:                                if (!fargs_is_remote(f->sources[i]))
1.1       benno     163:                                        continue;
1.35      deraadt   164:                                errx(1,
                    165:                                    "remote file in list of local sources: %s",
                    166:                                    f->sources[i]);
1.1       benno     167:                        }
1.6       deraadt   168:                if (f->mode == FARGS_RECEIVER)
1.1       benno     169:                        for (i = 0; i < f->sourcesz; i++) {
                    170:                                if (fargs_is_remote(f->sources[i]) &&
1.4       deraadt   171:                                    !fargs_is_daemon(f->sources[i]))
1.1       benno     172:                                        continue;
                    173:                                if (fargs_is_daemon(f->sources[i]))
1.35      deraadt   174:                                        errx(1, "remote daemon in list of "
                    175:                                            "remote sources: %s",
                    176:                                            f->sources[i]);
                    177:                                errx(1, "local file in list of remote sources: %s",
                    178:                                    f->sources[i]);
1.1       benno     179:                        }
                    180:        } else {
1.6       deraadt   181:                if (f->mode != FARGS_RECEIVER)
1.29      benno     182:                        errx(1, "sender mode for remote "
1.1       benno     183:                                "daemon receivers not yet supported");
                    184:                for (i = 0; i < f->sourcesz; i++) {
                    185:                        if (fargs_is_daemon(f->sources[i]))
                    186:                                continue;
1.29      benno     187:                        errx(1, "non-remote daemon file "
1.1       benno     188:                                "in list of remote daemon sources: "
                    189:                                "%s", f->sources[i]);
                    190:                }
                    191:        }
                    192:
                    193:        /*
                    194:         * If we're not remote and a sender, strip our hostname.
                    195:         * Then exit if we're a sender or a local connection.
                    196:         */
                    197:
1.4       deraadt   198:        if (!f->remote) {
1.6       deraadt   199:                if (f->host == NULL)
1.1       benno     200:                        return f;
1.6       deraadt   201:                if (f->mode == FARGS_SENDER) {
                    202:                        assert(f->host != NULL);
1.1       benno     203:                        assert(len > 0);
                    204:                        j = strlen(f->sink);
                    205:                        memmove(f->sink, f->sink + len + 1, j - len);
                    206:                        return f;
1.6       deraadt   207:                } else if (f->mode != FARGS_RECEIVER)
1.1       benno     208:                        return f;
                    209:        }
                    210:
                    211:        /*
                    212:         * Now strip the hostnames from the remote host.
                    213:         *   rsync://host/module/path -> module/path
                    214:         *   host::module/path -> module/path
                    215:         *   host:path -> path
                    216:         * Also make sure that the remote hosts are the same.
                    217:         */
                    218:
1.6       deraadt   219:        assert(f->host != NULL);
1.1       benno     220:        assert(len > 0);
                    221:
                    222:        for (i = 0; i < f->sourcesz; i++) {
                    223:                cp = f->sources[i];
                    224:                j = strlen(cp);
                    225:                if (f->remote &&
1.6       deraadt   226:                    strncasecmp(cp, "rsync://", 8) == 0) {
1.1       benno     227:                        /* rsync://path */
                    228:                        cp += 8;
1.29      benno     229:                        if ((ccp = strchr(cp, ':')))    /* skip :port */
1.26      deraadt   230:                                *ccp = '\0';
1.1       benno     231:                        if (strncmp(cp, f->host, len) ||
1.11      benno     232:                            (cp[len] != '/' && cp[len] != '\0'))
1.35      deraadt   233:                                errx(1, "different remote host: %s",
                    234:                                    f->sources[i]);
1.1       benno     235:                        memmove(f->sources[i],
                    236:                                f->sources[i] + len + 8 + 1,
                    237:                                j - len - 8);
1.6       deraadt   238:                } else if (f->remote && strncmp(cp, "::", 2) == 0) {
1.1       benno     239:                        /* ::path */
                    240:                        memmove(f->sources[i],
                    241:                                f->sources[i] + 2, j - 1);
                    242:                } else if (f->remote) {
                    243:                        /* host::path */
                    244:                        if (strncmp(cp, f->host, len) ||
1.6       deraadt   245:                            (cp[len] != ':' && cp[len] != '\0'))
1.35      deraadt   246:                                errx(1, "different remote host: %s",
                    247:                                    f->sources[i]);
1.11      benno     248:                        memmove(f->sources[i], f->sources[i] + len + 2,
                    249:                            j - len - 1);
1.6       deraadt   250:                } else if (cp[0] == ':') {
1.1       benno     251:                        /* :path */
                    252:                        memmove(f->sources[i], f->sources[i] + 1, j);
                    253:                } else {
                    254:                        /* host:path */
                    255:                        if (strncmp(cp, f->host, len) ||
1.6       deraadt   256:                            (cp[len] != ':' && cp[len] != '\0'))
1.35      deraadt   257:                                errx(1, "different remote host: %s",
                    258:                                    f->sources[i]);
1.1       benno     259:                        memmove(f->sources[i],
                    260:                                f->sources[i] + len + 1, j - len);
                    261:                }
                    262:        }
                    263:
                    264:        return f;
                    265: }
                    266:
                    267: int
                    268: main(int argc, char *argv[])
                    269: {
                    270:        struct opts      opts;
1.2       benno     271:        pid_t            child;
1.41      naddy     272:        int              fds[2], sd, rc, c, st, i;
1.32      deraadt   273:        struct sess       sess;
1.1       benno     274:        struct fargs    *fargs;
1.32      deraadt   275:        char            **args;
1.1       benno     276:        struct option    lopts[] = {
1.26      deraadt   277:                { "port",       required_argument, NULL,                3 },
1.21      deraadt   278:                { "rsh",        required_argument, NULL,                'e' },
1.8       deraadt   279:                { "rsync-path", required_argument, NULL,                1 },
                    280:                { "sender",     no_argument,    &opts.sender,           1 },
                    281:                { "server",     no_argument,    &opts.server,           1 },
1.20      deraadt   282:                { "dry-run",    no_argument,    &opts.dry_run,          1 },
                    283:                { "version",    no_argument,    NULL,                   2 },
1.23      deraadt   284:                { "archive",    no_argument,    NULL,                   'a' },
1.21      deraadt   285:                { "help",       no_argument,    NULL,                   'h' },
1.36      deraadt   286:                { "compress",   no_argument,    NULL,                   'z' },
1.37      naddy     287:                { "del",        no_argument,    &opts.del,              1 },
1.20      deraadt   288:                { "delete",     no_argument,    &opts.del,              1 },
                    289:                { "devices",    no_argument,    &opts.devices,          1 },
                    290:                { "no-devices", no_argument,    &opts.devices,          0 },
                    291:                { "group",      no_argument,    &opts.preserve_gids,    1 },
                    292:                { "no-group",   no_argument,    &opts.preserve_gids,    0 },
1.8       deraadt   293:                { "links",      no_argument,    &opts.preserve_links,   1 },
1.20      deraadt   294:                { "no-links",   no_argument,    &opts.preserve_links,   0 },
                    295:                { "owner",      no_argument,    &opts.preserve_uids,    1 },
                    296:                { "no-owner",   no_argument,    &opts.preserve_uids,    0 },
1.8       deraadt   297:                { "perms",      no_argument,    &opts.preserve_perms,   1 },
1.20      deraadt   298:                { "no-perms",   no_argument,    &opts.preserve_perms,   0 },
1.31      benno     299:                { "numeric-ids", no_argument,   &opts.numeric_ids,      1 },
1.8       deraadt   300:                { "recursive",  no_argument,    &opts.recursive,        1 },
1.20      deraadt   301:                { "no-recursive", no_argument,  &opts.recursive,        0 },
1.19      florian   302:                { "specials",   no_argument,    &opts.specials,         1 },
1.21      deraadt   303:                { "no-specials", no_argument,   &opts.specials,         0 },
1.20      deraadt   304:                { "times",      no_argument,    &opts.preserve_times,   1 },
                    305:                { "no-times",   no_argument,    &opts.preserve_times,   0 },
                    306:                { "verbose",    no_argument,    &opts.verbose,          1 },
                    307:                { "no-verbose", no_argument,    &opts.verbose,          0 },
1.8       deraadt   308:                { NULL,         0,              NULL,                   0 }};
1.1       benno     309:
                    310:        /* Global pledge. */
                    311:
1.19      florian   312:        if (pledge("stdio unix rpath wpath cpath dpath inet fattr chown dns getpw proc exec unveil",
1.6       deraadt   313:            NULL) == -1)
1.29      benno     314:                err(1, "pledge");
1.1       benno     315:
                    316:        memset(&opts, 0, sizeof(struct opts));
                    317:
1.36      deraadt   318:        while ((c = getopt_long(argc, argv, "Dae:ghlnoprtvz", lopts, NULL))
1.30      benno     319:            != -1) {
1.1       benno     320:                switch (c) {
1.19      florian   321:                case 'D':
                    322:                        opts.devices = 1;
                    323:                        opts.specials = 1;
                    324:                        break;
                    325:                case 'a':
                    326:                        opts.recursive = 1;
                    327:                        opts.preserve_links = 1;
                    328:                        opts.preserve_perms = 1;
                    329:                        opts.preserve_times = 1;
                    330:                        opts.preserve_gids = 1;
                    331:                        opts.preserve_uids = 1;
                    332:                        opts.devices = 1;
                    333:                        opts.specials = 1;
                    334:                        break;
1.1       benno     335:                case 'e':
1.9       deraadt   336:                        opts.ssh_prog = optarg;
1.1       benno     337:                        break;
1.10      benno     338:                case 'g':
                    339:                        opts.preserve_gids = 1;
                    340:                        break;
1.1       benno     341:                case 'l':
                    342:                        opts.preserve_links = 1;
                    343:                        break;
                    344:                case 'n':
                    345:                        opts.dry_run = 1;
                    346:                        break;
1.13      florian   347:                case 'o':
                    348:                        opts.preserve_uids = 1;
                    349:                        break;
1.1       benno     350:                case 'p':
                    351:                        opts.preserve_perms = 1;
                    352:                        break;
                    353:                case 'r':
                    354:                        opts.recursive = 1;
                    355:                        break;
                    356:                case 't':
                    357:                        opts.preserve_times = 1;
                    358:                        break;
                    359:                case 'v':
                    360:                        opts.verbose++;
                    361:                        break;
1.36      deraadt   362:                case 'z':
                    363:                        fprintf(stderr, "%s: -z not supported yet\n", getprogname());
                    364:                        break;
1.1       benno     365:                case 0:
                    366:                        /* Non-NULL flag values (e.g., --sender). */
                    367:                        break;
                    368:                case 1:
                    369:                        opts.rsync_path = optarg;
                    370:                        break;
1.17      deraadt   371:                case 2:
                    372:                        fprintf(stderr, "openrsync: protocol version %u\n",
                    373:                            RSYNC_PROTOCOL);
                    374:                        exit(0);
1.26      deraadt   375:                case 3:
                    376:                        opts.port = optarg;
                    377:                        break;
1.21      deraadt   378:                case 'h':
1.1       benno     379:                default:
                    380:                        goto usage;
                    381:                }
                    382:        }
                    383:
                    384:        argc -= optind;
                    385:        argv += optind;
                    386:
                    387:        /* FIXME: reference implementation rsync accepts this. */
                    388:
                    389:        if (argc < 2)
                    390:                goto usage;
                    391:
1.26      deraadt   392:        if (opts.port == NULL)
1.29      benno     393:                opts.port = "rsync";
1.26      deraadt   394:
1.1       benno     395:        /*
                    396:         * This is what happens when we're started with the "hidden"
                    397:         * --server option, which is invoked for the rsync on the remote
                    398:         * host by the parent.
                    399:         */
                    400:
1.32      deraadt   401:        if (opts.server)
                    402:                exit(rsync_server(&opts, (size_t)argc, argv));
1.1       benno     403:
                    404:        /*
                    405:         * Now we know that we're the client on the local machine
                    406:         * invoking rsync(1).
                    407:         * At this point, we need to start the client and server
                    408:         * initiation logic.
                    409:         * The client is what we continue running on this host; the
                    410:         * server is what we'll use to connect to the remote and
                    411:         * invoke rsync with the --server option.
                    412:         */
                    413:
1.26      deraadt   414:        fargs = fargs_parse(argc, argv, &opts);
1.6       deraadt   415:        assert(fargs != NULL);
1.1       benno     416:
                    417:        /*
                    418:         * If we're contacting an rsync:// daemon, then we don't need to
                    419:         * fork, because we won't start a server ourselves.
1.41      naddy     420:         * Route directly into the socket code, unless a remote shell
                    421:         * has explicitly been specified.
1.1       benno     422:         */
                    423:
1.41      naddy     424:        if (fargs->remote && opts.ssh_prog == NULL) {
1.6       deraadt   425:                assert(fargs->mode == FARGS_RECEIVER);
1.41      naddy     426:                if ((rc = rsync_connect(&opts, &sd, fargs)) == 0)
                    427:                        rc = rsync_socket(&opts, sd, fargs);
                    428:                exit(rc);
1.1       benno     429:        }
                    430:
                    431:        /* Drop the dns/inet possibility. */
                    432:
1.19      florian   433:        if (pledge("stdio unix rpath wpath cpath dpath fattr chown getpw proc exec unveil",
1.6       deraadt   434:            NULL) == -1)
1.29      benno     435:                err(1, "pledge");
1.1       benno     436:
                    437:        /* Create a bidirectional socket and start our child. */
                    438:
1.6       deraadt   439:        if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds) == -1)
1.29      benno     440:                err(1, "socketpair");
1.1       benno     441:
1.32      deraadt   442:        switch ((child = fork())) {
                    443:        case -1:
                    444:                err(1, "fork");
                    445:        case 0:
1.1       benno     446:                close(fds[0]);
1.32      deraadt   447:                if (pledge("stdio exec", NULL) == -1)
                    448:                        err(1, "pledge");
                    449:
                    450:                memset(&sess, 0, sizeof(struct sess));
                    451:                sess.opts = &opts;
1.1       benno     452:
1.41      naddy     453:                if ((args = fargs_cmdline(&sess, fargs, NULL)) == NULL) {
1.32      deraadt   454:                        ERRX1(&sess, "fargs_cmdline");
                    455:                        _exit(1);
                    456:                }
1.1       benno     457:
1.32      deraadt   458:                for (i = 0; args[i] != NULL; i++)
                    459:                        LOG2(&sess, "exec[%d] = %s", i, args[i]);
1.1       benno     460:
1.32      deraadt   461:                /* Make sure the child's stdin is from the sender. */
                    462:                if (dup2(fds[1], STDIN_FILENO) == -1) {
                    463:                        ERR(&sess, "dup2");
                    464:                        _exit(1);
1.39      deraadt   465:                }
                    466:                if (dup2(fds[1], STDOUT_FILENO) == -1) {
1.32      deraadt   467:                        ERR(&sess, "dup2");
                    468:                        _exit(1);
                    469:                }
                    470:                execvp(args[0], args);
                    471:                _exit(1);
1.1       benno     472:                /* NOTREACHED */
1.32      deraadt   473:        default:
                    474:                close(fds[1]);
1.41      naddy     475:                if (!fargs->remote)
                    476:                        rc = rsync_client(&opts, fds[0], fargs);
                    477:                else
                    478:                        rc = rsync_socket(&opts, fds[0], fargs);
1.32      deraadt   479:                break;
1.1       benno     480:        }
                    481:
                    482:        /*
                    483:         * If the client has an error and exits, the server may be
                    484:         * sitting around waiting to get data while we waitpid().
                    485:         * So close the connection here so that they don't hang.
                    486:         */
                    487:
1.34      deraadt   488:        if (rc)
1.1       benno     489:                close(fds[0]);
                    490:
1.6       deraadt   491:        if (waitpid(child, &st, 0) == -1)
1.29      benno     492:                err(1, "waitpid");
1.34      deraadt   493:
                    494:        /*
                    495:         * If we don't already have an error (rc == 0), then inherit the
                    496:         * error code of rsync_server() if it has exited.
                    497:         * If it hasn't exited, it overrides our return value.
                    498:         */
                    499:
                    500:        if (WIFEXITED(st) && rc == 0)
                    501:                rc = WEXITSTATUS(st);
                    502:        else if (!WIFEXITED(st))
                    503:                rc = 1;
                    504:
1.32      deraadt   505:        exit(rc);
1.1       benno     506: usage:
1.42    ! schwarze  507:        fprintf(stderr, "usage: %s"
        !           508:            " [-aDglnoprtv] [-e program] [--del] [--port=portnumber]\n"
        !           509:            "\t[--rsync-path=program] [--version] source ... directory\n",
1.32      deraadt   510:            getprogname());
                    511:        exit(1);
1.1       benno     512: }