[BACK]Return to cmds.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / ftp

Annotation of src/usr.bin/ftp/cmds.c, Revision 1.79

1.79    ! lukem       1: /*     $NetBSD: cmds.c,v 1.78 1999/11/09 22:03:49 lukem Exp $  */
1.39      thorpej     2:
                      3: /*-
1.70      lukem       4:  * Copyright (c) 1996-1999 The NetBSD Foundation, Inc.
1.39      thorpej     5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.70      lukem       8:  * by Luke Mewburn.
                      9:  *
                     10:  * This code is derived from software contributed to The NetBSD Foundation
1.39      thorpej    11:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
                     12:  * NASA Ames Research Center.
                     13:  *
                     14:  * Redistribution and use in source and binary forms, with or without
                     15:  * modification, are permitted provided that the following conditions
                     16:  * are met:
                     17:  * 1. Redistributions of source code must retain the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer.
                     19:  * 2. Redistributions in binary form must reproduce the above copyright
                     20:  *    notice, this list of conditions and the following disclaimer in the
                     21:  *    documentation and/or other materials provided with the distribution.
                     22:  * 3. All advertising materials mentioning features or use of this software
                     23:  *    must display the following acknowledgement:
                     24:  *     This product includes software developed by the NetBSD
                     25:  *     Foundation, Inc. and its contributors.
                     26:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     27:  *    contributors may be used to endorse or promote products derived
                     28:  *    from this software without specific prior written permission.
                     29:  *
                     30:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     31:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     32:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     33:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     34:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     35:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     36:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     37:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     38:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     39:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     40:  * POSSIBILITY OF SUCH DAMAGE.
                     41:  */
1.8       tls        42:
1.1       cgd        43: /*
1.4       cgd        44:  * Copyright (c) 1985, 1989, 1993, 1994
                     45:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd        46:  *
                     47:  * Redistribution and use in source and binary forms, with or without
                     48:  * modification, are permitted provided that the following conditions
                     49:  * are met:
                     50:  * 1. Redistributions of source code must retain the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer.
                     52:  * 2. Redistributions in binary form must reproduce the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer in the
                     54:  *    documentation and/or other materials provided with the distribution.
                     55:  * 3. All advertising materials mentioning features or use of this software
                     56:  *    must display the following acknowledgement:
                     57:  *     This product includes software developed by the University of
                     58:  *     California, Berkeley and its contributors.
                     59:  * 4. Neither the name of the University nor the names of its contributors
                     60:  *    may be used to endorse or promote products derived from this software
                     61:  *    without specific prior written permission.
                     62:  *
                     63:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     64:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     65:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     66:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     67:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     68:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     69:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     70:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     71:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     72:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     73:  * SUCH DAMAGE.
                     74:  */
                     75:
1.65      lukem      76: /*
                     77:  * Copyright (C) 1997 and 1998 WIDE Project.
                     78:  * All rights reserved.
                     79:  *
                     80:  * Redistribution and use in source and binary forms, with or without
                     81:  * modification, are permitted provided that the following conditions
                     82:  * are met:
                     83:  * 1. Redistributions of source code must retain the above copyright
                     84:  *    notice, this list of conditions and the following disclaimer.
                     85:  * 2. Redistributions in binary form must reproduce the above copyright
                     86:  *    notice, this list of conditions and the following disclaimer in the
                     87:  *    documentation and/or other materials provided with the distribution.
                     88:  * 3. Neither the name of the project nor the names of its contributors
                     89:  *    may be used to endorse or promote products derived from this software
                     90:  *    without specific prior written permission.
                     91:  *
                     92:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     93:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     94:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     95:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     96:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     97:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     98:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     99:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                    100:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                    101:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                    102:  * SUCH DAMAGE.
                    103:  */
                    104:
1.25      lukem     105: #include <sys/cdefs.h>
1.1       cgd       106: #ifndef lint
1.8       tls       107: #if 0
                    108: static char sccsid[] = "@(#)cmds.c     8.6 (Berkeley) 10/9/94";
                    109: #else
1.79    ! lukem     110: __RCSID("$NetBSD: cmds.c,v 1.78 1999/11/09 22:03:49 lukem Exp $");
1.8       tls       111: #endif
1.1       cgd       112: #endif /* not lint */
                    113:
                    114: /*
                    115:  * FTP User Program -- Command Routines.
                    116:  */
1.16      lukem     117: #include <sys/types.h>
                    118: #include <sys/socket.h>
                    119: #include <sys/stat.h>
1.1       cgd       120: #include <sys/wait.h>
                    121: #include <arpa/ftp.h>
                    122:
1.4       cgd       123: #include <ctype.h>
                    124: #include <err.h>
                    125: #include <glob.h>
1.42      lukem     126: #include <limits.h>
1.4       cgd       127: #include <netdb.h>
1.67      lukem     128: #include <paths.h>
1.1       cgd       129: #include <stdio.h>
1.4       cgd       130: #include <stdlib.h>
                    131: #include <string.h>
1.35      kleink    132: #include <time.h>
1.4       cgd       133: #include <unistd.h>
1.1       cgd       134:
                    135: #include "ftp_var.h"
                    136:
                    137: struct types {
                    138:        char    *t_name;
                    139:        char    *t_mode;
                    140:        int     t_type;
                    141:        char    *t_arg;
                    142: } types[] = {
                    143:        { "ascii",      "A",    TYPE_A, 0 },
                    144:        { "binary",     "I",    TYPE_I, 0 },
                    145:        { "image",      "I",    TYPE_I, 0 },
                    146:        { "ebcdic",     "E",    TYPE_E, 0 },
                    147:        { "tenex",      "L",    TYPE_L, bytename },
1.4       cgd       148:        { NULL }
1.1       cgd       149: };
                    150:
1.74      lukem     151: sigjmp_buf      jabort;
                    152: char           *mname;
                    153:
                    154: static int     confirm __P((const char *, const char *));
                    155:
                    156: static int
                    157: confirm(cmd, file)
                    158:        const char *cmd, *file;
                    159: {
                    160:        char line[BUFSIZ];
                    161:
                    162:        if (!interactive || confirmrest)
                    163:                return (1);
                    164:        while (1) {
                    165:                fprintf(ttyout, "%s %s [anpqy?]? ", cmd, file);
                    166:                (void)fflush(ttyout);
                    167:                if (fgets(line, sizeof(line), stdin) == NULL) {
                    168:                        mflag = 0;
                    169:                        fprintf(ttyout, "\nEOF received; %s aborted\n", mname);
                    170:                        clearerr(stdin);
                    171:                        return (0);
                    172:                }
                    173:                switch (tolower(*line)) {
                    174:                        case 'a':
                    175:                                confirmrest = 1;
                    176:                                fprintf(ttyout,
                    177:                                    "Prompting off for duration of %s.\n", cmd);
                    178:                                break;
                    179:                        case 'p':
                    180:                                interactive = 0;
                    181:                                fputs("Interactive mode: off.\n", ttyout);
                    182:                                break;
                    183:                        case 'q':
                    184:                                mflag = 0;
1.76      lukem     185:                                fprintf(ttyout, "%s aborted.\n", mname);
1.75      lukem     186:                                /* FALLTHROUGH */
                    187:                        case 'n':
1.74      lukem     188:                                return (0);
                    189:                        case '?':
                    190:                                fprintf(ttyout,
1.76      lukem     191:                                    "  confirmation options:\n"
1.74      lukem     192:                                    "\ta  answer `yes' for the duration of %s\n"
                    193:                                    "\tn  answer `no' for this file\n"
                    194:                                    "\tp  turn off `prompt' mode\n"
                    195:                                    "\tq  stop the current %s\n"
                    196:                                    "\ty  answer `yes' for this file\n"
                    197:                                    "\t?  this help list\n",
                    198:                                    cmd, cmd);
1.75      lukem     199:                                continue;       /* back to while(1) */
1.74      lukem     200:                }
1.75      lukem     201:                return (1);
1.74      lukem     202:        }
                    203:        /* NOTREACHED */
                    204: }
                    205:
1.1       cgd       206: /*
                    207:  * Set transfer type.
                    208:  */
1.4       cgd       209: void
1.1       cgd       210: settype(argc, argv)
                    211:        int argc;
                    212:        char *argv[];
                    213: {
1.4       cgd       214:        struct types *p;
1.1       cgd       215:        int comret;
                    216:
1.76      lukem     217:        if ((argc == 0 && argv != NULL) || argc > 2) {
1.1       cgd       218:                char *sep;
                    219:
1.37      lukem     220:                fprintf(ttyout, "usage: %s [", argv[0]);
1.1       cgd       221:                sep = " ";
                    222:                for (p = types; p->t_name; p++) {
1.37      lukem     223:                        fprintf(ttyout, "%s%s", sep, p->t_name);
1.1       cgd       224:                        sep = " | ";
                    225:                }
1.37      lukem     226:                fputs(" ]\n", ttyout);
1.1       cgd       227:                code = -1;
                    228:                return;
                    229:        }
                    230:        if (argc < 2) {
1.37      lukem     231:                fprintf(ttyout, "Using %s mode to transfer files.\n", typename);
1.1       cgd       232:                code = 0;
                    233:                return;
                    234:        }
                    235:        for (p = types; p->t_name; p++)
                    236:                if (strcmp(argv[1], p->t_name) == 0)
                    237:                        break;
                    238:        if (p->t_name == 0) {
1.37      lukem     239:                fprintf(ttyout, "%s: unknown mode.\n", argv[1]);
1.1       cgd       240:                code = -1;
                    241:                return;
                    242:        }
                    243:        if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
1.19      lukem     244:                comret = command("TYPE %s %s", p->t_mode, p->t_arg);
1.1       cgd       245:        else
                    246:                comret = command("TYPE %s", p->t_mode);
                    247:        if (comret == COMPLETE) {
1.63      lukem     248:                (void)strlcpy(typename, p->t_name, sizeof(typename));
1.1       cgd       249:                curtype = type = p->t_type;
                    250:        }
                    251: }
                    252:
                    253: /*
                    254:  * Internal form of settype; changes current type in use with server
                    255:  * without changing our notion of the type for data transfers.
                    256:  * Used to change to and from ascii for listings.
                    257:  */
1.4       cgd       258: void
1.1       cgd       259: changetype(newtype, show)
                    260:        int newtype, show;
                    261: {
1.4       cgd       262:        struct types *p;
1.1       cgd       263:        int comret, oldverbose = verbose;
                    264:
                    265:        if (newtype == 0)
                    266:                newtype = TYPE_I;
                    267:        if (newtype == curtype)
                    268:                return;
                    269:        if (debug == 0 && show == 0)
                    270:                verbose = 0;
                    271:        for (p = types; p->t_name; p++)
                    272:                if (newtype == p->t_type)
                    273:                        break;
                    274:        if (p->t_name == 0) {
1.19      lukem     275:                warnx("internal error: unknown type %d.", newtype);
1.1       cgd       276:                return;
                    277:        }
                    278:        if (newtype == TYPE_L && bytename[0] != '\0')
                    279:                comret = command("TYPE %s %s", p->t_mode, bytename);
                    280:        else
                    281:                comret = command("TYPE %s", p->t_mode);
                    282:        if (comret == COMPLETE)
                    283:                curtype = newtype;
                    284:        verbose = oldverbose;
                    285: }
                    286:
                    287: char *stype[] = {
                    288:        "type",
                    289:        "",
                    290:        0
                    291: };
                    292:
                    293: /*
                    294:  * Set binary transfer type.
                    295:  */
                    296: /*VARARGS*/
1.4       cgd       297: void
                    298: setbinary(argc, argv)
                    299:        int argc;
1.10      lukem     300:        char *argv[];
1.1       cgd       301: {
1.4       cgd       302:
1.76      lukem     303:        if (argc == 0 && argv != NULL) {
                    304:                fprintf(ttyout, "usage: %s\n", argv[0]);
                    305:                code = -1;
                    306:                return;
                    307:        }
1.1       cgd       308:        stype[1] = "binary";
                    309:        settype(2, stype);
                    310: }
                    311:
                    312: /*
                    313:  * Set ascii transfer type.
                    314:  */
                    315: /*VARARGS*/
1.4       cgd       316: void
                    317: setascii(argc, argv)
                    318:        int argc;
                    319:        char *argv[];
1.1       cgd       320: {
1.4       cgd       321:
1.76      lukem     322:        if (argc == 0 && argv != NULL) {
                    323:                fprintf(ttyout, "usage: %s\n", argv[0]);
                    324:                code = -1;
                    325:                return;
                    326:        }
1.1       cgd       327:        stype[1] = "ascii";
                    328:        settype(2, stype);
                    329: }
                    330:
                    331: /*
                    332:  * Set tenex transfer type.
                    333:  */
                    334: /*VARARGS*/
1.4       cgd       335: void
                    336: settenex(argc, argv)
                    337:        int argc;
                    338:        char *argv[];
1.1       cgd       339: {
1.4       cgd       340:
1.76      lukem     341:        if (argc == 0 && argv != NULL) {
                    342:                fprintf(ttyout, "usage: %s\n", argv[0]);
                    343:                code = -1;
                    344:                return;
                    345:        }
1.1       cgd       346:        stype[1] = "tenex";
                    347:        settype(2, stype);
                    348: }
                    349:
                    350: /*
                    351:  * Set file transfer mode.
                    352:  */
                    353: /*ARGSUSED*/
1.4       cgd       354: void
                    355: setftmode(argc, argv)
1.1       cgd       356:        int argc;
                    357:        char *argv[];
                    358: {
                    359:
1.76      lukem     360:        if ((argc == 0 && argv != NULL) || argc != 2) {
                    361:                fprintf(ttyout, "usage: %s mode-name\n", argv[0]);
                    362:                code = -1;
                    363:                return;
                    364:        }
1.37      lukem     365:        fprintf(ttyout, "We only support %s mode, sorry.\n", modename);
1.1       cgd       366:        code = -1;
                    367: }
                    368:
                    369: /*
                    370:  * Set file transfer format.
                    371:  */
                    372: /*ARGSUSED*/
