121737Sdist /* 236942Skarels * Copyright (c) 1985, 1989 Regents of the University of California. 333737Sbostic * All rights reserved. 433737Sbostic * 5*42665Sbostic * %sccs.include.redist.c% 621737Sdist */ 721737Sdist 810294Ssam #ifndef lint 9*42665Sbostic static char sccsid[] = "@(#)cmds.c 5.23 (Berkeley) 06/01/90"; 1033737Sbostic #endif /* not lint */ 1110294Ssam 1210294Ssam /* 1310294Ssam * FTP User Program -- Command Routines. 1410294Ssam */ 1536940Skarels #include <sys/param.h> 1636940Skarels #include <sys/wait.h> 1736940Skarels #include <sys/stat.h> 1810294Ssam #include <sys/socket.h> 1910294Ssam 2012396Ssam #include <arpa/ftp.h> 2112396Ssam 2210294Ssam #include <signal.h> 2310294Ssam #include <stdio.h> 2410294Ssam #include <errno.h> 2510294Ssam #include <netdb.h> 2626049Sminshall #include <ctype.h> 2736935Skarels #include <time.h> 2838132Srick #include <netinet/in.h> 2910294Ssam 3036940Skarels #include "ftp_var.h" 3137458Skarels #include "pathnames.h" 3210294Ssam 3311353Ssam extern char *globerr; 3411353Ssam extern char **glob(); 3511756Ssam extern char *home; 3611756Ssam extern char *remglob(); 3711756Ssam extern char *getenv(); 3811756Ssam extern char *index(); 3911756Ssam extern char *rindex(); 4038202Srick extern char *strerror(); 4138202Srick extern int errno; 4237224Skarels extern off_t restart_point; 4336935Skarels extern char reply_string[]; 4436935Skarels 4526049Sminshall char *mname; 4626049Sminshall jmp_buf jabort; 4726049Sminshall char *dotrans(), *domap(); 4810294Ssam 4910294Ssam /* 5010294Ssam * Connect to peer server and 5110294Ssam * auto-login, if possible. 5210294Ssam */ 5310294Ssam setpeer(argc, argv) 5410294Ssam int argc; 5510294Ssam char *argv[]; 5610294Ssam { 5725903Skarels char *host, *hookup(); 5838132Srick short port; 5910294Ssam 6010294Ssam if (connected) { 6126049Sminshall printf("Already connected to %s, use close first.\n", 6210294Ssam hostname); 6326049Sminshall code = -1; 6410294Ssam return; 6510294Ssam } 6610294Ssam if (argc < 2) { 6726497Sminshall (void) strcat(line, " "); 6810294Ssam printf("(to) "); 6926497Sminshall (void) gets(&line[strlen(line)]); 7010294Ssam makeargv(); 7110294Ssam argc = margc; 7210294Ssam argv = margv; 7310294Ssam } 7410294Ssam if (argc > 3) { 7510294Ssam printf("usage: %s host-name [port]\n", argv[0]); 7626049Sminshall code = -1; 7710294Ssam return; 7810294Ssam } 7910294Ssam port = sp->s_port; 8010294Ssam if (argc > 2) { 8111218Ssam port = atoi(argv[2]); 8210294Ssam if (port <= 0) { 8311218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 8411218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 8526049Sminshall code = -1; 8610294Ssam return; 8710294Ssam } 8810294Ssam port = htons(port); 8910294Ssam } 9010294Ssam host = hookup(argv[1], port); 9110294Ssam if (host) { 9237228Skarels int overbose; 9337228Skarels 9410294Ssam connected = 1; 9538032Skarels /* 9638032Skarels * Set up defaults for FTP. 9738032Skarels */ 9838032Skarels (void) strcpy(typename, "ascii"), type = TYPE_A; 9938032Skarels curtype = TYPE_A; 10038032Skarels (void) strcpy(formname, "non-print"), form = FORM_N; 10138032Skarels (void) strcpy(modename, "stream"), mode = MODE_S; 10238032Skarels (void) strcpy(structname, "file"), stru = STRU_F; 10338032Skarels (void) strcpy(bytename, "8"), bytesize = 8; 10437228Skarels if (autologin) 10537228Skarels (void) login(argv[1]); 10636940Skarels 10736935Skarels #if defined(unix) && NBBY == 8 10836935Skarels /* 10936935Skarels * this ifdef is to keep someone form "porting" this to an incompatible 11036935Skarels * system and not checking this out. This way they have to think about it. 11136935Skarels */ 11237228Skarels overbose = verbose; 11337228Skarels if (debug == 0) 11437228Skarels verbose = -1; 11537228Skarels if (command("SYST") == COMPLETE && overbose) { 11637228Skarels register char *cp, c; 11737228Skarels cp = index(reply_string+4, ' '); 11837228Skarels if (cp == NULL) 11937228Skarels cp = index(reply_string+4, '\r'); 12037228Skarels if (cp) { 12137228Skarels if (cp[-1] == '.') 12237228Skarels cp--; 12337228Skarels c = *cp; 12437228Skarels *cp = '\0'; 12537228Skarels } 12636935Skarels 12737228Skarels printf("Remote system type is %s.\n", 12837228Skarels reply_string+4); 12937228Skarels if (cp) 13037228Skarels *cp = c; 13137228Skarels } 13237228Skarels if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { 13338032Skarels if (proxy) 13438032Skarels unix_proxy = 1; 13538032Skarels else 13638032Skarels unix_server = 1; 13738032Skarels /* 13838032Skarels * Set type to 0 (not specified by user), 13938032Skarels * meaning binary by default, but don't bother 14038032Skarels * telling server. We can use binary 14138032Skarels * for text files unless changed by the user. 14238032Skarels */ 14338032Skarels type = 0; 14438032Skarels (void) strcpy(typename, "binary"); 14537228Skarels if (overbose) 14637228Skarels printf("Using %s mode to transfer files.\n", 14737228Skarels typename); 14838032Skarels } else { 14938032Skarels if (proxy) 15038032Skarels unix_proxy = 0; 15138032Skarels else 15238032Skarels unix_server = 0; 15338032Skarels if (overbose && 15438032Skarels !strncmp(reply_string, "215 TOPS20", 10)) 15538032Skarels printf( 15636940Skarels "Remember to set tenex mode when transfering binary files from this machine.\n"); 15737228Skarels } 15837228Skarels verbose = overbose; 15936935Skarels #endif /* unix */ 16010294Ssam } 16110294Ssam } 16210294Ssam 16310294Ssam struct types { 16410294Ssam char *t_name; 16510294Ssam char *t_mode; 16610294Ssam int t_type; 16711218Ssam char *t_arg; 16810294Ssam } types[] = { 16911218Ssam { "ascii", "A", TYPE_A, 0 }, 17011218Ssam { "binary", "I", TYPE_I, 0 }, 17111218Ssam { "image", "I", TYPE_I, 0 }, 17211218Ssam { "ebcdic", "E", TYPE_E, 0 }, 17311218Ssam { "tenex", "L", TYPE_L, bytename }, 17410294Ssam 0 17510294Ssam }; 17610294Ssam 17710294Ssam /* 17810294Ssam * Set transfer type. 17910294Ssam */ 18010294Ssam settype(argc, argv) 18110294Ssam char *argv[]; 18210294Ssam { 18310294Ssam register struct types *p; 18411218Ssam int comret; 18510294Ssam 18610294Ssam if (argc > 2) { 18710294Ssam char *sep; 18810294Ssam 18910294Ssam printf("usage: %s [", argv[0]); 19010294Ssam sep = " "; 19110294Ssam for (p = types; p->t_name; p++) { 19210294Ssam printf("%s%s", sep, p->t_name); 19338032Skarels sep = " | "; 19410294Ssam } 19510294Ssam printf(" ]\n"); 19626049Sminshall code = -1; 19710294Ssam return; 19810294Ssam } 19910294Ssam if (argc < 2) { 20010294Ssam printf("Using %s mode to transfer files.\n", typename); 20126049Sminshall code = 0; 20210294Ssam return; 20310294Ssam } 20410294Ssam for (p = types; p->t_name; p++) 20510294Ssam if (strcmp(argv[1], p->t_name) == 0) 20610294Ssam break; 20710294Ssam if (p->t_name == 0) { 20810294Ssam printf("%s: unknown mode\n", argv[1]); 20926049Sminshall code = -1; 21010294Ssam return; 21110294Ssam } 21211218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 21311218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 21411218Ssam else 21511218Ssam comret = command("TYPE %s", p->t_mode); 21611218Ssam if (comret == COMPLETE) { 21726497Sminshall (void) strcpy(typename, p->t_name); 21838032Skarels curtype = type = p->t_type; 21910294Ssam } 22010294Ssam } 22110294Ssam 22210294Ssam /* 22338032Skarels * Internal form of settype; changes current type in use with server 22438032Skarels * without changing our notion of the type for data transfers. 22538032Skarels * Used to change to and from ascii for listings. 22638032Skarels */ 22738032Skarels changetype(newtype, show) 22838032Skarels int newtype, show; 22938032Skarels { 23038032Skarels register struct types *p; 23138032Skarels int comret, oldverbose = verbose; 23238032Skarels 23338032Skarels if (newtype == 0) 23438032Skarels newtype = TYPE_I; 23538032Skarels if (newtype == curtype) 23638032Skarels return; 23738032Skarels if (debug == 0 && show == 0) 23838032Skarels verbose = 0; 23938032Skarels for (p = types; p->t_name; p++) 24038032Skarels if (newtype == p->t_type) 24138032Skarels break; 24238032Skarels if (p->t_name == 0) { 24338032Skarels printf("ftp: internal error: unknown type %d\n", newtype); 24438032Skarels return; 24538032Skarels } 24638032Skarels if (newtype == TYPE_L && bytename[0] != '\0') 24738032Skarels comret = command("TYPE %s %s", p->t_mode, bytename); 24838032Skarels else 24938032Skarels comret = command("TYPE %s", p->t_mode); 25038032Skarels if (comret == COMPLETE) 25138032Skarels curtype = newtype; 25238032Skarels verbose = oldverbose; 25338032Skarels } 25438032Skarels 25538132Srick char *stype[] = { 25638132Srick "type", 25738132Srick "", 25838132Srick 0 25938132Srick }; 26038132Srick 26138032Skarels /* 26210294Ssam * Set binary transfer type. 26310294Ssam */ 26410294Ssam /*VARARGS*/ 26510294Ssam setbinary() 26610294Ssam { 26738132Srick stype[1] = "binary"; 26838132Srick settype(2, stype); 26910294Ssam } 27010294Ssam 27110294Ssam /* 27210294Ssam * Set ascii transfer type. 27310294Ssam */ 27410294Ssam /*VARARGS*/ 27510294Ssam setascii() 27610294Ssam { 27738132Srick stype[1] = "ascii"; 27838132Srick settype(2, stype); 27910294Ssam } 28010294Ssam 28110294Ssam /* 28210294Ssam * Set tenex transfer type. 28310294Ssam */ 28410294Ssam /*VARARGS*/ 28510294Ssam settenex() 28610294Ssam { 28738132Srick stype[1] = "tenex"; 28838132Srick settype(2, stype); 28910294Ssam } 29010294Ssam 29110294Ssam /* 29210294Ssam * Set file transfer mode. 29310294Ssam */ 29426497Sminshall /*ARGSUSED*/ 29510294Ssam setmode(argc, argv) 29610294Ssam char *argv[]; 29710294Ssam { 29810294Ssam 29910294Ssam printf("We only support %s mode, sorry.\n", modename); 30026049Sminshall code = -1; 30110294Ssam } 30210294Ssam 30310294Ssam /* 30410294Ssam * Set file transfer format. 30510294Ssam */ 30626497Sminshall /*ARGSUSED*/ 30710294Ssam setform(argc, argv) 30810294Ssam char *argv[]; 30910294Ssam { 31010294Ssam 31110294Ssam printf("We only support %s format, sorry.\n", formname); 31226049Sminshall code = -1; 31310294Ssam } 31410294Ssam 31510294Ssam /* 31610294Ssam * Set file transfer structure. 31710294Ssam */ 31826497Sminshall /*ARGSUSED*/ 31910294Ssam setstruct(argc, argv) 32010294Ssam char *argv[]; 32110294Ssam { 32210294Ssam 32310294Ssam printf("We only support %s structure, sorry.\n", structname); 32426049Sminshall code = -1; 32510294Ssam } 32610294Ssam 32718286Sralph /* 32818286Sralph * Send a single file. 32918286Sralph */ 33010294Ssam put(argc, argv) 33111756Ssam int argc; 33210294Ssam char *argv[]; 33310294Ssam { 33411650Ssam char *cmd; 33526049Sminshall int loc = 0; 33637225Skarels char *oldargv1, *oldargv2; 33711650Ssam 33826049Sminshall if (argc == 2) { 33926049Sminshall argc++; 34026049Sminshall argv[2] = argv[1]; 34126049Sminshall loc++; 34226049Sminshall } 34310294Ssam if (argc < 2) { 34426497Sminshall (void) strcat(line, " "); 34510294Ssam printf("(local-file) "); 34626497Sminshall (void) gets(&line[strlen(line)]); 34710294Ssam makeargv(); 34810294Ssam argc = margc; 34910294Ssam argv = margv; 35010294Ssam } 35110294Ssam if (argc < 2) { 35210294Ssam usage: 35326049Sminshall printf("usage:%s local-file remote-file\n", argv[0]); 35426049Sminshall code = -1; 35510294Ssam return; 35610294Ssam } 35710294Ssam if (argc < 3) { 35826497Sminshall (void) strcat(line, " "); 35910294Ssam printf("(remote-file) "); 36026497Sminshall (void) gets(&line[strlen(line)]); 36110294Ssam makeargv(); 36210294Ssam argc = margc; 36310294Ssam argv = margv; 36410294Ssam } 36510294Ssam if (argc < 3) 36610294Ssam goto usage; 36725908Smckusick oldargv1 = argv[1]; 36837225Skarels oldargv2 = argv[2]; 36926049Sminshall if (!globulize(&argv[1])) { 37026049Sminshall code = -1; 37111353Ssam return; 37226049Sminshall } 37325908Smckusick /* 37425908Smckusick * If "globulize" modifies argv[1], and argv[2] is a copy of 37525908Smckusick * the old argv[1], make it a copy of the new argv[1]. 37625908Smckusick */ 37726049Sminshall if (argv[1] != oldargv1 && argv[2] == oldargv1) { 37825908Smckusick argv[2] = argv[1]; 37926049Sminshall } 38026049Sminshall cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); 38126049Sminshall if (loc && ntflag) { 38226049Sminshall argv[2] = dotrans(argv[2]); 38326049Sminshall } 38426049Sminshall if (loc && mapflag) { 38526049Sminshall argv[2] = domap(argv[2]); 38626049Sminshall } 38737225Skarels sendrequest(cmd, argv[1], argv[2], 38837225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 38910294Ssam } 39010294Ssam 39110294Ssam /* 39211756Ssam * Send multiple files. 39310294Ssam */ 39411353Ssam mput(argc, argv) 39539252Sbostic int argc; 39639252Sbostic char **argv; 39711353Ssam { 39839252Sbostic extern jmp_buf jabort; 39913212Ssam register int i; 40039252Sbostic sig_t oldintr; 40138132Srick int ointer; 40226049Sminshall char *tp; 40339252Sbostic void mabort(); 40411353Ssam 40511650Ssam if (argc < 2) { 40626497Sminshall (void) strcat(line, " "); 40711650Ssam printf("(local-files) "); 40826497Sminshall (void) gets(&line[strlen(line)]); 40911650Ssam makeargv(); 41011650Ssam argc = margc; 41111650Ssam argv = margv; 41211353Ssam } 41311353Ssam if (argc < 2) { 41426049Sminshall printf("usage:%s local-files\n", argv[0]); 41526049Sminshall code = -1; 41611353Ssam return; 41711353Ssam } 41826049Sminshall mname = argv[0]; 41926049Sminshall mflag = 1; 42026049Sminshall oldintr = signal(SIGINT, mabort); 42126049Sminshall (void) setjmp(jabort); 42226049Sminshall if (proxy) { 42326049Sminshall char *cp, *tp2, tmpbuf[MAXPATHLEN]; 42426049Sminshall 42526497Sminshall while ((cp = remglob(argv,0)) != NULL) { 42626049Sminshall if (*cp == 0) { 42726049Sminshall mflag = 0; 42826049Sminshall continue; 42926049Sminshall } 43026049Sminshall if (mflag && confirm(argv[0], cp)) { 43126049Sminshall tp = cp; 43226049Sminshall if (mcase) { 43326049Sminshall while (*tp && !islower(*tp)) { 43426049Sminshall tp++; 43526049Sminshall } 43626049Sminshall if (!*tp) { 43726049Sminshall tp = cp; 43826049Sminshall tp2 = tmpbuf; 43926049Sminshall while ((*tp2 = *tp) != NULL) { 44026049Sminshall if (isupper(*tp2)) { 44126049Sminshall *tp2 = 'a' + *tp2 - 'A'; 44226049Sminshall } 44326049Sminshall tp++; 44426049Sminshall tp2++; 44526049Sminshall } 44626049Sminshall } 44726049Sminshall tp = tmpbuf; 44826049Sminshall } 44926049Sminshall if (ntflag) { 45026049Sminshall tp = dotrans(tp); 45126049Sminshall } 45226049Sminshall if (mapflag) { 45326049Sminshall tp = domap(tp); 45426049Sminshall } 45537225Skarels sendrequest((sunique) ? "STOU" : "STOR", 45637225Skarels cp, tp, cp != tp || !interactive); 45726049Sminshall if (!mflag && fromatty) { 45826049Sminshall ointer = interactive; 45926049Sminshall interactive = 1; 46026049Sminshall if (confirm("Continue with","mput")) { 46126049Sminshall mflag++; 46226049Sminshall } 46326049Sminshall interactive = ointer; 46426049Sminshall } 46526049Sminshall } 46626049Sminshall } 46726049Sminshall (void) signal(SIGINT, oldintr); 46826049Sminshall mflag = 0; 46926049Sminshall return; 47026049Sminshall } 47113212Ssam for (i = 1; i < argc; i++) { 47213212Ssam register char **cpp, **gargs; 47313212Ssam 47413212Ssam if (!doglob) { 47526049Sminshall if (mflag && confirm(argv[0], argv[i])) { 47626049Sminshall tp = (ntflag) ? dotrans(argv[i]) : argv[i]; 47726049Sminshall tp = (mapflag) ? domap(tp) : tp; 47826049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 47937225Skarels argv[i], tp, tp != argv[i] || !interactive); 48026049Sminshall if (!mflag && fromatty) { 48126049Sminshall ointer = interactive; 48226049Sminshall interactive = 1; 48326049Sminshall if (confirm("Continue with","mput")) { 48426049Sminshall mflag++; 48526049Sminshall } 48626049Sminshall interactive = ointer; 48726049Sminshall } 48826049Sminshall } 48913212Ssam continue; 49013212Ssam } 49113212Ssam gargs = glob(argv[i]); 49211650Ssam if (globerr != NULL) { 49311650Ssam printf("%s\n", globerr); 49436421Sbostic if (gargs) { 49511650Ssam blkfree(gargs); 49638132Srick free((char *)gargs); 49736421Sbostic } 49813212Ssam continue; 49911353Ssam } 50026049Sminshall for (cpp = gargs; cpp && *cpp != NULL; cpp++) { 50126049Sminshall if (mflag && confirm(argv[0], *cpp)) { 50226049Sminshall tp = (ntflag) ? dotrans(*cpp) : *cpp; 50326049Sminshall tp = (mapflag) ? domap(tp) : tp; 50426049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 50537225Skarels *cpp, tp, *cpp != tp || !interactive); 50626049Sminshall if (!mflag && fromatty) { 50726049Sminshall ointer = interactive; 50826049Sminshall interactive = 1; 50926049Sminshall if (confirm("Continue with","mput")) { 51026049Sminshall mflag++; 51126049Sminshall } 51226049Sminshall interactive = ointer; 51326049Sminshall } 51426049Sminshall } 51526049Sminshall } 51636421Sbostic if (gargs != NULL) { 51713212Ssam blkfree(gargs); 51838132Srick free((char *)gargs); 51936421Sbostic } 52011353Ssam } 52126049Sminshall (void) signal(SIGINT, oldintr); 52226049Sminshall mflag = 0; 52311353Ssam } 52411353Ssam 52537224Skarels reget(argc, argv) 52637224Skarels char *argv[]; 52737224Skarels { 52837224Skarels (void) getit(argc, argv, 1, "r+w"); 52937224Skarels } 53036935Skarels 53137224Skarels get(argc, argv) 53237224Skarels char *argv[]; 53337224Skarels { 53437224Skarels (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" ); 53537224Skarels } 53637224Skarels 53711353Ssam /* 53811353Ssam * Receive one file. 53911353Ssam */ 54037224Skarels getit(argc, argv, restartit, mode) 54110294Ssam char *argv[]; 54237224Skarels char *mode; 54310294Ssam { 54426049Sminshall int loc = 0; 54537225Skarels char *oldargv1, *oldargv2; 54610294Ssam 54726049Sminshall if (argc == 2) { 54826049Sminshall argc++; 54926049Sminshall argv[2] = argv[1]; 55026049Sminshall loc++; 55126049Sminshall } 55210294Ssam if (argc < 2) { 55326497Sminshall (void) strcat(line, " "); 55410294Ssam printf("(remote-file) "); 55526497Sminshall (void) gets(&line[strlen(line)]); 55610294Ssam makeargv(); 55710294Ssam argc = margc; 55810294Ssam argv = margv; 55910294Ssam } 56010294Ssam if (argc < 2) { 56110294Ssam usage: 56226049Sminshall printf("usage: %s remote-file [ local-file ]\n", argv[0]); 56326049Sminshall code = -1; 56437224Skarels return (0); 56510294Ssam } 56610294Ssam if (argc < 3) { 56726497Sminshall (void) strcat(line, " "); 56810294Ssam printf("(local-file) "); 56926497Sminshall (void) gets(&line[strlen(line)]); 57010294Ssam makeargv(); 57110294Ssam argc = margc; 57210294Ssam argv = margv; 57310294Ssam } 57410294Ssam if (argc < 3) 57510294Ssam goto usage; 57637225Skarels oldargv1 = argv[1]; 57737225Skarels oldargv2 = argv[2]; 57826049Sminshall if (!globulize(&argv[2])) { 57926049Sminshall code = -1; 58037224Skarels return (0); 58126049Sminshall } 58226049Sminshall if (loc && mcase) { 58326049Sminshall char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; 58426049Sminshall 58526049Sminshall while (*tp && !islower(*tp)) { 58626049Sminshall tp++; 58726049Sminshall } 58826049Sminshall if (!*tp) { 58926049Sminshall tp = argv[2]; 59026049Sminshall tp2 = tmpbuf; 59126049Sminshall while ((*tp2 = *tp) != NULL) { 59226049Sminshall if (isupper(*tp2)) { 59326049Sminshall *tp2 = 'a' + *tp2 - 'A'; 59426049Sminshall } 59526049Sminshall tp++; 59626049Sminshall tp2++; 59726049Sminshall } 59826049Sminshall argv[2] = tmpbuf; 59926049Sminshall } 60026049Sminshall } 60136940Skarels if (loc && ntflag) 60226049Sminshall argv[2] = dotrans(argv[2]); 60336940Skarels if (loc && mapflag) 60426049Sminshall argv[2] = domap(argv[2]); 60537224Skarels if (restartit) { 60637224Skarels struct stat stbuf; 60737224Skarels int ret; 60837224Skarels 60937224Skarels ret = stat(argv[2], &stbuf); 61037224Skarels if (restartit == 1) { 61137224Skarels if (ret < 0) { 61238202Srick fprintf(stderr, "local: %s: %s\n", argv[2], 61338202Srick strerror(errno)); 61437224Skarels return (0); 61537224Skarels } 61637224Skarels restart_point = stbuf.st_size; 61737224Skarels } else { 61837224Skarels if (ret == 0) { 61937224Skarels int overbose; 62037224Skarels 62137224Skarels overbose = verbose; 62237224Skarels if (debug == 0) 62337224Skarels verbose = -1; 62437224Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 62537224Skarels int yy, mo, day, hour, min, sec; 62637224Skarels struct tm *tm; 62737224Skarels verbose = overbose; 62837224Skarels sscanf(reply_string, 62937224Skarels "%*s %04d%02d%02d%02d%02d%02d", 63037224Skarels &yy, &mo, &day, &hour, &min, &sec); 63137224Skarels tm = gmtime(&stbuf.st_mtime); 63237224Skarels tm->tm_mon++; 63337224Skarels if (tm->tm_year > yy%100) 63437224Skarels return (1); 63537224Skarels else if (tm->tm_year == yy%100) { 63637224Skarels if (tm->tm_mon > mo) 63737224Skarels return (1); 63837224Skarels } else if (tm->tm_mon == mo) { 63937224Skarels if (tm->tm_mday > day) 64037224Skarels return (1); 64137224Skarels } else if (tm->tm_mday == day) { 64237224Skarels if (tm->tm_hour > hour) 64337224Skarels return (1); 64437224Skarels } else if (tm->tm_hour == hour) { 64537224Skarels if (tm->tm_min > min) 64637224Skarels return (1); 64737224Skarels } else if (tm->tm_min == min) { 64837224Skarels if (tm->tm_sec > sec) 64937224Skarels return (1); 65037224Skarels } 65137224Skarels } else { 65238132Srick printf("%s\n", reply_string); 65337224Skarels verbose = overbose; 65437224Skarels return (0); 65537224Skarels } 65637224Skarels } 65737224Skarels } 65837224Skarels } 65937224Skarels 66037225Skarels recvrequest("RETR", argv[2], argv[1], mode, 66137225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 66237224Skarels restart_point = 0; 66337224Skarels return (0); 66410294Ssam } 66510294Ssam 66639252Sbostic void 66726049Sminshall mabort() 66826049Sminshall { 66926049Sminshall int ointer; 67026049Sminshall extern jmp_buf jabort; 67126049Sminshall 67226049Sminshall printf("\n"); 67326049Sminshall (void) fflush(stdout); 67426049Sminshall if (mflag && fromatty) { 67526049Sminshall ointer = interactive; 67626049Sminshall interactive = 1; 67726049Sminshall if (confirm("Continue with", mname)) { 67826049Sminshall interactive = ointer; 67926049Sminshall longjmp(jabort,0); 68026049Sminshall } 68126049Sminshall interactive = ointer; 68226049Sminshall } 68326049Sminshall mflag = 0; 68426049Sminshall longjmp(jabort,0); 68526049Sminshall } 68626049Sminshall 68711353Ssam /* 68811353Ssam * Get multiple files. 68911353Ssam */ 69011353Ssam mget(argc, argv) 69139252Sbostic int argc; 69239252Sbostic char **argv; 69311353Ssam { 69439252Sbostic extern jmp_buf jabort; 69539252Sbostic sig_t oldintr; 69639252Sbostic int ointer; 69726049Sminshall char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; 69839252Sbostic void mabort(); 69911353Ssam 70011353Ssam if (argc < 2) { 70126497Sminshall (void) strcat(line, " "); 70211756Ssam printf("(remote-files) "); 70326497Sminshall (void) gets(&line[strlen(line)]); 70411353Ssam makeargv(); 70511353Ssam argc = margc; 70611353Ssam argv = margv; 70711353Ssam } 70811353Ssam if (argc < 2) { 70926049Sminshall printf("usage:%s remote-files\n", argv[0]); 71026049Sminshall code = -1; 71111353Ssam return; 71211353Ssam } 71326049Sminshall mname = argv[0]; 71426049Sminshall mflag = 1; 71526049Sminshall oldintr = signal(SIGINT,mabort); 71626049Sminshall (void) setjmp(jabort); 71726497Sminshall while ((cp = remglob(argv,proxy)) != NULL) { 71826049Sminshall if (*cp == '\0') { 71926049Sminshall mflag = 0; 72026049Sminshall continue; 72126049Sminshall } 72226049Sminshall if (mflag && confirm(argv[0], cp)) { 72326049Sminshall tp = cp; 72426049Sminshall if (mcase) { 72526049Sminshall while (*tp && !islower(*tp)) { 72626049Sminshall tp++; 72726049Sminshall } 72826049Sminshall if (!*tp) { 72926049Sminshall tp = cp; 73026049Sminshall tp2 = tmpbuf; 73126049Sminshall while ((*tp2 = *tp) != NULL) { 73226049Sminshall if (isupper(*tp2)) { 73326049Sminshall *tp2 = 'a' + *tp2 - 'A'; 73426049Sminshall } 73526049Sminshall tp++; 73626049Sminshall tp2++; 73726049Sminshall } 73826049Sminshall } 73926049Sminshall tp = tmpbuf; 74026049Sminshall } 74126049Sminshall if (ntflag) { 74226049Sminshall tp = dotrans(tp); 74326049Sminshall } 74426049Sminshall if (mapflag) { 74526049Sminshall tp = domap(tp); 74626049Sminshall } 74737225Skarels recvrequest("RETR", tp, cp, "w", 74837225Skarels tp != cp || !interactive); 74926049Sminshall if (!mflag && fromatty) { 75026049Sminshall ointer = interactive; 75126049Sminshall interactive = 1; 75226049Sminshall if (confirm("Continue with","mget")) { 75326049Sminshall mflag++; 75426049Sminshall } 75526049Sminshall interactive = ointer; 75626049Sminshall } 75726049Sminshall } 75826049Sminshall } 75926049Sminshall (void) signal(SIGINT,oldintr); 76026049Sminshall mflag = 0; 76111650Ssam } 76211650Ssam 76311650Ssam char * 76426497Sminshall remglob(argv,doswitch) 76511650Ssam char *argv[]; 76626497Sminshall int doswitch; 76711650Ssam { 76811756Ssam char temp[16]; 76911650Ssam static char buf[MAXPATHLEN]; 77011650Ssam static FILE *ftemp = NULL; 77111650Ssam static char **args; 77213212Ssam int oldverbose, oldhash; 77311756Ssam char *cp, *mode; 77411650Ssam 77526049Sminshall if (!mflag) { 77626049Sminshall if (!doglob) { 77726049Sminshall args = NULL; 77826049Sminshall } 77926049Sminshall else { 78026049Sminshall if (ftemp) { 78126497Sminshall (void) fclose(ftemp); 78226049Sminshall ftemp = NULL; 78326049Sminshall } 78426049Sminshall } 78526049Sminshall return(NULL); 78626049Sminshall } 78711650Ssam if (!doglob) { 78811756Ssam if (args == NULL) 78911650Ssam args = argv; 79011650Ssam if ((cp = *++args) == NULL) 79111650Ssam args = NULL; 79211650Ssam return (cp); 79311353Ssam } 79411650Ssam if (ftemp == NULL) { 79537458Skarels (void) strcpy(temp, _PATH_TMP); 79626497Sminshall (void) mktemp(temp); 79711650Ssam oldverbose = verbose, verbose = 0; 79813212Ssam oldhash = hash, hash = 0; 79926049Sminshall if (doswitch) { 80026049Sminshall pswitch(!proxy); 80126049Sminshall } 80211756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 80337225Skarels recvrequest ("NLST", temp, *argv, mode, 0); 80426049Sminshall if (doswitch) { 80526049Sminshall pswitch(!proxy); 80626049Sminshall } 80713212Ssam verbose = oldverbose; hash = oldhash; 80811650Ssam ftemp = fopen(temp, "r"); 80926497Sminshall (void) unlink(temp); 81011650Ssam if (ftemp == NULL) { 81111650Ssam printf("can't find list of remote files, oops\n"); 81211756Ssam return (NULL); 81311353Ssam } 81411353Ssam } 81511650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 81626497Sminshall (void) fclose(ftemp), ftemp = NULL; 81711650Ssam return (NULL); 81811353Ssam } 81911650Ssam if ((cp = index(buf, '\n')) != NULL) 82011650Ssam *cp = '\0'; 82111650Ssam return (buf); 82211353Ssam } 82311353Ssam 82410294Ssam char * 82510294Ssam onoff(bool) 82610294Ssam int bool; 82710294Ssam { 82810294Ssam 82910294Ssam return (bool ? "on" : "off"); 83010294Ssam } 83110294Ssam 83210294Ssam /* 83310294Ssam * Show status. 83410294Ssam */ 83526497Sminshall /*ARGSUSED*/ 83610294Ssam status(argc, argv) 83710294Ssam char *argv[]; 83810294Ssam { 83926049Sminshall int i; 84010294Ssam 84110294Ssam if (connected) 84210294Ssam printf("Connected to %s.\n", hostname); 84310294Ssam else 84410294Ssam printf("Not connected.\n"); 84526049Sminshall if (!proxy) { 84626049Sminshall pswitch(1); 84726049Sminshall if (connected) { 84826049Sminshall printf("Connected for proxy commands to %s.\n", hostname); 84926049Sminshall } 85026049Sminshall else { 85126049Sminshall printf("No proxy connection.\n"); 85226049Sminshall } 85326049Sminshall pswitch(0); 85426049Sminshall } 85510294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 85610294Ssam modename, typename, formname, structname); 85711353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 85811353Ssam onoff(verbose), onoff(bell), onoff(interactive), 85911353Ssam onoff(doglob)); 86026049Sminshall printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), 86126049Sminshall onoff(runique)); 86226049Sminshall printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); 86326049Sminshall if (ntflag) { 86426049Sminshall printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); 86526049Sminshall } 86626049Sminshall else { 86726049Sminshall printf("Ntrans: off\n"); 86826049Sminshall } 86926049Sminshall if (mapflag) { 87026049Sminshall printf("Nmap: (in) %s (out) %s\n", mapin, mapout); 87126049Sminshall } 87226049Sminshall else { 87326049Sminshall printf("Nmap: off\n"); 87426049Sminshall } 87514143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 87614143Ssam onoff(hash), onoff(sendport)); 87726049Sminshall if (macnum > 0) { 87826049Sminshall printf("Macros:\n"); 87926049Sminshall for (i=0; i<macnum; i++) { 88026049Sminshall printf("\t%s\n",macros[i].mac_name); 88126049Sminshall } 88226049Sminshall } 88326049Sminshall code = 0; 88410294Ssam } 88510294Ssam 88610294Ssam /* 88710294Ssam * Set beep on cmd completed mode. 88810294Ssam */ 88910294Ssam /*VARARGS*/ 89010294Ssam setbell() 89110294Ssam { 89210294Ssam 89310294Ssam bell = !bell; 89410294Ssam printf("Bell mode %s.\n", onoff(bell)); 89526049Sminshall code = bell; 89610294Ssam } 89710294Ssam 89810294Ssam /* 89910294Ssam * Turn on packet tracing. 90010294Ssam */ 90110294Ssam /*VARARGS*/ 90210294Ssam settrace() 90310294Ssam { 90410294Ssam 90510294Ssam trace = !trace; 90610294Ssam printf("Packet tracing %s.\n", onoff(trace)); 90726049Sminshall code = trace; 90810294Ssam } 90910294Ssam 91010294Ssam /* 91111650Ssam * Toggle hash mark printing during transfers. 91211650Ssam */ 91311650Ssam /*VARARGS*/ 91411650Ssam sethash() 91511650Ssam { 91611650Ssam 91711650Ssam hash = !hash; 91811650Ssam printf("Hash mark printing %s", onoff(hash)); 91926049Sminshall code = hash; 92011650Ssam if (hash) 92137224Skarels printf(" (%d bytes/hash mark)", 1024); 92211650Ssam printf(".\n"); 92311650Ssam } 92411650Ssam 92511650Ssam /* 92610294Ssam * Turn on printing of server echo's. 92710294Ssam */ 92810294Ssam /*VARARGS*/ 92910294Ssam setverbose() 93010294Ssam { 93110294Ssam 93210294Ssam verbose = !verbose; 93310294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 93426049Sminshall code = verbose; 93510294Ssam } 93610294Ssam 93710294Ssam /* 93811650Ssam * Toggle PORT cmd use before each data connection. 93911650Ssam */ 94011650Ssam /*VARARGS*/ 94111650Ssam setport() 94211650Ssam { 94311650Ssam 94411650Ssam sendport = !sendport; 94511650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 94626049Sminshall code = sendport; 94711650Ssam } 94811650Ssam 94911650Ssam /* 95010294Ssam * Turn on interactive prompting 95110294Ssam * during mget, mput, and mdelete. 95210294Ssam */ 95310294Ssam /*VARARGS*/ 95410294Ssam setprompt() 95510294Ssam { 95610294Ssam 95710294Ssam interactive = !interactive; 95810294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 95926049Sminshall code = interactive; 96010294Ssam } 96110294Ssam 96210294Ssam /* 96311353Ssam * Toggle metacharacter interpretation 96411353Ssam * on local file names. 96511353Ssam */ 96611353Ssam /*VARARGS*/ 96711353Ssam setglob() 96811353Ssam { 96911353Ssam 97011353Ssam doglob = !doglob; 97111353Ssam printf("Globbing %s.\n", onoff(doglob)); 97226049Sminshall code = doglob; 97311353Ssam } 97411353Ssam 97511353Ssam /* 97610294Ssam * Set debugging mode on/off and/or 97710294Ssam * set level of debugging. 97810294Ssam */ 97911756Ssam /*VARARGS*/ 98010294Ssam setdebug(argc, argv) 98110294Ssam char *argv[]; 98210294Ssam { 98310294Ssam int val; 98410294Ssam 98510294Ssam if (argc > 1) { 98610294Ssam val = atoi(argv[1]); 98710294Ssam if (val < 0) { 98810294Ssam printf("%s: bad debugging value.\n", argv[1]); 98926049Sminshall code = -1; 99010294Ssam return; 99110294Ssam } 99210294Ssam } else 99310294Ssam val = !debug; 99410294Ssam debug = val; 99510294Ssam if (debug) 99610294Ssam options |= SO_DEBUG; 99710294Ssam else 99810294Ssam options &= ~SO_DEBUG; 99910294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 100026049Sminshall code = debug > 0; 100110294Ssam } 100210294Ssam 100310294Ssam /* 100410294Ssam * Set current working directory 100510294Ssam * on remote machine. 100610294Ssam */ 100710294Ssam cd(argc, argv) 100810294Ssam char *argv[]; 100910294Ssam { 101010294Ssam 101110294Ssam if (argc < 2) { 101226497Sminshall (void) strcat(line, " "); 101310294Ssam printf("(remote-directory) "); 101426497Sminshall (void) gets(&line[strlen(line)]); 101510294Ssam makeargv(); 101610294Ssam argc = margc; 101710294Ssam argv = margv; 101810294Ssam } 101910294Ssam if (argc < 2) { 102026049Sminshall printf("usage:%s remote-directory\n", argv[0]); 102126049Sminshall code = -1; 102210294Ssam return; 102310294Ssam } 102437224Skarels if (command("CWD %s", argv[1]) == ERROR && code == 500) { 102537224Skarels if (verbose) 102637224Skarels printf("CWD command not recognized, trying XCWD\n"); 102737224Skarels (void) command("XCWD %s", argv[1]); 102837224Skarels } 102910294Ssam } 103010294Ssam 103110294Ssam /* 103210294Ssam * Set current working directory 103310294Ssam * on local machine. 103410294Ssam */ 103510294Ssam lcd(argc, argv) 103610294Ssam char *argv[]; 103710294Ssam { 103811353Ssam char buf[MAXPATHLEN]; 103938132Srick extern char *getwd(); 104010294Ssam 104111353Ssam if (argc < 2) 104211353Ssam argc++, argv[1] = home; 104310294Ssam if (argc != 2) { 104426049Sminshall printf("usage:%s local-directory\n", argv[0]); 104526049Sminshall code = -1; 104610294Ssam return; 104710294Ssam } 104826049Sminshall if (!globulize(&argv[1])) { 104926049Sminshall code = -1; 105011353Ssam return; 105126049Sminshall } 105211353Ssam if (chdir(argv[1]) < 0) { 105338202Srick fprintf(stderr, "local: %s: %s\n", argv[1], strerror(errno)); 105426049Sminshall code = -1; 105511353Ssam return; 105611353Ssam } 105711353Ssam printf("Local directory now %s\n", getwd(buf)); 105826049Sminshall code = 0; 105910294Ssam } 106010294Ssam 106110294Ssam /* 106210294Ssam * Delete a single file. 106310294Ssam */ 106410294Ssam delete(argc, argv) 106510294Ssam char *argv[]; 106610294Ssam { 106710294Ssam 106810294Ssam if (argc < 2) { 106926497Sminshall (void) strcat(line, " "); 107010294Ssam printf("(remote-file) "); 107126497Sminshall (void) gets(&line[strlen(line)]); 107210294Ssam makeargv(); 107310294Ssam argc = margc; 107410294Ssam argv = margv; 107510294Ssam } 107610294Ssam if (argc < 2) { 107726049Sminshall printf("usage:%s remote-file\n", argv[0]); 107826049Sminshall code = -1; 107910294Ssam return; 108010294Ssam } 108110294Ssam (void) command("DELE %s", argv[1]); 108210294Ssam } 108310294Ssam 108410294Ssam /* 108511650Ssam * Delete multiple files. 108611650Ssam */ 108711650Ssam mdelete(argc, argv) 108839252Sbostic int argc; 108939252Sbostic char **argv; 109011650Ssam { 109139252Sbostic extern jmp_buf jabort; 109239252Sbostic sig_t oldintr; 109339252Sbostic int ointer; 109411650Ssam char *cp; 109539252Sbostic void mabort(); 109611650Ssam 109711650Ssam if (argc < 2) { 109826497Sminshall (void) strcat(line, " "); 109911650Ssam printf("(remote-files) "); 110026497Sminshall (void) gets(&line[strlen(line)]); 110111650Ssam makeargv(); 110211650Ssam argc = margc; 110311650Ssam argv = margv; 110411650Ssam } 110511650Ssam if (argc < 2) { 110626049Sminshall printf("usage:%s remote-files\n", argv[0]); 110726049Sminshall code = -1; 110811650Ssam return; 110911650Ssam } 111026049Sminshall mname = argv[0]; 111126049Sminshall mflag = 1; 111226049Sminshall oldintr = signal(SIGINT, mabort); 111326049Sminshall (void) setjmp(jabort); 111426497Sminshall while ((cp = remglob(argv,0)) != NULL) { 111526049Sminshall if (*cp == '\0') { 111626049Sminshall mflag = 0; 111726049Sminshall continue; 111826049Sminshall } 111926049Sminshall if (mflag && confirm(argv[0], cp)) { 112011650Ssam (void) command("DELE %s", cp); 112126049Sminshall if (!mflag && fromatty) { 112226049Sminshall ointer = interactive; 112326049Sminshall interactive = 1; 112426049Sminshall if (confirm("Continue with", "mdelete")) { 112526049Sminshall mflag++; 112626049Sminshall } 112726049Sminshall interactive = ointer; 112826049Sminshall } 112926049Sminshall } 113026049Sminshall } 113126049Sminshall (void) signal(SIGINT, oldintr); 113226049Sminshall mflag = 0; 113311650Ssam } 113411756Ssam 113511650Ssam /* 113610294Ssam * Rename a remote file. 113710294Ssam */ 113810294Ssam renamefile(argc, argv) 113910294Ssam char *argv[]; 114010294Ssam { 114110294Ssam 114210294Ssam if (argc < 2) { 114326497Sminshall (void) strcat(line, " "); 114410294Ssam printf("(from-name) "); 114526497Sminshall (void) gets(&line[strlen(line)]); 114610294Ssam makeargv(); 114710294Ssam argc = margc; 114810294Ssam argv = margv; 114910294Ssam } 115010294Ssam if (argc < 2) { 115110294Ssam usage: 115210294Ssam printf("%s from-name to-name\n", argv[0]); 115326049Sminshall code = -1; 115410294Ssam return; 115510294Ssam } 115610294Ssam if (argc < 3) { 115726497Sminshall (void) strcat(line, " "); 115810294Ssam printf("(to-name) "); 115926497Sminshall (void) gets(&line[strlen(line)]); 116010294Ssam makeargv(); 116110294Ssam argc = margc; 116210294Ssam argv = margv; 116310294Ssam } 116410294Ssam if (argc < 3) 116510294Ssam goto usage; 116610294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 116710294Ssam (void) command("RNTO %s", argv[2]); 116810294Ssam } 116910294Ssam 117010294Ssam /* 117110294Ssam * Get a directory listing 117210294Ssam * of remote files. 117310294Ssam */ 117410294Ssam ls(argc, argv) 117510294Ssam char *argv[]; 117610294Ssam { 117711756Ssam char *cmd; 117810294Ssam 117910294Ssam if (argc < 2) 118010294Ssam argc++, argv[1] = NULL; 118110294Ssam if (argc < 3) 118210294Ssam argc++, argv[2] = "-"; 118311756Ssam if (argc > 3) { 118411756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 118526049Sminshall code = -1; 118611756Ssam return; 118711756Ssam } 118836935Skarels cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 118926049Sminshall if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 119026049Sminshall code = -1; 119111353Ssam return; 119226049Sminshall } 119332344Scsvsj if (strcmp(argv[2], "-") && *argv[2] != '|') 119432344Scsvsj if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { 119532344Scsvsj code = -1; 119632344Scsvsj return; 119732344Scsvsj } 119837225Skarels recvrequest(cmd, argv[2], argv[1], "w", 0); 119910294Ssam } 120010294Ssam 120110294Ssam /* 120211756Ssam * Get a directory listing 120311756Ssam * of multiple remote files. 120411756Ssam */ 120511756Ssam mls(argc, argv) 120639252Sbostic int argc; 120739252Sbostic char **argv; 120811756Ssam { 120939252Sbostic extern jmp_buf jabort; 121039252Sbostic sig_t oldintr; 121139252Sbostic int ointer, i; 121226049Sminshall char *cmd, mode[1], *dest; 121339252Sbostic void mabort(); 121411756Ssam 121513212Ssam if (argc < 2) { 121626497Sminshall (void) strcat(line, " "); 121713212Ssam printf("(remote-files) "); 121826497Sminshall (void) gets(&line[strlen(line)]); 121913212Ssam makeargv(); 122013212Ssam argc = margc; 122113212Ssam argv = margv; 122213212Ssam } 122313212Ssam if (argc < 3) { 122426497Sminshall (void) strcat(line, " "); 122513212Ssam printf("(local-file) "); 122626497Sminshall (void) gets(&line[strlen(line)]); 122713212Ssam makeargv(); 122813212Ssam argc = margc; 122913212Ssam argv = margv; 123013212Ssam } 123113212Ssam if (argc < 3) { 123226049Sminshall printf("usage:%s remote-files local-file\n", argv[0]); 123326049Sminshall code = -1; 123413212Ssam return; 123513212Ssam } 123613212Ssam dest = argv[argc - 1]; 123713212Ssam argv[argc - 1] = NULL; 123826049Sminshall if (strcmp(dest, "-") && *dest != '|') 123926049Sminshall if (!globulize(&dest) || !confirm("output to local-file:", dest)) { 124026049Sminshall code = -1; 124113212Ssam return; 124226049Sminshall } 124336940Skarels cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 124426049Sminshall mname = argv[0]; 124526049Sminshall mflag = 1; 124626049Sminshall oldintr = signal(SIGINT, mabort); 124726049Sminshall (void) setjmp(jabort); 124826049Sminshall for (i = 1; mflag && i < argc-1; ++i) { 124926049Sminshall *mode = (i == 1) ? 'w' : 'a'; 125037225Skarels recvrequest(cmd, dest, argv[i], mode, 0); 125126049Sminshall if (!mflag && fromatty) { 125226049Sminshall ointer = interactive; 125326049Sminshall interactive = 1; 125426049Sminshall if (confirm("Continue with", argv[0])) { 125526049Sminshall mflag ++; 125626049Sminshall } 125726049Sminshall interactive = ointer; 125826049Sminshall } 125926049Sminshall } 126026049Sminshall (void) signal(SIGINT, oldintr); 126126049Sminshall mflag = 0; 126211756Ssam } 126311756Ssam 126411756Ssam /* 126510294Ssam * Do a shell escape 126610294Ssam */ 126726497Sminshall /*ARGSUSED*/ 126810294Ssam shell(argc, argv) 126939252Sbostic int argc; 127039252Sbostic char **argv; 127110294Ssam { 127238132Srick int pid; 127339252Sbostic sig_t old1, old2; 127426049Sminshall char shellnam[40], *shell, *namep; 127526497Sminshall union wait status; 127610294Ssam 127711756Ssam old1 = signal (SIGINT, SIG_IGN); 127811756Ssam old2 = signal (SIGQUIT, SIG_IGN); 127911756Ssam if ((pid = fork()) == 0) { 128011756Ssam for (pid = 3; pid < 20; pid++) 128126497Sminshall (void) close(pid); 128226497Sminshall (void) signal(SIGINT, SIG_DFL); 128326497Sminshall (void) signal(SIGQUIT, SIG_DFL); 128425908Smckusick shell = getenv("SHELL"); 128525908Smckusick if (shell == NULL) 128637458Skarels shell = _PATH_BSHELL; 128725908Smckusick namep = rindex(shell,'/'); 128825908Smckusick if (namep == NULL) 128925908Smckusick namep = shell; 129026497Sminshall (void) strcpy(shellnam,"-"); 129126497Sminshall (void) strcat(shellnam, ++namep); 129226049Sminshall if (strcmp(namep, "sh") != 0) 129326049Sminshall shellnam[0] = '+'; 129426049Sminshall if (debug) { 129526049Sminshall printf ("%s\n", shell); 129626497Sminshall (void) fflush (stdout); 129711756Ssam } 129826049Sminshall if (argc > 1) { 129926049Sminshall execl(shell,shellnam,"-c",altarg,(char *)0); 130026049Sminshall } 130126049Sminshall else { 130226049Sminshall execl(shell,shellnam,(char *)0); 130326049Sminshall } 130425908Smckusick perror(shell); 130526049Sminshall code = -1; 130611756Ssam exit(1); 130726049Sminshall } 130811756Ssam if (pid > 0) 130911756Ssam while (wait(&status) != pid) 131011756Ssam ; 131126497Sminshall (void) signal(SIGINT, old1); 131226497Sminshall (void) signal(SIGQUIT, old2); 131326049Sminshall if (pid == -1) { 131411756Ssam perror("Try again later"); 131526049Sminshall code = -1; 131626049Sminshall } 131726049Sminshall else { 131826049Sminshall code = 0; 131926049Sminshall } 132011756Ssam return (0); 132110294Ssam } 132210294Ssam 132310294Ssam /* 132410294Ssam * Send new user information (re-login) 132510294Ssam */ 132610294Ssam user(argc, argv) 132710294Ssam int argc; 132810294Ssam char **argv; 132910294Ssam { 133035658Sbostic char acct[80], *getpass(); 133126049Sminshall int n, aflag = 0; 133210294Ssam 133310294Ssam if (argc < 2) { 133426497Sminshall (void) strcat(line, " "); 133510294Ssam printf("(username) "); 133626497Sminshall (void) gets(&line[strlen(line)]); 133710294Ssam makeargv(); 133810294Ssam argc = margc; 133910294Ssam argv = margv; 134010294Ssam } 134110294Ssam if (argc > 4) { 134210294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 134326049Sminshall code = -1; 134411756Ssam return (0); 134510294Ssam } 134610294Ssam n = command("USER %s", argv[1]); 134710294Ssam if (n == CONTINUE) { 134810294Ssam if (argc < 3 ) 134935658Sbostic argv[2] = getpass("Password: "), argc++; 135010294Ssam n = command("PASS %s", argv[2]); 135110294Ssam } 135210294Ssam if (n == CONTINUE) { 135310294Ssam if (argc < 4) { 135410294Ssam printf("Account: "); (void) fflush(stdout); 135510294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 135610294Ssam acct[strlen(acct) - 1] = '\0'; 135710294Ssam argv[3] = acct; argc++; 135810294Ssam } 135926049Sminshall n = command("ACCT %s", argv[3]); 136026049Sminshall aflag++; 136110294Ssam } 136210294Ssam if (n != COMPLETE) { 136326497Sminshall fprintf(stdout, "Login failed.\n"); 136410294Ssam return (0); 136510294Ssam } 136626049Sminshall if (!aflag && argc == 4) { 136726049Sminshall (void) command("ACCT %s", argv[3]); 136826049Sminshall } 136910294Ssam return (1); 137010294Ssam } 137110294Ssam 137210294Ssam /* 137310294Ssam * Print working directory. 137410294Ssam */ 137510294Ssam /*VARARGS*/ 137610294Ssam pwd() 137710294Ssam { 137837224Skarels int oldverbose = verbose; 137911756Ssam 138037224Skarels /* 138137224Skarels * If we aren't verbose, this doesn't do anything! 138237224Skarels */ 138337224Skarels verbose = 1; 138437224Skarels if (command("PWD") == ERROR && code == 500) { 138537224Skarels printf("PWD command not recognized, trying XPWD\n"); 138637224Skarels (void) command("XPWD"); 138737224Skarels } 138837224Skarels verbose = oldverbose; 138910294Ssam } 139010294Ssam 139110294Ssam /* 139210294Ssam * Make a directory. 139310294Ssam */ 139410294Ssam makedir(argc, argv) 139510294Ssam char *argv[]; 139610294Ssam { 139710294Ssam 139810294Ssam if (argc < 2) { 139926497Sminshall (void) strcat(line, " "); 140010294Ssam printf("(directory-name) "); 140126497Sminshall (void) gets(&line[strlen(line)]); 140210294Ssam makeargv(); 140310294Ssam argc = margc; 140410294Ssam argv = margv; 140510294Ssam } 140610294Ssam if (argc < 2) { 140726049Sminshall printf("usage: %s directory-name\n", argv[0]); 140826049Sminshall code = -1; 140910294Ssam return; 141010294Ssam } 141137224Skarels if (command("MKD %s", argv[1]) == ERROR && code == 500) { 141237224Skarels if (verbose) 141337224Skarels printf("MKD command not recognized, trying XMKD\n"); 141437224Skarels (void) command("XMKD %s", argv[1]); 141537224Skarels } 141610294Ssam } 141710294Ssam 141810294Ssam /* 141910294Ssam * Remove a directory. 142010294Ssam */ 142110294Ssam removedir(argc, argv) 142210294Ssam char *argv[]; 142310294Ssam { 142410294Ssam 142510294Ssam if (argc < 2) { 142626497Sminshall (void) strcat(line, " "); 142710294Ssam printf("(directory-name) "); 142826497Sminshall (void) gets(&line[strlen(line)]); 142910294Ssam makeargv(); 143010294Ssam argc = margc; 143110294Ssam argv = margv; 143210294Ssam } 143310294Ssam if (argc < 2) { 143426049Sminshall printf("usage: %s directory-name\n", argv[0]); 143526049Sminshall code = -1; 143610294Ssam return; 143710294Ssam } 143837224Skarels if (command("RMD %s", argv[1]) == ERROR && code == 500) { 143937224Skarels if (verbose) 144037224Skarels printf("RMD command not recognized, trying XRMD\n"); 144137224Skarels (void) command("XRMD %s", argv[1]); 144237224Skarels } 144310294Ssam } 144410294Ssam 144510294Ssam /* 144610294Ssam * Send a line, verbatim, to the remote machine. 144710294Ssam */ 144810294Ssam quote(argc, argv) 144910294Ssam char *argv[]; 145010294Ssam { 145110294Ssam int i; 145210294Ssam char buf[BUFSIZ]; 145310294Ssam 145410294Ssam if (argc < 2) { 145526497Sminshall (void) strcat(line, " "); 145610294Ssam printf("(command line to send) "); 145726497Sminshall (void) gets(&line[strlen(line)]); 145810294Ssam makeargv(); 145910294Ssam argc = margc; 146010294Ssam argv = margv; 146110294Ssam } 146210294Ssam if (argc < 2) { 146310294Ssam printf("usage: %s line-to-send\n", argv[0]); 146426049Sminshall code = -1; 146510294Ssam return; 146610294Ssam } 146726497Sminshall (void) strcpy(buf, argv[1]); 146810294Ssam for (i = 2; i < argc; i++) { 146926497Sminshall (void) strcat(buf, " "); 147026497Sminshall (void) strcat(buf, argv[i]); 147110294Ssam } 147226049Sminshall if (command(buf) == PRELIM) { 147326049Sminshall while (getreply(0) == PRELIM); 147426049Sminshall } 147510294Ssam } 147610294Ssam 147710294Ssam /* 147837224Skarels * Send a SITE command to the remote machine. The line 147937224Skarels * is sent almost verbatim to the remote machine, the 148037224Skarels * first argument is changed to SITE. 148137224Skarels */ 148237224Skarels 148337224Skarels site(argc, argv) 148437224Skarels char *argv[]; 148537224Skarels { 148637224Skarels int i; 148737224Skarels char buf[BUFSIZ]; 148837224Skarels 148937224Skarels if (argc < 2) { 149037224Skarels (void) strcat(line, " "); 149137224Skarels printf("(arguments to SITE command) "); 149237224Skarels (void) gets(&line[strlen(line)]); 149337224Skarels makeargv(); 149437224Skarels argc = margc; 149537224Skarels argv = margv; 149637224Skarels } 149737224Skarels if (argc < 2) { 149837224Skarels printf("usage: %s line-to-send\n", argv[0]); 149937224Skarels code = -1; 150037224Skarels return; 150137224Skarels } 150237224Skarels (void) strcpy(buf, "SITE "); 150337224Skarels (void) strcat(buf, argv[1]); 150437224Skarels for (i = 2; i < argc; i++) { 150537224Skarels (void) strcat(buf, " "); 150637224Skarels (void) strcat(buf, argv[i]); 150737224Skarels } 150837224Skarels if (command(buf) == PRELIM) { 150937224Skarels while (getreply(0) == PRELIM); 151037224Skarels } 151137224Skarels } 151237224Skarels 151337224Skarels do_chmod(argc, argv) 151437224Skarels char *argv[]; 151537224Skarels { 151637224Skarels if (argc == 2) { 151737224Skarels printf("usage: %s mode file-name\n", argv[0]); 151837224Skarels code = -1; 151937224Skarels return; 152037224Skarels } 152137224Skarels if (argc < 3) { 152237224Skarels (void) strcat(line, " "); 152337224Skarels printf("(mode and file-name) "); 152437224Skarels (void) gets(&line[strlen(line)]); 152537224Skarels makeargv(); 152637224Skarels argc = margc; 152737224Skarels argv = margv; 152837224Skarels } 152937224Skarels if (argc != 3) { 153037224Skarels printf("usage: %s mode file-name\n", argv[0]); 153137224Skarels code = -1; 153237224Skarels return; 153337224Skarels } 153437224Skarels (void)command("SITE CHMOD %s %s", argv[1], argv[2]); 153537224Skarels } 153637224Skarels 153737224Skarels do_umask(argc, argv) 153837224Skarels char *argv[]; 153937224Skarels { 154037224Skarels int oldverbose = verbose; 154137224Skarels 154237224Skarels verbose = 1; 154337224Skarels (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 154437224Skarels verbose = oldverbose; 154537224Skarels } 154637224Skarels 154737224Skarels idle(argc, argv) 154837224Skarels char *argv[]; 154937224Skarels { 155037224Skarels int oldverbose = verbose; 155137224Skarels 155237224Skarels verbose = 1; 155337224Skarels (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 155437224Skarels verbose = oldverbose; 155537224Skarels } 155637224Skarels 155737224Skarels /* 155810294Ssam * Ask the other side for help. 155910294Ssam */ 156010294Ssam rmthelp(argc, argv) 156110294Ssam char *argv[]; 156210294Ssam { 156310294Ssam int oldverbose = verbose; 156410294Ssam 156510294Ssam verbose = 1; 156610294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 156710294Ssam verbose = oldverbose; 156810294Ssam } 156910294Ssam 157010294Ssam /* 157110294Ssam * Terminate session and exit. 157210294Ssam */ 157310294Ssam /*VARARGS*/ 157410294Ssam quit() 157510294Ssam { 157610294Ssam 157718286Sralph if (connected) 157818286Sralph disconnect(); 157926049Sminshall pswitch(1); 158026049Sminshall if (connected) { 158126049Sminshall disconnect(); 158226049Sminshall } 158310294Ssam exit(0); 158410294Ssam } 158510294Ssam 158610294Ssam /* 158710294Ssam * Terminate session, but don't exit. 158810294Ssam */ 158910294Ssam disconnect() 159010294Ssam { 159110294Ssam extern FILE *cout; 159210294Ssam extern int data; 159310294Ssam 159410294Ssam if (!connected) 159510294Ssam return; 159610294Ssam (void) command("QUIT"); 159726049Sminshall if (cout) { 159826049Sminshall (void) fclose(cout); 159926049Sminshall } 160010294Ssam cout = NULL; 160110294Ssam connected = 0; 160210294Ssam data = -1; 160326049Sminshall if (!proxy) { 160426049Sminshall macnum = 0; 160526049Sminshall } 160610294Ssam } 160711353Ssam 160811650Ssam confirm(cmd, file) 160911353Ssam char *cmd, *file; 161011353Ssam { 161111353Ssam char line[BUFSIZ]; 161211353Ssam 161311353Ssam if (!interactive) 161411650Ssam return (1); 161511353Ssam printf("%s %s? ", cmd, file); 161626497Sminshall (void) fflush(stdout); 161726497Sminshall (void) gets(line); 161811650Ssam return (*line != 'n' && *line != 'N'); 161911353Ssam } 162011353Ssam 162111353Ssam fatal(msg) 162211353Ssam char *msg; 162311353Ssam { 162411353Ssam 162526497Sminshall fprintf(stderr, "ftp: %s\n", msg); 162611353Ssam exit(1); 162711353Ssam } 162811353Ssam 162911353Ssam /* 163011353Ssam * Glob a local file name specification with 163111353Ssam * the expectation of a single return value. 163211353Ssam * Can't control multiple values being expanded 163311353Ssam * from the expression, we return only the first. 163411353Ssam */ 163511353Ssam globulize(cpp) 163611353Ssam char **cpp; 163711353Ssam { 163811353Ssam char **globbed; 163911353Ssam 164011353Ssam if (!doglob) 164111353Ssam return (1); 164211353Ssam globbed = glob(*cpp); 164311353Ssam if (globerr != NULL) { 164411353Ssam printf("%s: %s\n", *cpp, globerr); 164536421Sbostic if (globbed) { 164611353Ssam blkfree(globbed); 164738132Srick free((char *)globbed); 164836421Sbostic } 164911353Ssam return (0); 165011353Ssam } 165111353Ssam if (globbed) { 165211353Ssam *cpp = *globbed++; 165311353Ssam /* don't waste too much memory */ 165436421Sbostic if (*globbed) { 165511353Ssam blkfree(globbed); 165638132Srick free((char *)globbed); 165736421Sbostic } 165811353Ssam } 165911353Ssam return (1); 166011353Ssam } 166126049Sminshall 166226049Sminshall account(argc,argv) 166326049Sminshall int argc; 166426049Sminshall char **argv; 166526049Sminshall { 166635658Sbostic char acct[50], *getpass(), *ap; 166726049Sminshall 166826049Sminshall if (argc > 1) { 166926049Sminshall ++argv; 167026049Sminshall --argc; 167126049Sminshall (void) strncpy(acct,*argv,49); 167236268Sbostic acct[49] = '\0'; 167326049Sminshall while (argc > 1) { 167426049Sminshall --argc; 167526049Sminshall ++argv; 167626049Sminshall (void) strncat(acct,*argv, 49-strlen(acct)); 167726049Sminshall } 167826049Sminshall ap = acct; 167926049Sminshall } 168026049Sminshall else { 168135658Sbostic ap = getpass("Account:"); 168226049Sminshall } 168326049Sminshall (void) command("ACCT %s", ap); 168426049Sminshall } 168526049Sminshall 168626049Sminshall jmp_buf abortprox; 168726049Sminshall 168839252Sbostic void 168926049Sminshall proxabort() 169026049Sminshall { 169126049Sminshall extern int proxy; 169226049Sminshall 169326049Sminshall if (!proxy) { 169426049Sminshall pswitch(1); 169526049Sminshall } 169626049Sminshall if (connected) { 169726049Sminshall proxflag = 1; 169826049Sminshall } 169926049Sminshall else { 170026049Sminshall proxflag = 0; 170126049Sminshall } 170226049Sminshall pswitch(0); 170326049Sminshall longjmp(abortprox,1); 170426049Sminshall } 170526049Sminshall 170626049Sminshall doproxy(argc,argv) 170726049Sminshall int argc; 170826049Sminshall char *argv[]; 170926049Sminshall { 171039252Sbostic extern struct cmd cmdtab[]; 171139252Sbostic extern jmp_buf abortprox; 171226049Sminshall register struct cmd *c; 171326049Sminshall struct cmd *getcmd(); 171439252Sbostic sig_t oldintr; 171539252Sbostic void proxabort(); 171626049Sminshall 171726049Sminshall if (argc < 2) { 171826497Sminshall (void) strcat(line, " "); 171926049Sminshall printf("(command) "); 172026497Sminshall (void) gets(&line[strlen(line)]); 172126049Sminshall makeargv(); 172226049Sminshall argc = margc; 172326049Sminshall argv = margv; 172426049Sminshall } 172526049Sminshall if (argc < 2) { 172626049Sminshall printf("usage:%s command\n", argv[0]); 172726049Sminshall code = -1; 172826049Sminshall return; 172926049Sminshall } 173026049Sminshall c = getcmd(argv[1]); 173126049Sminshall if (c == (struct cmd *) -1) { 173226049Sminshall printf("?Ambiguous command\n"); 173326497Sminshall (void) fflush(stdout); 173426049Sminshall code = -1; 173526049Sminshall return; 173626049Sminshall } 173726049Sminshall if (c == 0) { 173826049Sminshall printf("?Invalid command\n"); 173926497Sminshall (void) fflush(stdout); 174026049Sminshall code = -1; 174126049Sminshall return; 174226049Sminshall } 174326049Sminshall if (!c->c_proxy) { 174426049Sminshall printf("?Invalid proxy command\n"); 174526497Sminshall (void) fflush(stdout); 174626049Sminshall code = -1; 174726049Sminshall return; 174826049Sminshall } 174926049Sminshall if (setjmp(abortprox)) { 175026049Sminshall code = -1; 175126049Sminshall return; 175226049Sminshall } 175326049Sminshall oldintr = signal(SIGINT, proxabort); 175426049Sminshall pswitch(1); 175526049Sminshall if (c->c_conn && !connected) { 175626049Sminshall printf("Not connected\n"); 175726497Sminshall (void) fflush(stdout); 175826049Sminshall pswitch(0); 175926049Sminshall (void) signal(SIGINT, oldintr); 176026049Sminshall code = -1; 176126049Sminshall return; 176226049Sminshall } 176326049Sminshall (*c->c_handler)(argc-1, argv+1); 176426049Sminshall if (connected) { 176526049Sminshall proxflag = 1; 176626049Sminshall } 176726049Sminshall else { 176826049Sminshall proxflag = 0; 176926049Sminshall } 177026049Sminshall pswitch(0); 177126049Sminshall (void) signal(SIGINT, oldintr); 177226049Sminshall } 177326049Sminshall 177426049Sminshall setcase() 177526049Sminshall { 177626049Sminshall mcase = !mcase; 177726049Sminshall printf("Case mapping %s.\n", onoff(mcase)); 177826049Sminshall code = mcase; 177926049Sminshall } 178026049Sminshall 178126049Sminshall setcr() 178226049Sminshall { 178326049Sminshall crflag = !crflag; 178426049Sminshall printf("Carriage Return stripping %s.\n", onoff(crflag)); 178526049Sminshall code = crflag; 178626049Sminshall } 178726049Sminshall 178826049Sminshall setntrans(argc,argv) 178926049Sminshall int argc; 179026049Sminshall char *argv[]; 179126049Sminshall { 179226049Sminshall if (argc == 1) { 179326049Sminshall ntflag = 0; 179426049Sminshall printf("Ntrans off.\n"); 179526049Sminshall code = ntflag; 179626049Sminshall return; 179726049Sminshall } 179826049Sminshall ntflag++; 179926049Sminshall code = ntflag; 180026049Sminshall (void) strncpy(ntin, argv[1], 16); 180126049Sminshall ntin[16] = '\0'; 180226049Sminshall if (argc == 2) { 180326049Sminshall ntout[0] = '\0'; 180426049Sminshall return; 180526049Sminshall } 180626049Sminshall (void) strncpy(ntout, argv[2], 16); 180726049Sminshall ntout[16] = '\0'; 180826049Sminshall } 180926049Sminshall 181026049Sminshall char * 181126049Sminshall dotrans(name) 181226049Sminshall char *name; 181326049Sminshall { 181426049Sminshall static char new[MAXPATHLEN]; 181526049Sminshall char *cp1, *cp2 = new; 181626049Sminshall register int i, ostop, found; 181726049Sminshall 181826049Sminshall for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++); 181926049Sminshall for (cp1 = name; *cp1; cp1++) { 182026049Sminshall found = 0; 182126049Sminshall for (i = 0; *(ntin + i) && i < 16; i++) { 182226049Sminshall if (*cp1 == *(ntin + i)) { 182326049Sminshall found++; 182426049Sminshall if (i < ostop) { 182526049Sminshall *cp2++ = *(ntout + i); 182626049Sminshall } 182726049Sminshall break; 182826049Sminshall } 182926049Sminshall } 183026049Sminshall if (!found) { 183126049Sminshall *cp2++ = *cp1; 183226049Sminshall } 183326049Sminshall } 183426049Sminshall *cp2 = '\0'; 183526049Sminshall return(new); 183626049Sminshall } 183726049Sminshall 183826049Sminshall setnmap(argc, argv) 183926049Sminshall int argc; 184026049Sminshall char *argv[]; 184126049Sminshall { 184226049Sminshall char *cp; 184326049Sminshall 184426049Sminshall if (argc == 1) { 184526049Sminshall mapflag = 0; 184626049Sminshall printf("Nmap off.\n"); 184726049Sminshall code = mapflag; 184826049Sminshall return; 184926049Sminshall } 185026049Sminshall if (argc < 3) { 185126497Sminshall (void) strcat(line, " "); 185226049Sminshall printf("(mapout) "); 185326497Sminshall (void) gets(&line[strlen(line)]); 185426049Sminshall makeargv(); 185526049Sminshall argc = margc; 185626049Sminshall argv = margv; 185726049Sminshall } 185826049Sminshall if (argc < 3) { 185926049Sminshall printf("Usage: %s [mapin mapout]\n",argv[0]); 186026049Sminshall code = -1; 186126049Sminshall return; 186226049Sminshall } 186326049Sminshall mapflag = 1; 186426049Sminshall code = 1; 186526049Sminshall cp = index(altarg, ' '); 186626049Sminshall if (proxy) { 186726049Sminshall while(*++cp == ' '); 186826049Sminshall altarg = cp; 186926049Sminshall cp = index(altarg, ' '); 187026049Sminshall } 187126049Sminshall *cp = '\0'; 187226049Sminshall (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 187326049Sminshall while (*++cp == ' '); 187426049Sminshall (void) strncpy(mapout, cp, MAXPATHLEN - 1); 187526049Sminshall } 187626049Sminshall 187726049Sminshall char * 187826049Sminshall domap(name) 187926049Sminshall char *name; 188026049Sminshall { 188126049Sminshall static char new[MAXPATHLEN]; 188226049Sminshall register char *cp1 = name, *cp2 = mapin; 188326049Sminshall char *tp[9], *te[9]; 188436689Scsvsj int i, toks[9], toknum = 0, match = 1; 188526049Sminshall 188626049Sminshall for (i=0; i < 9; ++i) { 188726049Sminshall toks[i] = 0; 188826049Sminshall } 188926049Sminshall while (match && *cp1 && *cp2) { 189026049Sminshall switch (*cp2) { 189126049Sminshall case '\\': 189226049Sminshall if (*++cp2 != *cp1) { 189326049Sminshall match = 0; 189426049Sminshall } 189526049Sminshall break; 189626049Sminshall case '$': 189726049Sminshall if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 189826049Sminshall if (*cp1 != *(++cp2+1)) { 189926049Sminshall toks[toknum = *cp2 - '1']++; 190026049Sminshall tp[toknum] = cp1; 190126049Sminshall while (*++cp1 && *(cp2+1) 190226049Sminshall != *cp1); 190326049Sminshall te[toknum] = cp1; 190426049Sminshall } 190526049Sminshall cp2++; 190626049Sminshall break; 190726049Sminshall } 190836935Skarels /* FALLTHROUGH */ 190926049Sminshall default: 191026049Sminshall if (*cp2 != *cp1) { 191126049Sminshall match = 0; 191226049Sminshall } 191326049Sminshall break; 191426049Sminshall } 191536689Scsvsj if (match && *cp1) { 191626049Sminshall cp1++; 191726049Sminshall } 191836689Scsvsj if (match && *cp2) { 191926049Sminshall cp2++; 192026049Sminshall } 192126049Sminshall } 192236689Scsvsj if (!match && *cp1) /* last token mismatch */ 192336689Scsvsj { 192436689Scsvsj toks[toknum] = 0; 192536689Scsvsj } 192626049Sminshall cp1 = new; 192726049Sminshall *cp1 = '\0'; 192826049Sminshall cp2 = mapout; 192926049Sminshall while (*cp2) { 193026049Sminshall match = 0; 193126049Sminshall switch (*cp2) { 193226049Sminshall case '\\': 193326049Sminshall if (*(cp2 + 1)) { 193426049Sminshall *cp1++ = *++cp2; 193526049Sminshall } 193626049Sminshall break; 193726049Sminshall case '[': 193826049Sminshall LOOP: 193926049Sminshall if (*++cp2 == '$' && isdigit(*(cp2+1))) { 194026049Sminshall if (*++cp2 == '0') { 194126049Sminshall char *cp3 = name; 194226049Sminshall 194326049Sminshall while (*cp3) { 194426049Sminshall *cp1++ = *cp3++; 194526049Sminshall } 194626049Sminshall match = 1; 194726049Sminshall } 194826049Sminshall else if (toks[toknum = *cp2 - '1']) { 194926049Sminshall char *cp3 = tp[toknum]; 195026049Sminshall 195126049Sminshall while (cp3 != te[toknum]) { 195226049Sminshall *cp1++ = *cp3++; 195326049Sminshall } 195426049Sminshall match = 1; 195526049Sminshall } 195626049Sminshall } 195726049Sminshall else { 195826049Sminshall while (*cp2 && *cp2 != ',' && 195926049Sminshall *cp2 != ']') { 196026049Sminshall if (*cp2 == '\\') { 196126049Sminshall cp2++; 196226049Sminshall } 196326049Sminshall else if (*cp2 == '$' && 196426049Sminshall isdigit(*(cp2+1))) { 196526049Sminshall if (*++cp2 == '0') { 196626049Sminshall char *cp3 = name; 196726049Sminshall 196826049Sminshall while (*cp3) { 196926049Sminshall *cp1++ = *cp3++; 197026049Sminshall } 197126049Sminshall } 197226049Sminshall else if (toks[toknum = 197326049Sminshall *cp2 - '1']) { 197426049Sminshall char *cp3=tp[toknum]; 197526049Sminshall 197626049Sminshall while (cp3 != 197726049Sminshall te[toknum]) { 197826049Sminshall *cp1++ = *cp3++; 197926049Sminshall } 198026049Sminshall } 198126049Sminshall } 198226049Sminshall else if (*cp2) { 198326049Sminshall *cp1++ = *cp2++; 198426049Sminshall } 198526049Sminshall } 198626049Sminshall if (!*cp2) { 198726049Sminshall printf("nmap: unbalanced brackets\n"); 198826049Sminshall return(name); 198926049Sminshall } 199026049Sminshall match = 1; 199126049Sminshall cp2--; 199226049Sminshall } 199326049Sminshall if (match) { 199426049Sminshall while (*++cp2 && *cp2 != ']') { 199526049Sminshall if (*cp2 == '\\' && *(cp2 + 1)) { 199626049Sminshall cp2++; 199726049Sminshall } 199826049Sminshall } 199926049Sminshall if (!*cp2) { 200026049Sminshall printf("nmap: unbalanced brackets\n"); 200126049Sminshall return(name); 200226049Sminshall } 200326049Sminshall break; 200426049Sminshall } 200526049Sminshall switch (*++cp2) { 200626049Sminshall case ',': 200726049Sminshall goto LOOP; 200826049Sminshall case ']': 200926049Sminshall break; 201026049Sminshall default: 201126049Sminshall cp2--; 201226049Sminshall goto LOOP; 201326049Sminshall } 201426049Sminshall break; 201526049Sminshall case '$': 201626049Sminshall if (isdigit(*(cp2 + 1))) { 201726049Sminshall if (*++cp2 == '0') { 201826049Sminshall char *cp3 = name; 201926049Sminshall 202026049Sminshall while (*cp3) { 202126049Sminshall *cp1++ = *cp3++; 202226049Sminshall } 202326049Sminshall } 202426049Sminshall else if (toks[toknum = *cp2 - '1']) { 202526049Sminshall char *cp3 = tp[toknum]; 202626049Sminshall 202726049Sminshall while (cp3 != te[toknum]) { 202826049Sminshall *cp1++ = *cp3++; 202926049Sminshall } 203026049Sminshall } 203126049Sminshall break; 203226049Sminshall } 203326049Sminshall /* intentional drop through */ 203426049Sminshall default: 203526049Sminshall *cp1++ = *cp2; 203626049Sminshall break; 203726049Sminshall } 203826049Sminshall cp2++; 203926049Sminshall } 204026049Sminshall *cp1 = '\0'; 204126049Sminshall if (!*new) { 204226049Sminshall return(name); 204326049Sminshall } 204426049Sminshall return(new); 204526049Sminshall } 204626049Sminshall 204726049Sminshall setsunique() 204826049Sminshall { 204926049Sminshall sunique = !sunique; 205026049Sminshall printf("Store unique %s.\n", onoff(sunique)); 205126049Sminshall code = sunique; 205226049Sminshall } 205326049Sminshall 205426049Sminshall setrunique() 205526049Sminshall { 205626049Sminshall runique = !runique; 205726049Sminshall printf("Receive unique %s.\n", onoff(runique)); 205826049Sminshall code = runique; 205926049Sminshall } 206026049Sminshall 206126049Sminshall /* change directory to perent directory */ 206226049Sminshall cdup() 206326049Sminshall { 206437224Skarels if (command("CDUP") == ERROR && code == 500) { 206537224Skarels if (verbose) 206637224Skarels printf("CDUP command not recognized, trying XCUP\n"); 206737224Skarels (void) command("XCUP"); 206837224Skarels } 206926049Sminshall } 207026049Sminshall 207137224Skarels /* restart transfer at specific point */ 207237224Skarels restart(argc, argv) 207337224Skarels int argc; 207437224Skarels char *argv[]; 207537224Skarels { 207637224Skarels extern long atol(); 207737224Skarels if (argc != 2) 207837224Skarels printf("restart: offset not specified\n"); 207937224Skarels else { 208037224Skarels restart_point = atol(argv[1]); 208137224Skarels printf("restarting at %ld. %s\n", restart_point, 208237224Skarels "execute get, put or append to initiate transfer"); 208337224Skarels } 208437224Skarels } 208536935Skarels 208636935Skarels /* show remote system type */ 208736935Skarels syst() 208836935Skarels { 208936935Skarels (void) command("SYST"); 209036935Skarels } 209136935Skarels 209226049Sminshall macdef(argc, argv) 209326049Sminshall int argc; 209426049Sminshall char *argv[]; 209526049Sminshall { 209626049Sminshall char *tmp; 209726049Sminshall int c; 209826049Sminshall 209926049Sminshall if (macnum == 16) { 210026049Sminshall printf("Limit of 16 macros have already been defined\n"); 210126049Sminshall code = -1; 210226049Sminshall return; 210326049Sminshall } 210426049Sminshall if (argc < 2) { 210526497Sminshall (void) strcat(line, " "); 210626049Sminshall printf("(macro name) "); 210726497Sminshall (void) gets(&line[strlen(line)]); 210826049Sminshall makeargv(); 210926049Sminshall argc = margc; 211026049Sminshall argv = margv; 211126049Sminshall } 211226049Sminshall if (argc != 2) { 211326049Sminshall printf("Usage: %s macro_name\n",argv[0]); 211426049Sminshall code = -1; 211526049Sminshall return; 211626049Sminshall } 211726049Sminshall if (interactive) { 211826049Sminshall printf("Enter macro line by line, terminating it with a null line\n"); 211926049Sminshall } 212026497Sminshall (void) strncpy(macros[macnum].mac_name, argv[1], 8); 212126049Sminshall if (macnum == 0) { 212226049Sminshall macros[macnum].mac_start = macbuf; 212326049Sminshall } 212426049Sminshall else { 212526049Sminshall macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 212626049Sminshall } 212726049Sminshall tmp = macros[macnum].mac_start; 212826049Sminshall while (tmp != macbuf+4096) { 212926049Sminshall if ((c = getchar()) == EOF) { 213026049Sminshall printf("macdef:end of file encountered\n"); 213126049Sminshall code = -1; 213226049Sminshall return; 213326049Sminshall } 213426049Sminshall if ((*tmp = c) == '\n') { 213526049Sminshall if (tmp == macros[macnum].mac_start) { 213626049Sminshall macros[macnum++].mac_end = tmp; 213726049Sminshall code = 0; 213826049Sminshall return; 213926049Sminshall } 214026049Sminshall if (*(tmp-1) == '\0') { 214126049Sminshall macros[macnum++].mac_end = tmp - 1; 214226049Sminshall code = 0; 214326049Sminshall return; 214426049Sminshall } 214526049Sminshall *tmp = '\0'; 214626049Sminshall } 214726049Sminshall tmp++; 214826049Sminshall } 214926049Sminshall while (1) { 215036935Skarels while ((c = getchar()) != '\n' && c != EOF) 215136935Skarels /* LOOP */; 215226049Sminshall if (c == EOF || getchar() == '\n') { 215326049Sminshall printf("Macro not defined - 4k buffer exceeded\n"); 215426049Sminshall code = -1; 215526049Sminshall return; 215626049Sminshall } 215726049Sminshall } 215826049Sminshall } 215936935Skarels 216036935Skarels /* 216136935Skarels * get size of file on remote machine 216236935Skarels */ 216336935Skarels sizecmd(argc, argv) 216436935Skarels char *argv[]; 216536935Skarels { 216636935Skarels 216736935Skarels if (argc < 2) { 216836935Skarels (void) strcat(line, " "); 216936935Skarels printf("(filename) "); 217036935Skarels (void) gets(&line[strlen(line)]); 217136935Skarels makeargv(); 217236935Skarels argc = margc; 217336935Skarels argv = margv; 217436935Skarels } 217536935Skarels if (argc < 2) { 217636935Skarels printf("usage:%s filename\n", argv[0]); 217736935Skarels code = -1; 217836935Skarels return; 217936935Skarels } 218036935Skarels (void) command("SIZE %s", argv[1]); 218136935Skarels } 218236935Skarels 218336935Skarels /* 218436935Skarels * get last modification time of file on remote machine 218536935Skarels */ 218636935Skarels modtime(argc, argv) 218736935Skarels char *argv[]; 218836935Skarels { 218936935Skarels int overbose; 219036935Skarels 219136935Skarels if (argc < 2) { 219236935Skarels (void) strcat(line, " "); 219336935Skarels printf("(filename) "); 219436935Skarels (void) gets(&line[strlen(line)]); 219536935Skarels makeargv(); 219636935Skarels argc = margc; 219736935Skarels argv = margv; 219836935Skarels } 219936935Skarels if (argc < 2) { 220036935Skarels printf("usage:%s filename\n", argv[0]); 220136935Skarels code = -1; 220236935Skarels return; 220336935Skarels } 220436940Skarels overbose = verbose; 220536940Skarels if (debug == 0) 220636940Skarels verbose = -1; 220736935Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 220836935Skarels int yy, mo, day, hour, min, sec; 220936935Skarels sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 221036935Skarels &day, &hour, &min, &sec); 221136935Skarels /* might want to print this in local time */ 221236935Skarels printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 221336935Skarels mo, day, yy, hour, min, sec); 221436935Skarels } else 221538132Srick printf("%s\n", reply_string); 221636935Skarels verbose = overbose; 221736935Skarels } 221836935Skarels 221936935Skarels /* 222037224Skarels * show status on reomte machine 222136935Skarels */ 222236935Skarels rmtstatus(argc, argv) 222336935Skarels char *argv[]; 222436935Skarels { 222536935Skarels (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 222636935Skarels } 222737224Skarels 222837224Skarels /* 222937224Skarels * get file if modtime is more recent than current file 223037224Skarels */ 223137224Skarels newer(argc, argv) 223237224Skarels char *argv[]; 223337224Skarels { 223437224Skarels if (getit(argc, argv, -1, "w")) 223537224Skarels printf("Local file \"%s\" is newer than remote file \"%s\"\n", 223637224Skarels argv[1], argv[2]); 223737224Skarels } 2238