121737Sdist /* 236942Skarels * Copyright (c) 1985, 1989 Regents of the University of California. 333737Sbostic * All rights reserved. 433737Sbostic * 533737Sbostic * Redistribution and use in source and binary forms are permitted 634901Sbostic * provided that the above copyright notice and this paragraph are 734901Sbostic * duplicated in all such forms and that any documentation, 834901Sbostic * advertising materials, and other materials related to such 934901Sbostic * distribution and use acknowledge that the software was developed 1034901Sbostic * by the University of California, Berkeley. The name of the 1134901Sbostic * University may not be used to endorse or promote products derived 1234901Sbostic * from this software without specific prior written permission. 1334901Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434901Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1536935Skarels * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621737Sdist */ 1721737Sdist 1810294Ssam #ifndef lint 19*39252Sbostic static char sccsid[] = "@(#)cmds.c 5.22 (Berkeley) 10/03/89"; 2033737Sbostic #endif /* not lint */ 2110294Ssam 2210294Ssam /* 2310294Ssam * FTP User Program -- Command Routines. 2410294Ssam */ 2536940Skarels #include <sys/param.h> 2636940Skarels #include <sys/wait.h> 2736940Skarels #include <sys/stat.h> 2810294Ssam #include <sys/socket.h> 2910294Ssam 3012396Ssam #include <arpa/ftp.h> 3112396Ssam 3210294Ssam #include <signal.h> 3310294Ssam #include <stdio.h> 3410294Ssam #include <errno.h> 3510294Ssam #include <netdb.h> 3626049Sminshall #include <ctype.h> 3736935Skarels #include <time.h> 3838132Srick #include <netinet/in.h> 3910294Ssam 4036940Skarels #include "ftp_var.h" 4137458Skarels #include "pathnames.h" 4210294Ssam 4311353Ssam extern char *globerr; 4411353Ssam extern char **glob(); 4511756Ssam extern char *home; 4611756Ssam extern char *remglob(); 4711756Ssam extern char *getenv(); 4811756Ssam extern char *index(); 4911756Ssam extern char *rindex(); 5038202Srick extern char *strerror(); 5138202Srick extern int errno; 5237224Skarels extern off_t restart_point; 5336935Skarels extern char reply_string[]; 5436935Skarels 5526049Sminshall char *mname; 5626049Sminshall jmp_buf jabort; 5726049Sminshall char *dotrans(), *domap(); 5810294Ssam 5910294Ssam /* 6010294Ssam * Connect to peer server and 6110294Ssam * auto-login, if possible. 6210294Ssam */ 6310294Ssam setpeer(argc, argv) 6410294Ssam int argc; 6510294Ssam char *argv[]; 6610294Ssam { 6725903Skarels char *host, *hookup(); 6838132Srick short port; 6910294Ssam 7010294Ssam if (connected) { 7126049Sminshall printf("Already connected to %s, use close first.\n", 7210294Ssam hostname); 7326049Sminshall code = -1; 7410294Ssam return; 7510294Ssam } 7610294Ssam if (argc < 2) { 7726497Sminshall (void) strcat(line, " "); 7810294Ssam printf("(to) "); 7926497Sminshall (void) gets(&line[strlen(line)]); 8010294Ssam makeargv(); 8110294Ssam argc = margc; 8210294Ssam argv = margv; 8310294Ssam } 8410294Ssam if (argc > 3) { 8510294Ssam printf("usage: %s host-name [port]\n", argv[0]); 8626049Sminshall code = -1; 8710294Ssam return; 8810294Ssam } 8910294Ssam port = sp->s_port; 9010294Ssam if (argc > 2) { 9111218Ssam port = atoi(argv[2]); 9210294Ssam if (port <= 0) { 9311218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 9411218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 9526049Sminshall code = -1; 9610294Ssam return; 9710294Ssam } 9810294Ssam port = htons(port); 9910294Ssam } 10010294Ssam host = hookup(argv[1], port); 10110294Ssam if (host) { 10237228Skarels int overbose; 10337228Skarels 10410294Ssam connected = 1; 10538032Skarels /* 10638032Skarels * Set up defaults for FTP. 10738032Skarels */ 10838032Skarels (void) strcpy(typename, "ascii"), type = TYPE_A; 10938032Skarels curtype = TYPE_A; 11038032Skarels (void) strcpy(formname, "non-print"), form = FORM_N; 11138032Skarels (void) strcpy(modename, "stream"), mode = MODE_S; 11238032Skarels (void) strcpy(structname, "file"), stru = STRU_F; 11338032Skarels (void) strcpy(bytename, "8"), bytesize = 8; 11437228Skarels if (autologin) 11537228Skarels (void) login(argv[1]); 11636940Skarels 11736935Skarels #if defined(unix) && NBBY == 8 11836935Skarels /* 11936935Skarels * this ifdef is to keep someone form "porting" this to an incompatible 12036935Skarels * system and not checking this out. This way they have to think about it. 12136935Skarels */ 12237228Skarels overbose = verbose; 12337228Skarels if (debug == 0) 12437228Skarels verbose = -1; 12537228Skarels if (command("SYST") == COMPLETE && overbose) { 12637228Skarels register char *cp, c; 12737228Skarels cp = index(reply_string+4, ' '); 12837228Skarels if (cp == NULL) 12937228Skarels cp = index(reply_string+4, '\r'); 13037228Skarels if (cp) { 13137228Skarels if (cp[-1] == '.') 13237228Skarels cp--; 13337228Skarels c = *cp; 13437228Skarels *cp = '\0'; 13537228Skarels } 13636935Skarels 13737228Skarels printf("Remote system type is %s.\n", 13837228Skarels reply_string+4); 13937228Skarels if (cp) 14037228Skarels *cp = c; 14137228Skarels } 14237228Skarels if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { 14338032Skarels if (proxy) 14438032Skarels unix_proxy = 1; 14538032Skarels else 14638032Skarels unix_server = 1; 14738032Skarels /* 14838032Skarels * Set type to 0 (not specified by user), 14938032Skarels * meaning binary by default, but don't bother 15038032Skarels * telling server. We can use binary 15138032Skarels * for text files unless changed by the user. 15238032Skarels */ 15338032Skarels type = 0; 15438032Skarels (void) strcpy(typename, "binary"); 15537228Skarels if (overbose) 15637228Skarels printf("Using %s mode to transfer files.\n", 15737228Skarels typename); 15838032Skarels } else { 15938032Skarels if (proxy) 16038032Skarels unix_proxy = 0; 16138032Skarels else 16238032Skarels unix_server = 0; 16338032Skarels if (overbose && 16438032Skarels !strncmp(reply_string, "215 TOPS20", 10)) 16538032Skarels printf( 16636940Skarels "Remember to set tenex mode when transfering binary files from this machine.\n"); 16737228Skarels } 16837228Skarels verbose = overbose; 16936935Skarels #endif /* unix */ 17010294Ssam } 17110294Ssam } 17210294Ssam 17310294Ssam struct types { 17410294Ssam char *t_name; 17510294Ssam char *t_mode; 17610294Ssam int t_type; 17711218Ssam char *t_arg; 17810294Ssam } types[] = { 17911218Ssam { "ascii", "A", TYPE_A, 0 }, 18011218Ssam { "binary", "I", TYPE_I, 0 }, 18111218Ssam { "image", "I", TYPE_I, 0 }, 18211218Ssam { "ebcdic", "E", TYPE_E, 0 }, 18311218Ssam { "tenex", "L", TYPE_L, bytename }, 18410294Ssam 0 18510294Ssam }; 18610294Ssam 18710294Ssam /* 18810294Ssam * Set transfer type. 18910294Ssam */ 19010294Ssam settype(argc, argv) 19110294Ssam char *argv[]; 19210294Ssam { 19310294Ssam register struct types *p; 19411218Ssam int comret; 19510294Ssam 19610294Ssam if (argc > 2) { 19710294Ssam char *sep; 19810294Ssam 19910294Ssam printf("usage: %s [", argv[0]); 20010294Ssam sep = " "; 20110294Ssam for (p = types; p->t_name; p++) { 20210294Ssam printf("%s%s", sep, p->t_name); 20338032Skarels sep = " | "; 20410294Ssam } 20510294Ssam printf(" ]\n"); 20626049Sminshall code = -1; 20710294Ssam return; 20810294Ssam } 20910294Ssam if (argc < 2) { 21010294Ssam printf("Using %s mode to transfer files.\n", typename); 21126049Sminshall code = 0; 21210294Ssam return; 21310294Ssam } 21410294Ssam for (p = types; p->t_name; p++) 21510294Ssam if (strcmp(argv[1], p->t_name) == 0) 21610294Ssam break; 21710294Ssam if (p->t_name == 0) { 21810294Ssam printf("%s: unknown mode\n", argv[1]); 21926049Sminshall code = -1; 22010294Ssam return; 22110294Ssam } 22211218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 22311218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 22411218Ssam else 22511218Ssam comret = command("TYPE %s", p->t_mode); 22611218Ssam if (comret == COMPLETE) { 22726497Sminshall (void) strcpy(typename, p->t_name); 22838032Skarels curtype = type = p->t_type; 22910294Ssam } 23010294Ssam } 23110294Ssam 23210294Ssam /* 23338032Skarels * Internal form of settype; changes current type in use with server 23438032Skarels * without changing our notion of the type for data transfers. 23538032Skarels * Used to change to and from ascii for listings. 23638032Skarels */ 23738032Skarels changetype(newtype, show) 23838032Skarels int newtype, show; 23938032Skarels { 24038032Skarels register struct types *p; 24138032Skarels int comret, oldverbose = verbose; 24238032Skarels 24338032Skarels if (newtype == 0) 24438032Skarels newtype = TYPE_I; 24538032Skarels if (newtype == curtype) 24638032Skarels return; 24738032Skarels if (debug == 0 && show == 0) 24838032Skarels verbose = 0; 24938032Skarels for (p = types; p->t_name; p++) 25038032Skarels if (newtype == p->t_type) 25138032Skarels break; 25238032Skarels if (p->t_name == 0) { 25338032Skarels printf("ftp: internal error: unknown type %d\n", newtype); 25438032Skarels return; 25538032Skarels } 25638032Skarels if (newtype == TYPE_L && bytename[0] != '\0') 25738032Skarels comret = command("TYPE %s %s", p->t_mode, bytename); 25838032Skarels else 25938032Skarels comret = command("TYPE %s", p->t_mode); 26038032Skarels if (comret == COMPLETE) 26138032Skarels curtype = newtype; 26238032Skarels verbose = oldverbose; 26338032Skarels } 26438032Skarels 26538132Srick char *stype[] = { 26638132Srick "type", 26738132Srick "", 26838132Srick 0 26938132Srick }; 27038132Srick 27138032Skarels /* 27210294Ssam * Set binary transfer type. 27310294Ssam */ 27410294Ssam /*VARARGS*/ 27510294Ssam setbinary() 27610294Ssam { 27738132Srick stype[1] = "binary"; 27838132Srick settype(2, stype); 27910294Ssam } 28010294Ssam 28110294Ssam /* 28210294Ssam * Set ascii transfer type. 28310294Ssam */ 28410294Ssam /*VARARGS*/ 28510294Ssam setascii() 28610294Ssam { 28738132Srick stype[1] = "ascii"; 28838132Srick settype(2, stype); 28910294Ssam } 29010294Ssam 29110294Ssam /* 29210294Ssam * Set tenex transfer type. 29310294Ssam */ 29410294Ssam /*VARARGS*/ 29510294Ssam settenex() 29610294Ssam { 29738132Srick stype[1] = "tenex"; 29838132Srick settype(2, stype); 29910294Ssam } 30010294Ssam 30110294Ssam /* 30210294Ssam * Set file transfer mode. 30310294Ssam */ 30426497Sminshall /*ARGSUSED*/ 30510294Ssam setmode(argc, argv) 30610294Ssam char *argv[]; 30710294Ssam { 30810294Ssam 30910294Ssam printf("We only support %s mode, sorry.\n", modename); 31026049Sminshall code = -1; 31110294Ssam } 31210294Ssam 31310294Ssam /* 31410294Ssam * Set file transfer format. 31510294Ssam */ 31626497Sminshall /*ARGSUSED*/ 31710294Ssam setform(argc, argv) 31810294Ssam char *argv[]; 31910294Ssam { 32010294Ssam 32110294Ssam printf("We only support %s format, sorry.\n", formname); 32226049Sminshall code = -1; 32310294Ssam } 32410294Ssam 32510294Ssam /* 32610294Ssam * Set file transfer structure. 32710294Ssam */ 32826497Sminshall /*ARGSUSED*/ 32910294Ssam setstruct(argc, argv) 33010294Ssam char *argv[]; 33110294Ssam { 33210294Ssam 33310294Ssam printf("We only support %s structure, sorry.\n", structname); 33426049Sminshall code = -1; 33510294Ssam } 33610294Ssam 33718286Sralph /* 33818286Sralph * Send a single file. 33918286Sralph */ 34010294Ssam put(argc, argv) 34111756Ssam int argc; 34210294Ssam char *argv[]; 34310294Ssam { 34411650Ssam char *cmd; 34526049Sminshall int loc = 0; 34637225Skarels char *oldargv1, *oldargv2; 34711650Ssam 34826049Sminshall if (argc == 2) { 34926049Sminshall argc++; 35026049Sminshall argv[2] = argv[1]; 35126049Sminshall loc++; 35226049Sminshall } 35310294Ssam if (argc < 2) { 35426497Sminshall (void) strcat(line, " "); 35510294Ssam printf("(local-file) "); 35626497Sminshall (void) gets(&line[strlen(line)]); 35710294Ssam makeargv(); 35810294Ssam argc = margc; 35910294Ssam argv = margv; 36010294Ssam } 36110294Ssam if (argc < 2) { 36210294Ssam usage: 36326049Sminshall printf("usage:%s local-file remote-file\n", argv[0]); 36426049Sminshall code = -1; 36510294Ssam return; 36610294Ssam } 36710294Ssam if (argc < 3) { 36826497Sminshall (void) strcat(line, " "); 36910294Ssam printf("(remote-file) "); 37026497Sminshall (void) gets(&line[strlen(line)]); 37110294Ssam makeargv(); 37210294Ssam argc = margc; 37310294Ssam argv = margv; 37410294Ssam } 37510294Ssam if (argc < 3) 37610294Ssam goto usage; 37725908Smckusick oldargv1 = argv[1]; 37837225Skarels oldargv2 = argv[2]; 37926049Sminshall if (!globulize(&argv[1])) { 38026049Sminshall code = -1; 38111353Ssam return; 38226049Sminshall } 38325908Smckusick /* 38425908Smckusick * If "globulize" modifies argv[1], and argv[2] is a copy of 38525908Smckusick * the old argv[1], make it a copy of the new argv[1]. 38625908Smckusick */ 38726049Sminshall if (argv[1] != oldargv1 && argv[2] == oldargv1) { 38825908Smckusick argv[2] = argv[1]; 38926049Sminshall } 39026049Sminshall cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); 39126049Sminshall if (loc && ntflag) { 39226049Sminshall argv[2] = dotrans(argv[2]); 39326049Sminshall } 39426049Sminshall if (loc && mapflag) { 39526049Sminshall argv[2] = domap(argv[2]); 39626049Sminshall } 39737225Skarels sendrequest(cmd, argv[1], argv[2], 39837225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 39910294Ssam } 40010294Ssam 40110294Ssam /* 40211756Ssam * Send multiple files. 40310294Ssam */ 40411353Ssam mput(argc, argv) 405*39252Sbostic int argc; 406*39252Sbostic char **argv; 40711353Ssam { 408*39252Sbostic extern jmp_buf jabort; 40913212Ssam register int i; 410*39252Sbostic sig_t oldintr; 41138132Srick int ointer; 41226049Sminshall char *tp; 413*39252Sbostic void mabort(); 41411353Ssam 41511650Ssam if (argc < 2) { 41626497Sminshall (void) strcat(line, " "); 41711650Ssam printf("(local-files) "); 41826497Sminshall (void) gets(&line[strlen(line)]); 41911650Ssam makeargv(); 42011650Ssam argc = margc; 42111650Ssam argv = margv; 42211353Ssam } 42311353Ssam if (argc < 2) { 42426049Sminshall printf("usage:%s local-files\n", argv[0]); 42526049Sminshall code = -1; 42611353Ssam return; 42711353Ssam } 42826049Sminshall mname = argv[0]; 42926049Sminshall mflag = 1; 43026049Sminshall oldintr = signal(SIGINT, mabort); 43126049Sminshall (void) setjmp(jabort); 43226049Sminshall if (proxy) { 43326049Sminshall char *cp, *tp2, tmpbuf[MAXPATHLEN]; 43426049Sminshall 43526497Sminshall while ((cp = remglob(argv,0)) != NULL) { 43626049Sminshall if (*cp == 0) { 43726049Sminshall mflag = 0; 43826049Sminshall continue; 43926049Sminshall } 44026049Sminshall if (mflag && confirm(argv[0], cp)) { 44126049Sminshall tp = cp; 44226049Sminshall if (mcase) { 44326049Sminshall while (*tp && !islower(*tp)) { 44426049Sminshall tp++; 44526049Sminshall } 44626049Sminshall if (!*tp) { 44726049Sminshall tp = cp; 44826049Sminshall tp2 = tmpbuf; 44926049Sminshall while ((*tp2 = *tp) != NULL) { 45026049Sminshall if (isupper(*tp2)) { 45126049Sminshall *tp2 = 'a' + *tp2 - 'A'; 45226049Sminshall } 45326049Sminshall tp++; 45426049Sminshall tp2++; 45526049Sminshall } 45626049Sminshall } 45726049Sminshall tp = tmpbuf; 45826049Sminshall } 45926049Sminshall if (ntflag) { 46026049Sminshall tp = dotrans(tp); 46126049Sminshall } 46226049Sminshall if (mapflag) { 46326049Sminshall tp = domap(tp); 46426049Sminshall } 46537225Skarels sendrequest((sunique) ? "STOU" : "STOR", 46637225Skarels cp, tp, cp != tp || !interactive); 46726049Sminshall if (!mflag && fromatty) { 46826049Sminshall ointer = interactive; 46926049Sminshall interactive = 1; 47026049Sminshall if (confirm("Continue with","mput")) { 47126049Sminshall mflag++; 47226049Sminshall } 47326049Sminshall interactive = ointer; 47426049Sminshall } 47526049Sminshall } 47626049Sminshall } 47726049Sminshall (void) signal(SIGINT, oldintr); 47826049Sminshall mflag = 0; 47926049Sminshall return; 48026049Sminshall } 48113212Ssam for (i = 1; i < argc; i++) { 48213212Ssam register char **cpp, **gargs; 48313212Ssam 48413212Ssam if (!doglob) { 48526049Sminshall if (mflag && confirm(argv[0], argv[i])) { 48626049Sminshall tp = (ntflag) ? dotrans(argv[i]) : argv[i]; 48726049Sminshall tp = (mapflag) ? domap(tp) : tp; 48826049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 48937225Skarels argv[i], tp, tp != argv[i] || !interactive); 49026049Sminshall if (!mflag && fromatty) { 49126049Sminshall ointer = interactive; 49226049Sminshall interactive = 1; 49326049Sminshall if (confirm("Continue with","mput")) { 49426049Sminshall mflag++; 49526049Sminshall } 49626049Sminshall interactive = ointer; 49726049Sminshall } 49826049Sminshall } 49913212Ssam continue; 50013212Ssam } 50113212Ssam gargs = glob(argv[i]); 50211650Ssam if (globerr != NULL) { 50311650Ssam printf("%s\n", globerr); 50436421Sbostic if (gargs) { 50511650Ssam blkfree(gargs); 50638132Srick free((char *)gargs); 50736421Sbostic } 50813212Ssam continue; 50911353Ssam } 51026049Sminshall for (cpp = gargs; cpp && *cpp != NULL; cpp++) { 51126049Sminshall if (mflag && confirm(argv[0], *cpp)) { 51226049Sminshall tp = (ntflag) ? dotrans(*cpp) : *cpp; 51326049Sminshall tp = (mapflag) ? domap(tp) : tp; 51426049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 51537225Skarels *cpp, tp, *cpp != tp || !interactive); 51626049Sminshall if (!mflag && fromatty) { 51726049Sminshall ointer = interactive; 51826049Sminshall interactive = 1; 51926049Sminshall if (confirm("Continue with","mput")) { 52026049Sminshall mflag++; 52126049Sminshall } 52226049Sminshall interactive = ointer; 52326049Sminshall } 52426049Sminshall } 52526049Sminshall } 52636421Sbostic if (gargs != NULL) { 52713212Ssam blkfree(gargs); 52838132Srick free((char *)gargs); 52936421Sbostic } 53011353Ssam } 53126049Sminshall (void) signal(SIGINT, oldintr); 53226049Sminshall mflag = 0; 53311353Ssam } 53411353Ssam 53537224Skarels reget(argc, argv) 53637224Skarels char *argv[]; 53737224Skarels { 53837224Skarels (void) getit(argc, argv, 1, "r+w"); 53937224Skarels } 54036935Skarels 54137224Skarels get(argc, argv) 54237224Skarels char *argv[]; 54337224Skarels { 54437224Skarels (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" ); 54537224Skarels } 54637224Skarels 54711353Ssam /* 54811353Ssam * Receive one file. 54911353Ssam */ 55037224Skarels getit(argc, argv, restartit, mode) 55110294Ssam char *argv[]; 55237224Skarels char *mode; 55310294Ssam { 55426049Sminshall int loc = 0; 55537225Skarels char *oldargv1, *oldargv2; 55610294Ssam 55726049Sminshall if (argc == 2) { 55826049Sminshall argc++; 55926049Sminshall argv[2] = argv[1]; 56026049Sminshall loc++; 56126049Sminshall } 56210294Ssam if (argc < 2) { 56326497Sminshall (void) strcat(line, " "); 56410294Ssam printf("(remote-file) "); 56526497Sminshall (void) gets(&line[strlen(line)]); 56610294Ssam makeargv(); 56710294Ssam argc = margc; 56810294Ssam argv = margv; 56910294Ssam } 57010294Ssam if (argc < 2) { 57110294Ssam usage: 57226049Sminshall printf("usage: %s remote-file [ local-file ]\n", argv[0]); 57326049Sminshall code = -1; 57437224Skarels return (0); 57510294Ssam } 57610294Ssam if (argc < 3) { 57726497Sminshall (void) strcat(line, " "); 57810294Ssam printf("(local-file) "); 57926497Sminshall (void) gets(&line[strlen(line)]); 58010294Ssam makeargv(); 58110294Ssam argc = margc; 58210294Ssam argv = margv; 58310294Ssam } 58410294Ssam if (argc < 3) 58510294Ssam goto usage; 58637225Skarels oldargv1 = argv[1]; 58737225Skarels oldargv2 = argv[2]; 58826049Sminshall if (!globulize(&argv[2])) { 58926049Sminshall code = -1; 59037224Skarels return (0); 59126049Sminshall } 59226049Sminshall if (loc && mcase) { 59326049Sminshall char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; 59426049Sminshall 59526049Sminshall while (*tp && !islower(*tp)) { 59626049Sminshall tp++; 59726049Sminshall } 59826049Sminshall if (!*tp) { 59926049Sminshall tp = argv[2]; 60026049Sminshall tp2 = tmpbuf; 60126049Sminshall while ((*tp2 = *tp) != NULL) { 60226049Sminshall if (isupper(*tp2)) { 60326049Sminshall *tp2 = 'a' + *tp2 - 'A'; 60426049Sminshall } 60526049Sminshall tp++; 60626049Sminshall tp2++; 60726049Sminshall } 60826049Sminshall argv[2] = tmpbuf; 60926049Sminshall } 61026049Sminshall } 61136940Skarels if (loc && ntflag) 61226049Sminshall argv[2] = dotrans(argv[2]); 61336940Skarels if (loc && mapflag) 61426049Sminshall argv[2] = domap(argv[2]); 61537224Skarels if (restartit) { 61637224Skarels struct stat stbuf; 61737224Skarels int ret; 61837224Skarels 61937224Skarels ret = stat(argv[2], &stbuf); 62037224Skarels if (restartit == 1) { 62137224Skarels if (ret < 0) { 62238202Srick fprintf(stderr, "local: %s: %s\n", argv[2], 62338202Srick strerror(errno)); 62437224Skarels return (0); 62537224Skarels } 62637224Skarels restart_point = stbuf.st_size; 62737224Skarels } else { 62837224Skarels if (ret == 0) { 62937224Skarels int overbose; 63037224Skarels 63137224Skarels overbose = verbose; 63237224Skarels if (debug == 0) 63337224Skarels verbose = -1; 63437224Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 63537224Skarels int yy, mo, day, hour, min, sec; 63637224Skarels struct tm *tm; 63737224Skarels verbose = overbose; 63837224Skarels sscanf(reply_string, 63937224Skarels "%*s %04d%02d%02d%02d%02d%02d", 64037224Skarels &yy, &mo, &day, &hour, &min, &sec); 64137224Skarels tm = gmtime(&stbuf.st_mtime); 64237224Skarels tm->tm_mon++; 64337224Skarels if (tm->tm_year > yy%100) 64437224Skarels return (1); 64537224Skarels else if (tm->tm_year == yy%100) { 64637224Skarels if (tm->tm_mon > mo) 64737224Skarels return (1); 64837224Skarels } else if (tm->tm_mon == mo) { 64937224Skarels if (tm->tm_mday > day) 65037224Skarels return (1); 65137224Skarels } else if (tm->tm_mday == day) { 65237224Skarels if (tm->tm_hour > hour) 65337224Skarels return (1); 65437224Skarels } else if (tm->tm_hour == hour) { 65537224Skarels if (tm->tm_min > min) 65637224Skarels return (1); 65737224Skarels } else if (tm->tm_min == min) { 65837224Skarels if (tm->tm_sec > sec) 65937224Skarels return (1); 66037224Skarels } 66137224Skarels } else { 66238132Srick printf("%s\n", reply_string); 66337224Skarels verbose = overbose; 66437224Skarels return (0); 66537224Skarels } 66637224Skarels } 66737224Skarels } 66837224Skarels } 66937224Skarels 67037225Skarels recvrequest("RETR", argv[2], argv[1], mode, 67137225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 67237224Skarels restart_point = 0; 67337224Skarels return (0); 67410294Ssam } 67510294Ssam 676*39252Sbostic void 67726049Sminshall mabort() 67826049Sminshall { 67926049Sminshall int ointer; 68026049Sminshall extern jmp_buf jabort; 68126049Sminshall 68226049Sminshall printf("\n"); 68326049Sminshall (void) fflush(stdout); 68426049Sminshall if (mflag && fromatty) { 68526049Sminshall ointer = interactive; 68626049Sminshall interactive = 1; 68726049Sminshall if (confirm("Continue with", mname)) { 68826049Sminshall interactive = ointer; 68926049Sminshall longjmp(jabort,0); 69026049Sminshall } 69126049Sminshall interactive = ointer; 69226049Sminshall } 69326049Sminshall mflag = 0; 69426049Sminshall longjmp(jabort,0); 69526049Sminshall } 69626049Sminshall 69711353Ssam /* 69811353Ssam * Get multiple files. 69911353Ssam */ 70011353Ssam mget(argc, argv) 701*39252Sbostic int argc; 702*39252Sbostic char **argv; 70311353Ssam { 704*39252Sbostic extern jmp_buf jabort; 705*39252Sbostic sig_t oldintr; 706*39252Sbostic int ointer; 70726049Sminshall char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; 708*39252Sbostic void mabort(); 70911353Ssam 71011353Ssam if (argc < 2) { 71126497Sminshall (void) strcat(line, " "); 71211756Ssam printf("(remote-files) "); 71326497Sminshall (void) gets(&line[strlen(line)]); 71411353Ssam makeargv(); 71511353Ssam argc = margc; 71611353Ssam argv = margv; 71711353Ssam } 71811353Ssam if (argc < 2) { 71926049Sminshall printf("usage:%s remote-files\n", argv[0]); 72026049Sminshall code = -1; 72111353Ssam return; 72211353Ssam } 72326049Sminshall mname = argv[0]; 72426049Sminshall mflag = 1; 72526049Sminshall oldintr = signal(SIGINT,mabort); 72626049Sminshall (void) setjmp(jabort); 72726497Sminshall while ((cp = remglob(argv,proxy)) != NULL) { 72826049Sminshall if (*cp == '\0') { 72926049Sminshall mflag = 0; 73026049Sminshall continue; 73126049Sminshall } 73226049Sminshall if (mflag && confirm(argv[0], cp)) { 73326049Sminshall tp = cp; 73426049Sminshall if (mcase) { 73526049Sminshall while (*tp && !islower(*tp)) { 73626049Sminshall tp++; 73726049Sminshall } 73826049Sminshall if (!*tp) { 73926049Sminshall tp = cp; 74026049Sminshall tp2 = tmpbuf; 74126049Sminshall while ((*tp2 = *tp) != NULL) { 74226049Sminshall if (isupper(*tp2)) { 74326049Sminshall *tp2 = 'a' + *tp2 - 'A'; 74426049Sminshall } 74526049Sminshall tp++; 74626049Sminshall tp2++; 74726049Sminshall } 74826049Sminshall } 74926049Sminshall tp = tmpbuf; 75026049Sminshall } 75126049Sminshall if (ntflag) { 75226049Sminshall tp = dotrans(tp); 75326049Sminshall } 75426049Sminshall if (mapflag) { 75526049Sminshall tp = domap(tp); 75626049Sminshall } 75737225Skarels recvrequest("RETR", tp, cp, "w", 75837225Skarels tp != cp || !interactive); 75926049Sminshall if (!mflag && fromatty) { 76026049Sminshall ointer = interactive; 76126049Sminshall interactive = 1; 76226049Sminshall if (confirm("Continue with","mget")) { 76326049Sminshall mflag++; 76426049Sminshall } 76526049Sminshall interactive = ointer; 76626049Sminshall } 76726049Sminshall } 76826049Sminshall } 76926049Sminshall (void) signal(SIGINT,oldintr); 77026049Sminshall mflag = 0; 77111650Ssam } 77211650Ssam 77311650Ssam char * 77426497Sminshall remglob(argv,doswitch) 77511650Ssam char *argv[]; 77626497Sminshall int doswitch; 77711650Ssam { 77811756Ssam char temp[16]; 77911650Ssam static char buf[MAXPATHLEN]; 78011650Ssam static FILE *ftemp = NULL; 78111650Ssam static char **args; 78213212Ssam int oldverbose, oldhash; 78311756Ssam char *cp, *mode; 78411650Ssam 78526049Sminshall if (!mflag) { 78626049Sminshall if (!doglob) { 78726049Sminshall args = NULL; 78826049Sminshall } 78926049Sminshall else { 79026049Sminshall if (ftemp) { 79126497Sminshall (void) fclose(ftemp); 79226049Sminshall ftemp = NULL; 79326049Sminshall } 79426049Sminshall } 79526049Sminshall return(NULL); 79626049Sminshall } 79711650Ssam if (!doglob) { 79811756Ssam if (args == NULL) 79911650Ssam args = argv; 80011650Ssam if ((cp = *++args) == NULL) 80111650Ssam args = NULL; 80211650Ssam return (cp); 80311353Ssam } 80411650Ssam if (ftemp == NULL) { 80537458Skarels (void) strcpy(temp, _PATH_TMP); 80626497Sminshall (void) mktemp(temp); 80711650Ssam oldverbose = verbose, verbose = 0; 80813212Ssam oldhash = hash, hash = 0; 80926049Sminshall if (doswitch) { 81026049Sminshall pswitch(!proxy); 81126049Sminshall } 81211756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 81337225Skarels recvrequest ("NLST", temp, *argv, mode, 0); 81426049Sminshall if (doswitch) { 81526049Sminshall pswitch(!proxy); 81626049Sminshall } 81713212Ssam verbose = oldverbose; hash = oldhash; 81811650Ssam ftemp = fopen(temp, "r"); 81926497Sminshall (void) unlink(temp); 82011650Ssam if (ftemp == NULL) { 82111650Ssam printf("can't find list of remote files, oops\n"); 82211756Ssam return (NULL); 82311353Ssam } 82411353Ssam } 82511650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 82626497Sminshall (void) fclose(ftemp), ftemp = NULL; 82711650Ssam return (NULL); 82811353Ssam } 82911650Ssam if ((cp = index(buf, '\n')) != NULL) 83011650Ssam *cp = '\0'; 83111650Ssam return (buf); 83211353Ssam } 83311353Ssam 83410294Ssam char * 83510294Ssam onoff(bool) 83610294Ssam int bool; 83710294Ssam { 83810294Ssam 83910294Ssam return (bool ? "on" : "off"); 84010294Ssam } 84110294Ssam 84210294Ssam /* 84310294Ssam * Show status. 84410294Ssam */ 84526497Sminshall /*ARGSUSED*/ 84610294Ssam status(argc, argv) 84710294Ssam char *argv[]; 84810294Ssam { 84926049Sminshall int i; 85010294Ssam 85110294Ssam if (connected) 85210294Ssam printf("Connected to %s.\n", hostname); 85310294Ssam else 85410294Ssam printf("Not connected.\n"); 85526049Sminshall if (!proxy) { 85626049Sminshall pswitch(1); 85726049Sminshall if (connected) { 85826049Sminshall printf("Connected for proxy commands to %s.\n", hostname); 85926049Sminshall } 86026049Sminshall else { 86126049Sminshall printf("No proxy connection.\n"); 86226049Sminshall } 86326049Sminshall pswitch(0); 86426049Sminshall } 86510294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 86610294Ssam modename, typename, formname, structname); 86711353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 86811353Ssam onoff(verbose), onoff(bell), onoff(interactive), 86911353Ssam onoff(doglob)); 87026049Sminshall printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), 87126049Sminshall onoff(runique)); 87226049Sminshall printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); 87326049Sminshall if (ntflag) { 87426049Sminshall printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); 87526049Sminshall } 87626049Sminshall else { 87726049Sminshall printf("Ntrans: off\n"); 87826049Sminshall } 87926049Sminshall if (mapflag) { 88026049Sminshall printf("Nmap: (in) %s (out) %s\n", mapin, mapout); 88126049Sminshall } 88226049Sminshall else { 88326049Sminshall printf("Nmap: off\n"); 88426049Sminshall } 88514143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 88614143Ssam onoff(hash), onoff(sendport)); 88726049Sminshall if (macnum > 0) { 88826049Sminshall printf("Macros:\n"); 88926049Sminshall for (i=0; i<macnum; i++) { 89026049Sminshall printf("\t%s\n",macros[i].mac_name); 89126049Sminshall } 89226049Sminshall } 89326049Sminshall code = 0; 89410294Ssam } 89510294Ssam 89610294Ssam /* 89710294Ssam * Set beep on cmd completed mode. 89810294Ssam */ 89910294Ssam /*VARARGS*/ 90010294Ssam setbell() 90110294Ssam { 90210294Ssam 90310294Ssam bell = !bell; 90410294Ssam printf("Bell mode %s.\n", onoff(bell)); 90526049Sminshall code = bell; 90610294Ssam } 90710294Ssam 90810294Ssam /* 90910294Ssam * Turn on packet tracing. 91010294Ssam */ 91110294Ssam /*VARARGS*/ 91210294Ssam settrace() 91310294Ssam { 91410294Ssam 91510294Ssam trace = !trace; 91610294Ssam printf("Packet tracing %s.\n", onoff(trace)); 91726049Sminshall code = trace; 91810294Ssam } 91910294Ssam 92010294Ssam /* 92111650Ssam * Toggle hash mark printing during transfers. 92211650Ssam */ 92311650Ssam /*VARARGS*/ 92411650Ssam sethash() 92511650Ssam { 92611650Ssam 92711650Ssam hash = !hash; 92811650Ssam printf("Hash mark printing %s", onoff(hash)); 92926049Sminshall code = hash; 93011650Ssam if (hash) 93137224Skarels printf(" (%d bytes/hash mark)", 1024); 93211650Ssam printf(".\n"); 93311650Ssam } 93411650Ssam 93511650Ssam /* 93610294Ssam * Turn on printing of server echo's. 93710294Ssam */ 93810294Ssam /*VARARGS*/ 93910294Ssam setverbose() 94010294Ssam { 94110294Ssam 94210294Ssam verbose = !verbose; 94310294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 94426049Sminshall code = verbose; 94510294Ssam } 94610294Ssam 94710294Ssam /* 94811650Ssam * Toggle PORT cmd use before each data connection. 94911650Ssam */ 95011650Ssam /*VARARGS*/ 95111650Ssam setport() 95211650Ssam { 95311650Ssam 95411650Ssam sendport = !sendport; 95511650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 95626049Sminshall code = sendport; 95711650Ssam } 95811650Ssam 95911650Ssam /* 96010294Ssam * Turn on interactive prompting 96110294Ssam * during mget, mput, and mdelete. 96210294Ssam */ 96310294Ssam /*VARARGS*/ 96410294Ssam setprompt() 96510294Ssam { 96610294Ssam 96710294Ssam interactive = !interactive; 96810294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 96926049Sminshall code = interactive; 97010294Ssam } 97110294Ssam 97210294Ssam /* 97311353Ssam * Toggle metacharacter interpretation 97411353Ssam * on local file names. 97511353Ssam */ 97611353Ssam /*VARARGS*/ 97711353Ssam setglob() 97811353Ssam { 97911353Ssam 98011353Ssam doglob = !doglob; 98111353Ssam printf("Globbing %s.\n", onoff(doglob)); 98226049Sminshall code = doglob; 98311353Ssam } 98411353Ssam 98511353Ssam /* 98610294Ssam * Set debugging mode on/off and/or 98710294Ssam * set level of debugging. 98810294Ssam */ 98911756Ssam /*VARARGS*/ 99010294Ssam setdebug(argc, argv) 99110294Ssam char *argv[]; 99210294Ssam { 99310294Ssam int val; 99410294Ssam 99510294Ssam if (argc > 1) { 99610294Ssam val = atoi(argv[1]); 99710294Ssam if (val < 0) { 99810294Ssam printf("%s: bad debugging value.\n", argv[1]); 99926049Sminshall code = -1; 100010294Ssam return; 100110294Ssam } 100210294Ssam } else 100310294Ssam val = !debug; 100410294Ssam debug = val; 100510294Ssam if (debug) 100610294Ssam options |= SO_DEBUG; 100710294Ssam else 100810294Ssam options &= ~SO_DEBUG; 100910294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 101026049Sminshall code = debug > 0; 101110294Ssam } 101210294Ssam 101310294Ssam /* 101410294Ssam * Set current working directory 101510294Ssam * on remote machine. 101610294Ssam */ 101710294Ssam cd(argc, argv) 101810294Ssam char *argv[]; 101910294Ssam { 102010294Ssam 102110294Ssam if (argc < 2) { 102226497Sminshall (void) strcat(line, " "); 102310294Ssam printf("(remote-directory) "); 102426497Sminshall (void) gets(&line[strlen(line)]); 102510294Ssam makeargv(); 102610294Ssam argc = margc; 102710294Ssam argv = margv; 102810294Ssam } 102910294Ssam if (argc < 2) { 103026049Sminshall printf("usage:%s remote-directory\n", argv[0]); 103126049Sminshall code = -1; 103210294Ssam return; 103310294Ssam } 103437224Skarels if (command("CWD %s", argv[1]) == ERROR && code == 500) { 103537224Skarels if (verbose) 103637224Skarels printf("CWD command not recognized, trying XCWD\n"); 103737224Skarels (void) command("XCWD %s", argv[1]); 103837224Skarels } 103910294Ssam } 104010294Ssam 104110294Ssam /* 104210294Ssam * Set current working directory 104310294Ssam * on local machine. 104410294Ssam */ 104510294Ssam lcd(argc, argv) 104610294Ssam char *argv[]; 104710294Ssam { 104811353Ssam char buf[MAXPATHLEN]; 104938132Srick extern char *getwd(); 105010294Ssam 105111353Ssam if (argc < 2) 105211353Ssam argc++, argv[1] = home; 105310294Ssam if (argc != 2) { 105426049Sminshall printf("usage:%s local-directory\n", argv[0]); 105526049Sminshall code = -1; 105610294Ssam return; 105710294Ssam } 105826049Sminshall if (!globulize(&argv[1])) { 105926049Sminshall code = -1; 106011353Ssam return; 106126049Sminshall } 106211353Ssam if (chdir(argv[1]) < 0) { 106338202Srick fprintf(stderr, "local: %s: %s\n", argv[1], strerror(errno)); 106426049Sminshall code = -1; 106511353Ssam return; 106611353Ssam } 106711353Ssam printf("Local directory now %s\n", getwd(buf)); 106826049Sminshall code = 0; 106910294Ssam } 107010294Ssam 107110294Ssam /* 107210294Ssam * Delete a single file. 107310294Ssam */ 107410294Ssam delete(argc, argv) 107510294Ssam char *argv[]; 107610294Ssam { 107710294Ssam 107810294Ssam if (argc < 2) { 107926497Sminshall (void) strcat(line, " "); 108010294Ssam printf("(remote-file) "); 108126497Sminshall (void) gets(&line[strlen(line)]); 108210294Ssam makeargv(); 108310294Ssam argc = margc; 108410294Ssam argv = margv; 108510294Ssam } 108610294Ssam if (argc < 2) { 108726049Sminshall printf("usage:%s remote-file\n", argv[0]); 108826049Sminshall code = -1; 108910294Ssam return; 109010294Ssam } 109110294Ssam (void) command("DELE %s", argv[1]); 109210294Ssam } 109310294Ssam 109410294Ssam /* 109511650Ssam * Delete multiple files. 109611650Ssam */ 109711650Ssam mdelete(argc, argv) 1098*39252Sbostic int argc; 1099*39252Sbostic char **argv; 110011650Ssam { 1101*39252Sbostic extern jmp_buf jabort; 1102*39252Sbostic sig_t oldintr; 1103*39252Sbostic int ointer; 110411650Ssam char *cp; 1105*39252Sbostic void mabort(); 110611650Ssam 110711650Ssam if (argc < 2) { 110826497Sminshall (void) strcat(line, " "); 110911650Ssam printf("(remote-files) "); 111026497Sminshall (void) gets(&line[strlen(line)]); 111111650Ssam makeargv(); 111211650Ssam argc = margc; 111311650Ssam argv = margv; 111411650Ssam } 111511650Ssam if (argc < 2) { 111626049Sminshall printf("usage:%s remote-files\n", argv[0]); 111726049Sminshall code = -1; 111811650Ssam return; 111911650Ssam } 112026049Sminshall mname = argv[0]; 112126049Sminshall mflag = 1; 112226049Sminshall oldintr = signal(SIGINT, mabort); 112326049Sminshall (void) setjmp(jabort); 112426497Sminshall while ((cp = remglob(argv,0)) != NULL) { 112526049Sminshall if (*cp == '\0') { 112626049Sminshall mflag = 0; 112726049Sminshall continue; 112826049Sminshall } 112926049Sminshall if (mflag && confirm(argv[0], cp)) { 113011650Ssam (void) command("DELE %s", cp); 113126049Sminshall if (!mflag && fromatty) { 113226049Sminshall ointer = interactive; 113326049Sminshall interactive = 1; 113426049Sminshall if (confirm("Continue with", "mdelete")) { 113526049Sminshall mflag++; 113626049Sminshall } 113726049Sminshall interactive = ointer; 113826049Sminshall } 113926049Sminshall } 114026049Sminshall } 114126049Sminshall (void) signal(SIGINT, oldintr); 114226049Sminshall mflag = 0; 114311650Ssam } 114411756Ssam 114511650Ssam /* 114610294Ssam * Rename a remote file. 114710294Ssam */ 114810294Ssam renamefile(argc, argv) 114910294Ssam char *argv[]; 115010294Ssam { 115110294Ssam 115210294Ssam if (argc < 2) { 115326497Sminshall (void) strcat(line, " "); 115410294Ssam printf("(from-name) "); 115526497Sminshall (void) gets(&line[strlen(line)]); 115610294Ssam makeargv(); 115710294Ssam argc = margc; 115810294Ssam argv = margv; 115910294Ssam } 116010294Ssam if (argc < 2) { 116110294Ssam usage: 116210294Ssam printf("%s from-name to-name\n", argv[0]); 116326049Sminshall code = -1; 116410294Ssam return; 116510294Ssam } 116610294Ssam if (argc < 3) { 116726497Sminshall (void) strcat(line, " "); 116810294Ssam printf("(to-name) "); 116926497Sminshall (void) gets(&line[strlen(line)]); 117010294Ssam makeargv(); 117110294Ssam argc = margc; 117210294Ssam argv = margv; 117310294Ssam } 117410294Ssam if (argc < 3) 117510294Ssam goto usage; 117610294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 117710294Ssam (void) command("RNTO %s", argv[2]); 117810294Ssam } 117910294Ssam 118010294Ssam /* 118110294Ssam * Get a directory listing 118210294Ssam * of remote files. 118310294Ssam */ 118410294Ssam ls(argc, argv) 118510294Ssam char *argv[]; 118610294Ssam { 118711756Ssam char *cmd; 118810294Ssam 118910294Ssam if (argc < 2) 119010294Ssam argc++, argv[1] = NULL; 119110294Ssam if (argc < 3) 119210294Ssam argc++, argv[2] = "-"; 119311756Ssam if (argc > 3) { 119411756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 119526049Sminshall code = -1; 119611756Ssam return; 119711756Ssam } 119836935Skarels cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 119926049Sminshall if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 120026049Sminshall code = -1; 120111353Ssam return; 120226049Sminshall } 120332344Scsvsj if (strcmp(argv[2], "-") && *argv[2] != '|') 120432344Scsvsj if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { 120532344Scsvsj code = -1; 120632344Scsvsj return; 120732344Scsvsj } 120837225Skarels recvrequest(cmd, argv[2], argv[1], "w", 0); 120910294Ssam } 121010294Ssam 121110294Ssam /* 121211756Ssam * Get a directory listing 121311756Ssam * of multiple remote files. 121411756Ssam */ 121511756Ssam mls(argc, argv) 1216*39252Sbostic int argc; 1217*39252Sbostic char **argv; 121811756Ssam { 1219*39252Sbostic extern jmp_buf jabort; 1220*39252Sbostic sig_t oldintr; 1221*39252Sbostic int ointer, i; 122226049Sminshall char *cmd, mode[1], *dest; 1223*39252Sbostic void mabort(); 122411756Ssam 122513212Ssam if (argc < 2) { 122626497Sminshall (void) strcat(line, " "); 122713212Ssam printf("(remote-files) "); 122826497Sminshall (void) gets(&line[strlen(line)]); 122913212Ssam makeargv(); 123013212Ssam argc = margc; 123113212Ssam argv = margv; 123213212Ssam } 123313212Ssam if (argc < 3) { 123426497Sminshall (void) strcat(line, " "); 123513212Ssam printf("(local-file) "); 123626497Sminshall (void) gets(&line[strlen(line)]); 123713212Ssam makeargv(); 123813212Ssam argc = margc; 123913212Ssam argv = margv; 124013212Ssam } 124113212Ssam if (argc < 3) { 124226049Sminshall printf("usage:%s remote-files local-file\n", argv[0]); 124326049Sminshall code = -1; 124413212Ssam return; 124513212Ssam } 124613212Ssam dest = argv[argc - 1]; 124713212Ssam argv[argc - 1] = NULL; 124826049Sminshall if (strcmp(dest, "-") && *dest != '|') 124926049Sminshall if (!globulize(&dest) || !confirm("output to local-file:", dest)) { 125026049Sminshall code = -1; 125113212Ssam return; 125226049Sminshall } 125336940Skarels cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 125426049Sminshall mname = argv[0]; 125526049Sminshall mflag = 1; 125626049Sminshall oldintr = signal(SIGINT, mabort); 125726049Sminshall (void) setjmp(jabort); 125826049Sminshall for (i = 1; mflag && i < argc-1; ++i) { 125926049Sminshall *mode = (i == 1) ? 'w' : 'a'; 126037225Skarels recvrequest(cmd, dest, argv[i], mode, 0); 126126049Sminshall if (!mflag && fromatty) { 126226049Sminshall ointer = interactive; 126326049Sminshall interactive = 1; 126426049Sminshall if (confirm("Continue with", argv[0])) { 126526049Sminshall mflag ++; 126626049Sminshall } 126726049Sminshall interactive = ointer; 126826049Sminshall } 126926049Sminshall } 127026049Sminshall (void) signal(SIGINT, oldintr); 127126049Sminshall mflag = 0; 127211756Ssam } 127311756Ssam 127411756Ssam /* 127510294Ssam * Do a shell escape 127610294Ssam */ 127726497Sminshall /*ARGSUSED*/ 127810294Ssam shell(argc, argv) 1279*39252Sbostic int argc; 1280*39252Sbostic char **argv; 128110294Ssam { 128238132Srick int pid; 1283*39252Sbostic sig_t old1, old2; 128426049Sminshall char shellnam[40], *shell, *namep; 128526497Sminshall union wait status; 128610294Ssam 128711756Ssam old1 = signal (SIGINT, SIG_IGN); 128811756Ssam old2 = signal (SIGQUIT, SIG_IGN); 128911756Ssam if ((pid = fork()) == 0) { 129011756Ssam for (pid = 3; pid < 20; pid++) 129126497Sminshall (void) close(pid); 129226497Sminshall (void) signal(SIGINT, SIG_DFL); 129326497Sminshall (void) signal(SIGQUIT, SIG_DFL); 129425908Smckusick shell = getenv("SHELL"); 129525908Smckusick if (shell == NULL) 129637458Skarels shell = _PATH_BSHELL; 129725908Smckusick namep = rindex(shell,'/'); 129825908Smckusick if (namep == NULL) 129925908Smckusick namep = shell; 130026497Sminshall (void) strcpy(shellnam,"-"); 130126497Sminshall (void) strcat(shellnam, ++namep); 130226049Sminshall if (strcmp(namep, "sh") != 0) 130326049Sminshall shellnam[0] = '+'; 130426049Sminshall if (debug) { 130526049Sminshall printf ("%s\n", shell); 130626497Sminshall (void) fflush (stdout); 130711756Ssam } 130826049Sminshall if (argc > 1) { 130926049Sminshall execl(shell,shellnam,"-c",altarg,(char *)0); 131026049Sminshall } 131126049Sminshall else { 131226049Sminshall execl(shell,shellnam,(char *)0); 131326049Sminshall } 131425908Smckusick perror(shell); 131526049Sminshall code = -1; 131611756Ssam exit(1); 131726049Sminshall } 131811756Ssam if (pid > 0) 131911756Ssam while (wait(&status) != pid) 132011756Ssam ; 132126497Sminshall (void) signal(SIGINT, old1); 132226497Sminshall (void) signal(SIGQUIT, old2); 132326049Sminshall if (pid == -1) { 132411756Ssam perror("Try again later"); 132526049Sminshall code = -1; 132626049Sminshall } 132726049Sminshall else { 132826049Sminshall code = 0; 132926049Sminshall } 133011756Ssam return (0); 133110294Ssam } 133210294Ssam 133310294Ssam /* 133410294Ssam * Send new user information (re-login) 133510294Ssam */ 133610294Ssam user(argc, argv) 133710294Ssam int argc; 133810294Ssam char **argv; 133910294Ssam { 134035658Sbostic char acct[80], *getpass(); 134126049Sminshall int n, aflag = 0; 134210294Ssam 134310294Ssam if (argc < 2) { 134426497Sminshall (void) strcat(line, " "); 134510294Ssam printf("(username) "); 134626497Sminshall (void) gets(&line[strlen(line)]); 134710294Ssam makeargv(); 134810294Ssam argc = margc; 134910294Ssam argv = margv; 135010294Ssam } 135110294Ssam if (argc > 4) { 135210294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 135326049Sminshall code = -1; 135411756Ssam return (0); 135510294Ssam } 135610294Ssam n = command("USER %s", argv[1]); 135710294Ssam if (n == CONTINUE) { 135810294Ssam if (argc < 3 ) 135935658Sbostic argv[2] = getpass("Password: "), argc++; 136010294Ssam n = command("PASS %s", argv[2]); 136110294Ssam } 136210294Ssam if (n == CONTINUE) { 136310294Ssam if (argc < 4) { 136410294Ssam printf("Account: "); (void) fflush(stdout); 136510294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 136610294Ssam acct[strlen(acct) - 1] = '\0'; 136710294Ssam argv[3] = acct; argc++; 136810294Ssam } 136926049Sminshall n = command("ACCT %s", argv[3]); 137026049Sminshall aflag++; 137110294Ssam } 137210294Ssam if (n != COMPLETE) { 137326497Sminshall fprintf(stdout, "Login failed.\n"); 137410294Ssam return (0); 137510294Ssam } 137626049Sminshall if (!aflag && argc == 4) { 137726049Sminshall (void) command("ACCT %s", argv[3]); 137826049Sminshall } 137910294Ssam return (1); 138010294Ssam } 138110294Ssam 138210294Ssam /* 138310294Ssam * Print working directory. 138410294Ssam */ 138510294Ssam /*VARARGS*/ 138610294Ssam pwd() 138710294Ssam { 138837224Skarels int oldverbose = verbose; 138911756Ssam 139037224Skarels /* 139137224Skarels * If we aren't verbose, this doesn't do anything! 139237224Skarels */ 139337224Skarels verbose = 1; 139437224Skarels if (command("PWD") == ERROR && code == 500) { 139537224Skarels printf("PWD command not recognized, trying XPWD\n"); 139637224Skarels (void) command("XPWD"); 139737224Skarels } 139837224Skarels verbose = oldverbose; 139910294Ssam } 140010294Ssam 140110294Ssam /* 140210294Ssam * Make a directory. 140310294Ssam */ 140410294Ssam makedir(argc, argv) 140510294Ssam char *argv[]; 140610294Ssam { 140710294Ssam 140810294Ssam if (argc < 2) { 140926497Sminshall (void) strcat(line, " "); 141010294Ssam printf("(directory-name) "); 141126497Sminshall (void) gets(&line[strlen(line)]); 141210294Ssam makeargv(); 141310294Ssam argc = margc; 141410294Ssam argv = margv; 141510294Ssam } 141610294Ssam if (argc < 2) { 141726049Sminshall printf("usage: %s directory-name\n", argv[0]); 141826049Sminshall code = -1; 141910294Ssam return; 142010294Ssam } 142137224Skarels if (command("MKD %s", argv[1]) == ERROR && code == 500) { 142237224Skarels if (verbose) 142337224Skarels printf("MKD command not recognized, trying XMKD\n"); 142437224Skarels (void) command("XMKD %s", argv[1]); 142537224Skarels } 142610294Ssam } 142710294Ssam 142810294Ssam /* 142910294Ssam * Remove a directory. 143010294Ssam */ 143110294Ssam removedir(argc, argv) 143210294Ssam char *argv[]; 143310294Ssam { 143410294Ssam 143510294Ssam if (argc < 2) { 143626497Sminshall (void) strcat(line, " "); 143710294Ssam printf("(directory-name) "); 143826497Sminshall (void) gets(&line[strlen(line)]); 143910294Ssam makeargv(); 144010294Ssam argc = margc; 144110294Ssam argv = margv; 144210294Ssam } 144310294Ssam if (argc < 2) { 144426049Sminshall printf("usage: %s directory-name\n", argv[0]); 144526049Sminshall code = -1; 144610294Ssam return; 144710294Ssam } 144837224Skarels if (command("RMD %s", argv[1]) == ERROR && code == 500) { 144937224Skarels if (verbose) 145037224Skarels printf("RMD command not recognized, trying XRMD\n"); 145137224Skarels (void) command("XRMD %s", argv[1]); 145237224Skarels } 145310294Ssam } 145410294Ssam 145510294Ssam /* 145610294Ssam * Send a line, verbatim, to the remote machine. 145710294Ssam */ 145810294Ssam quote(argc, argv) 145910294Ssam char *argv[]; 146010294Ssam { 146110294Ssam int i; 146210294Ssam char buf[BUFSIZ]; 146310294Ssam 146410294Ssam if (argc < 2) { 146526497Sminshall (void) strcat(line, " "); 146610294Ssam printf("(command line to send) "); 146726497Sminshall (void) gets(&line[strlen(line)]); 146810294Ssam makeargv(); 146910294Ssam argc = margc; 147010294Ssam argv = margv; 147110294Ssam } 147210294Ssam if (argc < 2) { 147310294Ssam printf("usage: %s line-to-send\n", argv[0]); 147426049Sminshall code = -1; 147510294Ssam return; 147610294Ssam } 147726497Sminshall (void) strcpy(buf, argv[1]); 147810294Ssam for (i = 2; i < argc; i++) { 147926497Sminshall (void) strcat(buf, " "); 148026497Sminshall (void) strcat(buf, argv[i]); 148110294Ssam } 148226049Sminshall if (command(buf) == PRELIM) { 148326049Sminshall while (getreply(0) == PRELIM); 148426049Sminshall } 148510294Ssam } 148610294Ssam 148710294Ssam /* 148837224Skarels * Send a SITE command to the remote machine. The line 148937224Skarels * is sent almost verbatim to the remote machine, the 149037224Skarels * first argument is changed to SITE. 149137224Skarels */ 149237224Skarels 149337224Skarels site(argc, argv) 149437224Skarels char *argv[]; 149537224Skarels { 149637224Skarels int i; 149737224Skarels char buf[BUFSIZ]; 149837224Skarels 149937224Skarels if (argc < 2) { 150037224Skarels (void) strcat(line, " "); 150137224Skarels printf("(arguments to SITE command) "); 150237224Skarels (void) gets(&line[strlen(line)]); 150337224Skarels makeargv(); 150437224Skarels argc = margc; 150537224Skarels argv = margv; 150637224Skarels } 150737224Skarels if (argc < 2) { 150837224Skarels printf("usage: %s line-to-send\n", argv[0]); 150937224Skarels code = -1; 151037224Skarels return; 151137224Skarels } 151237224Skarels (void) strcpy(buf, "SITE "); 151337224Skarels (void) strcat(buf, argv[1]); 151437224Skarels for (i = 2; i < argc; i++) { 151537224Skarels (void) strcat(buf, " "); 151637224Skarels (void) strcat(buf, argv[i]); 151737224Skarels } 151837224Skarels if (command(buf) == PRELIM) { 151937224Skarels while (getreply(0) == PRELIM); 152037224Skarels } 152137224Skarels } 152237224Skarels 152337224Skarels do_chmod(argc, argv) 152437224Skarels char *argv[]; 152537224Skarels { 152637224Skarels if (argc == 2) { 152737224Skarels printf("usage: %s mode file-name\n", argv[0]); 152837224Skarels code = -1; 152937224Skarels return; 153037224Skarels } 153137224Skarels if (argc < 3) { 153237224Skarels (void) strcat(line, " "); 153337224Skarels printf("(mode and file-name) "); 153437224Skarels (void) gets(&line[strlen(line)]); 153537224Skarels makeargv(); 153637224Skarels argc = margc; 153737224Skarels argv = margv; 153837224Skarels } 153937224Skarels if (argc != 3) { 154037224Skarels printf("usage: %s mode file-name\n", argv[0]); 154137224Skarels code = -1; 154237224Skarels return; 154337224Skarels } 154437224Skarels (void)command("SITE CHMOD %s %s", argv[1], argv[2]); 154537224Skarels } 154637224Skarels 154737224Skarels do_umask(argc, argv) 154837224Skarels char *argv[]; 154937224Skarels { 155037224Skarels int oldverbose = verbose; 155137224Skarels 155237224Skarels verbose = 1; 155337224Skarels (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 155437224Skarels verbose = oldverbose; 155537224Skarels } 155637224Skarels 155737224Skarels idle(argc, argv) 155837224Skarels char *argv[]; 155937224Skarels { 156037224Skarels int oldverbose = verbose; 156137224Skarels 156237224Skarels verbose = 1; 156337224Skarels (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 156437224Skarels verbose = oldverbose; 156537224Skarels } 156637224Skarels 156737224Skarels /* 156810294Ssam * Ask the other side for help. 156910294Ssam */ 157010294Ssam rmthelp(argc, argv) 157110294Ssam char *argv[]; 157210294Ssam { 157310294Ssam int oldverbose = verbose; 157410294Ssam 157510294Ssam verbose = 1; 157610294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 157710294Ssam verbose = oldverbose; 157810294Ssam } 157910294Ssam 158010294Ssam /* 158110294Ssam * Terminate session and exit. 158210294Ssam */ 158310294Ssam /*VARARGS*/ 158410294Ssam quit() 158510294Ssam { 158610294Ssam 158718286Sralph if (connected) 158818286Sralph disconnect(); 158926049Sminshall pswitch(1); 159026049Sminshall if (connected) { 159126049Sminshall disconnect(); 159226049Sminshall } 159310294Ssam exit(0); 159410294Ssam } 159510294Ssam 159610294Ssam /* 159710294Ssam * Terminate session, but don't exit. 159810294Ssam */ 159910294Ssam disconnect() 160010294Ssam { 160110294Ssam extern FILE *cout; 160210294Ssam extern int data; 160310294Ssam 160410294Ssam if (!connected) 160510294Ssam return; 160610294Ssam (void) command("QUIT"); 160726049Sminshall if (cout) { 160826049Sminshall (void) fclose(cout); 160926049Sminshall } 161010294Ssam cout = NULL; 161110294Ssam connected = 0; 161210294Ssam data = -1; 161326049Sminshall if (!proxy) { 161426049Sminshall macnum = 0; 161526049Sminshall } 161610294Ssam } 161711353Ssam 161811650Ssam confirm(cmd, file) 161911353Ssam char *cmd, *file; 162011353Ssam { 162111353Ssam char line[BUFSIZ]; 162211353Ssam 162311353Ssam if (!interactive) 162411650Ssam return (1); 162511353Ssam printf("%s %s? ", cmd, file); 162626497Sminshall (void) fflush(stdout); 162726497Sminshall (void) gets(line); 162811650Ssam return (*line != 'n' && *line != 'N'); 162911353Ssam } 163011353Ssam 163111353Ssam fatal(msg) 163211353Ssam char *msg; 163311353Ssam { 163411353Ssam 163526497Sminshall fprintf(stderr, "ftp: %s\n", msg); 163611353Ssam exit(1); 163711353Ssam } 163811353Ssam 163911353Ssam /* 164011353Ssam * Glob a local file name specification with 164111353Ssam * the expectation of a single return value. 164211353Ssam * Can't control multiple values being expanded 164311353Ssam * from the expression, we return only the first. 164411353Ssam */ 164511353Ssam globulize(cpp) 164611353Ssam char **cpp; 164711353Ssam { 164811353Ssam char **globbed; 164911353Ssam 165011353Ssam if (!doglob) 165111353Ssam return (1); 165211353Ssam globbed = glob(*cpp); 165311353Ssam if (globerr != NULL) { 165411353Ssam printf("%s: %s\n", *cpp, globerr); 165536421Sbostic if (globbed) { 165611353Ssam blkfree(globbed); 165738132Srick free((char *)globbed); 165836421Sbostic } 165911353Ssam return (0); 166011353Ssam } 166111353Ssam if (globbed) { 166211353Ssam *cpp = *globbed++; 166311353Ssam /* don't waste too much memory */ 166436421Sbostic if (*globbed) { 166511353Ssam blkfree(globbed); 166638132Srick free((char *)globbed); 166736421Sbostic } 166811353Ssam } 166911353Ssam return (1); 167011353Ssam } 167126049Sminshall 167226049Sminshall account(argc,argv) 167326049Sminshall int argc; 167426049Sminshall char **argv; 167526049Sminshall { 167635658Sbostic char acct[50], *getpass(), *ap; 167726049Sminshall 167826049Sminshall if (argc > 1) { 167926049Sminshall ++argv; 168026049Sminshall --argc; 168126049Sminshall (void) strncpy(acct,*argv,49); 168236268Sbostic acct[49] = '\0'; 168326049Sminshall while (argc > 1) { 168426049Sminshall --argc; 168526049Sminshall ++argv; 168626049Sminshall (void) strncat(acct,*argv, 49-strlen(acct)); 168726049Sminshall } 168826049Sminshall ap = acct; 168926049Sminshall } 169026049Sminshall else { 169135658Sbostic ap = getpass("Account:"); 169226049Sminshall } 169326049Sminshall (void) command("ACCT %s", ap); 169426049Sminshall } 169526049Sminshall 169626049Sminshall jmp_buf abortprox; 169726049Sminshall 1698*39252Sbostic void 169926049Sminshall proxabort() 170026049Sminshall { 170126049Sminshall extern int proxy; 170226049Sminshall 170326049Sminshall if (!proxy) { 170426049Sminshall pswitch(1); 170526049Sminshall } 170626049Sminshall if (connected) { 170726049Sminshall proxflag = 1; 170826049Sminshall } 170926049Sminshall else { 171026049Sminshall proxflag = 0; 171126049Sminshall } 171226049Sminshall pswitch(0); 171326049Sminshall longjmp(abortprox,1); 171426049Sminshall } 171526049Sminshall 171626049Sminshall doproxy(argc,argv) 171726049Sminshall int argc; 171826049Sminshall char *argv[]; 171926049Sminshall { 1720*39252Sbostic extern struct cmd cmdtab[]; 1721*39252Sbostic extern jmp_buf abortprox; 172226049Sminshall register struct cmd *c; 172326049Sminshall struct cmd *getcmd(); 1724*39252Sbostic sig_t oldintr; 1725*39252Sbostic void proxabort(); 172626049Sminshall 172726049Sminshall if (argc < 2) { 172826497Sminshall (void) strcat(line, " "); 172926049Sminshall printf("(command) "); 173026497Sminshall (void) gets(&line[strlen(line)]); 173126049Sminshall makeargv(); 173226049Sminshall argc = margc; 173326049Sminshall argv = margv; 173426049Sminshall } 173526049Sminshall if (argc < 2) { 173626049Sminshall printf("usage:%s command\n", argv[0]); 173726049Sminshall code = -1; 173826049Sminshall return; 173926049Sminshall } 174026049Sminshall c = getcmd(argv[1]); 174126049Sminshall if (c == (struct cmd *) -1) { 174226049Sminshall printf("?Ambiguous command\n"); 174326497Sminshall (void) fflush(stdout); 174426049Sminshall code = -1; 174526049Sminshall return; 174626049Sminshall } 174726049Sminshall if (c == 0) { 174826049Sminshall printf("?Invalid command\n"); 174926497Sminshall (void) fflush(stdout); 175026049Sminshall code = -1; 175126049Sminshall return; 175226049Sminshall } 175326049Sminshall if (!c->c_proxy) { 175426049Sminshall printf("?Invalid proxy command\n"); 175526497Sminshall (void) fflush(stdout); 175626049Sminshall code = -1; 175726049Sminshall return; 175826049Sminshall } 175926049Sminshall if (setjmp(abortprox)) { 176026049Sminshall code = -1; 176126049Sminshall return; 176226049Sminshall } 176326049Sminshall oldintr = signal(SIGINT, proxabort); 176426049Sminshall pswitch(1); 176526049Sminshall if (c->c_conn && !connected) { 176626049Sminshall printf("Not connected\n"); 176726497Sminshall (void) fflush(stdout); 176826049Sminshall pswitch(0); 176926049Sminshall (void) signal(SIGINT, oldintr); 177026049Sminshall code = -1; 177126049Sminshall return; 177226049Sminshall } 177326049Sminshall (*c->c_handler)(argc-1, argv+1); 177426049Sminshall if (connected) { 177526049Sminshall proxflag = 1; 177626049Sminshall } 177726049Sminshall else { 177826049Sminshall proxflag = 0; 177926049Sminshall } 178026049Sminshall pswitch(0); 178126049Sminshall (void) signal(SIGINT, oldintr); 178226049Sminshall } 178326049Sminshall 178426049Sminshall setcase() 178526049Sminshall { 178626049Sminshall mcase = !mcase; 178726049Sminshall printf("Case mapping %s.\n", onoff(mcase)); 178826049Sminshall code = mcase; 178926049Sminshall } 179026049Sminshall 179126049Sminshall setcr() 179226049Sminshall { 179326049Sminshall crflag = !crflag; 179426049Sminshall printf("Carriage Return stripping %s.\n", onoff(crflag)); 179526049Sminshall code = crflag; 179626049Sminshall } 179726049Sminshall 179826049Sminshall setntrans(argc,argv) 179926049Sminshall int argc; 180026049Sminshall char *argv[]; 180126049Sminshall { 180226049Sminshall if (argc == 1) { 180326049Sminshall ntflag = 0; 180426049Sminshall printf("Ntrans off.\n"); 180526049Sminshall code = ntflag; 180626049Sminshall return; 180726049Sminshall } 180826049Sminshall ntflag++; 180926049Sminshall code = ntflag; 181026049Sminshall (void) strncpy(ntin, argv[1], 16); 181126049Sminshall ntin[16] = '\0'; 181226049Sminshall if (argc == 2) { 181326049Sminshall ntout[0] = '\0'; 181426049Sminshall return; 181526049Sminshall } 181626049Sminshall (void) strncpy(ntout, argv[2], 16); 181726049Sminshall ntout[16] = '\0'; 181826049Sminshall } 181926049Sminshall 182026049Sminshall char * 182126049Sminshall dotrans(name) 182226049Sminshall char *name; 182326049Sminshall { 182426049Sminshall static char new[MAXPATHLEN]; 182526049Sminshall char *cp1, *cp2 = new; 182626049Sminshall register int i, ostop, found; 182726049Sminshall 182826049Sminshall for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++); 182926049Sminshall for (cp1 = name; *cp1; cp1++) { 183026049Sminshall found = 0; 183126049Sminshall for (i = 0; *(ntin + i) && i < 16; i++) { 183226049Sminshall if (*cp1 == *(ntin + i)) { 183326049Sminshall found++; 183426049Sminshall if (i < ostop) { 183526049Sminshall *cp2++ = *(ntout + i); 183626049Sminshall } 183726049Sminshall break; 183826049Sminshall } 183926049Sminshall } 184026049Sminshall if (!found) { 184126049Sminshall *cp2++ = *cp1; 184226049Sminshall } 184326049Sminshall } 184426049Sminshall *cp2 = '\0'; 184526049Sminshall return(new); 184626049Sminshall } 184726049Sminshall 184826049Sminshall setnmap(argc, argv) 184926049Sminshall int argc; 185026049Sminshall char *argv[]; 185126049Sminshall { 185226049Sminshall char *cp; 185326049Sminshall 185426049Sminshall if (argc == 1) { 185526049Sminshall mapflag = 0; 185626049Sminshall printf("Nmap off.\n"); 185726049Sminshall code = mapflag; 185826049Sminshall return; 185926049Sminshall } 186026049Sminshall if (argc < 3) { 186126497Sminshall (void) strcat(line, " "); 186226049Sminshall printf("(mapout) "); 186326497Sminshall (void) gets(&line[strlen(line)]); 186426049Sminshall makeargv(); 186526049Sminshall argc = margc; 186626049Sminshall argv = margv; 186726049Sminshall } 186826049Sminshall if (argc < 3) { 186926049Sminshall printf("Usage: %s [mapin mapout]\n",argv[0]); 187026049Sminshall code = -1; 187126049Sminshall return; 187226049Sminshall } 187326049Sminshall mapflag = 1; 187426049Sminshall code = 1; 187526049Sminshall cp = index(altarg, ' '); 187626049Sminshall if (proxy) { 187726049Sminshall while(*++cp == ' '); 187826049Sminshall altarg = cp; 187926049Sminshall cp = index(altarg, ' '); 188026049Sminshall } 188126049Sminshall *cp = '\0'; 188226049Sminshall (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 188326049Sminshall while (*++cp == ' '); 188426049Sminshall (void) strncpy(mapout, cp, MAXPATHLEN - 1); 188526049Sminshall } 188626049Sminshall 188726049Sminshall char * 188826049Sminshall domap(name) 188926049Sminshall char *name; 189026049Sminshall { 189126049Sminshall static char new[MAXPATHLEN]; 189226049Sminshall register char *cp1 = name, *cp2 = mapin; 189326049Sminshall char *tp[9], *te[9]; 189436689Scsvsj int i, toks[9], toknum = 0, match = 1; 189526049Sminshall 189626049Sminshall for (i=0; i < 9; ++i) { 189726049Sminshall toks[i] = 0; 189826049Sminshall } 189926049Sminshall while (match && *cp1 && *cp2) { 190026049Sminshall switch (*cp2) { 190126049Sminshall case '\\': 190226049Sminshall if (*++cp2 != *cp1) { 190326049Sminshall match = 0; 190426049Sminshall } 190526049Sminshall break; 190626049Sminshall case '$': 190726049Sminshall if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 190826049Sminshall if (*cp1 != *(++cp2+1)) { 190926049Sminshall toks[toknum = *cp2 - '1']++; 191026049Sminshall tp[toknum] = cp1; 191126049Sminshall while (*++cp1 && *(cp2+1) 191226049Sminshall != *cp1); 191326049Sminshall te[toknum] = cp1; 191426049Sminshall } 191526049Sminshall cp2++; 191626049Sminshall break; 191726049Sminshall } 191836935Skarels /* FALLTHROUGH */ 191926049Sminshall default: 192026049Sminshall if (*cp2 != *cp1) { 192126049Sminshall match = 0; 192226049Sminshall } 192326049Sminshall break; 192426049Sminshall } 192536689Scsvsj if (match && *cp1) { 192626049Sminshall cp1++; 192726049Sminshall } 192836689Scsvsj if (match && *cp2) { 192926049Sminshall cp2++; 193026049Sminshall } 193126049Sminshall } 193236689Scsvsj if (!match && *cp1) /* last token mismatch */ 193336689Scsvsj { 193436689Scsvsj toks[toknum] = 0; 193536689Scsvsj } 193626049Sminshall cp1 = new; 193726049Sminshall *cp1 = '\0'; 193826049Sminshall cp2 = mapout; 193926049Sminshall while (*cp2) { 194026049Sminshall match = 0; 194126049Sminshall switch (*cp2) { 194226049Sminshall case '\\': 194326049Sminshall if (*(cp2 + 1)) { 194426049Sminshall *cp1++ = *++cp2; 194526049Sminshall } 194626049Sminshall break; 194726049Sminshall case '[': 194826049Sminshall LOOP: 194926049Sminshall if (*++cp2 == '$' && isdigit(*(cp2+1))) { 195026049Sminshall if (*++cp2 == '0') { 195126049Sminshall char *cp3 = name; 195226049Sminshall 195326049Sminshall while (*cp3) { 195426049Sminshall *cp1++ = *cp3++; 195526049Sminshall } 195626049Sminshall match = 1; 195726049Sminshall } 195826049Sminshall else if (toks[toknum = *cp2 - '1']) { 195926049Sminshall char *cp3 = tp[toknum]; 196026049Sminshall 196126049Sminshall while (cp3 != te[toknum]) { 196226049Sminshall *cp1++ = *cp3++; 196326049Sminshall } 196426049Sminshall match = 1; 196526049Sminshall } 196626049Sminshall } 196726049Sminshall else { 196826049Sminshall while (*cp2 && *cp2 != ',' && 196926049Sminshall *cp2 != ']') { 197026049Sminshall if (*cp2 == '\\') { 197126049Sminshall cp2++; 197226049Sminshall } 197326049Sminshall else if (*cp2 == '$' && 197426049Sminshall isdigit(*(cp2+1))) { 197526049Sminshall if (*++cp2 == '0') { 197626049Sminshall char *cp3 = name; 197726049Sminshall 197826049Sminshall while (*cp3) { 197926049Sminshall *cp1++ = *cp3++; 198026049Sminshall } 198126049Sminshall } 198226049Sminshall else if (toks[toknum = 198326049Sminshall *cp2 - '1']) { 198426049Sminshall char *cp3=tp[toknum]; 198526049Sminshall 198626049Sminshall while (cp3 != 198726049Sminshall te[toknum]) { 198826049Sminshall *cp1++ = *cp3++; 198926049Sminshall } 199026049Sminshall } 199126049Sminshall } 199226049Sminshall else if (*cp2) { 199326049Sminshall *cp1++ = *cp2++; 199426049Sminshall } 199526049Sminshall } 199626049Sminshall if (!*cp2) { 199726049Sminshall printf("nmap: unbalanced brackets\n"); 199826049Sminshall return(name); 199926049Sminshall } 200026049Sminshall match = 1; 200126049Sminshall cp2--; 200226049Sminshall } 200326049Sminshall if (match) { 200426049Sminshall while (*++cp2 && *cp2 != ']') { 200526049Sminshall if (*cp2 == '\\' && *(cp2 + 1)) { 200626049Sminshall cp2++; 200726049Sminshall } 200826049Sminshall } 200926049Sminshall if (!*cp2) { 201026049Sminshall printf("nmap: unbalanced brackets\n"); 201126049Sminshall return(name); 201226049Sminshall } 201326049Sminshall break; 201426049Sminshall } 201526049Sminshall switch (*++cp2) { 201626049Sminshall case ',': 201726049Sminshall goto LOOP; 201826049Sminshall case ']': 201926049Sminshall break; 202026049Sminshall default: 202126049Sminshall cp2--; 202226049Sminshall goto LOOP; 202326049Sminshall } 202426049Sminshall break; 202526049Sminshall case '$': 202626049Sminshall if (isdigit(*(cp2 + 1))) { 202726049Sminshall if (*++cp2 == '0') { 202826049Sminshall char *cp3 = name; 202926049Sminshall 203026049Sminshall while (*cp3) { 203126049Sminshall *cp1++ = *cp3++; 203226049Sminshall } 203326049Sminshall } 203426049Sminshall else if (toks[toknum = *cp2 - '1']) { 203526049Sminshall char *cp3 = tp[toknum]; 203626049Sminshall 203726049Sminshall while (cp3 != te[toknum]) { 203826049Sminshall *cp1++ = *cp3++; 203926049Sminshall } 204026049Sminshall } 204126049Sminshall break; 204226049Sminshall } 204326049Sminshall /* intentional drop through */ 204426049Sminshall default: 204526049Sminshall *cp1++ = *cp2; 204626049Sminshall break; 204726049Sminshall } 204826049Sminshall cp2++; 204926049Sminshall } 205026049Sminshall *cp1 = '\0'; 205126049Sminshall if (!*new) { 205226049Sminshall return(name); 205326049Sminshall } 205426049Sminshall return(new); 205526049Sminshall } 205626049Sminshall 205726049Sminshall setsunique() 205826049Sminshall { 205926049Sminshall sunique = !sunique; 206026049Sminshall printf("Store unique %s.\n", onoff(sunique)); 206126049Sminshall code = sunique; 206226049Sminshall } 206326049Sminshall 206426049Sminshall setrunique() 206526049Sminshall { 206626049Sminshall runique = !runique; 206726049Sminshall printf("Receive unique %s.\n", onoff(runique)); 206826049Sminshall code = runique; 206926049Sminshall } 207026049Sminshall 207126049Sminshall /* change directory to perent directory */ 207226049Sminshall cdup() 207326049Sminshall { 207437224Skarels if (command("CDUP") == ERROR && code == 500) { 207537224Skarels if (verbose) 207637224Skarels printf("CDUP command not recognized, trying XCUP\n"); 207737224Skarels (void) command("XCUP"); 207837224Skarels } 207926049Sminshall } 208026049Sminshall 208137224Skarels /* restart transfer at specific point */ 208237224Skarels restart(argc, argv) 208337224Skarels int argc; 208437224Skarels char *argv[]; 208537224Skarels { 208637224Skarels extern long atol(); 208737224Skarels if (argc != 2) 208837224Skarels printf("restart: offset not specified\n"); 208937224Skarels else { 209037224Skarels restart_point = atol(argv[1]); 209137224Skarels printf("restarting at %ld. %s\n", restart_point, 209237224Skarels "execute get, put or append to initiate transfer"); 209337224Skarels } 209437224Skarels } 209536935Skarels 209636935Skarels /* show remote system type */ 209736935Skarels syst() 209836935Skarels { 209936935Skarels (void) command("SYST"); 210036935Skarels } 210136935Skarels 210226049Sminshall macdef(argc, argv) 210326049Sminshall int argc; 210426049Sminshall char *argv[]; 210526049Sminshall { 210626049Sminshall char *tmp; 210726049Sminshall int c; 210826049Sminshall 210926049Sminshall if (macnum == 16) { 211026049Sminshall printf("Limit of 16 macros have already been defined\n"); 211126049Sminshall code = -1; 211226049Sminshall return; 211326049Sminshall } 211426049Sminshall if (argc < 2) { 211526497Sminshall (void) strcat(line, " "); 211626049Sminshall printf("(macro name) "); 211726497Sminshall (void) gets(&line[strlen(line)]); 211826049Sminshall makeargv(); 211926049Sminshall argc = margc; 212026049Sminshall argv = margv; 212126049Sminshall } 212226049Sminshall if (argc != 2) { 212326049Sminshall printf("Usage: %s macro_name\n",argv[0]); 212426049Sminshall code = -1; 212526049Sminshall return; 212626049Sminshall } 212726049Sminshall if (interactive) { 212826049Sminshall printf("Enter macro line by line, terminating it with a null line\n"); 212926049Sminshall } 213026497Sminshall (void) strncpy(macros[macnum].mac_name, argv[1], 8); 213126049Sminshall if (macnum == 0) { 213226049Sminshall macros[macnum].mac_start = macbuf; 213326049Sminshall } 213426049Sminshall else { 213526049Sminshall macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 213626049Sminshall } 213726049Sminshall tmp = macros[macnum].mac_start; 213826049Sminshall while (tmp != macbuf+4096) { 213926049Sminshall if ((c = getchar()) == EOF) { 214026049Sminshall printf("macdef:end of file encountered\n"); 214126049Sminshall code = -1; 214226049Sminshall return; 214326049Sminshall } 214426049Sminshall if ((*tmp = c) == '\n') { 214526049Sminshall if (tmp == macros[macnum].mac_start) { 214626049Sminshall macros[macnum++].mac_end = tmp; 214726049Sminshall code = 0; 214826049Sminshall return; 214926049Sminshall } 215026049Sminshall if (*(tmp-1) == '\0') { 215126049Sminshall macros[macnum++].mac_end = tmp - 1; 215226049Sminshall code = 0; 215326049Sminshall return; 215426049Sminshall } 215526049Sminshall *tmp = '\0'; 215626049Sminshall } 215726049Sminshall tmp++; 215826049Sminshall } 215926049Sminshall while (1) { 216036935Skarels while ((c = getchar()) != '\n' && c != EOF) 216136935Skarels /* LOOP */; 216226049Sminshall if (c == EOF || getchar() == '\n') { 216326049Sminshall printf("Macro not defined - 4k buffer exceeded\n"); 216426049Sminshall code = -1; 216526049Sminshall return; 216626049Sminshall } 216726049Sminshall } 216826049Sminshall } 216936935Skarels 217036935Skarels /* 217136935Skarels * get size of file on remote machine 217236935Skarels */ 217336935Skarels sizecmd(argc, argv) 217436935Skarels char *argv[]; 217536935Skarels { 217636935Skarels 217736935Skarels if (argc < 2) { 217836935Skarels (void) strcat(line, " "); 217936935Skarels printf("(filename) "); 218036935Skarels (void) gets(&line[strlen(line)]); 218136935Skarels makeargv(); 218236935Skarels argc = margc; 218336935Skarels argv = margv; 218436935Skarels } 218536935Skarels if (argc < 2) { 218636935Skarels printf("usage:%s filename\n", argv[0]); 218736935Skarels code = -1; 218836935Skarels return; 218936935Skarels } 219036935Skarels (void) command("SIZE %s", argv[1]); 219136935Skarels } 219236935Skarels 219336935Skarels /* 219436935Skarels * get last modification time of file on remote machine 219536935Skarels */ 219636935Skarels modtime(argc, argv) 219736935Skarels char *argv[]; 219836935Skarels { 219936935Skarels int overbose; 220036935Skarels 220136935Skarels if (argc < 2) { 220236935Skarels (void) strcat(line, " "); 220336935Skarels printf("(filename) "); 220436935Skarels (void) gets(&line[strlen(line)]); 220536935Skarels makeargv(); 220636935Skarels argc = margc; 220736935Skarels argv = margv; 220836935Skarels } 220936935Skarels if (argc < 2) { 221036935Skarels printf("usage:%s filename\n", argv[0]); 221136935Skarels code = -1; 221236935Skarels return; 221336935Skarels } 221436940Skarels overbose = verbose; 221536940Skarels if (debug == 0) 221636940Skarels verbose = -1; 221736935Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 221836935Skarels int yy, mo, day, hour, min, sec; 221936935Skarels sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 222036935Skarels &day, &hour, &min, &sec); 222136935Skarels /* might want to print this in local time */ 222236935Skarels printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 222336935Skarels mo, day, yy, hour, min, sec); 222436935Skarels } else 222538132Srick printf("%s\n", reply_string); 222636935Skarels verbose = overbose; 222736935Skarels } 222836935Skarels 222936935Skarels /* 223037224Skarels * show status on reomte machine 223136935Skarels */ 223236935Skarels rmtstatus(argc, argv) 223336935Skarels char *argv[]; 223436935Skarels { 223536935Skarels (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 223636935Skarels } 223737224Skarels 223837224Skarels /* 223937224Skarels * get file if modtime is more recent than current file 224037224Skarels */ 224137224Skarels newer(argc, argv) 224237224Skarels char *argv[]; 224337224Skarels { 224437224Skarels if (getit(argc, argv, -1, "w")) 224537224Skarels printf("Local file \"%s\" is newer than remote file \"%s\"\n", 224637224Skarels argv[1], argv[2]); 224737224Skarels } 2248