1.4       cgd       373: void
1.1       cgd       374: setform(argc, argv)
                    375:        int argc;
                    376:        char *argv[];
                    377: {
                    378:
1.76      lukem     379:        if ((argc == 0 && argv != NULL) || argc != 2) {
                    380:                fprintf(ttyout, "usage: %s format\n", argv[0]);
                    381:                code = -1;
                    382:                return;
                    383:        }
1.37      lukem     384:        fprintf(ttyout, "We only support %s format, sorry.\n", formname);
1.1       cgd       385:        code = -1;
                    386: }
                    387:
                    388: /*
                    389:  * Set file transfer structure.
                    390:  */
                    391: /*ARGSUSED*/
1.4       cgd       392: void
1.1       cgd       393: setstruct(argc, argv)
                    394:        int argc;
                    395:        char *argv[];
                    396: {
                    397:
1.76      lukem     398:        if ((argc == 0 && argv != NULL) || argc != 2) {
                    399:                fprintf(ttyout, "usage: %s struct-mode\n", argv[0]);
                    400:                code = -1;
                    401:                return;
                    402:        }
1.37      lukem     403:        fprintf(ttyout, "We only support %s structure, sorry.\n", structname);
1.1       cgd       404:        code = -1;
                    405: }
                    406:
                    407: /*
                    408:  * Send a single file.
                    409:  */
1.4       cgd       410: void
1.1       cgd       411: put(argc, argv)
                    412:        int argc;
                    413:        char *argv[];
                    414: {
                    415:        char *cmd;
                    416:        int loc = 0;
1.63      lukem     417:        char *locfile, *remfile;
1.1       cgd       418:
                    419:        if (argc == 2) {
                    420:                argc++;
                    421:                argv[2] = argv[1];
                    422:                loc++;
                    423:        }
1.76      lukem     424:        if ((argc == 0 && argv != NULL) ||
                    425:            (argc == 1 && !another(&argc, &argv, "local-file")))
1.1       cgd       426:                goto usage;
1.10      lukem     427:        if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
1.1       cgd       428: usage:
1.76      lukem     429:                fprintf(ttyout, "usage: %s local-file [remote-file]\n",
1.37      lukem     430:                    argv[0]);
1.1       cgd       431:                code = -1;
                    432:                return;
                    433:        }
1.63      lukem     434:        if ((locfile = globulize(argv[1])) == NULL) {
1.1       cgd       435:                code = -1;
                    436:                return;
                    437:        }
1.63      lukem     438:        remfile = argv[2];
                    439:        if (loc)        /* If argv[2] is a copy of the old argv[1], update it */
                    440:                remfile = locfile;
1.1       cgd       441:        cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
1.63      lukem     442:        if (loc && ntflag)
                    443:                remfile = dotrans(remfile);
                    444:        if (loc && mapflag)
                    445:                remfile = domap(remfile);
                    446:        sendrequest(cmd, locfile, remfile,
                    447:            locfile != argv[1] || remfile != argv[2]);
                    448:        free(locfile);
1.1       cgd       449: }
                    450:
                    451: /*
                    452:  * Send multiple files.
                    453:  */
1.4       cgd       454: void
1.1       cgd       455: mput(argc, argv)
                    456:        int argc;
1.10      lukem     457:        char *argv[];
1.1       cgd       458: {
1.4       cgd       459:        int i;
1.1       cgd       460:        sig_t oldintr;
                    461:        int ointer;
                    462:        char *tp;
                    463:
1.76      lukem     464:        if ((argc == 0 && argv != NULL) ||
                    465:            (argc == 1 && !another(&argc, &argv, "local-files"))) {
1.37      lukem     466:                fprintf(ttyout, "usage: %s local-files\n", argv[0]);
1.1       cgd       467:                code = -1;
                    468:                return;
                    469:        }
                    470:        mname = argv[0];
                    471:        mflag = 1;
1.72      lukem     472:        oldintr = xsignal(SIGINT, mintr);
                    473:        if (sigsetjmp(jabort, 1))
                    474:                mabort();
1.1       cgd       475:        if (proxy) {
1.63      lukem     476:                char *cp;
1.1       cgd       477:
1.19      lukem     478:                while ((cp = remglob(argv, 0, NULL)) != NULL) {
1.76      lukem     479:                        if (*cp == '\0' || !connected) {
1.1       cgd       480:                                mflag = 0;
                    481:                                continue;
                    482:                        }
                    483:                        if (mflag && confirm(argv[0], cp)) {
                    484:                                tp = cp;
1.63      lukem     485:                                if (mcase)
                    486:                                        tp = docase(tp);
                    487:                                if (ntflag)
1.1       cgd       488:                                        tp = dotrans(tp);
1.63      lukem     489:                                if (mapflag)
1.1       cgd       490:                                        tp = domap(tp);
                    491:                                sendrequest((sunique) ? "STOU" : "STOR",
                    492:                                    cp, tp, cp != tp || !interactive);
                    493:                                if (!mflag && fromatty) {
                    494:                                        ointer = interactive;
                    495:                                        interactive = 1;
1.10      lukem     496:                                        if (confirm("Continue with", "mput")) {
1.1       cgd       497:                                                mflag++;
                    498:                                        }
                    499:                                        interactive = ointer;
                    500:                                }
                    501:                        }
                    502:                }
1.72      lukem     503:                goto cleanupmput;
1.1       cgd       504:        }
1.76      lukem     505:        for (i = 1; i < argc && connected; i++) {
1.9       lukem     506:                char **cpp;
1.4       cgd       507:                glob_t gl;
                    508:                int flags;
1.1       cgd       509:
                    510:                if (!doglob) {
                    511:                        if (mflag && confirm(argv[0], argv[i])) {
                    512:                                tp = (ntflag) ? dotrans(argv[i]) : argv[i];
                    513:                                tp = (mapflag) ? domap(tp) : tp;
                    514:                                sendrequest((sunique) ? "STOU" : "STOR",
                    515:                                    argv[i], tp, tp != argv[i] || !interactive);
                    516:                                if (!mflag && fromatty) {
                    517:                                        ointer = interactive;
                    518:                                        interactive = 1;
1.10      lukem     519:                                        if (confirm("Continue with", "mput")) {
1.1       cgd       520:                                                mflag++;
                    521:                                        }
                    522:                                        interactive = ointer;
                    523:                                }
                    524:                        }
                    525:                        continue;
                    526:                }
1.4       cgd       527:
                    528:                memset(&gl, 0, sizeof(gl));
1.38      kleink    529:                flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;
1.4       cgd       530:                if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
                    531:                        warnx("%s: not found", argv[i]);
                    532:                        globfree(&gl);
1.1       cgd       533:                        continue;
                    534:                }
1.76      lukem     535:                for (cpp = gl.gl_pathv; cpp && *cpp != NULL && connected;
                    536:                    cpp++) {
1.1       cgd       537:                        if (mflag && confirm(argv[0], *cpp)) {
                    538:                                tp = (ntflag) ? dotrans(*cpp) : *cpp;
                    539:                                tp = (mapflag) ? domap(tp) : tp;
                    540:                                sendrequest((sunique) ? "STOU" : "STOR",
                    541:                                    *cpp, tp, *cpp != tp || !interactive);
                    542:                                if (!mflag && fromatty) {
                    543:                                        ointer = interactive;
                    544:                                        interactive = 1;
1.10      lukem     545:                                        if (confirm("Continue with", "mput")) {
1.1       cgd       546:                                                mflag++;
                    547:                                        }
                    548:                                        interactive = ointer;
                    549:                                }
                    550:                        }
                    551:                }
1.4       cgd       552:                globfree(&gl);
1.1       cgd       553:        }
1.72      lukem     554: cleanupmput:
1.62      lukem     555:        (void)xsignal(SIGINT, oldintr);
1.1       cgd       556:        mflag = 0;
                    557: }
                    558:
1.4       cgd       559: void
1.1       cgd       560: reget(argc, argv)
                    561:        int argc;
                    562:        char *argv[];
                    563: {
1.4       cgd       564:
1.19      lukem     565:        (void)getit(argc, argv, 1, "r+w");
1.1       cgd       566: }
                    567:
1.4       cgd       568: void
1.1       cgd       569: get(argc, argv)
                    570:        int argc;
                    571:        char *argv[];
                    572: {
1.4       cgd       573:
1.19      lukem     574:        (void)getit(argc, argv, 0, restart_point ? "r+w" : "w" );
1.1       cgd       575: }
                    576:
                    577: /*
                    578:  * Receive one file.
                    579:  */
1.4       cgd       580: int
1.1       cgd       581: getit(argc, argv, restartit, mode)
                    582:        int argc;
                    583:        char *argv[];
1.4       cgd       584:        int restartit;
1.10      lukem     585:        const char *mode;
1.1       cgd       586: {
                    587:        int loc = 0;
1.27      lukem     588:        int rval = 0;
1.63      lukem     589:        char *remfile, *locfile, *olocfile;
1.1       cgd       590:
                    591:        if (argc == 2) {
                    592:                argc++;
                    593:                argv[2] = argv[1];
                    594:                loc++;
                    595:        }
1.76      lukem     596:        if ((argc == 0 && argv != NULL) ||
                    597:            (argc == 1 && !another(&argc, &argv, "remote-file")))
1.1       cgd       598:                goto usage;
1.10      lukem     599:        if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) {
1.1       cgd       600: usage:
1.76      lukem     601:                fprintf(ttyout, "usage: %s remote-file [local-file]\n",
1.37      lukem     602:                    argv[0]);
1.1       cgd       603:                code = -1;
                    604:                return (0);
                    605:        }
1.63      lukem     606:        remfile = argv[1];
                    607:        if ((olocfile = globulize(argv[2])) == NULL) {
1.1       cgd       608:                code = -1;
                    609:                return (0);
                    610:        }
1.63      lukem     611:        locfile = olocfile;
                    612:        if (loc && mcase)
                    613:                locfile = docase(locfile);
1.1       cgd       614:        if (loc && ntflag)
1.63      lukem     615:                locfile = dotrans(locfile);
1.1       cgd       616:        if (loc && mapflag)
1.63      lukem     617:                locfile = domap(locfile);
1.1       cgd       618:        if (restartit) {
                    619:                struct stat stbuf;
                    620:                int ret;
                    621:
1.63      lukem     622:                ret = stat(locfile, &stbuf);
1.1       cgd       623:                if (restartit == 1) {
                    624:                        if (ret < 0) {
1.63      lukem     625:                                warn("local: %s", locfile);
1.27      lukem     626:                                goto freegetit;
1.1       cgd       627:                        }
                    628:                        restart_point = stbuf.st_size;
                    629:                } else {
                    630:                        if (ret == 0) {
1.10      lukem     631:                                time_t mtime;
1.1       cgd       632:
1.13      lukem     633:                                mtime = remotemodtime(argv[1], 0);
1.10      lukem     634:                                if (mtime == -1)
1.27      lukem     635:                                        goto freegetit;
                    636:                                if (stbuf.st_mtime >= mtime) {
                    637:                                        rval = 1;
                    638:                                        goto freegetit;
                    639:                                }
1.1       cgd       640:                        }
                    641:                }
                    642:        }
                    643:
1.63      lukem     644:        recvrequest("RETR", locfile, remfile, mode,
                    645:            remfile != argv[1] || locfile != argv[2], loc);
1.1       cgd       646:        restart_point = 0;
1.27      lukem     647: freegetit:
1.63      lukem     648:        (void)free(olocfile);
1.27      lukem     649:        return (rval);
1.1       cgd       650: }
                    651:
1.4       cgd       652: /* ARGSUSED */
1.1       cgd       653: void
1.72      lukem     654: mintr(signo)
1.4       cgd       655:        int signo;
1.1       cgd       656: {
1.72      lukem     657:
                    658:        alarmtimer(0);
1.74      lukem     659:        if (fromatty)
                    660:                write(fileno(ttyout), "\n", 1);
1.72      lukem     661:        siglongjmp(jabort, 1);
                    662: }
                    663:
                    664: void
                    665: mabort()
                    666: {
1.10      lukem     667:        int ointer, oconf;
1.1       cgd       668:
                    669:        if (mflag && fromatty) {
                    670:                ointer = interactive;
1.10      lukem     671:                oconf = confirmrest;
1.1       cgd       672:                interactive = 1;
1.10      lukem     673:                confirmrest = 0;
1.1       cgd       674:                if (confirm("Continue with", mname)) {
                    675:                        interactive = ointer;
1.10      lukem     676:                        confirmrest = oconf;
1.72      lukem     677:                        return;
1.1       cgd       678:                }
                    679:                interactive = ointer;
1.10      lukem     680:                confirmrest = oconf;
1.1       cgd       681:        }
                    682:        mflag = 0;
                    683: }
                    684:
                    685: /*
                    686:  * Get multiple files.
                    687:  */
1.4       cgd       688: void
1.1       cgd       689: mget(argc, argv)
                    690:        int argc;
1.10      lukem     691:        char *argv[];
1.1       cgd       692: {
                    693:        sig_t oldintr;
1.4       cgd       694:        int ch, ointer;
1.1       cgd       695:        char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];
                    696:
1.76      lukem     697:        if ((argc == 0 && argv != NULL) ||
                    698:            (argc == 1 && !another(&argc, &argv, "remote-files"))) {
1.37      lukem     699:                fprintf(ttyout, "usage: %s remote-files\n", argv[0]);
1.1       cgd       700:                code = -1;
                    701:                return;
                    702:        }
                    703:        mname = argv[0];
                    704:        mflag = 1;
1.72      lukem     705:        oldintr = xsignal(SIGINT, mintr);
                    706:        if (sigsetjmp(jabort, 1))
                    707:                mabort();
1.19      lukem     708:        while ((cp = remglob(argv, proxy, NULL)) != NULL) {
1.76      lukem     709:                if (*cp == '\0' || !connected) {
1.1       cgd       710:                        mflag = 0;
                    711:                        continue;
                    712:                }
                    713:                if (mflag && confirm(argv[0], cp)) {
                    714:                        tp = cp;
                    715:                        if (mcase) {
1.24      pk        716:                                for (tp2 = tmpbuf; (ch = *tp++) != 0; )
1.4       cgd       717:                                        *tp2++ = isupper(ch) ? tolower(ch) : ch;
1.7       jtc       718:                                *tp2 = '\0';
1.1       cgd       719:                                tp = tmpbuf;
                    720:                        }
                    721:                        if (ntflag) {
                    722:                                tp = dotrans(tp);
                    723:                        }
                    724:                        if (mapflag) {
                    725:                                tp = domap(tp);
                    726:                        }
                    727:                        recvrequest("RETR", tp, cp, "w",
1.27      lukem     728:                            tp != cp || !interactive, 1);
1.1       cgd       729:                        if (!mflag && fromatty) {
                    730:                                ointer = interactive;
                    731:                                interactive = 1;
1.10      lukem     732:                                if (confirm("Continue with", "mget")) {
1.1       cgd       733:                                        mflag++;
                    734:                                }
                    735:                                interactive = ointer;
                    736:                        }
                    737:                }
                    738:        }
