cmds.c revision 72445
155682Smarkm/* 255682Smarkm * Copyright (c) 1985, 1989, 1993, 1994 355682Smarkm * The Regents of the University of California. All rights reserved. 455682Smarkm * 555682Smarkm * Redistribution and use in source and binary forms, with or without 655682Smarkm * modification, are permitted provided that the following conditions 755682Smarkm * are met: 855682Smarkm * 1. Redistributions of source code must retain the above copyright 955682Smarkm * notice, this list of conditions and the following disclaimer. 1055682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer in the 1255682Smarkm * documentation and/or other materials provided with the distribution. 1355682Smarkm * 3. All advertising materials mentioning features or use of this software 1455682Smarkm * must display the following acknowledgement: 1555682Smarkm * This product includes software developed by the University of 1655682Smarkm * California, Berkeley and its contributors. 1755682Smarkm * 4. Neither the name of the University nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm/* 3555682Smarkm * FTP User Program -- Command Routines. 3655682Smarkm */ 3755682Smarkm 3855682Smarkm#include "ftp_locl.h" 3972445SassarRCSID("$Id: cmds.c,v 1.41 2000/07/18 10:00:31 joda Exp $"); 4055682Smarkm 4155682Smarkmtypedef void (*sighand)(int); 4255682Smarkm 4355682Smarkmjmp_buf jabort; 4455682Smarkmchar *mname; 4555682Smarkmchar *home = "/"; 4655682Smarkm 4755682Smarkm/* 4855682Smarkm * `Another' gets another argument, and stores the new argc and argv. 4955682Smarkm * It reverts to the top level (via main.c's intr()) on EOF/error. 5055682Smarkm * 5155682Smarkm * Returns false if no new arguments have been added. 5255682Smarkm */ 5355682Smarkmint 5455682Smarkmanother(int *pargc, char ***pargv, char *prompt) 5555682Smarkm{ 5655682Smarkm int len = strlen(line), ret; 5755682Smarkm 5855682Smarkm if (len >= sizeof(line) - 3) { 5955682Smarkm printf("sorry, arguments too long\n"); 6055682Smarkm intr(0); 6155682Smarkm } 6255682Smarkm printf("(%s) ", prompt); 6355682Smarkm line[len++] = ' '; 6455682Smarkm if (fgets(&line[len], sizeof(line) - len, stdin) == NULL) 6555682Smarkm intr(0); 6655682Smarkm len += strlen(&line[len]); 6755682Smarkm if (len > 0 && line[len - 1] == '\n') 6855682Smarkm line[len - 1] = '\0'; 6955682Smarkm makeargv(); 7055682Smarkm ret = margc > *pargc; 7155682Smarkm *pargc = margc; 7255682Smarkm *pargv = margv; 7355682Smarkm return (ret); 7455682Smarkm} 7555682Smarkm 7655682Smarkm/* 7755682Smarkm * Connect to peer server and 7855682Smarkm * auto-login, if possible. 7955682Smarkm */ 8055682Smarkmvoid 8155682Smarkmsetpeer(int argc, char **argv) 8255682Smarkm{ 8355682Smarkm char *host; 8455682Smarkm short port; 8555682Smarkm struct servent *sp; 8655682Smarkm 8755682Smarkm if (connected) { 8855682Smarkm printf("Already connected to %s, use close first.\n", 8955682Smarkm hostname); 9055682Smarkm code = -1; 9155682Smarkm return; 9255682Smarkm } 9355682Smarkm if (argc < 2) 9455682Smarkm another(&argc, &argv, "to"); 9555682Smarkm if (argc < 2 || argc > 3) { 9655682Smarkm printf("usage: %s host-name [port]\n", argv[0]); 9755682Smarkm code = -1; 9855682Smarkm return; 9955682Smarkm } 10055682Smarkm sp = getservbyname("ftp", "tcp"); 10155682Smarkm if (sp == NULL) 10255682Smarkm errx(1, "You bastard. You removed ftp/tcp from services"); 10355682Smarkm port = sp->s_port; 10455682Smarkm if (argc > 2) { 10555682Smarkm port = atoi(argv[2]); 10655682Smarkm if (port <= 0) { 10755682Smarkm printf("%s: bad port number-- %s\n", argv[1], argv[2]); 10855682Smarkm printf ("usage: %s host-name [port]\n", argv[0]); 10955682Smarkm code = -1; 11055682Smarkm return; 11155682Smarkm } 11255682Smarkm port = htons(port); 11355682Smarkm } 11455682Smarkm host = hookup(argv[1], port); 11555682Smarkm if (host) { 11655682Smarkm int overbose; 11755682Smarkm 11855682Smarkm connected = 1; 11955682Smarkm /* 12055682Smarkm * Set up defaults for FTP. 12155682Smarkm */ 12255682Smarkm strlcpy(typename, "ascii", sizeof(typename)); 12355682Smarkm type = TYPE_A; 12455682Smarkm curtype = TYPE_A; 12555682Smarkm strlcpy(formname, "non-print", sizeof(formname)); 12655682Smarkm form = FORM_N; 12755682Smarkm strlcpy(modename, "stream", sizeof(modename)); 12855682Smarkm mode = MODE_S; 12955682Smarkm strlcpy(structname, "file", sizeof(structname)); 13055682Smarkm stru = STRU_F; 13155682Smarkm strlcpy(bytename, "8", sizeof(bytename)); 13255682Smarkm bytesize = 8; 13355682Smarkm if (autologin) 13455682Smarkm login(argv[1]); 13555682Smarkm 13655682Smarkm#if (defined(unix) || defined(__unix__) || defined(__unix) || defined(_AIX) || defined(_CRAY)) && NBBY == 8 13755682Smarkm/* 13855682Smarkm * this ifdef is to keep someone form "porting" this to an incompatible 13955682Smarkm * system and not checking this out. This way they have to think about it. 14055682Smarkm */ 14155682Smarkm overbose = verbose; 14255682Smarkm if (debug == 0) 14355682Smarkm verbose = -1; 14455682Smarkm if (command("SYST") == COMPLETE && overbose) { 14555682Smarkm char *cp, c; 14655682Smarkm cp = strchr(reply_string+4, ' '); 14755682Smarkm if (cp == NULL) 14855682Smarkm cp = strchr(reply_string+4, '\r'); 14955682Smarkm if (cp) { 15055682Smarkm if (cp[-1] == '.') 15155682Smarkm cp--; 15255682Smarkm c = *cp; 15355682Smarkm *cp = '\0'; 15455682Smarkm } 15555682Smarkm 15655682Smarkm printf("Remote system type is %s.\n", 15755682Smarkm reply_string+4); 15855682Smarkm if (cp) 15955682Smarkm *cp = c; 16055682Smarkm } 16155682Smarkm if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { 16255682Smarkm if (proxy) 16355682Smarkm unix_proxy = 1; 16455682Smarkm else 16555682Smarkm unix_server = 1; 16655682Smarkm /* 16755682Smarkm * Set type to 0 (not specified by user), 16855682Smarkm * meaning binary by default, but don't bother 16955682Smarkm * telling server. We can use binary 17055682Smarkm * for text files unless changed by the user. 17155682Smarkm */ 17255682Smarkm type = 0; 17355682Smarkm strlcpy(typename, "binary", sizeof(typename)); 17455682Smarkm if (overbose) 17555682Smarkm printf("Using %s mode to transfer files.\n", 17655682Smarkm typename); 17755682Smarkm } else { 17855682Smarkm if (proxy) 17955682Smarkm unix_proxy = 0; 18055682Smarkm else 18155682Smarkm unix_server = 0; 18255682Smarkm if (overbose && 18355682Smarkm !strncmp(reply_string, "215 TOPS20", 10)) 18455682Smarkm printf( 18555682Smarkm"Remember to set tenex mode when transfering binary files from this machine.\n"); 18655682Smarkm } 18755682Smarkm verbose = overbose; 18855682Smarkm#endif /* unix */ 18955682Smarkm } 19055682Smarkm} 19155682Smarkm 19255682Smarkmstruct types { 19355682Smarkm char *t_name; 19455682Smarkm char *t_mode; 19555682Smarkm int t_type; 19655682Smarkm char *t_arg; 19755682Smarkm} types[] = { 19855682Smarkm { "ascii", "A", TYPE_A, 0 }, 19955682Smarkm { "binary", "I", TYPE_I, 0 }, 20055682Smarkm { "image", "I", TYPE_I, 0 }, 20155682Smarkm { "ebcdic", "E", TYPE_E, 0 }, 20255682Smarkm { "tenex", "L", TYPE_L, bytename }, 20355682Smarkm { NULL } 20455682Smarkm}; 20555682Smarkm 20655682Smarkm/* 20755682Smarkm * Set transfer type. 20855682Smarkm */ 20955682Smarkmvoid 21055682Smarkmsettype(int argc, char **argv) 21155682Smarkm{ 21255682Smarkm struct types *p; 21355682Smarkm int comret; 21455682Smarkm 21555682Smarkm if (argc > 2) { 21655682Smarkm char *sep; 21755682Smarkm 21855682Smarkm printf("usage: %s [", argv[0]); 21955682Smarkm sep = " "; 22055682Smarkm for (p = types; p->t_name; p++) { 22155682Smarkm printf("%s%s", sep, p->t_name); 22255682Smarkm sep = " | "; 22355682Smarkm } 22455682Smarkm printf(" ]\n"); 22555682Smarkm code = -1; 22655682Smarkm return; 22755682Smarkm } 22855682Smarkm if (argc < 2) { 22955682Smarkm printf("Using %s mode to transfer files.\n", typename); 23055682Smarkm code = 0; 23155682Smarkm return; 23255682Smarkm } 23355682Smarkm for (p = types; p->t_name; p++) 23455682Smarkm if (strcmp(argv[1], p->t_name) == 0) 23555682Smarkm break; 23655682Smarkm if (p->t_name == 0) { 23755682Smarkm printf("%s: unknown mode\n", argv[1]); 23855682Smarkm code = -1; 23955682Smarkm return; 24055682Smarkm } 24155682Smarkm if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 24255682Smarkm comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 24355682Smarkm else 24455682Smarkm comret = command("TYPE %s", p->t_mode); 24555682Smarkm if (comret == COMPLETE) { 24655682Smarkm strlcpy(typename, p->t_name, sizeof(typename)); 24755682Smarkm curtype = type = p->t_type; 24855682Smarkm } 24955682Smarkm} 25055682Smarkm 25155682Smarkm/* 25255682Smarkm * Internal form of settype; changes current type in use with server 25355682Smarkm * without changing our notion of the type for data transfers. 25455682Smarkm * Used to change to and from ascii for listings. 25555682Smarkm */ 25655682Smarkmvoid 25755682Smarkmchangetype(int newtype, int show) 25855682Smarkm{ 25955682Smarkm struct types *p; 26055682Smarkm int comret, oldverbose = verbose; 26155682Smarkm 26255682Smarkm if (newtype == 0) 26355682Smarkm newtype = TYPE_I; 26455682Smarkm if (newtype == curtype) 26555682Smarkm return; 26655682Smarkm if (debug == 0 && show == 0) 26755682Smarkm verbose = 0; 26855682Smarkm for (p = types; p->t_name; p++) 26955682Smarkm if (newtype == p->t_type) 27055682Smarkm break; 27155682Smarkm if (p->t_name == 0) { 27255682Smarkm printf("ftp: internal error: unknown type %d\n", newtype); 27355682Smarkm return; 27455682Smarkm } 27555682Smarkm if (newtype == TYPE_L && bytename[0] != '\0') 27655682Smarkm comret = command("TYPE %s %s", p->t_mode, bytename); 27755682Smarkm else 27855682Smarkm comret = command("TYPE %s", p->t_mode); 27955682Smarkm if (comret == COMPLETE) 28055682Smarkm curtype = newtype; 28155682Smarkm verbose = oldverbose; 28255682Smarkm} 28355682Smarkm 28455682Smarkmchar *stype[] = { 28555682Smarkm "type", 28655682Smarkm "", 28755682Smarkm 0 28855682Smarkm}; 28955682Smarkm 29055682Smarkm/* 29155682Smarkm * Set binary transfer type. 29255682Smarkm */ 29355682Smarkm/*VARARGS*/ 29455682Smarkmvoid 29555682Smarkmsetbinary(int argc, char **argv) 29655682Smarkm{ 29755682Smarkm 29855682Smarkm stype[1] = "binary"; 29955682Smarkm settype(2, stype); 30055682Smarkm} 30155682Smarkm 30255682Smarkm/* 30355682Smarkm * Set ascii transfer type. 30455682Smarkm */ 30555682Smarkm/*VARARGS*/ 30655682Smarkmvoid 30755682Smarkmsetascii(int argc, char **argv) 30855682Smarkm{ 30955682Smarkm 31055682Smarkm stype[1] = "ascii"; 31155682Smarkm settype(2, stype); 31255682Smarkm} 31355682Smarkm 31455682Smarkm/* 31555682Smarkm * Set tenex transfer type. 31655682Smarkm */ 31755682Smarkm/*VARARGS*/ 31855682Smarkmvoid 31955682Smarkmsettenex(int argc, char **argv) 32055682Smarkm{ 32155682Smarkm 32255682Smarkm stype[1] = "tenex"; 32355682Smarkm settype(2, stype); 32455682Smarkm} 32555682Smarkm 32655682Smarkm/* 32755682Smarkm * Set file transfer mode. 32855682Smarkm */ 32955682Smarkm/*ARGSUSED*/ 33055682Smarkmvoid 33155682Smarkmsetftmode(int argc, char **argv) 33255682Smarkm{ 33355682Smarkm 33455682Smarkm printf("We only support %s mode, sorry.\n", modename); 33555682Smarkm code = -1; 33655682Smarkm} 33755682Smarkm 33855682Smarkm/* 33955682Smarkm * Set file transfer format. 34055682Smarkm */ 34155682Smarkm/*ARGSUSED*/ 34255682Smarkmvoid 34355682Smarkmsetform(int argc, char **argv) 34455682Smarkm{ 34555682Smarkm 34655682Smarkm printf("We only support %s format, sorry.\n", formname); 34755682Smarkm code = -1; 34855682Smarkm} 34955682Smarkm 35055682Smarkm/* 35155682Smarkm * Set file transfer structure. 35255682Smarkm */ 35355682Smarkm/*ARGSUSED*/ 35455682Smarkmvoid 35555682Smarkmsetstruct(int argc, char **argv) 35655682Smarkm{ 35755682Smarkm 35855682Smarkm printf("We only support %s structure, sorry.\n", structname); 35955682Smarkm code = -1; 36055682Smarkm} 36155682Smarkm 36255682Smarkm/* 36355682Smarkm * Send a single file. 36455682Smarkm */ 36555682Smarkmvoid 36655682Smarkmput(int argc, char **argv) 36755682Smarkm{ 36855682Smarkm char *cmd; 36955682Smarkm int loc = 0; 37055682Smarkm char *oldargv1, *oldargv2; 37155682Smarkm 37255682Smarkm if (argc == 2) { 37355682Smarkm argc++; 37455682Smarkm argv[2] = argv[1]; 37555682Smarkm loc++; 37655682Smarkm } 37755682Smarkm if (argc < 2 && !another(&argc, &argv, "local-file")) 37855682Smarkm goto usage; 37955682Smarkm if (argc < 3 && !another(&argc, &argv, "remote-file")) { 38055682Smarkmusage: 38155682Smarkm printf("usage: %s local-file remote-file\n", argv[0]); 38255682Smarkm code = -1; 38355682Smarkm return; 38455682Smarkm } 38555682Smarkm oldargv1 = argv[1]; 38655682Smarkm oldargv2 = argv[2]; 38755682Smarkm if (!globulize(&argv[1])) { 38855682Smarkm code = -1; 38955682Smarkm return; 39055682Smarkm } 39155682Smarkm /* 39255682Smarkm * If "globulize" modifies argv[1], and argv[2] is a copy of 39355682Smarkm * the old argv[1], make it a copy of the new argv[1]. 39455682Smarkm */ 39555682Smarkm if (argv[1] != oldargv1 && argv[2] == oldargv1) { 39655682Smarkm argv[2] = argv[1]; 39755682Smarkm } 39855682Smarkm cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); 39955682Smarkm if (loc && ntflag) { 40055682Smarkm argv[2] = dotrans(argv[2]); 40155682Smarkm } 40255682Smarkm if (loc && mapflag) { 40355682Smarkm argv[2] = domap(argv[2]); 40455682Smarkm } 40555682Smarkm sendrequest(cmd, argv[1], argv[2], 40655682Smarkm curtype == TYPE_I ? "rb" : "r", 40755682Smarkm argv[1] != oldargv1 || argv[2] != oldargv2); 40855682Smarkm} 40955682Smarkm 41055682Smarkm/* ARGSUSED */ 41155682Smarkmstatic RETSIGTYPE 41255682Smarkmmabort(int signo) 41355682Smarkm{ 41455682Smarkm int ointer; 41555682Smarkm 41655682Smarkm printf("\n"); 41755682Smarkm fflush(stdout); 41855682Smarkm if (mflag && fromatty) { 41955682Smarkm ointer = interactive; 42055682Smarkm interactive = 1; 42155682Smarkm if (confirm("Continue with", mname)) { 42255682Smarkm interactive = ointer; 42355682Smarkm longjmp(jabort,0); 42455682Smarkm } 42555682Smarkm interactive = ointer; 42655682Smarkm } 42755682Smarkm mflag = 0; 42855682Smarkm longjmp(jabort,0); 42955682Smarkm} 43055682Smarkm 43155682Smarkm/* 43255682Smarkm * Send multiple files. 43355682Smarkm */ 43455682Smarkmvoid 43555682Smarkmmput(int argc, char **argv) 43655682Smarkm{ 43755682Smarkm int i; 43872445Sassar RETSIGTYPE (*oldintr)(int); 43955682Smarkm int ointer; 44055682Smarkm char *tp; 44155682Smarkm 44255682Smarkm if (argc < 2 && !another(&argc, &argv, "local-files")) { 44355682Smarkm printf("usage: %s local-files\n", argv[0]); 44455682Smarkm code = -1; 44555682Smarkm return; 44655682Smarkm } 44755682Smarkm mname = argv[0]; 44855682Smarkm mflag = 1; 44955682Smarkm oldintr = signal(SIGINT, mabort); 45055682Smarkm setjmp(jabort); 45155682Smarkm if (proxy) { 45255682Smarkm char *cp, *tp2, tmpbuf[MaxPathLen]; 45355682Smarkm 45455682Smarkm while ((cp = remglob(argv,0)) != NULL) { 45555682Smarkm if (*cp == 0) { 45655682Smarkm mflag = 0; 45755682Smarkm continue; 45855682Smarkm } 45955682Smarkm if (mflag && confirm(argv[0], cp)) { 46055682Smarkm tp = cp; 46155682Smarkm if (mcase) { 46255682Smarkm while (*tp && !islower(*tp)) { 46355682Smarkm tp++; 46455682Smarkm } 46555682Smarkm if (!*tp) { 46655682Smarkm tp = cp; 46755682Smarkm tp2 = tmpbuf; 46855682Smarkm while ((*tp2 = *tp) != '\0') { 46955682Smarkm if (isupper(*tp2)) { 47055682Smarkm *tp2 = 'a' + *tp2 - 'A'; 47155682Smarkm } 47255682Smarkm tp++; 47355682Smarkm tp2++; 47455682Smarkm } 47555682Smarkm } 47655682Smarkm tp = tmpbuf; 47755682Smarkm } 47855682Smarkm if (ntflag) { 47955682Smarkm tp = dotrans(tp); 48055682Smarkm } 48155682Smarkm if (mapflag) { 48255682Smarkm tp = domap(tp); 48355682Smarkm } 48455682Smarkm sendrequest((sunique) ? "STOU" : "STOR", 48555682Smarkm cp, tp, 48655682Smarkm curtype == TYPE_I ? "rb" : "r", 48755682Smarkm cp != tp || !interactive); 48855682Smarkm if (!mflag && fromatty) { 48955682Smarkm ointer = interactive; 49055682Smarkm interactive = 1; 49155682Smarkm if (confirm("Continue with","mput")) { 49255682Smarkm mflag++; 49355682Smarkm } 49455682Smarkm interactive = ointer; 49555682Smarkm } 49655682Smarkm } 49755682Smarkm } 49855682Smarkm signal(SIGINT, oldintr); 49955682Smarkm mflag = 0; 50055682Smarkm return; 50155682Smarkm } 50255682Smarkm for (i = 1; i < argc; i++) { 50355682Smarkm char **cpp; 50455682Smarkm glob_t gl; 50555682Smarkm int flags; 50655682Smarkm 50755682Smarkm if (!doglob) { 50855682Smarkm if (mflag && confirm(argv[0], argv[i])) { 50955682Smarkm tp = (ntflag) ? dotrans(argv[i]) : argv[i]; 51055682Smarkm tp = (mapflag) ? domap(tp) : tp; 51155682Smarkm sendrequest((sunique) ? "STOU" : "STOR", 51255682Smarkm argv[i], 51355682Smarkm curtype == TYPE_I ? "rb" : "r", 51455682Smarkm tp, tp != argv[i] || !interactive); 51555682Smarkm if (!mflag && fromatty) { 51655682Smarkm ointer = interactive; 51755682Smarkm interactive = 1; 51855682Smarkm if (confirm("Continue with","mput")) { 51955682Smarkm mflag++; 52055682Smarkm } 52155682Smarkm interactive = ointer; 52255682Smarkm } 52355682Smarkm } 52455682Smarkm continue; 52555682Smarkm } 52655682Smarkm 52755682Smarkm memset(&gl, 0, sizeof(gl)); 52855682Smarkm flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 52955682Smarkm if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) { 53055682Smarkm warnx("%s: not found", argv[i]); 53155682Smarkm globfree(&gl); 53255682Smarkm continue; 53355682Smarkm } 53455682Smarkm for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) { 53555682Smarkm if (mflag && confirm(argv[0], *cpp)) { 53655682Smarkm tp = (ntflag) ? dotrans(*cpp) : *cpp; 53755682Smarkm tp = (mapflag) ? domap(tp) : tp; 53855682Smarkm sendrequest((sunique) ? "STOU" : "STOR", 53955682Smarkm *cpp, tp, 54055682Smarkm curtype == TYPE_I ? "rb" : "r", 54155682Smarkm *cpp != tp || !interactive); 54255682Smarkm if (!mflag && fromatty) { 54355682Smarkm ointer = interactive; 54455682Smarkm interactive = 1; 54555682Smarkm if (confirm("Continue with","mput")) { 54655682Smarkm mflag++; 54755682Smarkm } 54855682Smarkm interactive = ointer; 54955682Smarkm } 55055682Smarkm } 55155682Smarkm } 55255682Smarkm globfree(&gl); 55355682Smarkm } 55455682Smarkm signal(SIGINT, oldintr); 55555682Smarkm mflag = 0; 55655682Smarkm} 55755682Smarkm 55855682Smarkmvoid 55955682Smarkmreget(int argc, char **argv) 56055682Smarkm{ 56155682Smarkm getit(argc, argv, 1, curtype == TYPE_I ? "r+wb" : "r+w"); 56255682Smarkm} 56355682Smarkm 56455682Smarkmvoid 56555682Smarkmget(int argc, char **argv) 56655682Smarkm{ 56755682Smarkm char *mode; 56855682Smarkm 56972445Sassar if (restart_point) { 57055682Smarkm if (curtype == TYPE_I) 57155682Smarkm mode = "r+wb"; 57255682Smarkm else 57355682Smarkm mode = "r+w"; 57472445Sassar } else { 57555682Smarkm if (curtype == TYPE_I) 57655682Smarkm mode = "wb"; 57755682Smarkm else 57855682Smarkm mode = "w"; 57972445Sassar } 58055682Smarkm 58155682Smarkm getit(argc, argv, 0, mode); 58255682Smarkm} 58355682Smarkm 58455682Smarkm/* 58555682Smarkm * Receive one file. 58655682Smarkm */ 58755682Smarkmint 58855682Smarkmgetit(int argc, char **argv, int restartit, char *mode) 58955682Smarkm{ 59055682Smarkm int loc = 0; 59155682Smarkm int local_given = 1; 59255682Smarkm char *oldargv1, *oldargv2; 59355682Smarkm 59455682Smarkm if (argc == 2) { 59555682Smarkm argc++; 59655682Smarkm local_given = 0; 59755682Smarkm argv[2] = argv[1]; 59855682Smarkm loc++; 59955682Smarkm } 60055682Smarkm if ((argc < 2 && !another(&argc, &argv, "remote-file")) || 60155682Smarkm (argc < 3 && !another(&argc, &argv, "local-file"))) { 60255682Smarkm printf("usage: %s remote-file [ local-file ]\n", argv[0]); 60355682Smarkm code = -1; 60455682Smarkm return (0); 60555682Smarkm } 60655682Smarkm oldargv1 = argv[1]; 60755682Smarkm oldargv2 = argv[2]; 60855682Smarkm if (!globulize(&argv[2])) { 60955682Smarkm code = -1; 61055682Smarkm return (0); 61155682Smarkm } 61255682Smarkm if (loc && mcase) { 61355682Smarkm char *tp = argv[1], *tp2, tmpbuf[MaxPathLen]; 61455682Smarkm 61555682Smarkm while (*tp && !islower(*tp)) { 61655682Smarkm tp++; 61755682Smarkm } 61855682Smarkm if (!*tp) { 61955682Smarkm tp = argv[2]; 62055682Smarkm tp2 = tmpbuf; 62155682Smarkm while ((*tp2 = *tp) != '\0') { 62255682Smarkm if (isupper(*tp2)) { 62355682Smarkm *tp2 = 'a' + *tp2 - 'A'; 62455682Smarkm } 62555682Smarkm tp++; 62655682Smarkm tp2++; 62755682Smarkm } 62855682Smarkm argv[2] = tmpbuf; 62955682Smarkm } 63055682Smarkm } 63155682Smarkm if (loc && ntflag) 63255682Smarkm argv[2] = dotrans(argv[2]); 63355682Smarkm if (loc && mapflag) 63455682Smarkm argv[2] = domap(argv[2]); 63555682Smarkm if (restartit) { 63655682Smarkm struct stat stbuf; 63755682Smarkm int ret; 63855682Smarkm 63955682Smarkm ret = stat(argv[2], &stbuf); 64055682Smarkm if (restartit == 1) { 64155682Smarkm if (ret < 0) { 64255682Smarkm warn("local: %s", argv[2]); 64355682Smarkm return (0); 64455682Smarkm } 64555682Smarkm restart_point = stbuf.st_size; 64655682Smarkm } else if (ret == 0) { 64755682Smarkm int overbose; 64855682Smarkm int cmdret; 64955682Smarkm int yy, mo, day, hour, min, sec; 65055682Smarkm struct tm *tm; 65172445Sassar time_t mtime = stbuf.st_mtime; 65255682Smarkm 65355682Smarkm overbose = verbose; 65455682Smarkm if (debug == 0) 65555682Smarkm verbose = -1; 65655682Smarkm cmdret = command("MDTM %s", argv[1]); 65755682Smarkm verbose = overbose; 65855682Smarkm if (cmdret != COMPLETE) { 65955682Smarkm printf("%s\n", reply_string); 66055682Smarkm return (0); 66155682Smarkm } 66255682Smarkm if (sscanf(reply_string, 66355682Smarkm "%*s %04d%02d%02d%02d%02d%02d", 66455682Smarkm &yy, &mo, &day, &hour, &min, &sec) 66555682Smarkm != 6) { 66655682Smarkm printf ("bad MDTM result\n"); 66755682Smarkm return (0); 66855682Smarkm } 66955682Smarkm 67072445Sassar tm = gmtime(&mtime); 67155682Smarkm tm->tm_mon++; 67255682Smarkm tm->tm_year += 1900; 67355682Smarkm 67455682Smarkm if ((tm->tm_year > yy) || 67555682Smarkm (tm->tm_year == yy && 67655682Smarkm tm->tm_mon > mo) || 67755682Smarkm (tm->tm_mon == mo && 67855682Smarkm tm->tm_mday > day) || 67955682Smarkm (tm->tm_mday == day && 68055682Smarkm tm->tm_hour > hour) || 68155682Smarkm (tm->tm_hour == hour && 68255682Smarkm tm->tm_min > min) || 68355682Smarkm (tm->tm_min == min && 68455682Smarkm tm->tm_sec > sec)) 68555682Smarkm return (1); 68655682Smarkm } 68755682Smarkm } 68855682Smarkm 68955682Smarkm recvrequest("RETR", argv[2], argv[1], mode, 69055682Smarkm argv[1] != oldargv1 || argv[2] != oldargv2, local_given); 69155682Smarkm restart_point = 0; 69255682Smarkm return (0); 69355682Smarkm} 69455682Smarkm 69555682Smarkmstatic int 69655682Smarkmsuspicious_filename(const char *fn) 69755682Smarkm{ 69855682Smarkm return strstr(fn, "../") != NULL || *fn == '/'; 69955682Smarkm} 70055682Smarkm 70155682Smarkm/* 70255682Smarkm * Get multiple files. 70355682Smarkm */ 70455682Smarkmvoid 70555682Smarkmmget(int argc, char **argv) 70655682Smarkm{ 70755682Smarkm sighand oldintr; 70855682Smarkm int ch, ointer; 70955682Smarkm char *cp, *tp, *tp2, tmpbuf[MaxPathLen]; 71055682Smarkm 71155682Smarkm if (argc < 2 && !another(&argc, &argv, "remote-files")) { 71255682Smarkm printf("usage: %s remote-files\n", argv[0]); 71355682Smarkm code = -1; 71455682Smarkm return; 71555682Smarkm } 71655682Smarkm mname = argv[0]; 71755682Smarkm mflag = 1; 71855682Smarkm oldintr = signal(SIGINT, mabort); 71955682Smarkm setjmp(jabort); 72055682Smarkm while ((cp = remglob(argv,proxy)) != NULL) { 72155682Smarkm if (*cp == '\0') { 72255682Smarkm mflag = 0; 72355682Smarkm continue; 72455682Smarkm } 72555682Smarkm if (mflag && suspicious_filename(cp)) 72655682Smarkm printf("*** Suspicious filename: %s\n", cp); 72755682Smarkm if (mflag && confirm(argv[0], cp)) { 72855682Smarkm tp = cp; 72955682Smarkm if (mcase) { 73055682Smarkm for (tp2 = tmpbuf; (ch = *tp++);) 73155682Smarkm *tp2++ = isupper(ch) ? tolower(ch) : ch; 73255682Smarkm *tp2 = '\0'; 73355682Smarkm tp = tmpbuf; 73455682Smarkm } 73555682Smarkm if (ntflag) { 73655682Smarkm tp = dotrans(tp); 73755682Smarkm } 73855682Smarkm if (mapflag) { 73955682Smarkm tp = domap(tp); 74055682Smarkm } 74155682Smarkm recvrequest("RETR", tp, cp, 74255682Smarkm curtype == TYPE_I ? "wb" : "w", 74355682Smarkm tp != cp || !interactive, 0); 74455682Smarkm if (!mflag && fromatty) { 74555682Smarkm ointer = interactive; 74655682Smarkm interactive = 1; 74755682Smarkm if (confirm("Continue with","mget")) { 74855682Smarkm mflag++; 74955682Smarkm } 75055682Smarkm interactive = ointer; 75155682Smarkm } 75255682Smarkm } 75355682Smarkm } 75455682Smarkm signal(SIGINT,oldintr); 75555682Smarkm mflag = 0; 75655682Smarkm} 75755682Smarkm 75855682Smarkmchar * 75955682Smarkmremglob(char **argv, int doswitch) 76055682Smarkm{ 76155682Smarkm char temp[16]; 76255682Smarkm static char buf[MaxPathLen]; 76355682Smarkm static FILE *ftemp = NULL; 76455682Smarkm static char **args; 76555682Smarkm int oldverbose, oldhash; 76655682Smarkm char *cp, *mode; 76755682Smarkm 76855682Smarkm if (!mflag) { 76955682Smarkm if (!doglob) { 77055682Smarkm args = NULL; 77155682Smarkm } 77255682Smarkm else { 77355682Smarkm if (ftemp) { 77455682Smarkm fclose(ftemp); 77555682Smarkm ftemp = NULL; 77655682Smarkm } 77755682Smarkm } 77855682Smarkm return (NULL); 77955682Smarkm } 78055682Smarkm if (!doglob) { 78155682Smarkm if (args == NULL) 78255682Smarkm args = argv; 78355682Smarkm if ((cp = *++args) == NULL) 78455682Smarkm args = NULL; 78555682Smarkm return (cp); 78655682Smarkm } 78755682Smarkm if (ftemp == NULL) { 78855682Smarkm int fd; 78955682Smarkm strlcpy(temp, _PATH_TMP_XXX, sizeof(temp)); 79055682Smarkm fd = mkstemp(temp); 79155682Smarkm if(fd < 0){ 79255682Smarkm warn("unable to create temporary file %s", temp); 79355682Smarkm return NULL; 79455682Smarkm } 79555682Smarkm close(fd); 79655682Smarkm oldverbose = verbose, verbose = 0; 79755682Smarkm oldhash = hash, hash = 0; 79855682Smarkm if (doswitch) { 79955682Smarkm pswitch(!proxy); 80055682Smarkm } 80155682Smarkm for (mode = "w"; *++argv != NULL; mode = "a") 80255682Smarkm recvrequest ("NLST", temp, *argv, mode, 0, 0); 80355682Smarkm if (doswitch) { 80455682Smarkm pswitch(!proxy); 80555682Smarkm } 80655682Smarkm verbose = oldverbose; hash = oldhash; 80755682Smarkm ftemp = fopen(temp, "r"); 80855682Smarkm unlink(temp); 80955682Smarkm if (ftemp == NULL) { 81055682Smarkm printf("can't find list of remote files, oops\n"); 81155682Smarkm return (NULL); 81255682Smarkm } 81355682Smarkm } 81455682Smarkm while(fgets(buf, sizeof (buf), ftemp)) { 81555682Smarkm if ((cp = strchr(buf, '\n')) != NULL) 81655682Smarkm *cp = '\0'; 81755682Smarkm if(!interactive && suspicious_filename(buf)){ 81855682Smarkm printf("Ignoring remote globbed file `%s'\n", buf); 81955682Smarkm continue; 82055682Smarkm } 82155682Smarkm return buf; 82255682Smarkm } 82355682Smarkm fclose(ftemp); 82455682Smarkm ftemp = NULL; 82555682Smarkm return (NULL); 82655682Smarkm} 82755682Smarkm 82855682Smarkmchar * 82955682Smarkmonoff(int bool) 83055682Smarkm{ 83155682Smarkm 83255682Smarkm return (bool ? "on" : "off"); 83355682Smarkm} 83455682Smarkm 83555682Smarkm/* 83655682Smarkm * Show status. 83755682Smarkm */ 83855682Smarkm/*ARGSUSED*/ 83955682Smarkmvoid 84055682Smarkmstatus(int argc, char **argv) 84155682Smarkm{ 84255682Smarkm int i; 84355682Smarkm 84455682Smarkm if (connected) 84555682Smarkm printf("Connected to %s.\n", hostname); 84655682Smarkm else 84755682Smarkm printf("Not connected.\n"); 84855682Smarkm if (!proxy) { 84955682Smarkm pswitch(1); 85055682Smarkm if (connected) { 85155682Smarkm printf("Connected for proxy commands to %s.\n", hostname); 85255682Smarkm } 85355682Smarkm else { 85455682Smarkm printf("No proxy connection.\n"); 85555682Smarkm } 85655682Smarkm pswitch(0); 85755682Smarkm } 85855682Smarkm sec_status(); 85955682Smarkm printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 86055682Smarkm modename, typename, formname, structname); 86155682Smarkm printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 86255682Smarkm onoff(verbose), onoff(bell), onoff(interactive), 86355682Smarkm onoff(doglob)); 86455682Smarkm printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), 86555682Smarkm onoff(runique)); 86655682Smarkm printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); 86755682Smarkm if (ntflag) { 86855682Smarkm printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); 86955682Smarkm } 87055682Smarkm else { 87155682Smarkm printf("Ntrans: off\n"); 87255682Smarkm } 87355682Smarkm if (mapflag) { 87455682Smarkm printf("Nmap: (in) %s (out) %s\n", mapin, mapout); 87555682Smarkm } 87655682Smarkm else { 87755682Smarkm printf("Nmap: off\n"); 87855682Smarkm } 87955682Smarkm printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 88055682Smarkm onoff(hash), onoff(sendport)); 88155682Smarkm if (macnum > 0) { 88255682Smarkm printf("Macros:\n"); 88355682Smarkm for (i=0; i<macnum; i++) { 88455682Smarkm printf("\t%s\n",macros[i].mac_name); 88555682Smarkm } 88655682Smarkm } 88755682Smarkm code = 0; 88855682Smarkm} 88955682Smarkm 89055682Smarkm/* 89155682Smarkm * Set beep on cmd completed mode. 89255682Smarkm */ 89355682Smarkm/*VARARGS*/ 89455682Smarkmvoid 89555682Smarkmsetbell(int argc, char **argv) 89655682Smarkm{ 89755682Smarkm 89855682Smarkm bell = !bell; 89955682Smarkm printf("Bell mode %s.\n", onoff(bell)); 90055682Smarkm code = bell; 90155682Smarkm} 90255682Smarkm 90355682Smarkm/* 90455682Smarkm * Turn on packet tracing. 90555682Smarkm */ 90655682Smarkm/*VARARGS*/ 90755682Smarkmvoid 90855682Smarkmsettrace(int argc, char **argv) 90955682Smarkm{ 91055682Smarkm 91155682Smarkm trace = !trace; 91255682Smarkm printf("Packet tracing %s.\n", onoff(trace)); 91355682Smarkm code = trace; 91455682Smarkm} 91555682Smarkm 91655682Smarkm/* 91755682Smarkm * Toggle hash mark printing during transfers. 91855682Smarkm */ 91955682Smarkm/*VARARGS*/ 92055682Smarkmvoid 92155682Smarkmsethash(int argc, char **argv) 92255682Smarkm{ 92355682Smarkm 92455682Smarkm hash = !hash; 92555682Smarkm printf("Hash mark printing %s", onoff(hash)); 92655682Smarkm code = hash; 92755682Smarkm if (hash) 92855682Smarkm printf(" (%d bytes/hash mark)", 1024); 92955682Smarkm printf(".\n"); 93055682Smarkm} 93155682Smarkm 93255682Smarkm/* 93355682Smarkm * Turn on printing of server echo's. 93455682Smarkm */ 93555682Smarkm/*VARARGS*/ 93655682Smarkmvoid 93755682Smarkmsetverbose(int argc, char **argv) 93855682Smarkm{ 93955682Smarkm 94055682Smarkm verbose = !verbose; 94155682Smarkm printf("Verbose mode %s.\n", onoff(verbose)); 94255682Smarkm code = verbose; 94355682Smarkm} 94455682Smarkm 94555682Smarkm/* 94655682Smarkm * Toggle PORT cmd use before each data connection. 94755682Smarkm */ 94855682Smarkm/*VARARGS*/ 94955682Smarkmvoid 95055682Smarkmsetport(int argc, char **argv) 95155682Smarkm{ 95255682Smarkm 95355682Smarkm sendport = !sendport; 95455682Smarkm printf("Use of PORT cmds %s.\n", onoff(sendport)); 95555682Smarkm code = sendport; 95655682Smarkm} 95755682Smarkm 95855682Smarkm/* 95955682Smarkm * Turn on interactive prompting 96055682Smarkm * during mget, mput, and mdelete. 96155682Smarkm */ 96255682Smarkm/*VARARGS*/ 96355682Smarkmvoid 96455682Smarkmsetprompt(int argc, char **argv) 96555682Smarkm{ 96655682Smarkm 96755682Smarkm interactive = !interactive; 96855682Smarkm printf("Interactive mode %s.\n", onoff(interactive)); 96955682Smarkm code = interactive; 97055682Smarkm} 97155682Smarkm 97255682Smarkm/* 97355682Smarkm * Toggle metacharacter interpretation 97455682Smarkm * on local file names. 97555682Smarkm */ 97655682Smarkm/*VARARGS*/ 97755682Smarkmvoid 97855682Smarkmsetglob(int argc, char **argv) 97955682Smarkm{ 98055682Smarkm 98155682Smarkm doglob = !doglob; 98255682Smarkm printf("Globbing %s.\n", onoff(doglob)); 98355682Smarkm code = doglob; 98455682Smarkm} 98555682Smarkm 98655682Smarkm/* 98755682Smarkm * Set debugging mode on/off and/or 98855682Smarkm * set level of debugging. 98955682Smarkm */ 99055682Smarkm/*VARARGS*/ 99155682Smarkmvoid 99255682Smarkmsetdebug(int argc, char **argv) 99355682Smarkm{ 99455682Smarkm int val; 99555682Smarkm 99655682Smarkm if (argc > 1) { 99755682Smarkm val = atoi(argv[1]); 99855682Smarkm if (val < 0) { 99955682Smarkm printf("%s: bad debugging value.\n", argv[1]); 100055682Smarkm code = -1; 100155682Smarkm return; 100255682Smarkm } 100355682Smarkm } else 100455682Smarkm val = !debug; 100555682Smarkm debug = val; 100655682Smarkm if (debug) 100755682Smarkm options |= SO_DEBUG; 100855682Smarkm else 100955682Smarkm options &= ~SO_DEBUG; 101055682Smarkm printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 101155682Smarkm code = debug > 0; 101255682Smarkm} 101355682Smarkm 101455682Smarkm/* 101555682Smarkm * Set current working directory 101655682Smarkm * on remote machine. 101755682Smarkm */ 101855682Smarkmvoid 101955682Smarkmcd(int argc, char **argv) 102055682Smarkm{ 102155682Smarkm 102255682Smarkm if (argc < 2 && !another(&argc, &argv, "remote-directory")) { 102355682Smarkm printf("usage: %s remote-directory\n", argv[0]); 102455682Smarkm code = -1; 102555682Smarkm return; 102655682Smarkm } 102755682Smarkm if (command("CWD %s", argv[1]) == ERROR && code == 500) { 102855682Smarkm if (verbose) 102955682Smarkm printf("CWD command not recognized, trying XCWD\n"); 103055682Smarkm command("XCWD %s", argv[1]); 103155682Smarkm } 103255682Smarkm} 103355682Smarkm 103455682Smarkm/* 103555682Smarkm * Set current working directory 103655682Smarkm * on local machine. 103755682Smarkm */ 103855682Smarkmvoid 103955682Smarkmlcd(int argc, char **argv) 104055682Smarkm{ 104155682Smarkm char buf[MaxPathLen]; 104255682Smarkm 104355682Smarkm if (argc < 2) 104455682Smarkm argc++, argv[1] = home; 104555682Smarkm if (argc != 2) { 104655682Smarkm printf("usage: %s local-directory\n", argv[0]); 104755682Smarkm code = -1; 104855682Smarkm return; 104955682Smarkm } 105055682Smarkm if (!globulize(&argv[1])) { 105155682Smarkm code = -1; 105255682Smarkm return; 105355682Smarkm } 105455682Smarkm if (chdir(argv[1]) < 0) { 105555682Smarkm warn("local: %s", argv[1]); 105655682Smarkm code = -1; 105755682Smarkm return; 105855682Smarkm } 105955682Smarkm if (getcwd(buf, sizeof(buf)) != NULL) 106055682Smarkm printf("Local directory now %s\n", buf); 106155682Smarkm else 106255682Smarkm warnx("getwd: %s", buf); 106355682Smarkm code = 0; 106455682Smarkm} 106555682Smarkm 106655682Smarkm/* 106755682Smarkm * Delete a single file. 106855682Smarkm */ 106955682Smarkmvoid 107055682Smarkmdelete(int argc, char **argv) 107155682Smarkm{ 107255682Smarkm 107355682Smarkm if (argc < 2 && !another(&argc, &argv, "remote-file")) { 107455682Smarkm printf("usage: %s remote-file\n", argv[0]); 107555682Smarkm code = -1; 107655682Smarkm return; 107755682Smarkm } 107855682Smarkm command("DELE %s", argv[1]); 107955682Smarkm} 108055682Smarkm 108155682Smarkm/* 108255682Smarkm * Delete multiple files. 108355682Smarkm */ 108455682Smarkmvoid 108555682Smarkmmdelete(int argc, char **argv) 108655682Smarkm{ 108755682Smarkm sighand oldintr; 108855682Smarkm int ointer; 108955682Smarkm char *cp; 109055682Smarkm 109155682Smarkm if (argc < 2 && !another(&argc, &argv, "remote-files")) { 109255682Smarkm printf("usage: %s remote-files\n", argv[0]); 109355682Smarkm code = -1; 109455682Smarkm return; 109555682Smarkm } 109655682Smarkm mname = argv[0]; 109755682Smarkm mflag = 1; 109855682Smarkm oldintr = signal(SIGINT, mabort); 109955682Smarkm setjmp(jabort); 110055682Smarkm while ((cp = remglob(argv,0)) != NULL) { 110155682Smarkm if (*cp == '\0') { 110255682Smarkm mflag = 0; 110355682Smarkm continue; 110455682Smarkm } 110555682Smarkm if (mflag && confirm(argv[0], cp)) { 110655682Smarkm command("DELE %s", cp); 110755682Smarkm if (!mflag && fromatty) { 110855682Smarkm ointer = interactive; 110955682Smarkm interactive = 1; 111055682Smarkm if (confirm("Continue with", "mdelete")) { 111155682Smarkm mflag++; 111255682Smarkm } 111355682Smarkm interactive = ointer; 111455682Smarkm } 111555682Smarkm } 111655682Smarkm } 111755682Smarkm signal(SIGINT, oldintr); 111855682Smarkm mflag = 0; 111955682Smarkm} 112055682Smarkm 112155682Smarkm/* 112255682Smarkm * Rename a remote file. 112355682Smarkm */ 112455682Smarkmvoid 112555682Smarkmrenamefile(int argc, char **argv) 112655682Smarkm{ 112755682Smarkm 112855682Smarkm if (argc < 2 && !another(&argc, &argv, "from-name")) 112955682Smarkm goto usage; 113055682Smarkm if (argc < 3 && !another(&argc, &argv, "to-name")) { 113155682Smarkmusage: 113255682Smarkm printf("%s from-name to-name\n", argv[0]); 113355682Smarkm code = -1; 113455682Smarkm return; 113555682Smarkm } 113655682Smarkm if (command("RNFR %s", argv[1]) == CONTINUE) 113755682Smarkm command("RNTO %s", argv[2]); 113855682Smarkm} 113955682Smarkm 114055682Smarkm/* 114155682Smarkm * Get a directory listing 114255682Smarkm * of remote files. 114355682Smarkm */ 114455682Smarkmvoid 114555682Smarkmls(int argc, char **argv) 114655682Smarkm{ 114755682Smarkm char *cmd; 114855682Smarkm 114955682Smarkm if (argc < 2) 115055682Smarkm argc++, argv[1] = NULL; 115155682Smarkm if (argc < 3) 115255682Smarkm argc++, argv[2] = "-"; 115355682Smarkm if (argc > 3) { 115455682Smarkm printf("usage: %s remote-directory local-file\n", argv[0]); 115555682Smarkm code = -1; 115655682Smarkm return; 115755682Smarkm } 115855682Smarkm cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 115955682Smarkm if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 116055682Smarkm code = -1; 116155682Smarkm return; 116255682Smarkm } 116355682Smarkm if (strcmp(argv[2], "-") && *argv[2] != '|') 116455682Smarkm if (!globulize(&argv[2]) || !confirm("output to local-file:", 116555682Smarkm argv[2])) { 116655682Smarkm code = -1; 116755682Smarkm return; 116855682Smarkm } 116955682Smarkm recvrequest(cmd, argv[2], argv[1], "w", 0, 1); 117055682Smarkm} 117155682Smarkm 117255682Smarkm/* 117355682Smarkm * Get a directory listing 117455682Smarkm * of multiple remote files. 117555682Smarkm */ 117655682Smarkmvoid 117755682Smarkmmls(int argc, char **argv) 117855682Smarkm{ 117955682Smarkm sighand oldintr; 118055682Smarkm int ointer, i; 118155682Smarkm char *cmd, mode[1], *dest; 118255682Smarkm 118355682Smarkm if (argc < 2 && !another(&argc, &argv, "remote-files")) 118455682Smarkm goto usage; 118555682Smarkm if (argc < 3 && !another(&argc, &argv, "local-file")) { 118655682Smarkmusage: 118755682Smarkm printf("usage: %s remote-files local-file\n", argv[0]); 118855682Smarkm code = -1; 118955682Smarkm return; 119055682Smarkm } 119155682Smarkm dest = argv[argc - 1]; 119255682Smarkm argv[argc - 1] = NULL; 119355682Smarkm if (strcmp(dest, "-") && *dest != '|') 119455682Smarkm if (!globulize(&dest) || 119555682Smarkm !confirm("output to local-file:", dest)) { 119655682Smarkm code = -1; 119755682Smarkm return; 119855682Smarkm } 119955682Smarkm cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 120055682Smarkm mname = argv[0]; 120155682Smarkm mflag = 1; 120255682Smarkm oldintr = signal(SIGINT, mabort); 120355682Smarkm setjmp(jabort); 120455682Smarkm for (i = 1; mflag && i < argc-1; ++i) { 120555682Smarkm *mode = (i == 1) ? 'w' : 'a'; 120655682Smarkm recvrequest(cmd, dest, argv[i], mode, 0, 1); 120755682Smarkm if (!mflag && fromatty) { 120855682Smarkm ointer = interactive; 120955682Smarkm interactive = 1; 121055682Smarkm if (confirm("Continue with", argv[0])) { 121155682Smarkm mflag ++; 121255682Smarkm } 121355682Smarkm interactive = ointer; 121455682Smarkm } 121555682Smarkm } 121655682Smarkm signal(SIGINT, oldintr); 121755682Smarkm mflag = 0; 121855682Smarkm} 121955682Smarkm 122055682Smarkm/* 122155682Smarkm * Do a shell escape 122255682Smarkm */ 122355682Smarkm/*ARGSUSED*/ 122455682Smarkmvoid 122555682Smarkmshell(int argc, char **argv) 122655682Smarkm{ 122755682Smarkm pid_t pid; 122872445Sassar RETSIGTYPE (*old1)(int), (*old2)(int); 122955682Smarkm char shellnam[40], *shell, *namep; 123055682Smarkm int status; 123155682Smarkm 123255682Smarkm old1 = signal (SIGINT, SIG_IGN); 123355682Smarkm old2 = signal (SIGQUIT, SIG_IGN); 123455682Smarkm if ((pid = fork()) == 0) { 123555682Smarkm for (pid = 3; pid < 20; pid++) 123655682Smarkm close(pid); 123755682Smarkm signal(SIGINT, SIG_DFL); 123855682Smarkm signal(SIGQUIT, SIG_DFL); 123955682Smarkm shell = getenv("SHELL"); 124055682Smarkm if (shell == NULL) 124155682Smarkm shell = _PATH_BSHELL; 124255682Smarkm namep = strrchr(shell,'/'); 124355682Smarkm if (namep == NULL) 124455682Smarkm namep = shell; 124555682Smarkm snprintf (shellnam, sizeof(shellnam), 124655682Smarkm "-%s", ++namep); 124755682Smarkm if (strcmp(namep, "sh") != 0) 124855682Smarkm shellnam[0] = '+'; 124955682Smarkm if (debug) { 125055682Smarkm printf ("%s\n", shell); 125155682Smarkm fflush (stdout); 125255682Smarkm } 125355682Smarkm if (argc > 1) { 125455682Smarkm execl(shell,shellnam,"-c",altarg,(char *)0); 125555682Smarkm } 125655682Smarkm else { 125755682Smarkm execl(shell,shellnam,(char *)0); 125855682Smarkm } 125955682Smarkm warn("%s", shell); 126055682Smarkm code = -1; 126155682Smarkm exit(1); 126255682Smarkm } 126355682Smarkm if (pid > 0) 126455682Smarkm while (waitpid(-1, &status, 0) != pid) 126555682Smarkm ; 126655682Smarkm signal(SIGINT, old1); 126755682Smarkm signal(SIGQUIT, old2); 126855682Smarkm if (pid == -1) { 126955682Smarkm warn("%s", "Try again later"); 127055682Smarkm code = -1; 127155682Smarkm } 127255682Smarkm else { 127355682Smarkm code = 0; 127455682Smarkm } 127555682Smarkm} 127655682Smarkm 127755682Smarkm/* 127855682Smarkm * Send new user information (re-login) 127955682Smarkm */ 128055682Smarkmvoid 128155682Smarkmuser(int argc, char **argv) 128255682Smarkm{ 128355682Smarkm char acct[80]; 128455682Smarkm int n, aflag = 0; 128555682Smarkm char tmp[256]; 128655682Smarkm 128755682Smarkm if (argc < 2) 128855682Smarkm another(&argc, &argv, "username"); 128955682Smarkm if (argc < 2 || argc > 4) { 129055682Smarkm printf("usage: %s username [password] [account]\n", argv[0]); 129155682Smarkm code = -1; 129255682Smarkm return; 129355682Smarkm } 129455682Smarkm n = command("USER %s", argv[1]); 129555682Smarkm if (n == CONTINUE) { 129655682Smarkm if (argc < 3 ) { 129755682Smarkm des_read_pw_string (tmp, 129855682Smarkm sizeof(tmp), 129955682Smarkm "Password: ", 0); 130055682Smarkm argv[2] = tmp; 130155682Smarkm argc++; 130255682Smarkm } 130355682Smarkm n = command("PASS %s", argv[2]); 130455682Smarkm } 130555682Smarkm if (n == CONTINUE) { 130655682Smarkm if (argc < 4) { 130755682Smarkm printf("Account: "); fflush(stdout); 130855682Smarkm fgets(acct, sizeof(acct) - 1, stdin); 130955682Smarkm acct[strlen(acct) - 1] = '\0'; 131055682Smarkm argv[3] = acct; argc++; 131155682Smarkm } 131255682Smarkm n = command("ACCT %s", argv[3]); 131355682Smarkm aflag++; 131455682Smarkm } 131555682Smarkm if (n != COMPLETE) { 131655682Smarkm fprintf(stdout, "Login failed.\n"); 131755682Smarkm return; 131855682Smarkm } 131955682Smarkm if (!aflag && argc == 4) { 132055682Smarkm command("ACCT %s", argv[3]); 132155682Smarkm } 132255682Smarkm} 132355682Smarkm 132455682Smarkm/* 132555682Smarkm * Print working directory. 132655682Smarkm */ 132755682Smarkm/*VARARGS*/ 132855682Smarkmvoid 132955682Smarkmpwd(int argc, char **argv) 133055682Smarkm{ 133155682Smarkm int oldverbose = verbose; 133255682Smarkm 133355682Smarkm /* 133455682Smarkm * If we aren't verbose, this doesn't do anything! 133555682Smarkm */ 133655682Smarkm verbose = 1; 133755682Smarkm if (command("PWD") == ERROR && code == 500) { 133855682Smarkm printf("PWD command not recognized, trying XPWD\n"); 133955682Smarkm command("XPWD"); 134055682Smarkm } 134155682Smarkm verbose = oldverbose; 134255682Smarkm} 134355682Smarkm 134455682Smarkm/* 134555682Smarkm * Make a directory. 134655682Smarkm */ 134755682Smarkmvoid 134855682Smarkmmakedir(int argc, char **argv) 134955682Smarkm{ 135055682Smarkm 135155682Smarkm if (argc < 2 && !another(&argc, &argv, "directory-name")) { 135255682Smarkm printf("usage: %s directory-name\n", argv[0]); 135355682Smarkm code = -1; 135455682Smarkm return; 135555682Smarkm } 135655682Smarkm if (command("MKD %s", argv[1]) == ERROR && code == 500) { 135755682Smarkm if (verbose) 135855682Smarkm printf("MKD command not recognized, trying XMKD\n"); 135955682Smarkm command("XMKD %s", argv[1]); 136055682Smarkm } 136155682Smarkm} 136255682Smarkm 136355682Smarkm/* 136455682Smarkm * Remove a directory. 136555682Smarkm */ 136655682Smarkmvoid 136755682Smarkmremovedir(int argc, char **argv) 136855682Smarkm{ 136955682Smarkm 137055682Smarkm if (argc < 2 && !another(&argc, &argv, "directory-name")) { 137155682Smarkm printf("usage: %s directory-name\n", argv[0]); 137255682Smarkm code = -1; 137355682Smarkm return; 137455682Smarkm } 137555682Smarkm if (command("RMD %s", argv[1]) == ERROR && code == 500) { 137655682Smarkm if (verbose) 137755682Smarkm printf("RMD command not recognized, trying XRMD\n"); 137855682Smarkm command("XRMD %s", argv[1]); 137955682Smarkm } 138055682Smarkm} 138155682Smarkm 138255682Smarkm/* 138355682Smarkm * Send a line, verbatim, to the remote machine. 138455682Smarkm */ 138555682Smarkmvoid 138655682Smarkmquote(int argc, char **argv) 138755682Smarkm{ 138855682Smarkm 138955682Smarkm if (argc < 2 && !another(&argc, &argv, "command line to send")) { 139055682Smarkm printf("usage: %s line-to-send\n", argv[0]); 139155682Smarkm code = -1; 139255682Smarkm return; 139355682Smarkm } 139455682Smarkm quote1("", argc, argv); 139555682Smarkm} 139655682Smarkm 139755682Smarkm/* 139855682Smarkm * Send a SITE command to the remote machine. The line 139955682Smarkm * is sent verbatim to the remote machine, except that the 140055682Smarkm * word "SITE" is added at the front. 140155682Smarkm */ 140255682Smarkmvoid 140355682Smarkmsite(int argc, char **argv) 140455682Smarkm{ 140555682Smarkm 140655682Smarkm if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) { 140755682Smarkm printf("usage: %s line-to-send\n", argv[0]); 140855682Smarkm code = -1; 140955682Smarkm return; 141055682Smarkm } 141155682Smarkm quote1("SITE ", argc, argv); 141255682Smarkm} 141355682Smarkm 141455682Smarkm/* 141555682Smarkm * Turn argv[1..argc) into a space-separated string, then prepend initial text. 141655682Smarkm * Send the result as a one-line command and get response. 141755682Smarkm */ 141855682Smarkmvoid 141955682Smarkmquote1(char *initial, int argc, char **argv) 142055682Smarkm{ 142155682Smarkm int i; 142255682Smarkm char buf[BUFSIZ]; /* must be >= sizeof(line) */ 142355682Smarkm 142455682Smarkm strlcpy(buf, initial, sizeof(buf)); 142555682Smarkm for(i = 1; i < argc; i++) { 142655682Smarkm if(i > 1) 142755682Smarkm strlcat(buf, " ", sizeof(buf)); 142855682Smarkm strlcat(buf, argv[i], sizeof(buf)); 142955682Smarkm } 143055682Smarkm if (command("%s", buf) == PRELIM) { 143155682Smarkm while (getreply(0) == PRELIM) 143255682Smarkm continue; 143355682Smarkm } 143455682Smarkm} 143555682Smarkm 143655682Smarkmvoid 143755682Smarkmdo_chmod(int argc, char **argv) 143855682Smarkm{ 143955682Smarkm 144055682Smarkm if (argc < 2 && !another(&argc, &argv, "mode")) 144155682Smarkm goto usage; 144255682Smarkm if (argc < 3 && !another(&argc, &argv, "file-name")) { 144355682Smarkmusage: 144455682Smarkm printf("usage: %s mode file-name\n", argv[0]); 144555682Smarkm code = -1; 144655682Smarkm return; 144755682Smarkm } 144855682Smarkm command("SITE CHMOD %s %s", argv[1], argv[2]); 144955682Smarkm} 145055682Smarkm 145155682Smarkmvoid 145255682Smarkmdo_umask(int argc, char **argv) 145355682Smarkm{ 145455682Smarkm int oldverbose = verbose; 145555682Smarkm 145655682Smarkm verbose = 1; 145755682Smarkm command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 145855682Smarkm verbose = oldverbose; 145955682Smarkm} 146055682Smarkm 146155682Smarkmvoid 146255682Smarkmftp_idle(int argc, char **argv) 146355682Smarkm{ 146455682Smarkm int oldverbose = verbose; 146555682Smarkm 146655682Smarkm verbose = 1; 146755682Smarkm command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 146855682Smarkm verbose = oldverbose; 146955682Smarkm} 147055682Smarkm 147155682Smarkm/* 147255682Smarkm * Ask the other side for help. 147355682Smarkm */ 147455682Smarkmvoid 147555682Smarkmrmthelp(int argc, char **argv) 147655682Smarkm{ 147755682Smarkm int oldverbose = verbose; 147855682Smarkm 147955682Smarkm verbose = 1; 148055682Smarkm command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 148155682Smarkm verbose = oldverbose; 148255682Smarkm} 148355682Smarkm 148455682Smarkm/* 148555682Smarkm * Terminate session and exit. 148655682Smarkm */ 148755682Smarkm/*VARARGS*/ 148855682Smarkmvoid 148955682Smarkmquit(int argc, char **argv) 149055682Smarkm{ 149155682Smarkm 149255682Smarkm if (connected) 149355682Smarkm disconnect(0, 0); 149455682Smarkm pswitch(1); 149555682Smarkm if (connected) { 149655682Smarkm disconnect(0, 0); 149755682Smarkm } 149855682Smarkm exit(0); 149955682Smarkm} 150055682Smarkm 150155682Smarkm/* 150255682Smarkm * Terminate session, but don't exit. 150355682Smarkm */ 150455682Smarkmvoid 150555682Smarkmdisconnect(int argc, char **argv) 150655682Smarkm{ 150755682Smarkm 150855682Smarkm if (!connected) 150955682Smarkm return; 151055682Smarkm command("QUIT"); 151155682Smarkm if (cout) { 151255682Smarkm fclose(cout); 151355682Smarkm } 151455682Smarkm cout = NULL; 151555682Smarkm connected = 0; 151655682Smarkm sec_end(); 151755682Smarkm data = -1; 151855682Smarkm if (!proxy) { 151955682Smarkm macnum = 0; 152055682Smarkm } 152155682Smarkm} 152255682Smarkm 152355682Smarkmint 152455682Smarkmconfirm(char *cmd, char *file) 152555682Smarkm{ 152655682Smarkm char line[BUFSIZ]; 152755682Smarkm 152855682Smarkm if (!interactive) 152955682Smarkm return (1); 153055682Smarkm printf("%s %s? ", cmd, file); 153155682Smarkm fflush(stdout); 153255682Smarkm if (fgets(line, sizeof line, stdin) == NULL) 153355682Smarkm return (0); 153455682Smarkm return (*line == 'y' || *line == 'Y'); 153555682Smarkm} 153655682Smarkm 153755682Smarkmvoid 153855682Smarkmfatal(char *msg) 153955682Smarkm{ 154055682Smarkm 154155682Smarkm errx(1, "%s", msg); 154255682Smarkm} 154355682Smarkm 154455682Smarkm/* 154555682Smarkm * Glob a local file name specification with 154655682Smarkm * the expectation of a single return value. 154755682Smarkm * Can't control multiple values being expanded 154855682Smarkm * from the expression, we return only the first. 154955682Smarkm */ 155055682Smarkmint 155155682Smarkmglobulize(char **cpp) 155255682Smarkm{ 155355682Smarkm glob_t gl; 155455682Smarkm int flags; 155555682Smarkm 155655682Smarkm if (!doglob) 155755682Smarkm return (1); 155855682Smarkm 155955682Smarkm flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 156055682Smarkm memset(&gl, 0, sizeof(gl)); 156155682Smarkm if (glob(*cpp, flags, NULL, &gl) || 156255682Smarkm gl.gl_pathc == 0) { 156355682Smarkm warnx("%s: not found", *cpp); 156455682Smarkm globfree(&gl); 156555682Smarkm return (0); 156655682Smarkm } 156755682Smarkm *cpp = strdup(gl.gl_pathv[0]); /* XXX - wasted memory */ 156855682Smarkm globfree(&gl); 156955682Smarkm return (1); 157055682Smarkm} 157155682Smarkm 157255682Smarkmvoid 157355682Smarkmaccount(int argc, char **argv) 157455682Smarkm{ 157555682Smarkm char acct[50]; 157655682Smarkm 157755682Smarkm if (argc > 1) { 157855682Smarkm ++argv; 157955682Smarkm --argc; 158055682Smarkm strlcpy (acct, *argv, sizeof(acct)); 158155682Smarkm while (argc > 1) { 158255682Smarkm --argc; 158355682Smarkm ++argv; 158455682Smarkm strlcat(acct, *argv, sizeof(acct)); 158555682Smarkm } 158655682Smarkm } 158755682Smarkm else { 158855682Smarkm des_read_pw_string(acct, sizeof(acct), "Account:", 0); 158955682Smarkm } 159055682Smarkm command("ACCT %s", acct); 159155682Smarkm} 159255682Smarkm 159355682Smarkmjmp_buf abortprox; 159455682Smarkm 159555682Smarkmstatic RETSIGTYPE 159655682Smarkmproxabort(int sig) 159755682Smarkm{ 159855682Smarkm 159955682Smarkm if (!proxy) { 160055682Smarkm pswitch(1); 160155682Smarkm } 160255682Smarkm if (connected) { 160355682Smarkm proxflag = 1; 160455682Smarkm } 160555682Smarkm else { 160655682Smarkm proxflag = 0; 160755682Smarkm } 160855682Smarkm pswitch(0); 160955682Smarkm longjmp(abortprox,1); 161055682Smarkm} 161155682Smarkm 161255682Smarkmvoid 161355682Smarkmdoproxy(int argc, char **argv) 161455682Smarkm{ 161555682Smarkm struct cmd *c; 161672445Sassar RETSIGTYPE (*oldintr)(int); 161755682Smarkm 161855682Smarkm if (argc < 2 && !another(&argc, &argv, "command")) { 161955682Smarkm printf("usage: %s command\n", argv[0]); 162055682Smarkm code = -1; 162155682Smarkm return; 162255682Smarkm } 162355682Smarkm c = getcmd(argv[1]); 162455682Smarkm if (c == (struct cmd *) -1) { 162555682Smarkm printf("?Ambiguous command\n"); 162655682Smarkm fflush(stdout); 162755682Smarkm code = -1; 162855682Smarkm return; 162955682Smarkm } 163055682Smarkm if (c == 0) { 163155682Smarkm printf("?Invalid command\n"); 163255682Smarkm fflush(stdout); 163355682Smarkm code = -1; 163455682Smarkm return; 163555682Smarkm } 163655682Smarkm if (!c->c_proxy) { 163755682Smarkm printf("?Invalid proxy command\n"); 163855682Smarkm fflush(stdout); 163955682Smarkm code = -1; 164055682Smarkm return; 164155682Smarkm } 164255682Smarkm if (setjmp(abortprox)) { 164355682Smarkm code = -1; 164455682Smarkm return; 164555682Smarkm } 164655682Smarkm oldintr = signal(SIGINT, proxabort); 164755682Smarkm pswitch(1); 164855682Smarkm if (c->c_conn && !connected) { 164955682Smarkm printf("Not connected\n"); 165055682Smarkm fflush(stdout); 165155682Smarkm pswitch(0); 165255682Smarkm signal(SIGINT, oldintr); 165355682Smarkm code = -1; 165455682Smarkm return; 165555682Smarkm } 165655682Smarkm (*c->c_handler)(argc-1, argv+1); 165755682Smarkm if (connected) { 165855682Smarkm proxflag = 1; 165955682Smarkm } 166055682Smarkm else { 166155682Smarkm proxflag = 0; 166255682Smarkm } 166355682Smarkm pswitch(0); 166455682Smarkm signal(SIGINT, oldintr); 166555682Smarkm} 166655682Smarkm 166755682Smarkmvoid 166855682Smarkmsetcase(int argc, char **argv) 166955682Smarkm{ 167055682Smarkm 167155682Smarkm mcase = !mcase; 167255682Smarkm printf("Case mapping %s.\n", onoff(mcase)); 167355682Smarkm code = mcase; 167455682Smarkm} 167555682Smarkm 167655682Smarkmvoid 167755682Smarkmsetcr(int argc, char **argv) 167855682Smarkm{ 167955682Smarkm 168055682Smarkm crflag = !crflag; 168155682Smarkm printf("Carriage Return stripping %s.\n", onoff(crflag)); 168255682Smarkm code = crflag; 168355682Smarkm} 168455682Smarkm 168555682Smarkmvoid 168655682Smarkmsetntrans(int argc, char **argv) 168755682Smarkm{ 168855682Smarkm if (argc == 1) { 168955682Smarkm ntflag = 0; 169055682Smarkm printf("Ntrans off.\n"); 169155682Smarkm code = ntflag; 169255682Smarkm return; 169355682Smarkm } 169455682Smarkm ntflag++; 169555682Smarkm code = ntflag; 169655682Smarkm strlcpy (ntin, argv[1], 17); 169755682Smarkm if (argc == 2) { 169855682Smarkm ntout[0] = '\0'; 169955682Smarkm return; 170055682Smarkm } 170155682Smarkm strlcpy (ntout, argv[2], 17); 170255682Smarkm} 170355682Smarkm 170455682Smarkmchar * 170555682Smarkmdotrans(char *name) 170655682Smarkm{ 170755682Smarkm static char new[MaxPathLen]; 170855682Smarkm char *cp1, *cp2 = new; 170955682Smarkm int i, ostop, found; 171055682Smarkm 171155682Smarkm for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++) 171255682Smarkm continue; 171355682Smarkm for (cp1 = name; *cp1; cp1++) { 171455682Smarkm found = 0; 171555682Smarkm for (i = 0; *(ntin + i) && i < 16; i++) { 171655682Smarkm if (*cp1 == *(ntin + i)) { 171755682Smarkm found++; 171855682Smarkm if (i < ostop) { 171955682Smarkm *cp2++ = *(ntout + i); 172055682Smarkm } 172155682Smarkm break; 172255682Smarkm } 172355682Smarkm } 172455682Smarkm if (!found) { 172555682Smarkm *cp2++ = *cp1; 172655682Smarkm } 172755682Smarkm } 172855682Smarkm *cp2 = '\0'; 172955682Smarkm return (new); 173055682Smarkm} 173155682Smarkm 173255682Smarkmvoid 173355682Smarkmsetnmap(int argc, char **argv) 173455682Smarkm{ 173555682Smarkm char *cp; 173655682Smarkm 173755682Smarkm if (argc == 1) { 173855682Smarkm mapflag = 0; 173955682Smarkm printf("Nmap off.\n"); 174055682Smarkm code = mapflag; 174155682Smarkm return; 174255682Smarkm } 174355682Smarkm if (argc < 3 && !another(&argc, &argv, "mapout")) { 174455682Smarkm printf("Usage: %s [mapin mapout]\n",argv[0]); 174555682Smarkm code = -1; 174655682Smarkm return; 174755682Smarkm } 174855682Smarkm mapflag = 1; 174955682Smarkm code = 1; 175055682Smarkm cp = strchr(altarg, ' '); 175155682Smarkm if (proxy) { 175255682Smarkm while(*++cp == ' ') 175355682Smarkm continue; 175455682Smarkm altarg = cp; 175555682Smarkm cp = strchr(altarg, ' '); 175655682Smarkm } 175755682Smarkm *cp = '\0'; 175855682Smarkm strlcpy(mapin, altarg, MaxPathLen); 175955682Smarkm while (*++cp == ' ') 176055682Smarkm continue; 176155682Smarkm strlcpy(mapout, cp, MaxPathLen); 176255682Smarkm} 176355682Smarkm 176455682Smarkmchar * 176555682Smarkmdomap(char *name) 176655682Smarkm{ 176755682Smarkm static char new[MaxPathLen]; 176855682Smarkm char *cp1 = name, *cp2 = mapin; 176955682Smarkm char *tp[9], *te[9]; 177055682Smarkm int i, toks[9], toknum = 0, match = 1; 177155682Smarkm 177255682Smarkm for (i=0; i < 9; ++i) { 177355682Smarkm toks[i] = 0; 177455682Smarkm } 177555682Smarkm while (match && *cp1 && *cp2) { 177655682Smarkm switch (*cp2) { 177755682Smarkm case '\\': 177855682Smarkm if (*++cp2 != *cp1) { 177955682Smarkm match = 0; 178055682Smarkm } 178155682Smarkm break; 178255682Smarkm case '$': 178355682Smarkm if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 178455682Smarkm if (*cp1 != *(++cp2+1)) { 178555682Smarkm toks[toknum = *cp2 - '1']++; 178655682Smarkm tp[toknum] = cp1; 178755682Smarkm while (*++cp1 && *(cp2+1) 178855682Smarkm != *cp1); 178955682Smarkm te[toknum] = cp1; 179055682Smarkm } 179155682Smarkm cp2++; 179255682Smarkm break; 179355682Smarkm } 179455682Smarkm /* FALLTHROUGH */ 179555682Smarkm default: 179655682Smarkm if (*cp2 != *cp1) { 179755682Smarkm match = 0; 179855682Smarkm } 179955682Smarkm break; 180055682Smarkm } 180155682Smarkm if (match && *cp1) { 180255682Smarkm cp1++; 180355682Smarkm } 180455682Smarkm if (match && *cp2) { 180555682Smarkm cp2++; 180655682Smarkm } 180755682Smarkm } 180855682Smarkm if (!match && *cp1) /* last token mismatch */ 180955682Smarkm { 181055682Smarkm toks[toknum] = 0; 181155682Smarkm } 181255682Smarkm cp1 = new; 181355682Smarkm *cp1 = '\0'; 181455682Smarkm cp2 = mapout; 181555682Smarkm while (*cp2) { 181655682Smarkm match = 0; 181755682Smarkm switch (*cp2) { 181855682Smarkm case '\\': 181955682Smarkm if (*(cp2 + 1)) { 182055682Smarkm *cp1++ = *++cp2; 182155682Smarkm } 182255682Smarkm break; 182355682Smarkm case '[': 182455682SmarkmLOOP: 182555682Smarkm if (*++cp2 == '$' && isdigit(*(cp2+1))) { 182655682Smarkm if (*++cp2 == '0') { 182755682Smarkm char *cp3 = name; 182855682Smarkm 182955682Smarkm while (*cp3) { 183055682Smarkm *cp1++ = *cp3++; 183155682Smarkm } 183255682Smarkm match = 1; 183355682Smarkm } 183455682Smarkm else if (toks[toknum = *cp2 - '1']) { 183555682Smarkm char *cp3 = tp[toknum]; 183655682Smarkm 183755682Smarkm while (cp3 != te[toknum]) { 183855682Smarkm *cp1++ = *cp3++; 183955682Smarkm } 184055682Smarkm match = 1; 184155682Smarkm } 184255682Smarkm } 184355682Smarkm else { 184455682Smarkm while (*cp2 && *cp2 != ',' && 184555682Smarkm *cp2 != ']') { 184655682Smarkm if (*cp2 == '\\') { 184755682Smarkm cp2++; 184855682Smarkm } 184955682Smarkm else if (*cp2 == '$' && 185055682Smarkm isdigit(*(cp2+1))) { 185155682Smarkm if (*++cp2 == '0') { 185255682Smarkm char *cp3 = name; 185355682Smarkm 185455682Smarkm while (*cp3) { 185555682Smarkm *cp1++ = *cp3++; 185655682Smarkm } 185755682Smarkm } 185855682Smarkm else if (toks[toknum = 185955682Smarkm *cp2 - '1']) { 186055682Smarkm char *cp3=tp[toknum]; 186155682Smarkm 186255682Smarkm while (cp3 != 186355682Smarkm te[toknum]) { 186455682Smarkm *cp1++ = *cp3++; 186555682Smarkm } 186655682Smarkm } 186755682Smarkm } 186855682Smarkm else if (*cp2) { 186955682Smarkm *cp1++ = *cp2++; 187055682Smarkm } 187155682Smarkm } 187255682Smarkm if (!*cp2) { 187355682Smarkm printf("nmap: unbalanced brackets\n"); 187455682Smarkm return (name); 187555682Smarkm } 187655682Smarkm match = 1; 187755682Smarkm cp2--; 187855682Smarkm } 187955682Smarkm if (match) { 188055682Smarkm while (*++cp2 && *cp2 != ']') { 188155682Smarkm if (*cp2 == '\\' && *(cp2 + 1)) { 188255682Smarkm cp2++; 188355682Smarkm } 188455682Smarkm } 188555682Smarkm if (!*cp2) { 188655682Smarkm printf("nmap: unbalanced brackets\n"); 188755682Smarkm return (name); 188855682Smarkm } 188955682Smarkm break; 189055682Smarkm } 189155682Smarkm switch (*++cp2) { 189255682Smarkm case ',': 189355682Smarkm goto LOOP; 189455682Smarkm case ']': 189555682Smarkm break; 189655682Smarkm default: 189755682Smarkm cp2--; 189855682Smarkm goto LOOP; 189955682Smarkm } 190055682Smarkm break; 190155682Smarkm case '$': 190255682Smarkm if (isdigit(*(cp2 + 1))) { 190355682Smarkm if (*++cp2 == '0') { 190455682Smarkm char *cp3 = name; 190555682Smarkm 190655682Smarkm while (*cp3) { 190755682Smarkm *cp1++ = *cp3++; 190855682Smarkm } 190955682Smarkm } 191055682Smarkm else if (toks[toknum = *cp2 - '1']) { 191155682Smarkm char *cp3 = tp[toknum]; 191255682Smarkm 191355682Smarkm while (cp3 != te[toknum]) { 191455682Smarkm *cp1++ = *cp3++; 191555682Smarkm } 191655682Smarkm } 191755682Smarkm break; 191855682Smarkm } 191955682Smarkm /* intentional drop through */ 192055682Smarkm default: 192155682Smarkm *cp1++ = *cp2; 192255682Smarkm break; 192355682Smarkm } 192455682Smarkm cp2++; 192555682Smarkm } 192655682Smarkm *cp1 = '\0'; 192755682Smarkm if (!*new) { 192855682Smarkm return (name); 192955682Smarkm } 193055682Smarkm return (new); 193155682Smarkm} 193255682Smarkm 193355682Smarkmvoid 193455682Smarkmsetpassive(int argc, char **argv) 193555682Smarkm{ 193655682Smarkm 193755682Smarkm passivemode = !passivemode; 193855682Smarkm printf("Passive mode %s.\n", onoff(passivemode)); 193955682Smarkm code = passivemode; 194055682Smarkm} 194155682Smarkm 194255682Smarkmvoid 194355682Smarkmsetsunique(int argc, char **argv) 194455682Smarkm{ 194555682Smarkm 194655682Smarkm sunique = !sunique; 194755682Smarkm printf("Store unique %s.\n", onoff(sunique)); 194855682Smarkm code = sunique; 194955682Smarkm} 195055682Smarkm 195155682Smarkmvoid 195255682Smarkmsetrunique(int argc, char **argv) 195355682Smarkm{ 195455682Smarkm 195555682Smarkm runique = !runique; 195655682Smarkm printf("Receive unique %s.\n", onoff(runique)); 195755682Smarkm code = runique; 195855682Smarkm} 195955682Smarkm 196055682Smarkm/* change directory to perent directory */ 196155682Smarkmvoid 196255682Smarkmcdup(int argc, char **argv) 196355682Smarkm{ 196455682Smarkm 196555682Smarkm if (command("CDUP") == ERROR && code == 500) { 196655682Smarkm if (verbose) 196755682Smarkm printf("CDUP command not recognized, trying XCUP\n"); 196855682Smarkm command("XCUP"); 196955682Smarkm } 197055682Smarkm} 197155682Smarkm 197255682Smarkm/* restart transfer at specific point */ 197355682Smarkmvoid 197455682Smarkmrestart(int argc, char **argv) 197555682Smarkm{ 197655682Smarkm 197755682Smarkm if (argc != 2) 197855682Smarkm printf("restart: offset not specified\n"); 197955682Smarkm else { 198055682Smarkm restart_point = atol(argv[1]); 198155682Smarkm printf("restarting at %ld. %s\n", (long)restart_point, 198255682Smarkm "execute get, put or append to initiate transfer"); 198355682Smarkm } 198455682Smarkm} 198555682Smarkm 198655682Smarkm/* show remote system type */ 198755682Smarkmvoid 198855682Smarkmsyst(int argc, char **argv) 198955682Smarkm{ 199055682Smarkm 199155682Smarkm command("SYST"); 199255682Smarkm} 199355682Smarkm 199455682Smarkmvoid 199555682Smarkmmacdef(int argc, char **argv) 199655682Smarkm{ 199755682Smarkm char *tmp; 199855682Smarkm int c; 199955682Smarkm 200055682Smarkm if (macnum == 16) { 200155682Smarkm printf("Limit of 16 macros have already been defined\n"); 200255682Smarkm code = -1; 200355682Smarkm return; 200455682Smarkm } 200555682Smarkm if (argc < 2 && !another(&argc, &argv, "macro name")) { 200655682Smarkm printf("Usage: %s macro_name\n",argv[0]); 200755682Smarkm code = -1; 200855682Smarkm return; 200955682Smarkm } 201055682Smarkm if (interactive) { 201155682Smarkm printf("Enter macro line by line, terminating it with a null line\n"); 201255682Smarkm } 201355682Smarkm strlcpy(macros[macnum].mac_name, 201455682Smarkm argv[1], 201555682Smarkm sizeof(macros[macnum].mac_name)); 201655682Smarkm if (macnum == 0) { 201755682Smarkm macros[macnum].mac_start = macbuf; 201855682Smarkm } 201955682Smarkm else { 202055682Smarkm macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 202155682Smarkm } 202255682Smarkm tmp = macros[macnum].mac_start; 202355682Smarkm while (tmp != macbuf+4096) { 202455682Smarkm if ((c = getchar()) == EOF) { 202555682Smarkm printf("macdef:end of file encountered\n"); 202655682Smarkm code = -1; 202755682Smarkm return; 202855682Smarkm } 202955682Smarkm if ((*tmp = c) == '\n') { 203055682Smarkm if (tmp == macros[macnum].mac_start) { 203155682Smarkm macros[macnum++].mac_end = tmp; 203255682Smarkm code = 0; 203355682Smarkm return; 203455682Smarkm } 203555682Smarkm if (*(tmp-1) == '\0') { 203655682Smarkm macros[macnum++].mac_end = tmp - 1; 203755682Smarkm code = 0; 203855682Smarkm return; 203955682Smarkm } 204055682Smarkm *tmp = '\0'; 204155682Smarkm } 204255682Smarkm tmp++; 204355682Smarkm } 204455682Smarkm while (1) { 204555682Smarkm while ((c = getchar()) != '\n' && c != EOF) 204655682Smarkm /* LOOP */; 204755682Smarkm if (c == EOF || getchar() == '\n') { 204855682Smarkm printf("Macro not defined - 4k buffer exceeded\n"); 204955682Smarkm code = -1; 205055682Smarkm return; 205155682Smarkm } 205255682Smarkm } 205355682Smarkm} 205455682Smarkm 205555682Smarkm/* 205655682Smarkm * get size of file on remote machine 205755682Smarkm */ 205855682Smarkmvoid 205955682Smarkmsizecmd(int argc, char **argv) 206055682Smarkm{ 206155682Smarkm 206255682Smarkm if (argc < 2 && !another(&argc, &argv, "filename")) { 206355682Smarkm printf("usage: %s filename\n", argv[0]); 206455682Smarkm code = -1; 206555682Smarkm return; 206655682Smarkm } 206755682Smarkm command("SIZE %s", argv[1]); 206855682Smarkm} 206955682Smarkm 207055682Smarkm/* 207155682Smarkm * get last modification time of file on remote machine 207255682Smarkm */ 207355682Smarkmvoid 207455682Smarkmmodtime(int argc, char **argv) 207555682Smarkm{ 207655682Smarkm int overbose; 207755682Smarkm 207855682Smarkm if (argc < 2 && !another(&argc, &argv, "filename")) { 207955682Smarkm printf("usage: %s filename\n", argv[0]); 208055682Smarkm code = -1; 208155682Smarkm return; 208255682Smarkm } 208355682Smarkm overbose = verbose; 208455682Smarkm if (debug == 0) 208555682Smarkm verbose = -1; 208655682Smarkm if (command("MDTM %s", argv[1]) == COMPLETE) { 208755682Smarkm int yy, mo, day, hour, min, sec; 208855682Smarkm sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 208955682Smarkm &day, &hour, &min, &sec); 209055682Smarkm /* might want to print this in local time */ 209155682Smarkm printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 209255682Smarkm mo, day, yy, hour, min, sec); 209355682Smarkm } else 209455682Smarkm printf("%s\n", reply_string); 209555682Smarkm verbose = overbose; 209655682Smarkm} 209755682Smarkm 209855682Smarkm/* 209955682Smarkm * show status on reomte machine 210055682Smarkm */ 210155682Smarkmvoid 210255682Smarkmrmtstatus(int argc, char **argv) 210355682Smarkm{ 210455682Smarkm 210555682Smarkm command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 210655682Smarkm} 210755682Smarkm 210855682Smarkm/* 210955682Smarkm * get file if modtime is more recent than current file 211055682Smarkm */ 211155682Smarkmvoid 211255682Smarkmnewer(int argc, char **argv) 211355682Smarkm{ 211455682Smarkm 211555682Smarkm if (getit(argc, argv, -1, curtype == TYPE_I ? "wb" : "w")) 211655682Smarkm printf("Local file \"%s\" is newer than remote file \"%s\"\n", 211755682Smarkm argv[2], argv[1]); 211855682Smarkm} 2119