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