1.62      lukem     739:        (void)xsignal(SIGINT, oldintr);
1.1       cgd       740:        mflag = 0;
                    741: }
                    742:
                    743: char *
                    744: onoff(bool)
                    745:        int bool;
                    746: {
                    747:
                    748:        return (bool ? "on" : "off");
                    749: }
                    750:
                    751: /*
                    752:  * Show status.
                    753:  */
                    754: /*ARGSUSED*/
1.4       cgd       755: void
1.1       cgd       756: status(argc, argv)
                    757:        int argc;
                    758:        char *argv[];
                    759: {
                    760:        int i;
                    761:
1.76      lukem     762:        if (argc == 0 && argv != NULL) {
                    763:                fprintf(ttyout, "usage: %s\n", argv[0]);
                    764:                code = -1;
                    765:                return;
                    766:        }
1.1       cgd       767:        if (connected)
1.37      lukem     768:                fprintf(ttyout, "Connected %sto %s.\n",
1.23      lukem     769:                    connected == -1 ? "and logged in" : "", hostname);
1.1       cgd       770:        else
1.37      lukem     771:                fputs("Not connected.\n", ttyout);
1.1       cgd       772:        if (!proxy) {
                    773:                pswitch(1);
                    774:                if (connected) {
1.37      lukem     775:                        fprintf(ttyout, "Connected for proxy commands to %s.\n",
1.10      lukem     776:                            hostname);
1.1       cgd       777:                }
                    778:                else {
1.37      lukem     779:                        fputs("No proxy connection.\n", ttyout);
1.1       cgd       780:                }
                    781:                pswitch(0);
                    782:        }
1.54      itojun    783:        fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n", onoff(gatemode),
                    784:            *gateserver ? gateserver : "(none)", gateport);
1.76      lukem     785:        fprintf(ttyout, "Passive mode: %s; fallback to active mode: %s.\n",
                    786:            onoff(passivemode), onoff(activefallback));
1.37      lukem     787:        fprintf(ttyout, "Mode: %s; Type: %s; Form: %s; Structure: %s.\n",
                    788:            modename, typename, formname, structname);
                    789:        fprintf(ttyout, "Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s.\n",
                    790:            onoff(verbose), onoff(bell), onoff(interactive), onoff(doglob));
                    791:        fprintf(ttyout, "Store unique: %s; Receive unique: %s.\n",
                    792:            onoff(sunique), onoff(runique));
                    793:        fprintf(ttyout, "Preserve modification times: %s.\n", onoff(preserve));
                    794:        fprintf(ttyout, "Case: %s; CR stripping: %s.\n", onoff(mcase),
                    795:            onoff(crflag));
1.1       cgd       796:        if (ntflag) {
1.37      lukem     797:                fprintf(ttyout, "Ntrans: (in) %s (out) %s\n", ntin, ntout);
1.1       cgd       798:        }
                    799:        else {
1.37      lukem     800:                fputs("Ntrans: off.\n", ttyout);
1.1       cgd       801:        }
                    802:        if (mapflag) {
1.37      lukem     803:                fprintf(ttyout, "Nmap: (in) %s (out) %s\n", mapin, mapout);
1.1       cgd       804:        }
                    805:        else {
1.37      lukem     806:                fputs("Nmap: off.\n", ttyout);
1.1       cgd       807:        }
1.37      lukem     808:        fprintf(ttyout,
                    809:            "Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n",
1.11      lukem     810:            onoff(hash), mark, onoff(progress));
1.52      lukem     811:        fprintf(ttyout,
                    812:            "Get transfer rate throttle: %s; maximum: %d; increment %d.\n",
                    813:            onoff(rate_get), rate_get, rate_get_incr);
                    814:        fprintf(ttyout,
                    815:            "Put transfer rate throttle: %s; maximum: %d; increment %d.\n",
                    816:            onoff(rate_put), rate_put, rate_put_incr);
1.58      lukem     817:        fprintf(ttyout,
                    818:            "Socket buffer sizes: send %d, receive %d.\n",
                    819:            sndbuf_size, rcvbuf_size);
1.37      lukem     820:        fprintf(ttyout, "Use of PORT cmds: %s.\n", onoff(sendport));
1.68      lukem     821:        fprintf(ttyout, "Use of EPSV/EPRT cmds for IPv4: %s%s.\n", onoff(epsv4),
                    822:            epsv4bad ? " (disabled for this connection)" : "");
1.69      lukem     823:        fprintf(ttyout, "Command line editing: %s.\n",
                    824: #ifdef NO_EDITCOMPLETE
                    825:            "support not compiled in"
                    826: #else  /* !def NO_EDITCOMPLETE */
                    827:            onoff(editing)
                    828: #endif /* !def NO_EDITCOMPLETE */
                    829:            );
1.78      lukem     830:        fprintf(ttyout, "Version: %s %s\n", FTP_PRODUCT, FTP_VERSION);
1.1       cgd       831:        if (macnum > 0) {
1.37      lukem     832:                fputs("Macros:\n", ttyout);
1.1       cgd       833:                for (i=0; i<macnum; i++) {
1.37      lukem     834:                        fprintf(ttyout, "\t%s\n", macros[i].mac_name);
1.1       cgd       835:                }
                    836:        }
                    837:        code = 0;
                    838: }
                    839:
                    840: /*
1.10      lukem     841:  * Toggle a variable
                    842:  */
                    843: int
                    844: togglevar(argc, argv, var, mesg)
                    845:        int   argc;
                    846:        char *argv[];
                    847:        int  *var;
                    848:        const char *mesg;
                    849: {
1.76      lukem     850:        if (argc == 1) {
1.10      lukem     851:                *var = !*var;
                    852:        } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) {
                    853:                *var = 1;
                    854:        } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) {
                    855:                *var = 0;
                    856:        } else {
1.37      lukem     857:                fprintf(ttyout, "usage: %s [ on | off ]\n", argv[0]);
1.19      lukem     858:                return (-1);
1.10      lukem     859:        }
1.46      lukem     860:        if (mesg)
1.37      lukem     861:                fprintf(ttyout, "%s %s.\n", mesg, onoff(*var));
1.19      lukem     862:        return (*var);
1.10      lukem     863: }
                    864:
                    865: /*
1.1       cgd       866:  * Set beep on cmd completed mode.
                    867:  */
                    868: /*VARARGS*/
1.4       cgd       869: void
                    870: setbell(argc, argv)
                    871:        int argc;
                    872:        char *argv[];
1.1       cgd       873: {
                    874:
1.10      lukem     875:        code = togglevar(argc, argv, &bell, "Bell mode");
1.1       cgd       876: }
                    877:
1.16      lukem     878: /*
                    879:  * Set command line editing
                    880:  */
                    881: /*VARARGS*/
                    882: void
                    883: setedit(argc, argv)
                    884:        int argc;
                    885:        char *argv[];
                    886: {
                    887:
1.69      lukem     888: #ifdef NO_EDITCOMPLETE
1.76      lukem     889:        if (argc == 0 && argv != NULL) {
                    890:                fprintf(ttyout, "usage: %s\n", argv[0]);
                    891:                code = -1;
                    892:                return;
                    893:        }
1.69      lukem     894:        if (verbose)
                    895:                fputs("Editing support not compiled in; ignoring command.\n",
                    896:                    ttyout);
                    897: #else  /* !def NO_EDITCOMPLETE */
1.16      lukem     898:        code = togglevar(argc, argv, &editing, "Editing mode");
1.22      lukem     899:        controlediting();
1.69      lukem     900: #endif /* !def NO_EDITCOMPLETE */
1.16      lukem     901: }
                    902:
1.1       cgd       903: /*
                    904:  * Turn on packet tracing.
                    905:  */
                    906: /*VARARGS*/
1.4       cgd       907: void
                    908: settrace(argc, argv)
                    909:        int argc;
                    910:        char *argv[];
1.1       cgd       911: {
                    912:
1.10      lukem     913:        code = togglevar(argc, argv, &trace, "Packet tracing");
1.1       cgd       914: }
                    915:
                    916: /*
1.9       lukem     917:  * Toggle hash mark printing during transfers, or set hash mark bytecount.
1.1       cgd       918:  */
                    919: /*VARARGS*/
1.4       cgd       920: void
                    921: sethash(argc, argv)
                    922:        int argc;
                    923:        char *argv[];
1.1       cgd       924: {
1.10      lukem     925:        if (argc == 1)
1.9       lukem     926:                hash = !hash;
1.10      lukem     927:        else if (argc != 2) {
1.37      lukem     928:                fprintf(ttyout, "usage: %s [ on | off | bytecount ]\n",
                    929:                    argv[0]);
1.10      lukem     930:                code = -1;
                    931:                return;
                    932:        } else if (strcasecmp(argv[1], "on") == 0)
                    933:                hash = 1;
                    934:        else if (strcasecmp(argv[1], "off") == 0)
                    935:                hash = 0;
                    936:        else {
1.31      lukem     937:                int nmark;
                    938:
1.52      lukem     939:                nmark = strsuftoi(argv[1]);
                    940:                if (nmark < 1) {
1.37      lukem     941:                        fprintf(ttyout, "mark: bad bytecount value `%s'.\n",
                    942:                            argv[1]);
1.10      lukem     943:                        code = -1;
                    944:                        return;
1.9       lukem     945:                }
1.10      lukem     946:                mark = nmark;
                    947:                hash = 1;
1.9       lukem     948:        }
1.37      lukem     949:        fprintf(ttyout, "Hash mark printing %s", onoff(hash));
1.10      lukem     950:        if (hash)
1.37      lukem     951:                fprintf(ttyout, " (%d bytes/hash mark)", mark);
                    952:        fputs(".\n", ttyout);
1.44      lukem     953:        if (hash)
                    954:                progress = 0;
1.10      lukem     955:        code = hash;
1.1       cgd       956: }
                    957:
                    958: /*
                    959:  * Turn on printing of server echo's.
                    960:  */
                    961: /*VARARGS*/
1.4       cgd       962: void
                    963: setverbose(argc, argv)
                    964:        int argc;
                    965:        char *argv[];
1.1       cgd       966: {
                    967:
1.10      lukem     968:        code = togglevar(argc, argv, &verbose, "Verbose mode");
1.1       cgd       969: }
                    970:
                    971: /*
1.54      itojun    972:  * Toggle PORT/LPRT cmd use before each data connection.
1.1       cgd       973:  */
                    974: /*VARARGS*/
1.4       cgd       975: void
                    976: setport(argc, argv)
                    977:        int argc;
                    978:        char *argv[];
1.1       cgd       979: {
                    980:
1.54      itojun    981:        code = togglevar(argc, argv, &sendport, "Use of PORT/LPRT cmds");
1.1       cgd       982: }
                    983:
                    984: /*
1.11      lukem     985:  * Toggle transfer progress bar.
                    986:  */
                    987: /*VARARGS*/
                    988: void
                    989: setprogress(argc, argv)
                    990:        int argc;
                    991:        char *argv[];
                    992: {
                    993:
                    994:        code = togglevar(argc, argv, &progress, "Progress bar");
1.44      lukem     995:        if (progress)
                    996:                hash = 0;
1.11      lukem     997: }
                    998:
                    999: /*
1.27      lukem    1000:  * Turn on interactive prompting during mget, mput, and mdelete.
1.1       cgd      1001:  */
                   1002: /*VARARGS*/
1.4       cgd      1003: void
                   1004: setprompt(argc, argv)
                   1005:        int argc;
                   1006:        char *argv[];
1.1       cgd      1007: {
                   1008:
1.10      lukem    1009:        code = togglevar(argc, argv, &interactive, "Interactive mode");
1.1       cgd      1010: }
                   1011:
                   1012: /*
1.27      lukem    1013:  * Toggle gate-ftp mode, or set gate-ftp server
                   1014:  */
                   1015: /*VARARGS*/
                   1016: void
                   1017: setgate(argc, argv)
                   1018:        int argc;
                   1019:        char *argv[];
                   1020: {
                   1021:        static char gsbuf[MAXHOSTNAMELEN];
                   1022:
1.76      lukem    1023:        if ((argc == 0 && argv != NULL) || argc > 3) {
1.37      lukem    1024:                fprintf(ttyout,
1.76      lukem    1025:                    "usage: %s [ on | off | gateserver [port] ]\n", argv[0]);
1.27      lukem    1026:                code = -1;
                   1027:                return;
                   1028:        } else if (argc < 2) {
                   1029:                gatemode = !gatemode;
                   1030:        } else {
                   1031:                if (argc == 2 && strcasecmp(argv[1], "on") == 0)
                   1032:                        gatemode = 1;
                   1033:                else if (argc == 2 && strcasecmp(argv[1], "off") == 0)
                   1034:                        gatemode = 0;
                   1035:                else {
1.59      lukem    1036:                        if (argc == 3)
1.54      itojun   1037:                                gateport = strdup(argv[2]);
1.63      lukem    1038:                        (void)strlcpy(gsbuf, argv[1], sizeof(gsbuf));
1.27      lukem    1039:                        gateserver = gsbuf;
                   1040:                        gatemode = 1;
                   1041:                }
                   1042:        }
                   1043:        if (gatemode && (gateserver == NULL || *gateserver == '\0')) {
1.37      lukem    1044:                fprintf(ttyout,
1.27      lukem    1045:                    "Disabling gate-ftp mode - no gate-ftp server defined.\n");
                   1046:                gatemode = 0;
                   1047:        } else {
1.54      itojun   1048:                fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n",
1.37      lukem    1049:                    onoff(gatemode), *gateserver ? gateserver : "(none)",
1.54      itojun   1050:                    gateport);
1.27      lukem    1051:        }
                   1052:        code = gatemode;
                   1053: }
                   1054:
                   1055: /*
                   1056:  * Toggle metacharacter interpretation on local file names.
1.1       cgd      1057:  */
                   1058: /*VARARGS*/
