121737Sdist /* 262007Sbostic * Copyright (c) 1985, 1989, 1993 362007Sbostic * The Regents of the University of California. All rights reserved. 433737Sbostic * 542665Sbostic * %sccs.include.redist.c% 621737Sdist */ 721737Sdist 810294Ssam #ifndef lint 9*66670Spendry static char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 04/02/94"; 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> 19*66670Spendry #include <netinet/in.h> 2012396Ssam #include <arpa/ftp.h> 2112396Ssam 22*66670Spendry #include <ctype.h> 23*66670Spendry #include <err.h> 24*66670Spendry #include <netdb.h> 2510294Ssam #include <signal.h> 2610294Ssam #include <stdio.h> 27*66670Spendry #include <stdlib.h> 28*66670Spendry #include <string.h> 2936935Skarels #include <time.h> 30*66670Spendry #include <unistd.h> 3110294Ssam 3236940Skarels #include "ftp_var.h" 3337458Skarels #include "pathnames.h" 3410294Ssam 35*66670Spendry jmp_buf jabort; 36*66670Spendry char *mname; 3736935Skarels 3810294Ssam /* 3945260Sbostic * `Another' gets another argument, and stores the new argc and argv. 4045260Sbostic * It reverts to the top level (via main.c's intr()) on EOF/error. 4145260Sbostic * 4245260Sbostic * Returns false if no new arguments have been added. 4345260Sbostic */ 44*66670Spendry int 4545260Sbostic another(pargc, pargv, prompt) 4645260Sbostic int *pargc; 4745260Sbostic char ***pargv; 4845260Sbostic char *prompt; 4945260Sbostic { 5045260Sbostic int len = strlen(line), ret; 5145260Sbostic 5245260Sbostic if (len >= sizeof(line) - 3) { 5345260Sbostic printf("sorry, arguments too long\n"); 5445260Sbostic intr(); 5545260Sbostic } 5645260Sbostic printf("(%s) ", prompt); 5745260Sbostic line[len++] = ' '; 5845260Sbostic if (fgets(&line[len], sizeof(line) - len, stdin) == NULL) 5945260Sbostic intr(); 6045260Sbostic len += strlen(&line[len]); 6145260Sbostic if (len > 0 && line[len - 1] == '\n') 6245260Sbostic line[len - 1] = '\0'; 6345260Sbostic makeargv(); 6445260Sbostic ret = margc > *pargc; 6545260Sbostic *pargc = margc; 6645260Sbostic *pargv = margv; 6745260Sbostic return (ret); 6845260Sbostic } 6945260Sbostic 7045260Sbostic /* 7110294Ssam * Connect to peer server and 7210294Ssam * auto-login, if possible. 7310294Ssam */ 74*66670Spendry void 7510294Ssam setpeer(argc, argv) 7610294Ssam int argc; 7710294Ssam char *argv[]; 7810294Ssam { 79*66670Spendry char *host; 8038132Srick short port; 8110294Ssam 8210294Ssam if (connected) { 8326049Sminshall printf("Already connected to %s, use close first.\n", 8410294Ssam hostname); 8526049Sminshall code = -1; 8610294Ssam return; 8710294Ssam } 8845260Sbostic if (argc < 2) 8945260Sbostic (void) another(&argc, &argv, "to"); 9045260Sbostic if (argc < 2 || argc > 3) { 9110294Ssam printf("usage: %s host-name [port]\n", argv[0]); 9226049Sminshall code = -1; 9310294Ssam return; 9410294Ssam } 9510294Ssam port = sp->s_port; 9610294Ssam if (argc > 2) { 9711218Ssam port = atoi(argv[2]); 9810294Ssam if (port <= 0) { 9911218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 10011218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 10126049Sminshall code = -1; 10210294Ssam return; 10310294Ssam } 10410294Ssam port = htons(port); 10510294Ssam } 10610294Ssam host = hookup(argv[1], port); 10710294Ssam if (host) { 10837228Skarels int overbose; 10937228Skarels 11010294Ssam connected = 1; 11138032Skarels /* 11238032Skarels * Set up defaults for FTP. 11338032Skarels */ 11438032Skarels (void) strcpy(typename, "ascii"), type = TYPE_A; 11538032Skarels curtype = TYPE_A; 11638032Skarels (void) strcpy(formname, "non-print"), form = FORM_N; 11738032Skarels (void) strcpy(modename, "stream"), mode = MODE_S; 11838032Skarels (void) strcpy(structname, "file"), stru = STRU_F; 11938032Skarels (void) strcpy(bytename, "8"), bytesize = 8; 12037228Skarels if (autologin) 12137228Skarels (void) login(argv[1]); 12236940Skarels 12336935Skarels #if defined(unix) && NBBY == 8 12436935Skarels /* 12536935Skarels * this ifdef is to keep someone form "porting" this to an incompatible 12636935Skarels * system and not checking this out. This way they have to think about it. 12736935Skarels */ 12837228Skarels overbose = verbose; 12937228Skarels if (debug == 0) 13037228Skarels verbose = -1; 13137228Skarels if (command("SYST") == COMPLETE && overbose) { 132*66670Spendry char *cp, c; 133*66670Spendry cp = strchr(reply_string+4, ' '); 13437228Skarels if (cp == NULL) 135*66670Spendry cp = strchr(reply_string+4, '\r'); 13637228Skarels if (cp) { 13737228Skarels if (cp[-1] == '.') 13837228Skarels cp--; 13937228Skarels c = *cp; 14037228Skarels *cp = '\0'; 14137228Skarels } 14236935Skarels 14337228Skarels printf("Remote system type is %s.\n", 14437228Skarels reply_string+4); 14537228Skarels if (cp) 14637228Skarels *cp = c; 14737228Skarels } 14837228Skarels if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { 14938032Skarels if (proxy) 15038032Skarels unix_proxy = 1; 15138032Skarels else 15238032Skarels unix_server = 1; 15338032Skarels /* 15438032Skarels * Set type to 0 (not specified by user), 15538032Skarels * meaning binary by default, but don't bother 15638032Skarels * telling server. We can use binary 15738032Skarels * for text files unless changed by the user. 15838032Skarels */ 15938032Skarels type = 0; 16038032Skarels (void) strcpy(typename, "binary"); 16137228Skarels if (overbose) 16237228Skarels printf("Using %s mode to transfer files.\n", 16337228Skarels typename); 16438032Skarels } else { 16538032Skarels if (proxy) 16638032Skarels unix_proxy = 0; 16738032Skarels else 16838032Skarels unix_server = 0; 16938032Skarels if (overbose && 17038032Skarels !strncmp(reply_string, "215 TOPS20", 10)) 17138032Skarels printf( 17236940Skarels "Remember to set tenex mode when transfering binary files from this machine.\n"); 17337228Skarels } 17437228Skarels verbose = overbose; 17536935Skarels #endif /* unix */ 17610294Ssam } 17710294Ssam } 17810294Ssam 17910294Ssam struct types { 18010294Ssam char *t_name; 18110294Ssam char *t_mode; 18210294Ssam int t_type; 18311218Ssam char *t_arg; 18410294Ssam } types[] = { 18511218Ssam { "ascii", "A", TYPE_A, 0 }, 18611218Ssam { "binary", "I", TYPE_I, 0 }, 18711218Ssam { "image", "I", TYPE_I, 0 }, 18811218Ssam { "ebcdic", "E", TYPE_E, 0 }, 18911218Ssam { "tenex", "L", TYPE_L, bytename }, 190*66670Spendry { NULL } 19110294Ssam }; 19210294Ssam 19310294Ssam /* 19410294Ssam * Set transfer type. 19510294Ssam */ 196*66670Spendry void 19710294Ssam settype(argc, argv) 19845260Sbostic int argc; 19910294Ssam char *argv[]; 20010294Ssam { 201*66670Spendry struct types *p; 20211218Ssam int comret; 20310294Ssam 20410294Ssam if (argc > 2) { 20510294Ssam char *sep; 20610294Ssam 20710294Ssam printf("usage: %s [", argv[0]); 20810294Ssam sep = " "; 20910294Ssam for (p = types; p->t_name; p++) { 21010294Ssam printf("%s%s", sep, p->t_name); 21138032Skarels sep = " | "; 21210294Ssam } 21310294Ssam printf(" ]\n"); 21426049Sminshall code = -1; 21510294Ssam return; 21610294Ssam } 21710294Ssam if (argc < 2) { 21810294Ssam printf("Using %s mode to transfer files.\n", typename); 21926049Sminshall code = 0; 22010294Ssam return; 22110294Ssam } 22210294Ssam for (p = types; p->t_name; p++) 22310294Ssam if (strcmp(argv[1], p->t_name) == 0) 22410294Ssam break; 22510294Ssam if (p->t_name == 0) { 22610294Ssam printf("%s: unknown mode\n", argv[1]); 22726049Sminshall code = -1; 22810294Ssam return; 22910294Ssam } 23011218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 23111218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 23211218Ssam else 23311218Ssam comret = command("TYPE %s", p->t_mode); 23411218Ssam if (comret == COMPLETE) { 23526497Sminshall (void) strcpy(typename, p->t_name); 23638032Skarels curtype = type = p->t_type; 23710294Ssam } 23810294Ssam } 23910294Ssam 24010294Ssam /* 24138032Skarels * Internal form of settype; changes current type in use with server 24238032Skarels * without changing our notion of the type for data transfers. 24338032Skarels * Used to change to and from ascii for listings. 24438032Skarels */ 245*66670Spendry void 24638032Skarels changetype(newtype, show) 24738032Skarels int newtype, show; 24838032Skarels { 249*66670Spendry struct types *p; 25038032Skarels int comret, oldverbose = verbose; 25138032Skarels 25238032Skarels if (newtype == 0) 25338032Skarels newtype = TYPE_I; 25438032Skarels if (newtype == curtype) 25538032Skarels return; 25638032Skarels if (debug == 0 && show == 0) 25738032Skarels verbose = 0; 25838032Skarels for (p = types; p->t_name; p++) 25938032Skarels if (newtype == p->t_type) 26038032Skarels break; 26138032Skarels if (p->t_name == 0) { 26238032Skarels printf("ftp: internal error: unknown type %d\n", newtype); 26338032Skarels return; 26438032Skarels } 26538032Skarels if (newtype == TYPE_L && bytename[0] != '\0') 26638032Skarels comret = command("TYPE %s %s", p->t_mode, bytename); 26738032Skarels else 26838032Skarels comret = command("TYPE %s", p->t_mode); 26938032Skarels if (comret == COMPLETE) 27038032Skarels curtype = newtype; 27138032Skarels verbose = oldverbose; 27238032Skarels } 27338032Skarels 27438132Srick char *stype[] = { 27538132Srick "type", 27638132Srick "", 27738132Srick 0 27838132Srick }; 27938132Srick 28038032Skarels /* 28110294Ssam * Set binary transfer type. 28210294Ssam */ 28310294Ssam /*VARARGS*/ 284*66670Spendry void 285*66670Spendry setbinary(argc, argv) 286*66670Spendry int argc; 287*66670Spendry char **argv; 28810294Ssam { 289*66670Spendry 29038132Srick stype[1] = "binary"; 29138132Srick settype(2, stype); 29210294Ssam } 29310294Ssam 29410294Ssam /* 29510294Ssam * Set ascii transfer type. 29610294Ssam */ 29710294Ssam /*VARARGS*/ 298*66670Spendry void 299*66670Spendry setascii(argc, argv) 300*66670Spendry int argc; 301*66670Spendry char *argv[]; 30210294Ssam { 303*66670Spendry 30438132Srick stype[1] = "ascii"; 30538132Srick settype(2, stype); 30610294Ssam } 30710294Ssam 30810294Ssam /* 30910294Ssam * Set tenex transfer type. 31010294Ssam */ 31110294Ssam /*VARARGS*/ 312*66670Spendry void 313*66670Spendry settenex(argc, argv) 314*66670Spendry int argc; 315*66670Spendry char *argv[]; 31610294Ssam { 317*66670Spendry 31838132Srick stype[1] = "tenex"; 31938132Srick settype(2, stype); 32010294Ssam } 32110294Ssam 32210294Ssam /* 32310294Ssam * Set file transfer mode. 32410294Ssam */ 32526497Sminshall /*ARGSUSED*/ 326*66670Spendry void 327*66670Spendry setftmode(argc, argv) 32845260Sbostic int argc; 32910294Ssam char *argv[]; 33010294Ssam { 33110294Ssam 33210294Ssam printf("We only support %s mode, sorry.\n", modename); 33326049Sminshall code = -1; 33410294Ssam } 33510294Ssam 33610294Ssam /* 33710294Ssam * Set file transfer format. 33810294Ssam */ 33926497Sminshall /*ARGSUSED*/ 340*66670Spendry void 34110294Ssam setform(argc, argv) 34245260Sbostic int argc; 34310294Ssam char *argv[]; 34410294Ssam { 34510294Ssam 34610294Ssam printf("We only support %s format, sorry.\n", formname); 34726049Sminshall code = -1; 34810294Ssam } 34910294Ssam 35010294Ssam /* 35110294Ssam * Set file transfer structure. 35210294Ssam */ 35326497Sminshall /*ARGSUSED*/ 354*66670Spendry void 35510294Ssam setstruct(argc, argv) 35645260Sbostic int argc; 35710294Ssam char *argv[]; 35810294Ssam { 35910294Ssam 36010294Ssam printf("We only support %s structure, sorry.\n", structname); 36126049Sminshall code = -1; 36210294Ssam } 36310294Ssam 36418286Sralph /* 36518286Sralph * Send a single file. 36618286Sralph */ 367*66670Spendry void 36810294Ssam put(argc, argv) 36911756Ssam int argc; 37010294Ssam char *argv[]; 37110294Ssam { 37211650Ssam char *cmd; 37326049Sminshall int loc = 0; 37437225Skarels char *oldargv1, *oldargv2; 37511650Ssam 37626049Sminshall if (argc == 2) { 37726049Sminshall argc++; 37826049Sminshall argv[2] = argv[1]; 37926049Sminshall loc++; 38026049Sminshall } 38145260Sbostic if (argc < 2 && !another(&argc, &argv, "local-file")) 38245260Sbostic goto usage; 38345260Sbostic if (argc < 3 && !another(&argc, &argv, "remote-file")) { 38410294Ssam usage: 38545260Sbostic printf("usage: %s local-file remote-file\n", argv[0]); 38626049Sminshall code = -1; 38710294Ssam return; 38810294Ssam } 38925908Smckusick oldargv1 = argv[1]; 39037225Skarels oldargv2 = argv[2]; 39126049Sminshall if (!globulize(&argv[1])) { 39226049Sminshall code = -1; 39311353Ssam return; 39426049Sminshall } 39525908Smckusick /* 39625908Smckusick * If "globulize" modifies argv[1], and argv[2] is a copy of 39725908Smckusick * the old argv[1], make it a copy of the new argv[1]. 39825908Smckusick */ 39926049Sminshall if (argv[1] != oldargv1 && argv[2] == oldargv1) { 40025908Smckusick argv[2] = argv[1]; 40126049Sminshall } 40226049Sminshall cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); 40326049Sminshall if (loc && ntflag) { 40426049Sminshall argv[2] = dotrans(argv[2]); 40526049Sminshall } 40626049Sminshall if (loc && mapflag) { 40726049Sminshall argv[2] = domap(argv[2]); 40826049Sminshall } 40937225Skarels sendrequest(cmd, argv[1], argv[2], 41037225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 41110294Ssam } 41210294Ssam 41310294Ssam /* 41411756Ssam * Send multiple files. 41510294Ssam */ 416*66670Spendry void 41711353Ssam mput(argc, argv) 41839252Sbostic int argc; 41939252Sbostic char **argv; 42011353Ssam { 421*66670Spendry int i; 42239252Sbostic sig_t oldintr; 42338132Srick int ointer; 42426049Sminshall char *tp; 42511353Ssam 42645260Sbostic if (argc < 2 && !another(&argc, &argv, "local-files")) { 42745260Sbostic printf("usage: %s local-files\n", argv[0]); 42826049Sminshall code = -1; 42911353Ssam return; 43011353Ssam } 43126049Sminshall mname = argv[0]; 43226049Sminshall mflag = 1; 43326049Sminshall oldintr = signal(SIGINT, mabort); 43426049Sminshall (void) setjmp(jabort); 43526049Sminshall if (proxy) { 43626049Sminshall char *cp, *tp2, tmpbuf[MAXPATHLEN]; 43726049Sminshall 43826497Sminshall while ((cp = remglob(argv,0)) != NULL) { 43926049Sminshall if (*cp == 0) { 44026049Sminshall mflag = 0; 44126049Sminshall continue; 44226049Sminshall } 44326049Sminshall if (mflag && confirm(argv[0], cp)) { 44426049Sminshall tp = cp; 44526049Sminshall if (mcase) { 44626049Sminshall while (*tp && !islower(*tp)) { 44726049Sminshall tp++; 44826049Sminshall } 44926049Sminshall if (!*tp) { 45026049Sminshall tp = cp; 45126049Sminshall tp2 = tmpbuf; 45226049Sminshall while ((*tp2 = *tp) != NULL) { 45326049Sminshall if (isupper(*tp2)) { 45426049Sminshall *tp2 = 'a' + *tp2 - 'A'; 45526049Sminshall } 45626049Sminshall tp++; 45726049Sminshall tp2++; 45826049Sminshall } 45926049Sminshall } 46026049Sminshall tp = tmpbuf; 46126049Sminshall } 46226049Sminshall if (ntflag) { 46326049Sminshall tp = dotrans(tp); 46426049Sminshall } 46526049Sminshall if (mapflag) { 46626049Sminshall tp = domap(tp); 46726049Sminshall } 46837225Skarels sendrequest((sunique) ? "STOU" : "STOR", 46937225Skarels cp, tp, cp != tp || !interactive); 47026049Sminshall if (!mflag && fromatty) { 47126049Sminshall ointer = interactive; 47226049Sminshall interactive = 1; 47326049Sminshall if (confirm("Continue with","mput")) { 47426049Sminshall mflag++; 47526049Sminshall } 47626049Sminshall interactive = ointer; 47726049Sminshall } 47826049Sminshall } 47926049Sminshall } 48026049Sminshall (void) signal(SIGINT, oldintr); 48126049Sminshall mflag = 0; 48226049Sminshall return; 48326049Sminshall } 48413212Ssam for (i = 1; i < argc; i++) { 485*66670Spendry char **cpp, **gargs; 48613212Ssam 48713212Ssam if (!doglob) { 48826049Sminshall if (mflag && confirm(argv[0], argv[i])) { 48926049Sminshall tp = (ntflag) ? dotrans(argv[i]) : argv[i]; 49026049Sminshall tp = (mapflag) ? domap(tp) : tp; 49126049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 49237225Skarels argv[i], tp, tp != argv[i] || !interactive); 49326049Sminshall if (!mflag && fromatty) { 49426049Sminshall ointer = interactive; 49526049Sminshall interactive = 1; 49626049Sminshall if (confirm("Continue with","mput")) { 49726049Sminshall mflag++; 49826049Sminshall } 49926049Sminshall interactive = ointer; 50026049Sminshall } 50126049Sminshall } 50213212Ssam continue; 50313212Ssam } 50447024Sbostic gargs = ftpglob(argv[i]); 50511650Ssam if (globerr != NULL) { 50611650Ssam printf("%s\n", globerr); 50736421Sbostic if (gargs) { 50811650Ssam blkfree(gargs); 50938132Srick free((char *)gargs); 51036421Sbostic } 51113212Ssam continue; 51211353Ssam } 51326049Sminshall for (cpp = gargs; cpp && *cpp != NULL; cpp++) { 51426049Sminshall if (mflag && confirm(argv[0], *cpp)) { 51526049Sminshall tp = (ntflag) ? dotrans(*cpp) : *cpp; 51626049Sminshall tp = (mapflag) ? domap(tp) : tp; 51726049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 51837225Skarels *cpp, tp, *cpp != tp || !interactive); 51926049Sminshall if (!mflag && fromatty) { 52026049Sminshall ointer = interactive; 52126049Sminshall interactive = 1; 52226049Sminshall if (confirm("Continue with","mput")) { 52326049Sminshall mflag++; 52426049Sminshall } 52526049Sminshall interactive = ointer; 52626049Sminshall } 52726049Sminshall } 52826049Sminshall } 52936421Sbostic if (gargs != NULL) { 53013212Ssam blkfree(gargs); 53138132Srick free((char *)gargs); 53236421Sbostic } 53311353Ssam } 53426049Sminshall (void) signal(SIGINT, oldintr); 53526049Sminshall mflag = 0; 53611353Ssam } 53711353Ssam 538*66670Spendry void 53937224Skarels reget(argc, argv) 54045260Sbostic int argc; 54137224Skarels char *argv[]; 54237224Skarels { 543*66670Spendry 54437224Skarels (void) getit(argc, argv, 1, "r+w"); 54537224Skarels } 54636935Skarels 547*66670Spendry void 54837224Skarels get(argc, argv) 54945260Sbostic int argc; 55037224Skarels char *argv[]; 55137224Skarels { 552*66670Spendry 55337224Skarels (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" ); 55437224Skarels } 55537224Skarels 55611353Ssam /* 55711353Ssam * Receive one file. 55811353Ssam */ 559*66670Spendry int 56037224Skarels getit(argc, argv, restartit, mode) 56145260Sbostic int argc; 56210294Ssam char *argv[]; 56337224Skarels char *mode; 564*66670Spendry int restartit; 56510294Ssam { 56626049Sminshall int loc = 0; 56737225Skarels char *oldargv1, *oldargv2; 56810294Ssam 56926049Sminshall if (argc == 2) { 57026049Sminshall argc++; 57126049Sminshall argv[2] = argv[1]; 57226049Sminshall loc++; 57326049Sminshall } 57445260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-file")) 57545260Sbostic goto usage; 57645260Sbostic if (argc < 3 && !another(&argc, &argv, "local-file")) { 57710294Ssam usage: 57826049Sminshall printf("usage: %s remote-file [ local-file ]\n", argv[0]); 57926049Sminshall code = -1; 58037224Skarels return (0); 58110294Ssam } 58237225Skarels oldargv1 = argv[1]; 58337225Skarels oldargv2 = argv[2]; 58426049Sminshall if (!globulize(&argv[2])) { 58526049Sminshall code = -1; 58637224Skarels return (0); 58726049Sminshall } 58826049Sminshall if (loc && mcase) { 58926049Sminshall char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; 59026049Sminshall 59126049Sminshall while (*tp && !islower(*tp)) { 59226049Sminshall tp++; 59326049Sminshall } 59426049Sminshall if (!*tp) { 59526049Sminshall tp = argv[2]; 59626049Sminshall tp2 = tmpbuf; 59726049Sminshall while ((*tp2 = *tp) != NULL) { 59826049Sminshall if (isupper(*tp2)) { 59926049Sminshall *tp2 = 'a' + *tp2 - 'A'; 60026049Sminshall } 60126049Sminshall tp++; 60226049Sminshall tp2++; 60326049Sminshall } 60426049Sminshall argv[2] = tmpbuf; 60526049Sminshall } 60626049Sminshall } 60736940Skarels if (loc && ntflag) 60826049Sminshall argv[2] = dotrans(argv[2]); 60936940Skarels if (loc && mapflag) 61026049Sminshall argv[2] = domap(argv[2]); 61137224Skarels if (restartit) { 61237224Skarels struct stat stbuf; 61337224Skarels int ret; 61437224Skarels 61537224Skarels ret = stat(argv[2], &stbuf); 61637224Skarels if (restartit == 1) { 61737224Skarels if (ret < 0) { 618*66670Spendry warn("local: %s", argv[2]); 61937224Skarels return (0); 62037224Skarels } 62137224Skarels restart_point = stbuf.st_size; 62237224Skarels } else { 62337224Skarels if (ret == 0) { 62437224Skarels int overbose; 62537224Skarels 62637224Skarels overbose = verbose; 62737224Skarels if (debug == 0) 62837224Skarels verbose = -1; 62937224Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 63037224Skarels int yy, mo, day, hour, min, sec; 63137224Skarels struct tm *tm; 63237224Skarels verbose = overbose; 63337224Skarels sscanf(reply_string, 63437224Skarels "%*s %04d%02d%02d%02d%02d%02d", 63537224Skarels &yy, &mo, &day, &hour, &min, &sec); 63637224Skarels tm = gmtime(&stbuf.st_mtime); 63737224Skarels tm->tm_mon++; 63837224Skarels if (tm->tm_year > yy%100) 63937224Skarels return (1); 64054056Sandrew if ((tm->tm_year == yy%100 && 64154056Sandrew tm->tm_mon > mo) || 64254056Sandrew (tm->tm_mon == mo && 64354056Sandrew tm->tm_mday > day) || 64454056Sandrew (tm->tm_mday == day && 64554056Sandrew tm->tm_hour > hour) || 64654056Sandrew (tm->tm_hour == hour && 64754056Sandrew tm->tm_min > min) || 64854056Sandrew (tm->tm_min == min && 64954056Sandrew tm->tm_sec > sec)) 65054056Sandrew return (1); 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 666*66670Spendry /* ARGSUSED */ 66739252Sbostic void 668*66670Spendry mabort(signo) 669*66670Spendry int signo; 67026049Sminshall { 67126049Sminshall int ointer; 67226049Sminshall 67326049Sminshall printf("\n"); 67426049Sminshall (void) fflush(stdout); 67526049Sminshall if (mflag && fromatty) { 67626049Sminshall ointer = interactive; 67726049Sminshall interactive = 1; 67826049Sminshall if (confirm("Continue with", mname)) { 67926049Sminshall interactive = ointer; 68026049Sminshall longjmp(jabort,0); 68126049Sminshall } 68226049Sminshall interactive = ointer; 68326049Sminshall } 68426049Sminshall mflag = 0; 68526049Sminshall longjmp(jabort,0); 68626049Sminshall } 68726049Sminshall 68811353Ssam /* 68911353Ssam * Get multiple files. 69011353Ssam */ 691*66670Spendry void 69211353Ssam mget(argc, argv) 69339252Sbostic int argc; 69439252Sbostic char **argv; 69511353Ssam { 69639252Sbostic sig_t oldintr; 69754056Sandrew int ch, ointer; 69826049Sminshall char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; 69911353Ssam 70045260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) { 70145260Sbostic printf("usage: %s remote-files\n", argv[0]); 70226049Sminshall code = -1; 70311353Ssam return; 70411353Ssam } 70526049Sminshall mname = argv[0]; 70626049Sminshall mflag = 1; 707*66670Spendry oldintr = signal(SIGINT, mabort); 70826049Sminshall (void) setjmp(jabort); 70926497Sminshall while ((cp = remglob(argv,proxy)) != NULL) { 71026049Sminshall if (*cp == '\0') { 71126049Sminshall mflag = 0; 71226049Sminshall continue; 71326049Sminshall } 71426049Sminshall if (mflag && confirm(argv[0], cp)) { 71526049Sminshall tp = cp; 71626049Sminshall if (mcase) { 71754056Sandrew for (tp2 = tmpbuf; ch = *tp++;) 71854056Sandrew *tp2++ = isupper(ch) ? tolower(ch) : ch; 71926049Sminshall tp = tmpbuf; 72026049Sminshall } 72126049Sminshall if (ntflag) { 72226049Sminshall tp = dotrans(tp); 72326049Sminshall } 72426049Sminshall if (mapflag) { 72526049Sminshall tp = domap(tp); 72626049Sminshall } 72737225Skarels recvrequest("RETR", tp, cp, "w", 72837225Skarels tp != cp || !interactive); 72926049Sminshall if (!mflag && fromatty) { 73026049Sminshall ointer = interactive; 73126049Sminshall interactive = 1; 73226049Sminshall if (confirm("Continue with","mget")) { 73326049Sminshall mflag++; 73426049Sminshall } 73526049Sminshall interactive = ointer; 73626049Sminshall } 73726049Sminshall } 73826049Sminshall } 73926049Sminshall (void) signal(SIGINT,oldintr); 74026049Sminshall mflag = 0; 74111650Ssam } 74211650Ssam 74311650Ssam char * 74426497Sminshall remglob(argv,doswitch) 74511650Ssam char *argv[]; 74626497Sminshall int doswitch; 74711650Ssam { 74811756Ssam char temp[16]; 74911650Ssam static char buf[MAXPATHLEN]; 75011650Ssam static FILE *ftemp = NULL; 75111650Ssam static char **args; 75213212Ssam int oldverbose, oldhash; 75311756Ssam char *cp, *mode; 75411650Ssam 75526049Sminshall if (!mflag) { 75626049Sminshall if (!doglob) { 75726049Sminshall args = NULL; 75826049Sminshall } 75926049Sminshall else { 76026049Sminshall if (ftemp) { 76126497Sminshall (void) fclose(ftemp); 76226049Sminshall ftemp = NULL; 76326049Sminshall } 76426049Sminshall } 765*66670Spendry return (NULL); 76626049Sminshall } 76711650Ssam if (!doglob) { 76811756Ssam if (args == NULL) 76911650Ssam args = argv; 77011650Ssam if ((cp = *++args) == NULL) 77111650Ssam args = NULL; 77211650Ssam return (cp); 77311353Ssam } 77411650Ssam if (ftemp == NULL) { 77537458Skarels (void) strcpy(temp, _PATH_TMP); 77626497Sminshall (void) mktemp(temp); 77711650Ssam oldverbose = verbose, verbose = 0; 77813212Ssam oldhash = hash, hash = 0; 77926049Sminshall if (doswitch) { 78026049Sminshall pswitch(!proxy); 78126049Sminshall } 78211756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 78337225Skarels recvrequest ("NLST", temp, *argv, mode, 0); 78426049Sminshall if (doswitch) { 78526049Sminshall pswitch(!proxy); 78626049Sminshall } 78713212Ssam verbose = oldverbose; hash = oldhash; 78811650Ssam ftemp = fopen(temp, "r"); 78926497Sminshall (void) unlink(temp); 79011650Ssam if (ftemp == NULL) { 79111650Ssam printf("can't find list of remote files, oops\n"); 79211756Ssam return (NULL); 79311353Ssam } 79411353Ssam } 79511650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 79626497Sminshall (void) fclose(ftemp), ftemp = NULL; 79711650Ssam return (NULL); 79811353Ssam } 799*66670Spendry if ((cp = strchr(buf, '\n')) != NULL) 80011650Ssam *cp = '\0'; 80111650Ssam return (buf); 80211353Ssam } 80311353Ssam 80410294Ssam char * 80510294Ssam onoff(bool) 80610294Ssam int bool; 80710294Ssam { 80810294Ssam 80910294Ssam return (bool ? "on" : "off"); 81010294Ssam } 81110294Ssam 81210294Ssam /* 81310294Ssam * Show status. 81410294Ssam */ 81526497Sminshall /*ARGSUSED*/ 816*66670Spendry void 81710294Ssam status(argc, argv) 81845260Sbostic int argc; 81910294Ssam char *argv[]; 82010294Ssam { 82126049Sminshall int i; 82210294Ssam 82310294Ssam if (connected) 82410294Ssam printf("Connected to %s.\n", hostname); 82510294Ssam else 82610294Ssam printf("Not connected.\n"); 82726049Sminshall if (!proxy) { 82826049Sminshall pswitch(1); 82926049Sminshall if (connected) { 83026049Sminshall printf("Connected for proxy commands to %s.\n", hostname); 83126049Sminshall } 83226049Sminshall else { 83326049Sminshall printf("No proxy connection.\n"); 83426049Sminshall } 83526049Sminshall pswitch(0); 83626049Sminshall } 83710294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 83810294Ssam modename, typename, formname, structname); 83911353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 84011353Ssam onoff(verbose), onoff(bell), onoff(interactive), 84111353Ssam onoff(doglob)); 84226049Sminshall printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), 84326049Sminshall onoff(runique)); 84426049Sminshall printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); 84526049Sminshall if (ntflag) { 84626049Sminshall printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); 84726049Sminshall } 84826049Sminshall else { 84926049Sminshall printf("Ntrans: off\n"); 85026049Sminshall } 85126049Sminshall if (mapflag) { 85226049Sminshall printf("Nmap: (in) %s (out) %s\n", mapin, mapout); 85326049Sminshall } 85426049Sminshall else { 85526049Sminshall printf("Nmap: off\n"); 85626049Sminshall } 85714143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 85814143Ssam onoff(hash), onoff(sendport)); 85926049Sminshall if (macnum > 0) { 86026049Sminshall printf("Macros:\n"); 86126049Sminshall for (i=0; i<macnum; i++) { 86226049Sminshall printf("\t%s\n",macros[i].mac_name); 86326049Sminshall } 86426049Sminshall } 86526049Sminshall code = 0; 86610294Ssam } 86710294Ssam 86810294Ssam /* 86910294Ssam * Set beep on cmd completed mode. 87010294Ssam */ 87110294Ssam /*VARARGS*/ 872*66670Spendry void 873*66670Spendry setbell(argc, argv) 874*66670Spendry int argc; 875*66670Spendry char *argv[]; 87610294Ssam { 87710294Ssam 87810294Ssam bell = !bell; 87910294Ssam printf("Bell mode %s.\n", onoff(bell)); 88026049Sminshall code = bell; 88110294Ssam } 88210294Ssam 88310294Ssam /* 88410294Ssam * Turn on packet tracing. 88510294Ssam */ 88610294Ssam /*VARARGS*/ 887*66670Spendry void 888*66670Spendry settrace(argc, argv) 889*66670Spendry int argc; 890*66670Spendry char *argv[]; 89110294Ssam { 89210294Ssam 89310294Ssam trace = !trace; 89410294Ssam printf("Packet tracing %s.\n", onoff(trace)); 89526049Sminshall code = trace; 89610294Ssam } 89710294Ssam 89810294Ssam /* 89911650Ssam * Toggle hash mark printing during transfers. 90011650Ssam */ 90111650Ssam /*VARARGS*/ 902*66670Spendry void 903*66670Spendry sethash(argc, argv) 904*66670Spendry int argc; 905*66670Spendry char *argv[]; 90611650Ssam { 90711650Ssam 90811650Ssam hash = !hash; 90911650Ssam printf("Hash mark printing %s", onoff(hash)); 91026049Sminshall code = hash; 91111650Ssam if (hash) 91237224Skarels printf(" (%d bytes/hash mark)", 1024); 91311650Ssam printf(".\n"); 91411650Ssam } 91511650Ssam 91611650Ssam /* 91710294Ssam * Turn on printing of server echo's. 91810294Ssam */ 91910294Ssam /*VARARGS*/ 920*66670Spendry void 921*66670Spendry setverbose(argc, argv) 922*66670Spendry int argc; 923*66670Spendry char *argv[]; 92410294Ssam { 92510294Ssam 92610294Ssam verbose = !verbose; 92710294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 92826049Sminshall code = verbose; 92910294Ssam } 93010294Ssam 93110294Ssam /* 93211650Ssam * Toggle PORT cmd use before each data connection. 93311650Ssam */ 93411650Ssam /*VARARGS*/ 935*66670Spendry void 936*66670Spendry setport(argc, argv) 937*66670Spendry int argc; 938*66670Spendry char *argv[]; 93911650Ssam { 94011650Ssam 94111650Ssam sendport = !sendport; 94211650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 94326049Sminshall code = sendport; 94411650Ssam } 94511650Ssam 94611650Ssam /* 94710294Ssam * Turn on interactive prompting 94810294Ssam * during mget, mput, and mdelete. 94910294Ssam */ 95010294Ssam /*VARARGS*/ 951*66670Spendry void 952*66670Spendry setprompt(argc, argv) 953*66670Spendry int argc; 954*66670Spendry char *argv[]; 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*/ 967*66670Spendry void 968*66670Spendry setglob(argc, argv) 969*66670Spendry int argc; 970*66670Spendry char *argv[]; 97111353Ssam { 97211353Ssam 97311353Ssam doglob = !doglob; 97411353Ssam printf("Globbing %s.\n", onoff(doglob)); 97526049Sminshall code = doglob; 97611353Ssam } 97711353Ssam 97811353Ssam /* 97910294Ssam * Set debugging mode on/off and/or 98010294Ssam * set level of debugging. 98110294Ssam */ 98211756Ssam /*VARARGS*/ 983*66670Spendry void 98410294Ssam setdebug(argc, argv) 98545260Sbostic int argc; 98610294Ssam char *argv[]; 98710294Ssam { 98810294Ssam int val; 98910294Ssam 99010294Ssam if (argc > 1) { 99110294Ssam val = atoi(argv[1]); 99210294Ssam if (val < 0) { 99310294Ssam printf("%s: bad debugging value.\n", argv[1]); 99426049Sminshall code = -1; 99510294Ssam return; 99610294Ssam } 99710294Ssam } else 99810294Ssam val = !debug; 99910294Ssam debug = val; 100010294Ssam if (debug) 100110294Ssam options |= SO_DEBUG; 100210294Ssam else 100310294Ssam options &= ~SO_DEBUG; 100410294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 100526049Sminshall code = debug > 0; 100610294Ssam } 100710294Ssam 100810294Ssam /* 100910294Ssam * Set current working directory 101010294Ssam * on remote machine. 101110294Ssam */ 1012*66670Spendry void 101310294Ssam cd(argc, argv) 101445260Sbostic int argc; 101510294Ssam char *argv[]; 101610294Ssam { 101710294Ssam 101845260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-directory")) { 101945260Sbostic printf("usage: %s remote-directory\n", argv[0]); 102026049Sminshall code = -1; 102110294Ssam return; 102210294Ssam } 102337224Skarels if (command("CWD %s", argv[1]) == ERROR && code == 500) { 102437224Skarels if (verbose) 102537224Skarels printf("CWD command not recognized, trying XCWD\n"); 102637224Skarels (void) command("XCWD %s", argv[1]); 102737224Skarels } 102810294Ssam } 102910294Ssam 103010294Ssam /* 103110294Ssam * Set current working directory 103210294Ssam * on local machine. 103310294Ssam */ 1034*66670Spendry void 103510294Ssam lcd(argc, argv) 103645260Sbostic int argc; 103710294Ssam char *argv[]; 103810294Ssam { 103911353Ssam char buf[MAXPATHLEN]; 104010294Ssam 104111353Ssam if (argc < 2) 104211353Ssam argc++, argv[1] = home; 104310294Ssam if (argc != 2) { 104445260Sbostic 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) { 1053*66670Spendry warn("local: %s", argv[1]); 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 */ 1064*66670Spendry void 106510294Ssam delete(argc, argv) 106645260Sbostic int argc; 106710294Ssam char *argv[]; 106810294Ssam { 106910294Ssam 107045260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-file")) { 107145260Sbostic printf("usage: %s remote-file\n", argv[0]); 107226049Sminshall code = -1; 107310294Ssam return; 107410294Ssam } 107510294Ssam (void) command("DELE %s", argv[1]); 107610294Ssam } 107710294Ssam 107810294Ssam /* 107911650Ssam * Delete multiple files. 108011650Ssam */ 1081*66670Spendry void 108211650Ssam mdelete(argc, argv) 108339252Sbostic int argc; 108439252Sbostic char **argv; 108511650Ssam { 108639252Sbostic sig_t oldintr; 108739252Sbostic int ointer; 108811650Ssam char *cp; 108911650Ssam 109045260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) { 109145260Sbostic printf("usage: %s remote-files\n", argv[0]); 109226049Sminshall code = -1; 109311650Ssam return; 109411650Ssam } 109526049Sminshall mname = argv[0]; 109626049Sminshall mflag = 1; 109726049Sminshall oldintr = signal(SIGINT, mabort); 109826049Sminshall (void) setjmp(jabort); 109926497Sminshall while ((cp = remglob(argv,0)) != NULL) { 110026049Sminshall if (*cp == '\0') { 110126049Sminshall mflag = 0; 110226049Sminshall continue; 110326049Sminshall } 110426049Sminshall if (mflag && confirm(argv[0], cp)) { 110511650Ssam (void) command("DELE %s", cp); 110626049Sminshall if (!mflag && fromatty) { 110726049Sminshall ointer = interactive; 110826049Sminshall interactive = 1; 110926049Sminshall if (confirm("Continue with", "mdelete")) { 111026049Sminshall mflag++; 111126049Sminshall } 111226049Sminshall interactive = ointer; 111326049Sminshall } 111426049Sminshall } 111526049Sminshall } 111626049Sminshall (void) signal(SIGINT, oldintr); 111726049Sminshall mflag = 0; 111811650Ssam } 111911756Ssam 112011650Ssam /* 112110294Ssam * Rename a remote file. 112210294Ssam */ 1123*66670Spendry void 112410294Ssam renamefile(argc, argv) 112545260Sbostic int argc; 112610294Ssam char *argv[]; 112710294Ssam { 112810294Ssam 112945260Sbostic if (argc < 2 && !another(&argc, &argv, "from-name")) 113045260Sbostic goto usage; 113145260Sbostic if (argc < 3 && !another(&argc, &argv, "to-name")) { 113210294Ssam usage: 113310294Ssam printf("%s from-name to-name\n", argv[0]); 113426049Sminshall code = -1; 113510294Ssam return; 113610294Ssam } 113710294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 113810294Ssam (void) command("RNTO %s", argv[2]); 113910294Ssam } 114010294Ssam 114110294Ssam /* 114210294Ssam * Get a directory listing 114310294Ssam * of remote files. 114410294Ssam */ 1145*66670Spendry void 114610294Ssam ls(argc, argv) 114745260Sbostic int argc; 114810294Ssam char *argv[]; 114910294Ssam { 115011756Ssam char *cmd; 115110294Ssam 115210294Ssam if (argc < 2) 115310294Ssam argc++, argv[1] = NULL; 115410294Ssam if (argc < 3) 115510294Ssam argc++, argv[2] = "-"; 115611756Ssam if (argc > 3) { 115711756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 115826049Sminshall code = -1; 115911756Ssam return; 116011756Ssam } 116136935Skarels cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 116226049Sminshall if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 116326049Sminshall code = -1; 116411353Ssam return; 116526049Sminshall } 116632344Scsvsj if (strcmp(argv[2], "-") && *argv[2] != '|') 116732344Scsvsj if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { 116832344Scsvsj code = -1; 116932344Scsvsj return; 117032344Scsvsj } 117137225Skarels recvrequest(cmd, argv[2], argv[1], "w", 0); 117210294Ssam } 117310294Ssam 117410294Ssam /* 117511756Ssam * Get a directory listing 117611756Ssam * of multiple remote files. 117711756Ssam */ 1178*66670Spendry void 117911756Ssam mls(argc, argv) 118039252Sbostic int argc; 118139252Sbostic char **argv; 118211756Ssam { 118339252Sbostic sig_t oldintr; 118439252Sbostic int ointer, i; 118526049Sminshall char *cmd, mode[1], *dest; 118611756Ssam 118745260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) 118845260Sbostic goto usage; 118945260Sbostic if (argc < 3 && !another(&argc, &argv, "local-file")) { 119045260Sbostic usage: 119145260Sbostic printf("usage: %s remote-files local-file\n", argv[0]); 119226049Sminshall code = -1; 119313212Ssam return; 119413212Ssam } 119513212Ssam dest = argv[argc - 1]; 119613212Ssam argv[argc - 1] = NULL; 119726049Sminshall if (strcmp(dest, "-") && *dest != '|') 119845260Sbostic if (!globulize(&dest) || 119945260Sbostic !confirm("output to local-file:", dest)) { 120026049Sminshall code = -1; 120113212Ssam return; 120226049Sminshall } 120336940Skarels cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 120426049Sminshall mname = argv[0]; 120526049Sminshall mflag = 1; 120626049Sminshall oldintr = signal(SIGINT, mabort); 120726049Sminshall (void) setjmp(jabort); 120826049Sminshall for (i = 1; mflag && i < argc-1; ++i) { 120926049Sminshall *mode = (i == 1) ? 'w' : 'a'; 121037225Skarels recvrequest(cmd, dest, argv[i], mode, 0); 121126049Sminshall if (!mflag && fromatty) { 121226049Sminshall ointer = interactive; 121326049Sminshall interactive = 1; 121426049Sminshall if (confirm("Continue with", argv[0])) { 121526049Sminshall mflag ++; 121626049Sminshall } 121726049Sminshall interactive = ointer; 121826049Sminshall } 121926049Sminshall } 122026049Sminshall (void) signal(SIGINT, oldintr); 122126049Sminshall mflag = 0; 122211756Ssam } 122311756Ssam 122411756Ssam /* 122510294Ssam * Do a shell escape 122610294Ssam */ 122726497Sminshall /*ARGSUSED*/ 1228*66670Spendry void 122910294Ssam shell(argc, argv) 123039252Sbostic int argc; 123139252Sbostic char **argv; 123210294Ssam { 1233*66670Spendry pid_t pid; 123439252Sbostic sig_t old1, old2; 123526049Sminshall char shellnam[40], *shell, *namep; 123626497Sminshall union wait status; 123710294Ssam 123811756Ssam old1 = signal (SIGINT, SIG_IGN); 123911756Ssam old2 = signal (SIGQUIT, SIG_IGN); 124011756Ssam if ((pid = fork()) == 0) { 124111756Ssam for (pid = 3; pid < 20; pid++) 124226497Sminshall (void) close(pid); 124326497Sminshall (void) signal(SIGINT, SIG_DFL); 124426497Sminshall (void) signal(SIGQUIT, SIG_DFL); 124525908Smckusick shell = getenv("SHELL"); 124625908Smckusick if (shell == NULL) 124737458Skarels shell = _PATH_BSHELL; 1248*66670Spendry namep = strrchr(shell,'/'); 124925908Smckusick if (namep == NULL) 125025908Smckusick namep = shell; 125126497Sminshall (void) strcpy(shellnam,"-"); 125226497Sminshall (void) strcat(shellnam, ++namep); 125326049Sminshall if (strcmp(namep, "sh") != 0) 125426049Sminshall shellnam[0] = '+'; 125526049Sminshall if (debug) { 125626049Sminshall printf ("%s\n", shell); 125726497Sminshall (void) fflush (stdout); 125811756Ssam } 125926049Sminshall if (argc > 1) { 126026049Sminshall execl(shell,shellnam,"-c",altarg,(char *)0); 126126049Sminshall } 126226049Sminshall else { 126326049Sminshall execl(shell,shellnam,(char *)0); 126426049Sminshall } 1265*66670Spendry warn("%s", shell); 126626049Sminshall code = -1; 126711756Ssam exit(1); 1268*66670Spendry } 126911756Ssam if (pid > 0) 127046828Sbostic while (wait((int *)&status) != pid) 127111756Ssam ; 127226497Sminshall (void) signal(SIGINT, old1); 127326497Sminshall (void) signal(SIGQUIT, old2); 127426049Sminshall if (pid == -1) { 1275*66670Spendry warn("%s", "Try again later"); 127626049Sminshall code = -1; 127726049Sminshall } 127826049Sminshall else { 127926049Sminshall code = 0; 128026049Sminshall } 128110294Ssam } 128210294Ssam 128310294Ssam /* 128410294Ssam * Send new user information (re-login) 128510294Ssam */ 1286*66670Spendry void 128710294Ssam user(argc, argv) 128810294Ssam int argc; 128910294Ssam char **argv; 129010294Ssam { 1291*66670Spendry char acct[80]; 129226049Sminshall int n, aflag = 0; 129310294Ssam 129445260Sbostic if (argc < 2) 129545260Sbostic (void) another(&argc, &argv, "username"); 129645260Sbostic if (argc < 2 || argc > 4) { 129710294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 129826049Sminshall code = -1; 1299*66670Spendry return; 130010294Ssam } 130110294Ssam n = command("USER %s", argv[1]); 130210294Ssam if (n == CONTINUE) { 130310294Ssam if (argc < 3 ) 130435658Sbostic argv[2] = getpass("Password: "), argc++; 130510294Ssam n = command("PASS %s", argv[2]); 130610294Ssam } 130710294Ssam if (n == CONTINUE) { 130810294Ssam if (argc < 4) { 130910294Ssam printf("Account: "); (void) fflush(stdout); 131010294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 131110294Ssam acct[strlen(acct) - 1] = '\0'; 131210294Ssam argv[3] = acct; argc++; 131310294Ssam } 131426049Sminshall n = command("ACCT %s", argv[3]); 131526049Sminshall aflag++; 131610294Ssam } 131710294Ssam if (n != COMPLETE) { 131826497Sminshall fprintf(stdout, "Login failed.\n"); 1319*66670Spendry return; 132010294Ssam } 132126049Sminshall if (!aflag && argc == 4) { 132226049Sminshall (void) command("ACCT %s", argv[3]); 132326049Sminshall } 132410294Ssam } 132510294Ssam 132610294Ssam /* 132710294Ssam * Print working directory. 132810294Ssam */ 132910294Ssam /*VARARGS*/ 1330*66670Spendry void 1331*66670Spendry pwd(argc, argv) 1332*66670Spendry int argc; 1333*66670Spendry char *argv[]; 133410294Ssam { 133537224Skarels int oldverbose = verbose; 133611756Ssam 133737224Skarels /* 133837224Skarels * If we aren't verbose, this doesn't do anything! 133937224Skarels */ 134037224Skarels verbose = 1; 134137224Skarels if (command("PWD") == ERROR && code == 500) { 134237224Skarels printf("PWD command not recognized, trying XPWD\n"); 134337224Skarels (void) command("XPWD"); 134437224Skarels } 134537224Skarels verbose = oldverbose; 134610294Ssam } 134710294Ssam 134810294Ssam /* 134910294Ssam * Make a directory. 135010294Ssam */ 1351*66670Spendry void 135210294Ssam makedir(argc, argv) 135345260Sbostic int argc; 135410294Ssam char *argv[]; 135510294Ssam { 135610294Ssam 135745260Sbostic if (argc < 2 && !another(&argc, &argv, "directory-name")) { 135826049Sminshall printf("usage: %s directory-name\n", argv[0]); 135926049Sminshall code = -1; 136010294Ssam return; 136110294Ssam } 136237224Skarels if (command("MKD %s", argv[1]) == ERROR && code == 500) { 136337224Skarels if (verbose) 136437224Skarels printf("MKD command not recognized, trying XMKD\n"); 136537224Skarels (void) command("XMKD %s", argv[1]); 136637224Skarels } 136710294Ssam } 136810294Ssam 136910294Ssam /* 137010294Ssam * Remove a directory. 137110294Ssam */ 1372*66670Spendry void 137310294Ssam removedir(argc, argv) 137445260Sbostic int argc; 137510294Ssam char *argv[]; 137610294Ssam { 137710294Ssam 137845260Sbostic if (argc < 2 && !another(&argc, &argv, "directory-name")) { 137926049Sminshall printf("usage: %s directory-name\n", argv[0]); 138026049Sminshall code = -1; 138110294Ssam return; 138210294Ssam } 138337224Skarels if (command("RMD %s", argv[1]) == ERROR && code == 500) { 138437224Skarels if (verbose) 138537224Skarels printf("RMD command not recognized, trying XRMD\n"); 138637224Skarels (void) command("XRMD %s", argv[1]); 138737224Skarels } 138810294Ssam } 138910294Ssam 139010294Ssam /* 139110294Ssam * Send a line, verbatim, to the remote machine. 139210294Ssam */ 1393*66670Spendry void 139410294Ssam quote(argc, argv) 139545260Sbostic int argc; 139610294Ssam char *argv[]; 139710294Ssam { 139810294Ssam 139945260Sbostic if (argc < 2 && !another(&argc, &argv, "command line to send")) { 140010294Ssam printf("usage: %s line-to-send\n", argv[0]); 140126049Sminshall code = -1; 140210294Ssam return; 140310294Ssam } 140445260Sbostic quote1("", argc, argv); 140510294Ssam } 140610294Ssam 140710294Ssam /* 140837224Skarels * Send a SITE command to the remote machine. The line 140945260Sbostic * is sent verbatim to the remote machine, except that the 141045260Sbostic * word "SITE" is added at the front. 141137224Skarels */ 1412*66670Spendry void 141337224Skarels site(argc, argv) 141445260Sbostic int argc; 141537224Skarels char *argv[]; 141637224Skarels { 141737224Skarels 141845260Sbostic if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) { 141937224Skarels printf("usage: %s line-to-send\n", argv[0]); 142037224Skarels code = -1; 142137224Skarels return; 142237224Skarels } 142345260Sbostic quote1("SITE ", argc, argv); 142445260Sbostic } 142545260Sbostic 142645260Sbostic /* 142745260Sbostic * Turn argv[1..argc) into a space-separated string, then prepend initial text. 142845260Sbostic * Send the result as a one-line command and get response. 142945260Sbostic */ 1430*66670Spendry void 143145260Sbostic quote1(initial, argc, argv) 143245260Sbostic char *initial; 143345260Sbostic int argc; 143445260Sbostic char **argv; 143545260Sbostic { 1436*66670Spendry int i, len; 143745260Sbostic char buf[BUFSIZ]; /* must be >= sizeof(line) */ 143845260Sbostic 143945260Sbostic (void) strcpy(buf, initial); 144045260Sbostic if (argc > 1) { 144145260Sbostic len = strlen(buf); 144245260Sbostic len += strlen(strcpy(&buf[len], argv[1])); 144345260Sbostic for (i = 2; i < argc; i++) { 144445260Sbostic buf[len++] = ' '; 144545260Sbostic len += strlen(strcpy(&buf[len], argv[i])); 144645260Sbostic } 144737224Skarels } 144837224Skarels if (command(buf) == PRELIM) { 1449*66670Spendry while (getreply(0) == PRELIM) 1450*66670Spendry continue; 145137224Skarels } 145237224Skarels } 145337224Skarels 1454*66670Spendry void 145537224Skarels do_chmod(argc, argv) 145645260Sbostic int argc; 145737224Skarels char *argv[]; 145837224Skarels { 145945260Sbostic 146045260Sbostic if (argc < 2 && !another(&argc, &argv, "mode")) 146145260Sbostic goto usage; 146245260Sbostic if (argc < 3 && !another(&argc, &argv, "file-name")) { 146345260Sbostic usage: 146437224Skarels printf("usage: %s mode file-name\n", argv[0]); 146537224Skarels code = -1; 146637224Skarels return; 146737224Skarels } 146845260Sbostic (void) command("SITE CHMOD %s %s", argv[1], argv[2]); 146937224Skarels } 147037224Skarels 1471*66670Spendry void 147237224Skarels do_umask(argc, argv) 147345260Sbostic int argc; 147437224Skarels char *argv[]; 147537224Skarels { 147637224Skarels int oldverbose = verbose; 147737224Skarels 147837224Skarels verbose = 1; 147937224Skarels (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 148037224Skarels verbose = oldverbose; 148137224Skarels } 148237224Skarels 1483*66670Spendry void 148437224Skarels idle(argc, argv) 148545260Sbostic int argc; 148637224Skarels char *argv[]; 148737224Skarels { 148837224Skarels int oldverbose = verbose; 148937224Skarels 149037224Skarels verbose = 1; 149137224Skarels (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 149237224Skarels verbose = oldverbose; 149337224Skarels } 149437224Skarels 149537224Skarels /* 149610294Ssam * Ask the other side for help. 149710294Ssam */ 1498*66670Spendry void 149910294Ssam rmthelp(argc, argv) 150045260Sbostic int argc; 150110294Ssam char *argv[]; 150210294Ssam { 150310294Ssam int oldverbose = verbose; 150410294Ssam 150510294Ssam verbose = 1; 150610294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 150710294Ssam verbose = oldverbose; 150810294Ssam } 150910294Ssam 151010294Ssam /* 151110294Ssam * Terminate session and exit. 151210294Ssam */ 151310294Ssam /*VARARGS*/ 1514*66670Spendry void 1515*66670Spendry quit(argc, argv) 1516*66670Spendry int argc; 1517*66670Spendry char *argv[]; 151810294Ssam { 151910294Ssam 152018286Sralph if (connected) 1521*66670Spendry disconnect(0, 0); 152226049Sminshall pswitch(1); 152326049Sminshall if (connected) { 1524*66670Spendry disconnect(0, 0); 152526049Sminshall } 152610294Ssam exit(0); 152710294Ssam } 152810294Ssam 152910294Ssam /* 153010294Ssam * Terminate session, but don't exit. 153110294Ssam */ 1532*66670Spendry void 1533*66670Spendry disconnect(argc, argv) 1534*66670Spendry int argc; 1535*66670Spendry char *argv[]; 153610294Ssam { 153710294Ssam 153810294Ssam if (!connected) 153910294Ssam return; 154010294Ssam (void) command("QUIT"); 154126049Sminshall if (cout) { 154226049Sminshall (void) fclose(cout); 154326049Sminshall } 154410294Ssam cout = NULL; 154510294Ssam connected = 0; 154610294Ssam data = -1; 154726049Sminshall if (!proxy) { 154826049Sminshall macnum = 0; 154926049Sminshall } 155010294Ssam } 155111353Ssam 1552*66670Spendry int 155311650Ssam confirm(cmd, file) 155411353Ssam char *cmd, *file; 155511353Ssam { 155611353Ssam char line[BUFSIZ]; 155711353Ssam 155811353Ssam if (!interactive) 155911650Ssam return (1); 156011353Ssam printf("%s %s? ", cmd, file); 156126497Sminshall (void) fflush(stdout); 156245260Sbostic if (fgets(line, sizeof line, stdin) == NULL) 156345260Sbostic return (0); 156411650Ssam return (*line != 'n' && *line != 'N'); 156511353Ssam } 156611353Ssam 1567*66670Spendry void 156811353Ssam fatal(msg) 156911353Ssam char *msg; 157011353Ssam { 157111353Ssam 1572*66670Spendry errx(1, "%s", msg); 157311353Ssam } 157411353Ssam 157511353Ssam /* 157611353Ssam * Glob a local file name specification with 157711353Ssam * the expectation of a single return value. 157811353Ssam * Can't control multiple values being expanded 157911353Ssam * from the expression, we return only the first. 158011353Ssam */ 1581*66670Spendry int 158211353Ssam globulize(cpp) 158311353Ssam char **cpp; 158411353Ssam { 158511353Ssam char **globbed; 158611353Ssam 158711353Ssam if (!doglob) 158811353Ssam return (1); 158947024Sbostic globbed = ftpglob(*cpp); 159011353Ssam if (globerr != NULL) { 159111353Ssam printf("%s: %s\n", *cpp, globerr); 159236421Sbostic if (globbed) { 159311353Ssam blkfree(globbed); 159438132Srick free((char *)globbed); 159536421Sbostic } 159611353Ssam return (0); 159711353Ssam } 159811353Ssam if (globbed) { 159911353Ssam *cpp = *globbed++; 160011353Ssam /* don't waste too much memory */ 1601*66670Spendry if (globbed) { 1602*66670Spendry blkfree(globbed); 160351444Srick free((char *)*globbed); 160436421Sbostic } 160511353Ssam } 160611353Ssam return (1); 160711353Ssam } 160826049Sminshall 1609*66670Spendry void 161026049Sminshall account(argc,argv) 161126049Sminshall int argc; 161226049Sminshall char **argv; 161326049Sminshall { 161435658Sbostic char acct[50], *getpass(), *ap; 161526049Sminshall 161626049Sminshall if (argc > 1) { 161726049Sminshall ++argv; 161826049Sminshall --argc; 161926049Sminshall (void) strncpy(acct,*argv,49); 162036268Sbostic acct[49] = '\0'; 162126049Sminshall while (argc > 1) { 162226049Sminshall --argc; 162326049Sminshall ++argv; 162426049Sminshall (void) strncat(acct,*argv, 49-strlen(acct)); 162526049Sminshall } 162626049Sminshall ap = acct; 162726049Sminshall } 162826049Sminshall else { 162935658Sbostic ap = getpass("Account:"); 163026049Sminshall } 163126049Sminshall (void) command("ACCT %s", ap); 163226049Sminshall } 163326049Sminshall 163426049Sminshall jmp_buf abortprox; 163526049Sminshall 163639252Sbostic void 163726049Sminshall proxabort() 163826049Sminshall { 163926049Sminshall 164026049Sminshall if (!proxy) { 164126049Sminshall pswitch(1); 164226049Sminshall } 164326049Sminshall if (connected) { 164426049Sminshall proxflag = 1; 164526049Sminshall } 164626049Sminshall else { 164726049Sminshall proxflag = 0; 164826049Sminshall } 164926049Sminshall pswitch(0); 165026049Sminshall longjmp(abortprox,1); 165126049Sminshall } 165226049Sminshall 1653*66670Spendry void 1654*66670Spendry doproxy(argc, argv) 165526049Sminshall int argc; 165626049Sminshall char *argv[]; 165726049Sminshall { 1658*66670Spendry struct cmd *c; 165939252Sbostic sig_t oldintr; 166026049Sminshall 166145260Sbostic if (argc < 2 && !another(&argc, &argv, "command")) { 166245260Sbostic printf("usage: %s command\n", argv[0]); 166326049Sminshall code = -1; 166426049Sminshall return; 166526049Sminshall } 166626049Sminshall c = getcmd(argv[1]); 166726049Sminshall if (c == (struct cmd *) -1) { 166826049Sminshall printf("?Ambiguous command\n"); 166926497Sminshall (void) fflush(stdout); 167026049Sminshall code = -1; 167126049Sminshall return; 167226049Sminshall } 167326049Sminshall if (c == 0) { 167426049Sminshall printf("?Invalid command\n"); 167526497Sminshall (void) fflush(stdout); 167626049Sminshall code = -1; 167726049Sminshall return; 167826049Sminshall } 167926049Sminshall if (!c->c_proxy) { 168026049Sminshall printf("?Invalid proxy command\n"); 168126497Sminshall (void) fflush(stdout); 168226049Sminshall code = -1; 168326049Sminshall return; 168426049Sminshall } 168526049Sminshall if (setjmp(abortprox)) { 168626049Sminshall code = -1; 168726049Sminshall return; 168826049Sminshall } 168926049Sminshall oldintr = signal(SIGINT, proxabort); 169026049Sminshall pswitch(1); 169126049Sminshall if (c->c_conn && !connected) { 169226049Sminshall printf("Not connected\n"); 169326497Sminshall (void) fflush(stdout); 169426049Sminshall pswitch(0); 169526049Sminshall (void) signal(SIGINT, oldintr); 169626049Sminshall code = -1; 169726049Sminshall return; 169826049Sminshall } 169926049Sminshall (*c->c_handler)(argc-1, argv+1); 170026049Sminshall if (connected) { 170126049Sminshall proxflag = 1; 170226049Sminshall } 170326049Sminshall else { 170426049Sminshall proxflag = 0; 170526049Sminshall } 170626049Sminshall pswitch(0); 170726049Sminshall (void) signal(SIGINT, oldintr); 170826049Sminshall } 170926049Sminshall 1710*66670Spendry void 1711*66670Spendry setcase(argc, argv) 1712*66670Spendry int argc; 1713*66670Spendry char *argv[]; 171426049Sminshall { 1715*66670Spendry 171626049Sminshall mcase = !mcase; 171726049Sminshall printf("Case mapping %s.\n", onoff(mcase)); 171826049Sminshall code = mcase; 171926049Sminshall } 172026049Sminshall 1721*66670Spendry void 1722*66670Spendry setcr(argc, argv) 1723*66670Spendry int argc; 1724*66670Spendry char *argv[]; 172526049Sminshall { 1726*66670Spendry 172726049Sminshall crflag = !crflag; 172826049Sminshall printf("Carriage Return stripping %s.\n", onoff(crflag)); 172926049Sminshall code = crflag; 173026049Sminshall } 173126049Sminshall 1732*66670Spendry void 173326049Sminshall setntrans(argc,argv) 173426049Sminshall int argc; 173526049Sminshall char *argv[]; 173626049Sminshall { 173726049Sminshall if (argc == 1) { 173826049Sminshall ntflag = 0; 173926049Sminshall printf("Ntrans off.\n"); 174026049Sminshall code = ntflag; 174126049Sminshall return; 174226049Sminshall } 174326049Sminshall ntflag++; 174426049Sminshall code = ntflag; 174526049Sminshall (void) strncpy(ntin, argv[1], 16); 174626049Sminshall ntin[16] = '\0'; 174726049Sminshall if (argc == 2) { 174826049Sminshall ntout[0] = '\0'; 174926049Sminshall return; 175026049Sminshall } 175126049Sminshall (void) strncpy(ntout, argv[2], 16); 175226049Sminshall ntout[16] = '\0'; 175326049Sminshall } 175426049Sminshall 175526049Sminshall char * 175626049Sminshall dotrans(name) 175726049Sminshall char *name; 175826049Sminshall { 175926049Sminshall static char new[MAXPATHLEN]; 176026049Sminshall char *cp1, *cp2 = new; 1761*66670Spendry int i, ostop, found; 176226049Sminshall 1763*66670Spendry for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++) 1764*66670Spendry continue; 176526049Sminshall for (cp1 = name; *cp1; cp1++) { 176626049Sminshall found = 0; 176726049Sminshall for (i = 0; *(ntin + i) && i < 16; i++) { 176826049Sminshall if (*cp1 == *(ntin + i)) { 176926049Sminshall found++; 177026049Sminshall if (i < ostop) { 177126049Sminshall *cp2++ = *(ntout + i); 177226049Sminshall } 177326049Sminshall break; 177426049Sminshall } 177526049Sminshall } 177626049Sminshall if (!found) { 177726049Sminshall *cp2++ = *cp1; 177826049Sminshall } 177926049Sminshall } 178026049Sminshall *cp2 = '\0'; 1781*66670Spendry return (new); 178226049Sminshall } 178326049Sminshall 1784*66670Spendry void 178526049Sminshall setnmap(argc, argv) 178626049Sminshall int argc; 178726049Sminshall char *argv[]; 178826049Sminshall { 178926049Sminshall char *cp; 179026049Sminshall 179126049Sminshall if (argc == 1) { 179226049Sminshall mapflag = 0; 179326049Sminshall printf("Nmap off.\n"); 179426049Sminshall code = mapflag; 179526049Sminshall return; 179626049Sminshall } 179745260Sbostic if (argc < 3 && !another(&argc, &argv, "mapout")) { 179826049Sminshall printf("Usage: %s [mapin mapout]\n",argv[0]); 179926049Sminshall code = -1; 180026049Sminshall return; 180126049Sminshall } 180226049Sminshall mapflag = 1; 180326049Sminshall code = 1; 1804*66670Spendry cp = strchr(altarg, ' '); 180526049Sminshall if (proxy) { 1806*66670Spendry while(*++cp == ' ') 1807*66670Spendry continue; 180826049Sminshall altarg = cp; 1809*66670Spendry cp = strchr(altarg, ' '); 181026049Sminshall } 181126049Sminshall *cp = '\0'; 181226049Sminshall (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 1813*66670Spendry while (*++cp == ' ') 1814*66670Spendry continue; 181526049Sminshall (void) strncpy(mapout, cp, MAXPATHLEN - 1); 181626049Sminshall } 181726049Sminshall 181826049Sminshall char * 181926049Sminshall domap(name) 182026049Sminshall char *name; 182126049Sminshall { 182226049Sminshall static char new[MAXPATHLEN]; 1823*66670Spendry char *cp1 = name, *cp2 = mapin; 182426049Sminshall char *tp[9], *te[9]; 182536689Scsvsj int i, toks[9], toknum = 0, match = 1; 182626049Sminshall 182726049Sminshall for (i=0; i < 9; ++i) { 182826049Sminshall toks[i] = 0; 182926049Sminshall } 183026049Sminshall while (match && *cp1 && *cp2) { 183126049Sminshall switch (*cp2) { 183226049Sminshall case '\\': 183326049Sminshall if (*++cp2 != *cp1) { 183426049Sminshall match = 0; 183526049Sminshall } 183626049Sminshall break; 183726049Sminshall case '$': 183826049Sminshall if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 183926049Sminshall if (*cp1 != *(++cp2+1)) { 184026049Sminshall toks[toknum = *cp2 - '1']++; 184126049Sminshall tp[toknum] = cp1; 184226049Sminshall while (*++cp1 && *(cp2+1) 184326049Sminshall != *cp1); 184426049Sminshall te[toknum] = cp1; 184526049Sminshall } 184626049Sminshall cp2++; 184726049Sminshall break; 184826049Sminshall } 184936935Skarels /* FALLTHROUGH */ 185026049Sminshall default: 185126049Sminshall if (*cp2 != *cp1) { 185226049Sminshall match = 0; 185326049Sminshall } 185426049Sminshall break; 185526049Sminshall } 185636689Scsvsj if (match && *cp1) { 185726049Sminshall cp1++; 185826049Sminshall } 185936689Scsvsj if (match && *cp2) { 186026049Sminshall cp2++; 186126049Sminshall } 186226049Sminshall } 186336689Scsvsj if (!match && *cp1) /* last token mismatch */ 186436689Scsvsj { 186536689Scsvsj toks[toknum] = 0; 186636689Scsvsj } 186726049Sminshall cp1 = new; 186826049Sminshall *cp1 = '\0'; 186926049Sminshall cp2 = mapout; 187026049Sminshall while (*cp2) { 187126049Sminshall match = 0; 187226049Sminshall switch (*cp2) { 187326049Sminshall case '\\': 187426049Sminshall if (*(cp2 + 1)) { 187526049Sminshall *cp1++ = *++cp2; 187626049Sminshall } 187726049Sminshall break; 187826049Sminshall case '[': 187926049Sminshall LOOP: 188026049Sminshall if (*++cp2 == '$' && isdigit(*(cp2+1))) { 188126049Sminshall if (*++cp2 == '0') { 188226049Sminshall char *cp3 = name; 188326049Sminshall 188426049Sminshall while (*cp3) { 188526049Sminshall *cp1++ = *cp3++; 188626049Sminshall } 188726049Sminshall match = 1; 188826049Sminshall } 188926049Sminshall else if (toks[toknum = *cp2 - '1']) { 189026049Sminshall char *cp3 = tp[toknum]; 189126049Sminshall 189226049Sminshall while (cp3 != te[toknum]) { 189326049Sminshall *cp1++ = *cp3++; 189426049Sminshall } 189526049Sminshall match = 1; 189626049Sminshall } 189726049Sminshall } 189826049Sminshall else { 189926049Sminshall while (*cp2 && *cp2 != ',' && 190026049Sminshall *cp2 != ']') { 190126049Sminshall if (*cp2 == '\\') { 190226049Sminshall cp2++; 190326049Sminshall } 190426049Sminshall else if (*cp2 == '$' && 190526049Sminshall isdigit(*(cp2+1))) { 190626049Sminshall if (*++cp2 == '0') { 190726049Sminshall char *cp3 = name; 190826049Sminshall 190926049Sminshall while (*cp3) { 191026049Sminshall *cp1++ = *cp3++; 191126049Sminshall } 191226049Sminshall } 191326049Sminshall else if (toks[toknum = 191426049Sminshall *cp2 - '1']) { 191526049Sminshall char *cp3=tp[toknum]; 191626049Sminshall 191726049Sminshall while (cp3 != 191826049Sminshall te[toknum]) { 191926049Sminshall *cp1++ = *cp3++; 192026049Sminshall } 192126049Sminshall } 192226049Sminshall } 192326049Sminshall else if (*cp2) { 192426049Sminshall *cp1++ = *cp2++; 192526049Sminshall } 192626049Sminshall } 192726049Sminshall if (!*cp2) { 192826049Sminshall printf("nmap: unbalanced brackets\n"); 1929*66670Spendry return (name); 193026049Sminshall } 193126049Sminshall match = 1; 193226049Sminshall cp2--; 193326049Sminshall } 193426049Sminshall if (match) { 193526049Sminshall while (*++cp2 && *cp2 != ']') { 193626049Sminshall if (*cp2 == '\\' && *(cp2 + 1)) { 193726049Sminshall cp2++; 193826049Sminshall } 193926049Sminshall } 194026049Sminshall if (!*cp2) { 194126049Sminshall printf("nmap: unbalanced brackets\n"); 1942*66670Spendry return (name); 194326049Sminshall } 194426049Sminshall break; 194526049Sminshall } 194626049Sminshall switch (*++cp2) { 194726049Sminshall case ',': 194826049Sminshall goto LOOP; 194926049Sminshall case ']': 195026049Sminshall break; 195126049Sminshall default: 195226049Sminshall cp2--; 195326049Sminshall goto LOOP; 195426049Sminshall } 195526049Sminshall break; 195626049Sminshall case '$': 195726049Sminshall if (isdigit(*(cp2 + 1))) { 195826049Sminshall if (*++cp2 == '0') { 195926049Sminshall char *cp3 = name; 196026049Sminshall 196126049Sminshall while (*cp3) { 196226049Sminshall *cp1++ = *cp3++; 196326049Sminshall } 196426049Sminshall } 196526049Sminshall else if (toks[toknum = *cp2 - '1']) { 196626049Sminshall char *cp3 = tp[toknum]; 196726049Sminshall 196826049Sminshall while (cp3 != te[toknum]) { 196926049Sminshall *cp1++ = *cp3++; 197026049Sminshall } 197126049Sminshall } 197226049Sminshall break; 197326049Sminshall } 197426049Sminshall /* intentional drop through */ 197526049Sminshall default: 197626049Sminshall *cp1++ = *cp2; 197726049Sminshall break; 197826049Sminshall } 197926049Sminshall cp2++; 198026049Sminshall } 198126049Sminshall *cp1 = '\0'; 198226049Sminshall if (!*new) { 1983*66670Spendry return (name); 198426049Sminshall } 1985*66670Spendry return (new); 198626049Sminshall } 198726049Sminshall 1988*66670Spendry void 1989*66670Spendry setsunique(argc, argv) 1990*66670Spendry int argc; 1991*66670Spendry char *argv[]; 199226049Sminshall { 1993*66670Spendry 199426049Sminshall sunique = !sunique; 199526049Sminshall printf("Store unique %s.\n", onoff(sunique)); 199626049Sminshall code = sunique; 199726049Sminshall } 199826049Sminshall 1999*66670Spendry void 2000*66670Spendry setrunique(argc, argv) 2001*66670Spendry int argc; 2002*66670Spendry char *argv[]; 200326049Sminshall { 2004*66670Spendry 200526049Sminshall runique = !runique; 200626049Sminshall printf("Receive unique %s.\n", onoff(runique)); 200726049Sminshall code = runique; 200826049Sminshall } 200926049Sminshall 201026049Sminshall /* change directory to perent directory */ 2011*66670Spendry void 2012*66670Spendry cdup(argc, argv) 2013*66670Spendry int argc; 2014*66670Spendry char *argv[]; 201526049Sminshall { 2016*66670Spendry 201737224Skarels if (command("CDUP") == ERROR && code == 500) { 201837224Skarels if (verbose) 201937224Skarels printf("CDUP command not recognized, trying XCUP\n"); 202037224Skarels (void) command("XCUP"); 202137224Skarels } 202226049Sminshall } 202326049Sminshall 202437224Skarels /* restart transfer at specific point */ 2025*66670Spendry void 202637224Skarels restart(argc, argv) 202737224Skarels int argc; 202837224Skarels char *argv[]; 202937224Skarels { 2030*66670Spendry 203137224Skarels if (argc != 2) 203237224Skarels printf("restart: offset not specified\n"); 203337224Skarels else { 203437224Skarels restart_point = atol(argv[1]); 2035*66670Spendry printf("restarting at %qd. %s\n", restart_point, 203637224Skarels "execute get, put or append to initiate transfer"); 203737224Skarels } 203837224Skarels } 203936935Skarels 204036935Skarels /* show remote system type */ 2041*66670Spendry void 2042*66670Spendry syst(argc, argv) 2043*66670Spendry int argc; 2044*66670Spendry char *argv[]; 204536935Skarels { 2046*66670Spendry 204736935Skarels (void) command("SYST"); 204836935Skarels } 204936935Skarels 2050*66670Spendry void 205126049Sminshall macdef(argc, argv) 205226049Sminshall int argc; 205326049Sminshall char *argv[]; 205426049Sminshall { 205526049Sminshall char *tmp; 205626049Sminshall int c; 205726049Sminshall 205826049Sminshall if (macnum == 16) { 205926049Sminshall printf("Limit of 16 macros have already been defined\n"); 206026049Sminshall code = -1; 206126049Sminshall return; 206226049Sminshall } 206345260Sbostic if (argc < 2 && !another(&argc, &argv, "macro name")) { 206426049Sminshall printf("Usage: %s macro_name\n",argv[0]); 206526049Sminshall code = -1; 206626049Sminshall return; 206726049Sminshall } 206826049Sminshall if (interactive) { 206926049Sminshall printf("Enter macro line by line, terminating it with a null line\n"); 207026049Sminshall } 207126497Sminshall (void) strncpy(macros[macnum].mac_name, argv[1], 8); 207226049Sminshall if (macnum == 0) { 207326049Sminshall macros[macnum].mac_start = macbuf; 207426049Sminshall } 207526049Sminshall else { 207626049Sminshall macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 207726049Sminshall } 207826049Sminshall tmp = macros[macnum].mac_start; 207926049Sminshall while (tmp != macbuf+4096) { 208026049Sminshall if ((c = getchar()) == EOF) { 208126049Sminshall printf("macdef:end of file encountered\n"); 208226049Sminshall code = -1; 208326049Sminshall return; 208426049Sminshall } 208526049Sminshall if ((*tmp = c) == '\n') { 208626049Sminshall if (tmp == macros[macnum].mac_start) { 208726049Sminshall macros[macnum++].mac_end = tmp; 208826049Sminshall code = 0; 208926049Sminshall return; 209026049Sminshall } 209126049Sminshall if (*(tmp-1) == '\0') { 209226049Sminshall macros[macnum++].mac_end = tmp - 1; 209326049Sminshall code = 0; 209426049Sminshall return; 209526049Sminshall } 209626049Sminshall *tmp = '\0'; 209726049Sminshall } 209826049Sminshall tmp++; 209926049Sminshall } 210026049Sminshall while (1) { 210136935Skarels while ((c = getchar()) != '\n' && c != EOF) 210236935Skarels /* LOOP */; 210326049Sminshall if (c == EOF || getchar() == '\n') { 210426049Sminshall printf("Macro not defined - 4k buffer exceeded\n"); 210526049Sminshall code = -1; 210626049Sminshall return; 210726049Sminshall } 210826049Sminshall } 210926049Sminshall } 211036935Skarels 211136935Skarels /* 211236935Skarels * get size of file on remote machine 211336935Skarels */ 2114*66670Spendry void 211536935Skarels sizecmd(argc, argv) 211645260Sbostic int argc; 211736935Skarels char *argv[]; 211836935Skarels { 211936935Skarels 212045260Sbostic if (argc < 2 && !another(&argc, &argv, "filename")) { 212145260Sbostic printf("usage: %s filename\n", argv[0]); 212236935Skarels code = -1; 212336935Skarels return; 212436935Skarels } 212536935Skarels (void) command("SIZE %s", argv[1]); 212636935Skarels } 212736935Skarels 212836935Skarels /* 212936935Skarels * get last modification time of file on remote machine 213036935Skarels */ 2131*66670Spendry void 213236935Skarels modtime(argc, argv) 213345260Sbostic int argc; 213436935Skarels char *argv[]; 213536935Skarels { 213636935Skarels int overbose; 213736935Skarels 213845260Sbostic if (argc < 2 && !another(&argc, &argv, "filename")) { 213945260Sbostic printf("usage: %s filename\n", argv[0]); 214036935Skarels code = -1; 214136935Skarels return; 214236935Skarels } 214336940Skarels overbose = verbose; 214436940Skarels if (debug == 0) 214536940Skarels verbose = -1; 214636935Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 214736935Skarels int yy, mo, day, hour, min, sec; 214836935Skarels sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 214936935Skarels &day, &hour, &min, &sec); 215036935Skarels /* might want to print this in local time */ 215136935Skarels printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 215236935Skarels mo, day, yy, hour, min, sec); 215336935Skarels } else 215438132Srick printf("%s\n", reply_string); 215536935Skarels verbose = overbose; 215636935Skarels } 215736935Skarels 215836935Skarels /* 215937224Skarels * show status on reomte machine 216036935Skarels */ 2161*66670Spendry void 216236935Skarels rmtstatus(argc, argv) 216345260Sbostic int argc; 216436935Skarels char *argv[]; 216536935Skarels { 2166*66670Spendry 216736935Skarels (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 216836935Skarels } 216937224Skarels 217037224Skarels /* 217137224Skarels * get file if modtime is more recent than current file 217237224Skarels */ 2173*66670Spendry void 217437224Skarels newer(argc, argv) 217545260Sbostic int argc; 217637224Skarels char *argv[]; 217737224Skarels { 2178*66670Spendry 217937224Skarels if (getit(argc, argv, -1, "w")) 218037224Skarels printf("Local file \"%s\" is newer than remote file \"%s\"\n", 218154742Sandrew argv[2], argv[1]); 218237224Skarels } 2183