1.4       cgd      1059: void
                   1060: setglob(argc, argv)
                   1061:        int argc;
                   1062:        char *argv[];
1.1       cgd      1063: {
1.9       lukem    1064:
1.10      lukem    1065:        code = togglevar(argc, argv, &doglob, "Globbing");
                   1066: }
                   1067:
                   1068: /*
1.40      lukem    1069:  * Toggle preserving modification times on retrieved files.
1.10      lukem    1070:  */
                   1071: /*VARARGS*/
                   1072: void
                   1073: setpreserve(argc, argv)
                   1074:        int argc;
                   1075:        char *argv[];
                   1076: {
                   1077:
                   1078:        code = togglevar(argc, argv, &preserve, "Preserve modification times");
1.1       cgd      1079: }
                   1080:
                   1081: /*
1.27      lukem    1082:  * Set debugging mode on/off and/or set level of debugging.
1.1       cgd      1083:  */
                   1084: /*VARARGS*/
1.4       cgd      1085: void
1.1       cgd      1086: setdebug(argc, argv)
                   1087:        int argc;
                   1088:        char *argv[];
                   1089: {
1.76      lukem    1090:        if ((argc == 0 && argv != NULL) || argc > 2) {
1.37      lukem    1091:                fprintf(ttyout, "usage: %s [ on | off | debuglevel ]\n",
                   1092:                    argv[0]);
1.10      lukem    1093:                code = -1;
                   1094:                return;
                   1095:        } else if (argc == 2) {
                   1096:                if (strcasecmp(argv[1], "on") == 0)
                   1097:                        debug = 1;
                   1098:                else if (strcasecmp(argv[1], "off") == 0)
                   1099:                        debug = 0;
                   1100:                else {
1.52      lukem    1101:                        int val;
1.25      lukem    1102:
1.52      lukem    1103:                        val = strsuftoi(argv[1]);
                   1104:                        if (val < 0) {
1.37      lukem    1105:                                fprintf(ttyout, "%s: bad debugging value.\n",
                   1106:                                    argv[1]);
1.10      lukem    1107:                                code = -1;
                   1108:                                return;
                   1109:                        }
1.52      lukem    1110:                        debug = val;
1.1       cgd      1111:                }
                   1112:        } else
1.11      lukem    1113:                debug = !debug;
1.1       cgd      1114:        if (debug)
                   1115:                options |= SO_DEBUG;
                   1116:        else
                   1117:                options &= ~SO_DEBUG;
1.37      lukem    1118:        fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(debug), debug);
1.1       cgd      1119:        code = debug > 0;
                   1120: }
                   1121:
                   1122: /*
1.27      lukem    1123:  * Set current working directory on remote machine.
1.1       cgd      1124:  */
1.4       cgd      1125: void
1.1       cgd      1126: cd(argc, argv)
                   1127:        int argc;
                   1128:        char *argv[];
                   1129: {
1.16      lukem    1130:        int r;
1.1       cgd      1131:
1.76      lukem    1132:        if ((argc == 1 && !another(&argc, &argv, "remote-directory")) ||
                   1133:            (argc == 0 && argv != NULL) || argc > 2) {
1.37      lukem    1134:                fprintf(ttyout, "usage: %s remote-directory\n", argv[0]);
1.1       cgd      1135:                code = -1;
                   1136:                return;
                   1137:        }
1.17      veego    1138:        r = command("CWD %s", argv[1]);
1.16      lukem    1139:        if (r == ERROR && code == 500) {
1.1       cgd      1140:                if (verbose)
1.37      lukem    1141:                        fputs("CWD command not recognized, trying XCWD.\n",
                   1142:                            ttyout);
1.16      lukem    1143:                r = command("XCWD %s", argv[1]);
1.1       cgd      1144:        }
1.79    ! lukem    1145:        if (r == COMPLETE) {
1.16      lukem    1146:                dirchange = 1;
1.79    ! lukem    1147:                updateremotepwd();
        !          1148:        }
1.1       cgd      1149: }
                   1150:
                   1151: /*
1.27      lukem    1152:  * Set current working directory on local machine.
1.1       cgd      1153:  */
1.4       cgd      1154: void
1.1       cgd      1155: lcd(argc, argv)
                   1156:        int argc;
                   1157:        char *argv[];
                   1158: {
                   1159:        char buf[MAXPATHLEN];
1.63      lukem    1160:        char *locdir;
1.1       cgd      1161:
1.76      lukem    1162:        code = -1;
                   1163:        if (argc == 1) {
1.64      lukem    1164:                argc++;
                   1165:                argv[1] = home;
                   1166:        }
1.1       cgd      1167:        if (argc != 2) {
1.76      lukem    1168:                fprintf(ttyout, "usage: %s [local-directory]\n", argv[0]);
1.1       cgd      1169:                return;
                   1170:        }
1.76      lukem    1171:        if ((locdir = globulize(argv[1])) == NULL)
1.1       cgd      1172:                return;
1.76      lukem    1173:        if (chdir(locdir) < 0)
1.63      lukem    1174:                warn("local: %s", locdir);
1.76      lukem    1175:        else {
                   1176:                if (getcwd(buf, sizeof(buf)) != NULL) {
1.37      lukem    1177:                        fprintf(ttyout, "Local directory now %s\n", buf);
1.76      lukem    1178:                        code = 0;
                   1179:                } else
1.63      lukem    1180:                        warn("getcwd: %s", locdir);
1.1       cgd      1181:        }
1.63      lukem    1182:        (void)free(locdir);
1.1       cgd      1183: }
                   1184:
                   1185: /*
                   1186:  * Delete a single file.
                   1187:  */
1.4       cgd      1188: void
1.1       cgd      1189: delete(argc, argv)
                   1190:        int argc;
                   1191:        char *argv[];
                   1192: {
                   1193:
1.76      lukem    1194:        if ((argc == 1 && !another(&argc, &argv, "remote-file")) ||
                   1195:            (argc == 0 && argv != NULL) || argc > 2) {
1.37      lukem    1196:                fprintf(ttyout, "usage: %s remote-file\n", argv[0]);
1.1       cgd      1197:                code = -1;
                   1198:                return;
                   1199:        }
1.19      lukem    1200:        (void)command("DELE %s", argv[1]);
1.1       cgd      1201: }
                   1202:
                   1203: /*
                   1204:  * Delete multiple files.
                   1205:  */
1.4       cgd      1206: void
1.1       cgd      1207: mdelete(argc, argv)
                   1208:        int argc;
1.10      lukem    1209:        char *argv[];
1.1       cgd      1210: {
                   1211:        sig_t oldintr;
                   1212:        int ointer;
                   1213:        char *cp;
                   1214:
1.76      lukem    1215:        if ((argc == 1 && !another(&argc, &argv, "remote-files")) ||
                   1216:            (argc == 0 && argv != NULL)) {
                   1217:                fprintf(ttyout, "usage: %s [remote-files]\n", argv[0]);
1.1       cgd      1218:                code = -1;
                   1219:                return;
                   1220:        }
                   1221:        mname = argv[0];
                   1222:        mflag = 1;
1.72      lukem    1223:        oldintr = xsignal(SIGINT, mintr);
                   1224:        if (sigsetjmp(jabort, 1))
                   1225:                mabort();
1.19      lukem    1226:        while ((cp = remglob(argv, 0, NULL)) != NULL) {
1.1       cgd      1227:                if (*cp == '\0') {
                   1228:                        mflag = 0;
                   1229:                        continue;
                   1230:                }
                   1231:                if (mflag && confirm(argv[0], cp)) {
1.19      lukem    1232:                        (void)command("DELE %s", cp);
1.1       cgd      1233:                        if (!mflag && fromatty) {
                   1234:                                ointer = interactive;
                   1235:                                interactive = 1;
                   1236:                                if (confirm("Continue with", "mdelete")) {
                   1237:                                        mflag++;
                   1238:                                }
                   1239:                                interactive = ointer;
                   1240:                        }
                   1241:                }
                   1242:        }
1.62      lukem    1243:        (void)xsignal(SIGINT, oldintr);
1.1       cgd      1244:        mflag = 0;
                   1245: }
                   1246:
                   1247: /*
                   1248:  * Rename a remote file.
                   1249:  */
1.4       cgd      1250: void
1.1       cgd      1251: renamefile(argc, argv)
                   1252:        int argc;
                   1253:        char *argv[];
                   1254: {
                   1255:
1.76      lukem    1256:        if ((argc == 0 && argv != NULL) ||
                   1257:            (argc == 1 && !another(&argc, &argv, "from-name")))
1.1       cgd      1258:                goto usage;
1.10      lukem    1259:        if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) {
1.1       cgd      1260: usage:
1.37      lukem    1261:                fprintf(ttyout, "usage: %s from-name to-name\n", argv[0]);
1.1       cgd      1262:                code = -1;
                   1263:                return;
                   1264:        }
                   1265:        if (command("RNFR %s", argv[1]) == CONTINUE)
1.19      lukem    1266:                (void)command("RNTO %s", argv[2]);
1.1       cgd      1267: }
                   1268:
                   1269: /*
1.27      lukem    1270:  * Get a directory listing of remote files.
1.1       cgd      1271:  */
1.4       cgd      1272: void
1.1       cgd      1273: ls(argc, argv)
                   1274:        int argc;
                   1275:        char *argv[];
                   1276: {
1.10      lukem    1277:        const char *cmd;
1.63      lukem    1278:        char *remdir, *locfile;
                   1279:        int freelocfile, pagecmd;
1.1       cgd      1280:
1.63      lukem    1281:        remdir = NULL;
                   1282:        locfile = "-";
                   1283:        freelocfile = pagecmd = 0;
                   1284:                        /*
                   1285:                         * assume all `pager' versions of the commands
                   1286:                         * are the only ones that start with `p'
                   1287:                         */
                   1288:        if (argv[0][0] == 'p')
                   1289:                pagecmd = 1;
1.76      lukem    1290:        if (argc == 0 && argv != NULL)
                   1291:                goto usage;
1.63      lukem    1292:
                   1293:        cmd = "NLST";
                   1294:        if (strcmp(argv[0] + pagecmd, "dir") == 0)
                   1295:                cmd = "LIST";
                   1296:
                   1297:        if (argc > 1)
                   1298:                remdir = argv[1];
                   1299:        if (argc > 2)
                   1300:                locfile = argv[2];
                   1301:        if (argc > 3 || (pagecmd && argc > 2)) {
1.76      lukem    1302:  usage:
1.63      lukem    1303:                if (pagecmd)
                   1304:                        fprintf(ttyout,
                   1305:                            "usage: %s [remote-directory]\n", argv[0]);
                   1306:                else
                   1307:                        fprintf(ttyout,
                   1308:                            "usage: %s [remote-directory [local-file]]\n",
                   1309:                            argv[0]);
1.1       cgd      1310:                code = -1;
1.63      lukem    1311:                goto freels;
1.1       cgd      1312:        }
1.63      lukem    1313:
                   1314:        if (pagecmd) {
                   1315:                char *p;
                   1316:                int len;
                   1317:
1.76      lukem    1318:                p = getoptionvalue("pager");
                   1319:                if (EMPTYSTRING(p))
                   1320:                        p = DEFAULTPAGER;
1.63      lukem    1321:                len = strlen(p) + 2;
                   1322:                locfile = xmalloc(len);
                   1323:                locfile[0] = '|';
                   1324:                (void)strlcpy(locfile + 1, p, len - 1);
                   1325:                freelocfile = 1;
                   1326:        } else if ((strcmp(locfile, "-") != 0) && *locfile != '|') {
                   1327:                if ((locfile = globulize(locfile)) == NULL ||
                   1328:                    !confirm("output to local-file:", locfile)) {
1.1       cgd      1329:                        code = -1;
1.27      lukem    1330:                        goto freels;
1.63      lukem    1331:                }
                   1332:                freelocfile = 1;
1.1       cgd      1333:        }
1.63      lukem    1334:        recvrequest(cmd, locfile, remdir, "w", 0, 0);
1.27      lukem    1335: freels:
1.63      lukem    1336:        if (freelocfile && locfile)
                   1337:                (void)free(locfile);
1.1       cgd      1338: }
                   1339:
                   1340: /*
1.27      lukem    1341:  * Get a directory listing of multiple remote files.
1.1       cgd      1342:  */
1.4       cgd      1343: void
1.1       cgd      1344: mls(argc, argv)
                   1345:        int argc;
1.10      lukem    1346:        char *argv[];
1.1       cgd      1347: {
                   1348:        sig_t oldintr;
                   1349:        int ointer, i;
1.25      lukem    1350:        int dolist;
1.27      lukem    1351:        char mode[1], *dest, *odest;
1.1       cgd      1352:
1.76      lukem    1353:        if (argc == 0 && argv != NULL)
                   1354:                goto usage;
1.1       cgd      1355:        if (argc < 2 && !another(&argc, &argv, "remote-files"))
                   1356:                goto usage;
                   1357:        if (argc < 3 && !another(&argc, &argv, "local-file")) {
                   1358: usage:
1.37      lukem    1359:                fprintf(ttyout, "usage: %s remote-files local-file\n", argv[0]);
1.1       cgd      1360:                code = -1;
                   1361:                return;
                   1362:        }
1.27      lukem    1363:        odest = dest = argv[argc - 1];
1.1       cgd      1364:        argv[argc - 1] = NULL;
                   1365:        if (strcmp(dest, "-") && *dest != '|')
1.63      lukem    1366:                if (((dest = globulize(dest)) == NULL) ||
1.1       cgd      1367:                    !confirm("output to local-file:", dest)) {
                   1368:                        code = -1;
                   1369:                        return;
                   1370:        }
1.25      lukem    1371:        dolist = strcmp(argv[0], "mls");
1.1       cgd      1372:        mname = argv[0];
                   1373:        mflag = 1;
1.72      lukem    1374:        oldintr = xsignal(SIGINT, mintr);
                   1375:        if (sigsetjmp(jabort, 1))
                   1376:                mabort();
1.76      lukem    1377:        for (i = 1; mflag && i < argc-1 && connected; i++) {
1.1       cgd      1378:                *mode = (i == 1) ? 'w' : 'a';
1.27      lukem    1379:                recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], mode,
                   1380:                    0, 0);
1.1       cgd      1381:                if (!mflag && fromatty) {
                   1382:                        ointer = interactive;
                   1383:                        interactive = 1;
                   1384:                        if (confirm("Continue with", argv[0])) {
                   1385:                                mflag ++;
                   1386:                        }
                   1387:                        interactive = ointer;
                   1388:                }
                   1389:        }
1.62      lukem    1390:        (void)xsignal(SIGINT, oldintr);
1.1       cgd      1391:        mflag = 0;
1.27      lukem    1392:        if (dest != odest)                      /* free up after globulize() */
                   1393:                free(dest);
1.1       cgd      1394: }
                   1395:
                   1396: /*
                   1397:  * Do a shell escape
                   1398:  */
                   1399: /*ARGSUSED*/
1.4       cgd      1400: void
1.1       cgd      1401: shell(argc, argv)
                   1402:        int argc;
1.10      lukem    1403:        char *argv[];
1.1       cgd      1404: {
1.4       cgd      1405:        pid_t pid;
1.71      lukem    1406:        sig_t old1;
1.13      lukem    1407:        char shellnam[MAXPATHLEN], *shell, *namep;
1.29      lukem    1408:        int wait_status;
1.1       cgd      1409:
1.76      lukem    1410:        if (argc == 0 && argv != NULL) {
                   1411:                fprintf(ttyout, "usage: %s [command [args]]\n", argv[0]);
                   1412:                code = -1;
                   1413:                return;
                   1414:        }
1.62      lukem    1415:        old1 = xsignal(SIGINT, SIG_IGN);
1.1       cgd      1416:        if ((pid = fork()) == 0) {
                   1417:                for (pid = 3; pid < 20; pid++)
1.19      lukem    1418:                        (void)close(pid);
1.62      lukem    1419:                (void)xsignal(SIGINT, SIG_DFL);
1.1       cgd      1420:                shell = getenv("SHELL");
                   1421:                if (shell == NULL)
                   1422:                        shell = _PATH_BSHELL;
1.10      lukem    1423:                namep = strrchr(shell, '/');
1.1       cgd      1424:                if (namep == NULL)
                   1425:                        namep = shell;
1.71      lukem    1426:                else
                   1427:                        namep++;
                   1428:                (void)strlcpy(shellnam, namep, sizeof(shellnam));
1.1       cgd      1429:                if (debug) {
1.37      lukem    1430:                        fputs(shell, ttyout);
                   1431:                        putc('\n', ttyout);
1.1       cgd      1432:                }
                   1433:                if (argc > 1) {
1.10      lukem    1434:                        execl(shell, shellnam, "-c", altarg, (char *)0);
1.1       cgd      1435:                }
                   1436:                else {
1.10      lukem    1437:                        execl(shell, shellnam, (char *)0);
1.1       cgd      1438:                }
1.4       cgd      1439:                warn("%s", shell);
1.1       cgd      1440:                code = -1;
                   1441:                exit(1);
1.4       cgd      1442:        }
1.1       cgd      1443:        if (pid > 0)
1.29      lukem    1444:                while (wait(&wait_status) != pid)
1.1       cgd      1445:                        ;
1.62      lukem    1446:        (void)xsignal(SIGINT, old1);
1.1       cgd      1447:        if (pid == -1) {
1.19      lukem    1448:                warn("Try again later");
1.1       cgd      1449:                code = -1;
1.76      lukem    1450:        } else
1.1       cgd      1451:                code = 0;
                   1452: }
                   1453:
                   1454: /*
                   1455:  * Send new user information (re-login)
                   1456:  */
1.4       cgd      1457: void
1.1       cgd      1458: user(argc, argv)
                   1459:        int argc;
1.10      lukem    1460:        char *argv[];
1.1       cgd      1461: {
1.4       cgd      1462:        char acct[80];
1.1       cgd      1463:        int n, aflag = 0;
                   1464:
1.76      lukem    1465:        if (argc == 0 && argv != NULL)
                   1466:                goto usage;
1.1       cgd      1467:        if (argc < 2)
1.19      lukem    1468:                (void)another(&argc, &argv, "username");
1.1       cgd      1469:        if (argc < 2 || argc > 4) {
1.76      lukem    1470:  usage:
                   1471:                fprintf(ttyout, "usage: %s username [password [account]]\n",
1.37      lukem    1472:                    argv[0]);
1.1       cgd      1473:                code = -1;
1.4       cgd      1474:                return;
1.1       cgd      1475:        }
                   1476:        n = command("USER %s", argv[1]);
                   1477:        if (n == CONTINUE) {
1.49      lukem    1478:                if (argc < 3) {
                   1479:                        argv[2] = getpass("Password: ");
                   1480:                        argc++;
                   1481:                }
1.1       cgd      1482:                n = command("PASS %s", argv[2]);
                   1483:        }
                   1484:        if (n == CONTINUE) {
                   1485:                if (argc < 4) {
1.37      lukem    1486:                        (void)fputs("Account: ", ttyout);
                   1487:                        (void)fflush(ttyout);
1.49      lukem    1488:                        if (fgets(acct, sizeof(acct) - 1, stdin) == NULL) {
                   1489:                                fprintf(ttyout,
                   1490:                                    "\nEOF received; login aborted.\n");
1.74      lukem    1491:                                clearerr(stdin);
1.49      lukem    1492:                                code = -1;
                   1493:                                return;
                   1494:                        }
1.1       cgd      1495:                        acct[strlen(acct) - 1] = '\0';
                   1496:                        argv[3] = acct; argc++;
                   1497:                }
                   1498:                n = command("ACCT %s", argv[3]);
                   1499:                aflag++;
                   1500:        }
                   1501:        if (n != COMPLETE) {
1.37      lukem    1502:                fputs("Login failed.\n", ttyout);
1.4       cgd      1503:                return;
1.1       cgd      1504:        }
                   1505:        if (!aflag && argc == 4) {
1.19      lukem    1506:                (void)command("ACCT %s", argv[3]);
1.1       cgd      1507:        }
1.23      lukem    1508:        connected = -1;
1.1       cgd      1509: }
                   1510:
                   1511: /*
1.10      lukem    1512:  * Print working directory on remote machine.
1.1       cgd      1513:  */
                   1514: /*VARARGS*/
1.4       cgd      1515: void
                   1516: pwd(argc, argv)
                   1517:        int argc;
                   1518:        char *argv[];
1.1       cgd      1519: {
                   1520:        int oldverbose = verbose;
                   1521:
1.76      lukem    1522:        if (argc == 0 && argv != NULL) {
                   1523:                fprintf(ttyout, "usage: %s\n", argv[0]);
                   1524:                code = -1;
                   1525:                return;
                   1526:        }
1.1       cgd      1527:        /*
                   1528:         * If we aren't verbose, this doesn't do anything!
                   1529:         */
                   1530:        verbose = 1;
                   1531:        if (command("PWD") == ERROR && code == 500) {
1.37      lukem    1532:                fputs("PWD command not recognized, trying XPWD.\n", ttyout);
1.19      lukem    1533:                (void)command("XPWD");
1.1       cgd      1534:        }
                   1535:        verbose = oldverbose;
                   1536: }
                   1537:
                   1538: /*
1.10      lukem    1539:  * Print working directory on local machine.
                   1540:  */
                   1541: void
                   1542: lpwd(argc, argv)
                   1543:        int argc;
                   1544:        char *argv[];
                   1545: {
                   1546:        char buf[MAXPATHLEN];
                   1547:
1.76      lukem    1548:        if (argc == 0 && argv != NULL) {
                   1549:                fprintf(ttyout, "usage: %s\n", argv[0]);
                   1550:                code = -1;
                   1551:                return;
                   1552:        }
                   1553:        if (getcwd(buf, sizeof(buf)) != NULL) {
1.37      lukem    1554:                fprintf(ttyout, "Local directory %s\n", buf);
1.76      lukem    1555:                code = 0;
                   1556:        } else {
1.18      lukem    1557:                warn("getcwd");
1.76      lukem    1558:                code = -1;
                   1559:        }
1.10      lukem    1560: }
                   1561:
                   1562: /*
1.1       cgd      1563:  * Make a directory.
                   1564:  */
1.4       cgd      1565: void
1.1       cgd      1566: makedir(argc, argv)
                   1567:        int argc;
                   1568:        char *argv[];
                   1569: {
                   1570:
1.76      lukem    1571:        if ((argc == 1 && !another(&argc, &argv, "directory-name")) ||
                   1572:            (argc == 0 && argv != NULL) || argc > 2) {
1.37      lukem    1573:                fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1       cgd      1574:                code = -1;
                   1575:                return;
                   1576:        }
                   1577:        if (command("MKD %s", argv[1]) == ERROR && code == 500) {
                   1578:                if (verbose)
1.37      lukem    1579:                        fputs("MKD command not recognized, trying XMKD.\n",
                   1580:                            ttyout);
1.19      lukem    1581:                (void)command("XMKD %s", argv[1]);
1.1       cgd      1582:        }
                   1583: }
                   1584:
                   1585: /*
                   1586:  * Remove a directory.
                   1587:  */
1.4       cgd      1588: void
1.1       cgd      1589: removedir(argc, argv)
                   1590:        int argc;
                   1591:        char *argv[];
                   1592: {
                   1593:
1.76      lukem    1594:        if ((argc == 1 && !another(&argc, &argv, "directory-name")) ||
                   1595:            (argc == 0 && argv != NULL) || argc > 2) {
1.37      lukem    1596:                fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1       cgd      1597:                code = -1;
                   1598:                return;
                   1599:        }
                   1600:        if (command("RMD %s", argv[1]) == ERROR && code == 500) {
                   1601:                if (verbose)
1.37      lukem    1602:                        fputs("RMD command not recognized, trying XRMD.\n",
                   1603:                            ttyout);
1.19      lukem    1604:                (void)command("XRMD %s", argv[1]);
1.1       cgd      1605:        }
                   1606: }
                   1607:
                   1608: /*
                   1609:  * Send a line, verbatim, to the remote machine.
                   1610:  */
1.4       cgd      1611: void
1.1       cgd      1612: quote(argc, argv)
                   1613:        int argc;
                   1614:        char *argv[];
                   1615: {
                   1616:
1.76      lukem    1617:        if ((argc == 1 && !another(&argc, &argv, "command line to send")) ||
                   1618:            (argc == 0 && argv != NULL)) {
1.37      lukem    1619:                fprintf(ttyout, "usage: %s line-to-send\n", argv[0]);
1.1       cgd      1620:                code = -1;
                   1621:                return;
                   1622:        }
                   1623:        quote1("", argc, argv);
                   1624: }
                   1625:
                   1626: /*
                   1627:  * Send a SITE command to the remote machine.  The line
                   1628:  * is sent verbatim to the remote machine, except that the
                   1629:  * word "SITE" is added at the front.
                   1630:  */
1.4       cgd      1631: void
1.1       cgd      1632: site(argc, argv)
                   1633:        int argc;
                   1634:        char *argv[];
                   1635: {
                   1636:
1.76      lukem    1637:        if ((argc == 1 && !another(&argc, &argv, "arguments to SITE command"))
                   1638:            || (argc == 0 && argv != NULL)) {
1.37      lukem    1639:                fprintf(ttyout, "usage: %s line-to-send\n", argv[0]);
1.1       cgd      1640:                code = -1;
                   1641:                return;
                   1642:        }
                   1643:        quote1("SITE ", argc, argv);
                   1644: }
                   1645:
                   1646: /*
                   1647:  * Turn argv[1..argc) into a space-separated string, then prepend initial text.
                   1648:  * Send the result as a one-line command and get response.
                   1649:  */
1.4       cgd      1650: void
1.1       cgd      1651: quote1(initial, argc, argv)
1.10      lukem    1652:        const char *initial;
1.1       cgd      1653:        int argc;
1.10      lukem    1654:        char *argv[];
1.1       cgd      1655: {
1.63      lukem    1656:        int i;
1.1       cgd      1657:        char buf[BUFSIZ];               /* must be >= sizeof(line) */
                   1658:
1.63      lukem    1659:        (void)strlcpy(buf, initial, sizeof(buf));
                   1660:        for (i = 1; i < argc; i++) {
                   1661:                (void)strlcat(buf, argv[i], sizeof(buf));
                   1662:                if (i < (argc - 1))
                   1663:                        (void)strlcat(buf, " ", sizeof(buf));
1.1       cgd      1664:        }
1.43      lukem    1665:        if (command("%s", buf) == PRELIM) {
1.4       cgd      1666:                while (getreply(0) == PRELIM)
                   1667:                        continue;
1.1       cgd      1668:        }
                   1669: }
                   1670:
1.4       cgd      1671: void
1.1       cgd      1672: do_chmod(argc, argv)
                   1673:        int argc;
                   1674:        char *argv[];
                   1675: {
                   1676:
1.76      lukem    1677:        if ((argc == 0 && argv != NULL) ||
                   1678:            (argc == 1 && !another(&argc, &argv, "mode")))
1.1       cgd      1679:                goto usage;
1.76      lukem    1680:        if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
1.1       cgd      1681: usage:
1.76      lukem    1682:                fprintf(ttyout, "usage: %s mode remote-file\n", argv[0]);
1.1       cgd      1683:                code = -1;
                   1684:                return;
                   1685:        }
1.19      lukem    1686:        (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1.1       cgd      1687: }
                   1688:
1.4       cgd      1689: void
1.1       cgd      1690: do_umask(argc, argv)
                   1691:        int argc;
                   1692:        char *argv[];
                   1693: {
                   1694:        int oldverbose = verbose;
                   1695:
1.76      lukem    1696:        if (argc == 0 && argv != NULL) {
                   1697:                fprintf(ttyout, "usage: %s [umask]\n", argv[0]);
                   1698:                code = -1;
                   1699:                return;
                   1700:        }
1.1       cgd      1701:        verbose = 1;
1.19      lukem    1702:        (void)command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
1.1       cgd      1703:        verbose = oldverbose;
                   1704: }
                   1705:
1.4       cgd      1706: void
1.62      lukem    1707: idlecmd(argc, argv)
1.1       cgd      1708:        int argc;
                   1709:        char *argv[];
                   1710: {
                   1711:        int oldverbose = verbose;
                   1712:
1.76      lukem    1713:        if (argc != 2) {
                   1714:                fprintf(ttyout, "usage: %s [seconds]\n", argv[0]);
                   1715:                code = -1;
                   1716:                return;
                   1717:        }
1.1       cgd      1718:        verbose = 1;
1.19      lukem    1719:        (void)command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
1.1       cgd      1720:        verbose = oldverbose;
                   1721: }
                   1722:
                   1723: /*
                   1724:  * Ask the other side for help.
                   1725:  */
1.4       cgd      1726: void
1.1       cgd      1727: rmthelp(argc, argv)
                   1728:        int argc;
                   1729:        char *argv[];
                   1730: {
                   1731:        int oldverbose = verbose;
                   1732:
1.76      lukem    1733:        if (argc == 0 && argv != NULL) {
                   1734:                fprintf(ttyout, "usage: %s\n", argv[0]);
                   1735:                code = -1;
                   1736:                return;
                   1737:        }
1.1       cgd      1738:        verbose = 1;
1.19      lukem    1739:        (void)command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1.1       cgd      1740:        verbose = oldverbose;
                   1741: }
                   1742:
                   1743: /*
                   1744:  * Terminate session and exit.
                   1745:  */
                   1746: /*VARARGS*/
1.4       cgd      1747: void
                   1748: quit(argc, argv)
                   1749:        int argc;
                   1750:        char *argv[];
1.1       cgd      1751: {
                   1752:
1.76      lukem    1753:        if (argc == 0 && argv != NULL) {
                   1754:                fprintf(ttyout, "usage: %s\n", argv[0]);
                   1755:                code = -1;
                   1756:                return;
                   1757:        }
1.1       cgd      1758:        if (connected)
1.76      lukem    1759:                disconnect(0, NULL);
1.1       cgd      1760:        pswitch(1);
1.76      lukem    1761:        if (connected)
                   1762:                disconnect(0, NULL);
1.1       cgd      1763:        exit(0);
                   1764: }
                   1765:
                   1766: /*
                   1767:  * Terminate session, but don't exit.
                   1768:  */
1.4       cgd      1769: void
                   1770: disconnect(argc, argv)
                   1771:        int argc;
                   1772:        char *argv[];
1.1       cgd      1773: {
                   1774:
1.76      lukem    1775:        if (argc == 0 && argv != NULL) {
                   1776:                fprintf(ttyout, "usage: %s\n", argv[0]);
                   1777:                code = -1;
                   1778:                return;
                   1779:        }
1.1       cgd      1780:        if (!connected)
                   1781:                return;
1.19      lukem    1782:        (void)command("QUIT");
1.76      lukem    1783:        cleanuppeer();
1.1       cgd      1784: }
                   1785:
1.4       cgd      1786: void
1.10      lukem    1787: account(argc, argv)
1.1       cgd      1788:        int argc;
1.10      lukem    1789:        char *argv[];
1.1       cgd      1790: {
1.13      lukem    1791:        char *ap;
1.1       cgd      1792:
1.76      lukem    1793:        if ((argc == 0 && argv != NULL) || argc > 2) {
1.37      lukem    1794:                fprintf(ttyout, "usage: %s [password]\n", argv[0]);
1.13      lukem    1795:                code = -1;
                   1796:                return;
1.1       cgd      1797:        }
1.13      lukem    1798:        else if (argc == 2)
                   1799:                ap = argv[1];
                   1800:        else
1.1       cgd      1801:                ap = getpass("Account:");
1.19      lukem    1802:        (void)command("ACCT %s", ap);
1.1       cgd      1803: }
                   1804:
1.73      lukem    1805: sigjmp_buf abortprox;
1.1       cgd      1806:
                   1807: void
1.19      lukem    1808: proxabort(notused)
                   1809:        int notused;
1.1       cgd      1810: {
                   1811:
1.18      lukem    1812:        alarmtimer(0);
1.1       cgd      1813:        if (!proxy) {
                   1814:                pswitch(1);
                   1815:        }
                   1816:        if (connected) {
                   1817:                proxflag = 1;
                   1818:        }
                   1819:        else {
                   1820:                proxflag = 0;
                   1821:        }
                   1822:        pswitch(0);
1.72      lukem    1823:        siglongjmp(abortprox, 1);
1.1       cgd      1824: }
                   1825:
1.4       cgd      1826: void
                   1827: doproxy(argc, argv)
1.1       cgd      1828:        int argc;
                   1829:        char *argv[];
                   1830: {
1.4       cgd      1831:        struct cmd *c;
1.14      lukem    1832:        int cmdpos;
1.1       cgd      1833:        sig_t oldintr;
                   1834:
1.76      lukem    1835:        if ((argc == 0 && argv != NULL) ||
                   1836:            (argc == 1 && !another(&argc, &argv, "command"))) {
1.37      lukem    1837:                fprintf(ttyout, "usage: %s command\n", argv[0]);
1.1       cgd      1838:                code = -1;
                   1839:                return;
                   1840:        }
                   1841:        c = getcmd(argv[1]);
                   1842:        if (c == (struct cmd *) -1) {
1.37      lukem    1843:                fputs("?Ambiguous command.\n", ttyout);
1.1       cgd      1844:                code = -1;
                   1845:                return;
                   1846:        }
                   1847:        if (c == 0) {
1.37      lukem    1848:                fputs("?Invalid command.\n", ttyout);
1.1       cgd      1849:                code = -1;
                   1850:                return;
                   1851:        }
                   1852:        if (!c->c_proxy) {
1.37      lukem    1853:                fputs("?Invalid proxy command.\n", ttyout);
1.1       cgd      1854:                code = -1;
                   1855:                return;
                   1856:        }
1.72      lukem    1857:        if (sigsetjmp(abortprox, 1)) {
1.1       cgd      1858:                code = -1;
                   1859:                return;
                   1860:        }
1.62      lukem    1861:        oldintr = xsignal(SIGINT, proxabort);
1.1       cgd      1862:        pswitch(1);
                   1863:        if (c->c_conn && !connected) {
1.37      lukem    1864:                fputs("Not connected.\n", ttyout);
1.1       cgd      1865:                pswitch(0);
1.62      lukem    1866:                (void)xsignal(SIGINT, oldintr);
1.1       cgd      1867:                code = -1;
                   1868:                return;
                   1869:        }
1.14      lukem    1870:        cmdpos = strcspn(line, " \t");
                   1871:        if (cmdpos > 0)         /* remove leading "proxy " from input buffer */
                   1872:                memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
1.1       cgd      1873:        (*c->c_handler)(argc-1, argv+1);
                   1874:        if (connected) {
                   1875:                proxflag = 1;
                   1876:        }
                   1877:        else {
                   1878:                proxflag = 0;
                   1879:        }
                   1880:        pswitch(0);
1.62      lukem    1881:        (void)xsignal(SIGINT, oldintr);
1.1       cgd      1882: }
                   1883:
1.4       cgd      1884: void
                   1885: setcase(argc, argv)
                   1886:        int argc;
                   1887:        char *argv[];
1.1       cgd      1888: {
1.4       cgd      1889:
1.10      lukem    1890:        code = togglevar(argc, argv, &mcase, "Case mapping");
1.1       cgd      1891: }
                   1892:
1.63      lukem    1893: /*
                   1894:  * convert the given name to lower case if it's all upper case, into
                   1895:  * a static buffer which is returned to the caller
                   1896:  */
                   1897: char *
                   1898: docase(name)
                   1899:        char *name;
                   1900: {
                   1901:        static char new[MAXPATHLEN];
                   1902:        int i, dochange;
                   1903:
                   1904:        dochange = 1;
                   1905:        for (i = 0; name[i] != '\0' && i < sizeof(new) - 1; i++) {
                   1906:                new[i] = name[i];
                   1907:                if (islower((unsigned char)new[i]))
                   1908:                        dochange = 0;
                   1909:        }
                   1910:        new[i] = '\0';
                   1911:
                   1912:        if (dochange) {
                   1913:                for (i = 0; new[i] != '\0'; i++)
                   1914:                        if (isupper((unsigned char)new[i]))
                   1915:                                new[i] = tolower(new[i]);
                   1916:        }
                   1917:        return (new);
                   1918: }
                   1919:
1.4       cgd      1920: void
                   1921: setcr(argc, argv)
                   1922:        int argc;
                   1923:        char *argv[];
1.1       cgd      1924: {
1.4       cgd      1925:
1.10      lukem    1926:        code = togglevar(argc, argv, &crflag, "Carriage Return stripping");
1.1       cgd      1927: }
                   1928:
1.4       cgd      1929: void
1.10      lukem    1930: setntrans(argc, argv)
1.1       cgd      1931:        int argc;
                   1932:        char *argv[];
                   1933: {
1.76      lukem    1934:
                   1935:        if ((argc == 0 && argv != NULL) || argc > 3) {
                   1936:                fprintf(ttyout, "usage: %s [inchars [outchars]]\n", argv[0]);
                   1937:                code = -1;
                   1938:                return;
                   1939:        }
1.1       cgd      1940:        if (argc == 1) {
                   1941:                ntflag = 0;
1.37      lukem    1942:                fputs("Ntrans off.\n", ttyout);
1.1       cgd      1943:                code = ntflag;
                   1944:                return;
                   1945:        }
                   1946:        ntflag++;
                   1947:        code = ntflag;
1.63      lukem    1948:        (void)strlcpy(ntin, argv[1], sizeof(ntin));
1.1       cgd      1949:        if (argc == 2) {
                   1950:                ntout[0] = '\0';
                   1951:                return;
                   1952:        }
1.63      lukem    1953:        (void)strlcpy(ntout, argv[2], sizeof(ntout));
1.1       cgd      1954: }
                   1955:
                   1956: char *
                   1957: dotrans(name)
                   1958:        char *name;
                   1959: {
                   1960:        static char new[MAXPATHLEN];
                   1961:        char *cp1, *cp2 = new;
1.4       cgd      1962:        int i, ostop, found;
1.1       cgd      1963:
1.4       cgd      1964:        for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
                   1965:                continue;
1.1       cgd      1966:        for (cp1 = name; *cp1; cp1++) {
                   1967:                found = 0;
                   1968:                for (i = 0; *(ntin + i) && i < 16; i++) {
                   1969:                        if (*cp1 == *(ntin + i)) {
                   1970:                                found++;
                   1971:                                if (i < ostop) {
                   1972:                                        *cp2++ = *(ntout + i);
                   1973:                                }
                   1974:                                break;
                   1975:                        }
                   1976:                }
                   1977:                if (!found) {
                   1978:                        *cp2++ = *cp1;
                   1979:                }
                   1980:        }
                   1981:        *cp2 = '\0';
1.4       cgd      1982:        return (new);
1.1       cgd      1983: }
                   1984:
1.4       cgd      1985: void
1.1       cgd      1986: setnmap(argc, argv)
                   1987:        int argc;
                   1988:        char *argv[];
                   1989: {
                   1990:        char *cp;
                   1991:
                   1992:        if (argc == 1) {
                   1993:                mapflag = 0;
1.37      lukem    1994:                fputs("Nmap off.\n", ttyout);
1.1       cgd      1995:                code = mapflag;
                   1996:                return;
                   1997:        }
1.76      lukem    1998:        if ((argc == 0 && argv != NULL) ||
                   1999:            (argc < 3 && !another(&argc, &argv, "mapout")) || argc > 3) {
1.37      lukem    2000:                fprintf(ttyout, "usage: %s [mapin mapout]\n", argv[0]);
1.1       cgd      2001:                code = -1;
                   2002:                return;
                   2003:        }
                   2004:        mapflag = 1;
                   2005:        code = 1;
1.4       cgd      2006:        cp = strchr(altarg, ' ');
1.1       cgd      2007:        if (proxy) {
1.4       cgd      2008:                while(*++cp == ' ')
                   2009:                        continue;
1.1       cgd      2010:                altarg = cp;
1.4       cgd      2011:                cp = strchr(altarg, ' ');
1.1       cgd      2012:        }
                   2013:        *cp = '\0';
1.63      lukem    2014:        (void)strlcpy(mapin, altarg, MAXPATHLEN);
1.4       cgd      2015:        while (*++cp == ' ')
                   2016:                continue;
1.63      lukem    2017:        (void)strlcpy(mapout, cp, MAXPATHLEN);
1.1       cgd      2018: }
                   2019:
                   2020: char *
                   2021: domap(name)
                   2022:        char *name;
                   2023: {
                   2024:        static char new[MAXPATHLEN];
1.4       cgd      2025:        char *cp1 = name, *cp2 = mapin;
1.1       cgd      2026:        char *tp[9], *te[9];
                   2027:        int i, toks[9], toknum = 0, match = 1;
                   2028:
                   2029:        for (i=0; i < 9; ++i) {
                   2030:                toks[i] = 0;
                   2031:        }
                   2032:        while (match && *cp1 && *cp2) {
                   2033:                switch (*cp2) {
                   2034:                        case '\\':
                   2035:                                if (*++cp2 != *cp1) {
                   2036:                                        match = 0;
                   2037:                                }
                   2038:                                break;
                   2039:                        case '$':
                   2040:                                if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
                   2041:                                        if (*cp1 != *(++cp2+1)) {
                   2042:                                                toks[toknum = *cp2 - '1']++;
                   2043:                                                tp[toknum] = cp1;
                   2044:                                                while (*++cp1 && *(cp2+1)
                   2045:                                                        != *cp1);
                   2046:                                                te[toknum] = cp1;
                   2047:                                        }
                   2048:                                        cp2++;
                   2049:                                        break;
                   2050:                                }
                   2051:                                /* FALLTHROUGH */
                   2052:                        default:
                   2053:                                if (*cp2 != *cp1) {
                   2054:                                        match = 0;
                   2055:                                }
                   2056:                                break;
                   2057:                }
                   2058:                if (match && *cp1) {
                   2059:                        cp1++;
                   2060:                }
                   2061:                if (match && *cp2) {
                   2062:                        cp2++;
                   2063:                }
                   2064:        }
                   2065:        if (!match && *cp1) /* last token mismatch */
                   2066:        {
                   2067:                toks[toknum] = 0;
                   2068:        }
                   2069:        cp1 = new;
                   2070:        *cp1 = '\0';
                   2071:        cp2 = mapout;
                   2072:        while (*cp2) {
                   2073:                match = 0;
                   2074:                switch (*cp2) {
                   2075:                        case '\\':
                   2076:                                if (*(cp2 + 1)) {
                   2077:                                        *cp1++ = *++cp2;
                   2078:                                }
                   2079:                                break;
                   2080:                        case '[':
                   2081: LOOP:
1.36      christos 2082:                                if (*++cp2 == '$' &&
                   2083:                                    isdigit((unsigned char)*(cp2+1))) {
1.1       cgd      2084:                                        if (*++cp2 == '0') {
                   2085:                                                char *cp3 = name;
                   2086:
                   2087:                                                while (*cp3) {
                   2088:                                                        *cp1++ = *cp3++;
                   2089:                                                }
                   2090:                                                match = 1;
                   2091:                                        }
                   2092:                                        else if (toks[toknum = *cp2 - '1']) {
                   2093:                                                char *cp3 = tp[toknum];
                   2094:
                   2095:                                                while (cp3 != te[toknum]) {
                   2096:                                                        *cp1++ = *cp3++;
                   2097:                                                }
                   2098:                                                match = 1;
                   2099:                                        }
                   2100:                                }
                   2101:                                else {
1.9       lukem    2102:                                        while (*cp2 && *cp2 != ',' &&
1.1       cgd      2103:                                            *cp2 != ']') {
                   2104:                                                if (*cp2 == '\\') {
                   2105:                                                        cp2++;
                   2106:                                                }
                   2107:                                                else if (*cp2 == '$' &&
1.36      christos 2108:                                                    isdigit((unsigned char)*(cp2+1))) {
1.1       cgd      2109:                                                        if (*++cp2 == '0') {
                   2110:                                                           char *cp3 = name;
                   2111:
                   2112:                                                           while (*cp3) {
                   2113:                                                                *cp1++ = *cp3++;
                   2114:                                                           }
                   2115:                                                        }
                   2116:                                                        else if (toks[toknum =
                   2117:                                                            *cp2 - '1']) {
                   2118:                                                           char *cp3=tp[toknum];
                   2119:
                   2120:                                                           while (cp3 !=
                   2121:                                                                  te[toknum]) {
                   2122:                                                                *cp1++ = *cp3++;
                   2123:                                                           }
                   2124:                                                        }
                   2125:                                                }
                   2126:                                                else if (*cp2) {
                   2127:                                                        *cp1++ = *cp2++;
                   2128:                                                }
                   2129:                                        }
                   2130:                                        if (!*cp2) {
1.37      lukem    2131:                                                fputs(
                   2132:                                                "nmap: unbalanced brackets.\n",
                   2133:                                                    ttyout);
1.4       cgd      2134:                                                return (name);
1.1       cgd      2135:                                        }
                   2136:                                        match = 1;
                   2137:                                        cp2--;
                   2138:                                }
                   2139:                                if (match) {
                   2140:                                        while (*++cp2 && *cp2 != ']') {
                   2141:                                              if (*cp2 == '\\' && *(cp2 + 1)) {
                   2142:                                                        cp2++;
                   2143:                                              }
                   2144:                                        }
                   2145:                                        if (!*cp2) {
1.37      lukem    2146:                                                fputs(
                   2147:                                                "nmap: unbalanced brackets.\n",
                   2148:                                                    ttyout);
1.4       cgd      2149:                                                return (name);
1.1       cgd      2150:                                        }
                   2151:                                        break;
                   2152:                                }
                   2153:                                switch (*++cp2) {
                   2154:                                        case ',':
                   2155:                                                goto LOOP;
                   2156:                                        case ']':
                   2157:                                                break;
                   2158:                                        default:
                   2159:                                                cp2--;
                   2160:                                                goto LOOP;
                   2161:                                }
                   2162:                                break;
                   2163:                        case '$':
1.36      christos 2164:                                if (isdigit((unsigned char)*(cp2 + 1))) {
1.1       cgd      2165:                                        if (*++cp2 == '0') {
                   2166:                                                char *cp3 = name;
                   2167:
                   2168:                                                while (*cp3) {
                   2169:                                                        *cp1++ = *cp3++;
                   2170:                                                }
                   2171:                                        }
                   2172:                                        else if (toks[toknum = *cp2 - '1']) {
                   2173:                                                char *cp3 = tp[toknum];
                   2174:
                   2175:                                                while (cp3 != te[toknum]) {
                   2176:                                                        *cp1++ = *cp3++;
                   2177:                                                }
                   2178:                                        }
                   2179:                                        break;
                   2180:                                }
                   2181:                                /* intentional drop through */
                   2182:                        default:
                   2183:                                *cp1++ = *cp2;
                   2184:                                break;
                   2185:                }
                   2186:                cp2++;
                   2187:        }
                   2188:        *cp1 = '\0';
                   2189:        if (!*new) {
1.4       cgd      2190:                return (name);
1.1       cgd      2191:        }
1.4       cgd      2192:        return (new);
1.1       cgd      2193: }
                   2194:
1.4       cgd      2195: void
1.5       cgd      2196: setpassive(argc, argv)
                   2197:        int argc;
                   2198:        char *argv[];
                   2199: {
                   2200:
1.76      lukem    2201:        if (argc == 1) {
                   2202:                passivemode = !passivemode;
                   2203:                activefallback = passivemode;
                   2204:        } else if (argc != 2) {
                   2205:  passiveusage:
                   2206:                fprintf(ttyout, "usage: %s [ on | off | auto ]\n", argv[0]);
                   2207:                code = -1;
                   2208:                return;
                   2209:        } else if (strcasecmp(argv[1], "on") == 0) {
                   2210:                passivemode = 1;
                   2211:                activefallback = 0;
                   2212:        } else if (strcasecmp(argv[1], "off") == 0) {
                   2213:                passivemode = 0;
                   2214:                activefallback = 0;
                   2215:        } else if (strcasecmp(argv[1], "auto") == 0) {
                   2216:                passivemode = 1;
                   2217:                activefallback = 1;
                   2218:        } else
                   2219:                goto passiveusage;
                   2220:        fprintf(ttyout, "Passive mode: %s; fallback to active mode: %s.\n",
                   2221:            onoff(passivemode), onoff(activefallback));
                   2222:        code = passivemode;
1.5       cgd      2223: }
                   2224:
                   2225: void
1.68      lukem    2226: setepsv4(argc, argv)
                   2227:        int argc;
                   2228:        char *argv[];
                   2229: {
                   2230:
                   2231:        code = togglevar(argc, argv, &epsv4,
                   2232:            verbose ? "EPSV/EPRT on IPv4" : NULL);
                   2233:        epsv4bad = 0;
                   2234: }
                   2235:
                   2236: void
1.4       cgd      2237: setsunique(argc, argv)
                   2238:        int argc;
                   2239:        char *argv[];
1.1       cgd      2240: {
1.4       cgd      2241:
1.10      lukem    2242:        code = togglevar(argc, argv, &sunique, "Store unique");
1.1       cgd      2243: }
                   2244:
1.4       cgd      2245: void
                   2246: setrunique(argc, argv)
                   2247:        int argc;
                   2248:        char *argv[];
1.1       cgd      2249: {
1.4       cgd      2250:
1.10      lukem    2251:        code = togglevar(argc, argv, &runique, "Receive unique");
1.1       cgd      2252: }
                   2253:
1.52      lukem    2254: int
                   2255: parserate(argc, argv, cmdlineopt)
                   2256:        int argc;
                   2257:        char *argv[];
                   2258:        int cmdlineopt;
                   2259: {
                   2260:        int dir, max, incr, showonly;
                   2261:        sig_t oldusr1, oldusr2;
                   2262:
                   2263:        if (argc > 4 || (argc < (cmdlineopt ? 3 : 2))) {
                   2264: usage:
                   2265:                if (cmdlineopt)
                   2266:                        fprintf(ttyout,
1.66      lukem    2267:        "usage: %s (all|get|put),maximum-bytes[,increment-bytes]]\n",
1.52      lukem    2268:                            argv[0]);
                   2269:                else
                   2270:                        fprintf(ttyout,
1.66      lukem    2271:        "usage: %s (all|get|put) [maximum-bytes [increment-bytes]]\n",
1.52      lukem    2272:                            argv[0]);
                   2273:                return -1;
                   2274:        }
                   2275:        dir = max = incr = showonly = 0;
1.76      lukem    2276: #define        RATE_GET        1
                   2277: #define        RATE_PUT        2
                   2278: #define        RATE_ALL        (RATE_GET | RATE_PUT)
1.52      lukem    2279:
                   2280:        if (strcasecmp(argv[1], "all") == 0)
                   2281:                dir = RATE_ALL;
                   2282:        else if (strcasecmp(argv[1], "get") == 0)
                   2283:                dir = RATE_GET;
                   2284:        else if (strcasecmp(argv[1], "put") == 0)
                   2285:                dir = RATE_PUT;
                   2286:        else
                   2287:                goto usage;
                   2288:
                   2289:        if (argc >= 3) {
                   2290:                if ((max = strsuftoi(argv[2])) < 0)
                   2291:                        goto usage;
                   2292:        } else
                   2293:                showonly = 1;
                   2294:
                   2295:        if (argc == 4) {
                   2296:                if ((incr = strsuftoi(argv[3])) <= 0)
                   2297:                        goto usage;
                   2298:        } else
                   2299:                incr = DEFAULTINCR;
                   2300:
1.62      lukem    2301:        oldusr1 = xsignal(SIGUSR1, SIG_IGN);
                   2302:        oldusr2 = xsignal(SIGUSR2, SIG_IGN);
1.52      lukem    2303:        if (dir & RATE_GET) {
                   2304:                if (!showonly) {
                   2305:                        rate_get = max;
                   2306:                        rate_get_incr = incr;
                   2307:                }
                   2308:                if (!cmdlineopt || verbose)
                   2309:                        fprintf(ttyout,
1.53      lukem    2310:                "Get transfer rate throttle: %s; maximum: %d; increment %d.\n",
1.52      lukem    2311:                            onoff(rate_get), rate_get, rate_get_incr);
                   2312:        }
                   2313:        if (dir & RATE_PUT) {
                   2314:                if (!showonly) {
                   2315:                        rate_put = max;
                   2316:                        rate_put_incr = incr;
                   2317:                }
                   2318:                if (!cmdlineopt || verbose)
                   2319:                        fprintf(ttyout,
1.53      lukem    2320:                "Put transfer rate throttle: %s; maximum: %d; increment %d.\n",
1.52      lukem    2321:                            onoff(rate_put), rate_put, rate_put_incr);
                   2322:        }
1.62      lukem    2323:        (void)xsignal(SIGUSR1, oldusr1);
                   2324:        (void)xsignal(SIGUSR2, oldusr2);
1.52      lukem    2325:        return 0;
                   2326: }
                   2327:
                   2328: void
                   2329: setrate(argc, argv)
                   2330:        int argc;
                   2331:        char *argv[];
                   2332: {
                   2333:
                   2334:        code = parserate(argc, argv, 0);
                   2335: }
                   2336:
1.16      lukem    2337: /* change directory to parent directory */
1.4       cgd      2338: void
                   2339: cdup(argc, argv)
                   2340:        int argc;
                   2341:        char *argv[];
1.1       cgd      2342: {
1.16      lukem    2343:        int r;
1.4       cgd      2344:
1.76      lukem    2345:        if (argc == 0 && argv != NULL) {
                   2346:                fprintf(ttyout, "usage: %s\n", argv[0]);
                   2347:                code = -1;
                   2348:                return;
                   2349:        }
1.16      lukem    2350:        r = command("CDUP");
                   2351:        if (r == ERROR && code == 500) {
1.1       cgd      2352:                if (verbose)
1.37      lukem    2353:                        fputs("CDUP command not recognized, trying XCUP.\n",
                   2354:                            ttyout);
1.16      lukem    2355:                r = command("XCUP");
1.1       cgd      2356:        }
1.79    ! lukem    2357:        if (r == COMPLETE) {
1.16      lukem    2358:                dirchange = 1;
1.79    ! lukem    2359:                updateremotepwd();
        !          2360:        }
1.1       cgd      2361: }
                   2362:
1.27      lukem    2363: /*
                   2364:  * Restart transfer at specific point
                   2365:  */
1.4       cgd      2366: void
1.1       cgd      2367: restart(argc, argv)
                   2368:        int argc;
                   2369:        char *argv[];
                   2370: {
1.4       cgd      2371:
1.76      lukem    2372:        if ((argc == 0 && argv != NULL) || argc > 2) {
1.37      lukem    2373:                fprintf(ttyout, "usage: %s [restart_point]\n", argv[0]);
1.31      lukem    2374:                code = -1;
                   2375:                return;
                   2376:        }
                   2377:        if (argc == 2) {
1.60      lukem    2378:                off_t rp;
1.31      lukem    2379:                char *ep;
                   2380:
1.36      christos 2381: #ifndef NO_QUAD
1.31      lukem    2382:                rp = strtoq(argv[1], &ep, 10);
1.36      christos 2383: #else
                   2384:                rp = strtol(argv[1], &ep, 10);
                   2385: #endif
1.31      lukem    2386:                if (rp < 0 || *ep != '\0')
1.37      lukem    2387:                        fprintf(ttyout, "restart: Invalid offset `%s'\n",
                   2388:                            argv[1]);
1.31      lukem    2389:                else
                   2390:                        restart_point = rp;
1.1       cgd      2391:        }
1.31      lukem    2392:        if (restart_point == 0)
1.37      lukem    2393:                fputs("No restart point defined.\n", ttyout);
1.31      lukem    2394:        else
1.37      lukem    2395:                fprintf(ttyout,
1.36      christos 2396: #ifndef NO_QUAD
1.61      lukem    2397:                    "Restarting at %lld for next get, put or append\n",
1.31      lukem    2398:                    (long long)restart_point);
1.36      christos 2399: #else
1.37      lukem    2400:                    "Restarting at %ld for next get, put or append\n",
1.36      christos 2401:                    (long)restart_point);
                   2402: #endif
1.1       cgd      2403: }
                   2404:
1.47      lukem    2405: /*
1.27      lukem    2406:  * Show remote system type
                   2407:  */
1.4       cgd      2408: void
                   2409: syst(argc, argv)
                   2410:        int argc;
                   2411:        char *argv[];
1.1       cgd      2412: {
1.4       cgd      2413:
1.76      lukem    2414:        if (argc == 0 && argv != NULL) {
                   2415:                fprintf(ttyout, "usage: %s\n", argv[0]);
                   2416:                code = -1;
                   2417:                return;
                   2418:        }
1.19      lukem    2419:        (void)command("SYST");
1.1       cgd      2420: }
                   2421:
1.4       cgd      2422: void
1.1       cgd      2423: macdef(argc, argv)
                   2424:        int argc;
                   2425:        char *argv[];
                   2426: {
                   2427:        char *tmp;
                   2428:        int c;
                   2429:
1.76      lukem    2430:        if (argc == 0 && argv != NULL)
                   2431:                goto usage;
1.1       cgd      2432:        if (macnum == 16) {
1.37      lukem    2433:                fputs("Limit of 16 macros have already been defined.\n",
                   2434:                    ttyout);
1.1       cgd      2435:                code = -1;
                   2436:                return;
                   2437:        }
1.10      lukem    2438:        if ((argc < 2 && !another(&argc, &argv, "macro name")) || argc > 2) {
1.76      lukem    2439:  usage:
1.37      lukem    2440:                fprintf(ttyout, "usage: %s macro_name\n", argv[0]);
1.1       cgd      2441:                code = -1;
                   2442:                return;
                   2443:        }
1.19      lukem    2444:        if (interactive)
1.37      lukem    2445:                fputs(
                   2446:                "Enter macro line by line, terminating it with a null line.\n",
                   2447:                    ttyout);
1.63      lukem    2448:        (void)strlcpy(macros[macnum].mac_name, argv[1],
                   2449:            sizeof(macros[macnum].mac_name));
1.19      lukem    2450:        if (macnum == 0)
1.1       cgd      2451:                macros[macnum].mac_start = macbuf;
1.19      lukem    2452:        else
1.1       cgd      2453:                macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
                   2454:        tmp = macros[macnum].mac_start;
                   2455:        while (tmp != macbuf+4096) {
                   2456:                if ((c = getchar()) == EOF) {
1.37      lukem    2457:                        fputs("macdef: end of file encountered.\n", ttyout);
1.1       cgd      2458:                        code = -1;
                   2459:                        return;
                   2460:                }
                   2461:                if ((*tmp = c) == '\n') {
                   2462:                        if (tmp == macros[macnum].mac_start) {
                   2463:                                macros[macnum++].mac_end = tmp;
                   2464:                                code = 0;
                   2465:                                return;
                   2466:                        }
                   2467:                        if (*(tmp-1) == '\0') {
                   2468:                                macros[macnum++].mac_end = tmp - 1;
                   2469:                                code = 0;
                   2470:                                return;
                   2471:                        }
                   2472:                        *tmp = '\0';
                   2473:                }
                   2474:                tmp++;
                   2475:        }
                   2476:        while (1) {
                   2477:                while ((c = getchar()) != '\n' && c != EOF)
                   2478:                        /* LOOP */;
                   2479:                if (c == EOF || getchar() == '\n') {
1.37      lukem    2480:                        fputs("Macro not defined - 4K buffer exceeded.\n",
                   2481:                            ttyout);
1.1       cgd      2482:                        code = -1;
                   2483:                        return;
                   2484:                }
                   2485:        }
                   2486: }
                   2487:
                   2488: /*
1.27      lukem    2489:  * Get size of file on remote machine
1.1       cgd      2490:  */
1.4       cgd      2491: void
1.1       cgd      2492: sizecmd(argc, argv)
                   2493:        int argc;
                   2494:        char *argv[];
                   2495: {
1.11      lukem    2496:        off_t size;
1.1       cgd      2497:
1.76      lukem    2498:        if ((argc == 1 && !another(&argc, &argv, "remote-file")) ||
                   2499:            (argc == 0 && argv != NULL) || argc > 2) {
                   2500:                fprintf(ttyout, "usage: %s remote-file\n", argv[0]);
1.1       cgd      2501:                code = -1;
                   2502:                return;
                   2503:        }
1.13      lukem    2504:        size = remotesize(argv[1], 1);
1.11      lukem    2505:        if (size != -1)
1.37      lukem    2506:                fprintf(ttyout,
1.36      christos 2507: #ifndef NO_QUAD
1.61      lukem    2508:                    "%s\t%lld\n", argv[1], (long long)size);
1.36      christos 2509: #else
1.37      lukem    2510:                    "%s\t%ld\n", argv[1], (long)size);
1.36      christos 2511: #endif
1.76      lukem    2512:        code = (size > 0);
1.10      lukem    2513: }
                   2514:
                   2515: /*
1.27      lukem    2516:  * Get last modification time of file on remote machine
1.10      lukem    2517:  */
                   2518: void
                   2519: modtime(argc, argv)
                   2520:        int argc;
                   2521:        char *argv[];
                   2522: {
                   2523:        time_t mtime;
                   2524:
1.76      lukem    2525:        if ((argc == 1 && !another(&argc, &argv, "remote-file")) ||
                   2526:            (argc == 0 && argv != NULL) || argc > 2) {
                   2527:                fprintf(ttyout, "usage: %s remote-file\n", argv[0]);
1.10      lukem    2528:                code = -1;
                   2529:                return;
                   2530:        }
1.13      lukem    2531:        mtime = remotemodtime(argv[1], 1);
1.10      lukem    2532:        if (mtime != -1)
1.37      lukem    2533:                fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime)));
1.76      lukem    2534:        code = (mtime > 0);
1.1       cgd      2535: }
                   2536:
                   2537: /*
1.27      lukem    2538:  * Show status on remote machine
1.1       cgd      2539:  */
1.4       cgd      2540: void
1.1       cgd      2541: rmtstatus(argc, argv)
                   2542:        int argc;
                   2543:        char *argv[];
                   2544: {
1.4       cgd      2545:
1.76      lukem    2546:        if (argc == 0 && argv != NULL) {
                   2547:                fprintf(ttyout, "usage: %s [remote-file]\n", argv[0]);
                   2548:                code = -1;
                   2549:                return;
                   2550:        }
1.19      lukem    2551:        (void)command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
1.1       cgd      2552: }
                   2553:
                   2554: /*
1.27      lukem    2555:  * Get file if modtime is more recent than current file
1.1       cgd      2556:  */
1.4       cgd      2557: void
1.1       cgd      2558: newer(argc, argv)
                   2559:        int argc;
                   2560:        char *argv[];
                   2561: {
1.4       cgd      2562:
1.1       cgd      2563:        if (getit(argc, argv, -1, "w"))
1.37      lukem    2564:                fprintf(ttyout,
                   2565:                    "Local file \"%s\" is newer than remote file \"%s\".\n",
                   2566:                    argv[2], argv[1]);
1.19      lukem    2567: }
                   2568:
                   2569: /*
1.76      lukem    2570:  * Display one local file through $PAGER.
1.19      lukem    2571:  */
                   2572: void
1.63      lukem    2573: lpage(argc, argv)
1.19      lukem    2574:        int argc;
                   2575:        char *argv[];
                   2576: {
1.63      lukem    2577:        int len;
                   2578:        char *p, *pager, *locfile;
1.19      lukem    2579:
1.76      lukem    2580:        if ((argc == 0 && argv != NULL) ||
                   2581:            (argc == 1 && !another(&argc, &argv, "local-file")) || argc > 2) {
                   2582:                fprintf(ttyout, "usage: %s local-file\n", argv[0]);
1.19      lukem    2583:                code = -1;
                   2584:                return;
                   2585:        }
1.63      lukem    2586:        if ((locfile = globulize(argv[1])) == NULL) {
                   2587:                code = -1;
                   2588:                return;
                   2589:        }
1.76      lukem    2590:        p = getoptionvalue("pager");
                   2591:        if (EMPTYSTRING(p))
                   2592:                p = DEFAULTPAGER;
1.63      lukem    2593:        len = strlen(p) + strlen(locfile) + 2;
                   2594:        pager = xmalloc(len);
                   2595:        (void)strlcpy(pager, p,         len);
                   2596:        (void)strlcat(pager, " ",       len);
                   2597:        (void)strlcat(pager, locfile,   len);
                   2598:        system(pager);
1.76      lukem    2599:        code = 0;
1.63      lukem    2600:        (void)free(pager);
                   2601:        (void)free(locfile);
                   2602: }
                   2603:
                   2604: /*
1.76      lukem    2605:  * Display one remote file through $PAGER.
1.63      lukem    2606:  */
                   2607: void
                   2608: page(argc, argv)
                   2609:        int argc;
                   2610:        char *argv[];
                   2611: {
                   2612:        int ohash, orestart_point, overbose, len;
                   2613:        char *p, *pager;
                   2614:
1.76      lukem    2615:        if ((argc == 0 && argv != NULL) ||
                   2616:            (argc == 1 && !another(&argc, &argv, "remote-file")) || argc > 2) {
                   2617:                fprintf(ttyout, "usage: %s remote-file\n", argv[0]);
1.19      lukem    2618:                code = -1;
                   2619:                return;
                   2620:        }
1.76      lukem    2621:        p = getoptionvalue("pager");
                   2622:        if (EMPTYSTRING(p))
                   2623:                p = DEFAULTPAGER;
1.49      lukem    2624:        len = strlen(p) + 2;
                   2625:        pager = xmalloc(len);
1.57      lukem    2626:        pager[0] = '|';
1.63      lukem    2627:        (void)strlcpy(pager + 1, p, len - 1);
1.19      lukem    2628:
                   2629:        ohash = hash;
1.37      lukem    2630:        orestart_point = restart_point;
1.19      lukem    2631:        overbose = verbose;
1.37      lukem    2632:        hash = restart_point = verbose = 0;
1.27      lukem    2633:        recvrequest("RETR", pager, argv[1], "r+w", 1, 0);
1.19      lukem    2634:        hash = ohash;
1.37      lukem    2635:        restart_point = orestart_point;
1.19      lukem    2636:        verbose = overbose;
1.63      lukem    2637:        (void)free(pager);
1.39      thorpej  2638: }
                   2639:
                   2640: /*
1.58      lukem    2641:  * Set the socket send or receive buffer size.
1.39      thorpej  2642:  */
                   2643: void
1.58      lukem    2644: setxferbuf(argc, argv)
1.39      thorpej  2645:        int argc;
                   2646:        char *argv[];
                   2647: {
1.58      lukem    2648:        int size, dir;
1.39      thorpej  2649:
                   2650:        if (argc != 2) {
1.58      lukem    2651:  usage:
                   2652:                fprintf(ttyout, "usage: %s size\n", argv[0]);
1.39      thorpej  2653:                code = -1;
                   2654:                return;
                   2655:        }
1.58      lukem    2656:        if (strcasecmp(argv[0], "sndbuf") == 0)
                   2657:                dir = RATE_PUT;
                   2658:        else if (strcasecmp(argv[0], "rcvbuf") == 0)
                   2659:                dir = RATE_GET;
                   2660:        else if (strcasecmp(argv[0], "xferbuf") == 0)
                   2661:                dir = RATE_ALL;
1.39      thorpej  2662:        else
1.58      lukem    2663:                goto usage;
1.39      thorpej  2664:
1.58      lukem    2665:        if ((size = strsuftoi(argv[1])) == -1)
                   2666:                goto usage;
1.39      thorpej  2667:
1.58      lukem    2668:        if (size == 0) {
                   2669:                fprintf(ttyout, "%s: size must be positive.\n", argv[0]);
                   2670:                goto usage;
1.39      thorpej  2671:        }
                   2672:
1.58      lukem    2673:        if (dir & RATE_PUT)
                   2674:                sndbuf_size = size;
                   2675:        if (dir & RATE_GET)
                   2676:                rcvbuf_size = size;
                   2677:        fprintf(ttyout, "Socket buffer sizes: send %d, receive %d.\n",
                   2678:            sndbuf_size, rcvbuf_size);
1.76      lukem    2679:        code = 0;
                   2680: }
                   2681:
                   2682: /*
                   2683:  * Set or display options (defaults are provided by various env vars)
                   2684:  */
                   2685: void
                   2686: setoption(argc, argv)
                   2687:        int argc;
                   2688:        char *argv[];
                   2689: {
                   2690:        struct option *o;
                   2691:
                   2692:        code = -1;
                   2693:        if ((argc == 0 && argv != NULL) || (argc != 1 && argc != 3)) {
                   2694:                fprintf(ttyout, "usage: %s [option value]\n", argv[0]);
                   2695:                return;
                   2696:        }
                   2697:
                   2698: #define        OPTIONINDENT ((int) sizeof("http_proxy"))
                   2699:        if (argc == 1) {
                   2700:                for (o = optiontab; o->name != NULL; o++) {
                   2701:                        fprintf(ttyout, "%-*s\t%s\n", OPTIONINDENT,
                   2702:                            o->name, o->value ? o->value : "");
                   2703:                }
                   2704:        } else {
                   2705:                o = getoption(argv[1]);
                   2706:                if (o == NULL) {
                   2707:                        fprintf(ttyout, "No such option `%s'.\n", argv[1]);
                   2708:                        return;
                   2709:                }
                   2710:                FREEPTR(o->value);
                   2711:                o->value = xstrdup(argv[2]);
                   2712:                if (verbose)
                   2713:                        fprintf(ttyout, "Setting `%s' to `%s'.\n",
                   2714:                            o->name, o->value);
                   2715:        }
                   2716:        code = 0;
                   2717: }
                   2718:
                   2719: /*
                   2720:  * Unset an option
                   2721:  */
                   2722: void
                   2723: unsetoption(argc, argv)
                   2724:        int argc;
                   2725:        char *argv[];
                   2726: {
                   2727:        struct option *o;
                   2728:
                   2729:        code = -1;
                   2730:        if ((argc == 0 && argv != NULL) || argc !=  2) {
                   2731:                fprintf(ttyout, "usage: %s option\n", argv[0]);
                   2732:                return;
                   2733:        }
                   2734:
                   2735:        o = getoption(argv[1]);
                   2736:        if (o == NULL) {
                   2737:                fprintf(ttyout, "No such option `%s'.\n", argv[1]);
                   2738:                return;
                   2739:        }
                   2740:        FREEPTR(o->value);
                   2741:        fprintf(ttyout, "Unsetting `%s'.\n", o->name);
                   2742:        code = 0;
1.1       cgd      2743: }

CVSweb <webmaster@jp.NetBSD.org>