121737Sdist /* 266672Spendry * Copyright (c) 1985, 1989, 1993, 1994 362007Sbostic * The Regents of the University of California. All rights reserved. 433737Sbostic * 542665Sbostic * %sccs.include.redist.c% 621737Sdist */ 721737Sdist 810294Ssam #ifndef lint 9*66723Spendry static char sccsid[] = "@(#)cmds.c 8.5 (Berkeley) 04/06/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> 1966670Spendry #include <netinet/in.h> 2012396Ssam #include <arpa/ftp.h> 2112396Ssam 2266670Spendry #include <ctype.h> 2366670Spendry #include <err.h> 2466692Spendry #include <glob.h> 2566670Spendry #include <netdb.h> 2610294Ssam #include <signal.h> 2710294Ssam #include <stdio.h> 2866670Spendry #include <stdlib.h> 2966670Spendry #include <string.h> 3036935Skarels #include <time.h> 3166670Spendry #include <unistd.h> 3210294Ssam 3336940Skarels #include "ftp_var.h" 3437458Skarels #include "pathnames.h" 3510294Ssam 3666670Spendry jmp_buf jabort; 3766670Spendry char *mname; 3866692Spendry char *home = "/"; 3936935Skarels 4010294Ssam /* 4145260Sbostic * `Another' gets another argument, and stores the new argc and argv. 4245260Sbostic * It reverts to the top level (via main.c's intr()) on EOF/error. 4345260Sbostic * 4445260Sbostic * Returns false if no new arguments have been added. 4545260Sbostic */ 4666670Spendry int 4745260Sbostic another(pargc, pargv, prompt) 4845260Sbostic int *pargc; 4945260Sbostic char ***pargv; 5045260Sbostic char *prompt; 5145260Sbostic { 5245260Sbostic int len = strlen(line), ret; 5345260Sbostic 5445260Sbostic if (len >= sizeof(line) - 3) { 5545260Sbostic printf("sorry, arguments too long\n"); 5645260Sbostic intr(); 5745260Sbostic } 5845260Sbostic printf("(%s) ", prompt); 5945260Sbostic line[len++] = ' '; 6045260Sbostic if (fgets(&line[len], sizeof(line) - len, stdin) == NULL) 6145260Sbostic intr(); 6245260Sbostic len += strlen(&line[len]); 6345260Sbostic if (len > 0 && line[len - 1] == '\n') 6445260Sbostic line[len - 1] = '\0'; 6545260Sbostic makeargv(); 6645260Sbostic ret = margc > *pargc; 6745260Sbostic *pargc = margc; 6845260Sbostic *pargv = margv; 6945260Sbostic return (ret); 7045260Sbostic } 7145260Sbostic 7245260Sbostic /* 7310294Ssam * Connect to peer server and 7410294Ssam * auto-login, if possible. 7510294Ssam */ 7666670Spendry void 7710294Ssam setpeer(argc, argv) 7810294Ssam int argc; 7910294Ssam char *argv[]; 8010294Ssam { 8166670Spendry char *host; 8238132Srick short port; 8310294Ssam 8410294Ssam if (connected) { 8526049Sminshall printf("Already connected to %s, use close first.\n", 8610294Ssam hostname); 8726049Sminshall code = -1; 8810294Ssam return; 8910294Ssam } 9045260Sbostic if (argc < 2) 9145260Sbostic (void) another(&argc, &argv, "to"); 9245260Sbostic if (argc < 2 || argc > 3) { 9310294Ssam printf("usage: %s host-name [port]\n", argv[0]); 9426049Sminshall code = -1; 9510294Ssam return; 9610294Ssam } 9710294Ssam port = sp->s_port; 9810294Ssam if (argc > 2) { 9911218Ssam port = atoi(argv[2]); 10010294Ssam if (port <= 0) { 10111218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 10211218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 10326049Sminshall code = -1; 10410294Ssam return; 10510294Ssam } 10610294Ssam port = htons(port); 10710294Ssam } 10810294Ssam host = hookup(argv[1], port); 10910294Ssam if (host) { 11037228Skarels int overbose; 11137228Skarels 11210294Ssam connected = 1; 11338032Skarels /* 11438032Skarels * Set up defaults for FTP. 11538032Skarels */ 11638032Skarels (void) strcpy(typename, "ascii"), type = TYPE_A; 11738032Skarels curtype = TYPE_A; 11838032Skarels (void) strcpy(formname, "non-print"), form = FORM_N; 11938032Skarels (void) strcpy(modename, "stream"), mode = MODE_S; 12038032Skarels (void) strcpy(structname, "file"), stru = STRU_F; 12138032Skarels (void) strcpy(bytename, "8"), bytesize = 8; 12237228Skarels if (autologin) 12337228Skarels (void) login(argv[1]); 12436940Skarels 12536935Skarels #if defined(unix) && NBBY == 8 12636935Skarels /* 12736935Skarels * this ifdef is to keep someone form "porting" this to an incompatible 12836935Skarels * system and not checking this out. This way they have to think about it. 12936935Skarels */ 13037228Skarels overbose = verbose; 13137228Skarels if (debug == 0) 13237228Skarels verbose = -1; 13337228Skarels if (command("SYST") == COMPLETE && overbose) { 13466670Spendry char *cp, c; 13566670Spendry cp = strchr(reply_string+4, ' '); 13637228Skarels if (cp == NULL) 13766670Spendry cp = strchr(reply_string+4, '\r'); 13837228Skarels if (cp) { 13937228Skarels if (cp[-1] == '.') 14037228Skarels cp--; 14137228Skarels c = *cp; 14237228Skarels *cp = '\0'; 14337228Skarels } 14436935Skarels 14537228Skarels printf("Remote system type is %s.\n", 14637228Skarels reply_string+4); 14737228Skarels if (cp) 14837228Skarels *cp = c; 14937228Skarels } 15037228Skarels if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { 15138032Skarels if (proxy) 15238032Skarels unix_proxy = 1; 15338032Skarels else 15438032Skarels unix_server = 1; 15538032Skarels /* 15638032Skarels * Set type to 0 (not specified by user), 15738032Skarels * meaning binary by default, but don't bother 15838032Skarels * telling server. We can use binary 15938032Skarels * for text files unless changed by the user. 16038032Skarels */ 16138032Skarels type = 0; 16238032Skarels (void) strcpy(typename, "binary"); 16337228Skarels if (overbose) 16437228Skarels printf("Using %s mode to transfer files.\n", 16537228Skarels typename); 16638032Skarels } else { 16738032Skarels if (proxy) 16838032Skarels unix_proxy = 0; 16938032Skarels else 17038032Skarels unix_server = 0; 17138032Skarels if (overbose && 17238032Skarels !strncmp(reply_string, "215 TOPS20", 10)) 17338032Skarels printf( 17436940Skarels "Remember to set tenex mode when transfering binary files from this machine.\n"); 17537228Skarels } 17637228Skarels verbose = overbose; 17736935Skarels #endif /* unix */ 17810294Ssam } 17910294Ssam } 18010294Ssam 18110294Ssam struct types { 18210294Ssam char *t_name; 18310294Ssam char *t_mode; 18410294Ssam int t_type; 18511218Ssam char *t_arg; 18610294Ssam } types[] = { 18711218Ssam { "ascii", "A", TYPE_A, 0 }, 18811218Ssam { "binary", "I", TYPE_I, 0 }, 18911218Ssam { "image", "I", TYPE_I, 0 }, 19011218Ssam { "ebcdic", "E", TYPE_E, 0 }, 19111218Ssam { "tenex", "L", TYPE_L, bytename }, 19266670Spendry { NULL } 19310294Ssam }; 19410294Ssam 19510294Ssam /* 19610294Ssam * Set transfer type. 19710294Ssam */ 19866670Spendry void 19910294Ssam settype(argc, argv) 20045260Sbostic int argc; 20110294Ssam char *argv[]; 20210294Ssam { 20366670Spendry struct types *p; 20411218Ssam int comret; 20510294Ssam 20610294Ssam if (argc > 2) { 20710294Ssam char *sep; 20810294Ssam 20910294Ssam printf("usage: %s [", argv[0]); 21010294Ssam sep = " "; 21110294Ssam for (p = types; p->t_name; p++) { 21210294Ssam printf("%s%s", sep, p->t_name); 21338032Skarels sep = " | "; 21410294Ssam } 21510294Ssam printf(" ]\n"); 21626049Sminshall code = -1; 21710294Ssam return; 21810294Ssam } 21910294Ssam if (argc < 2) { 22010294Ssam printf("Using %s mode to transfer files.\n", typename); 22126049Sminshall code = 0; 22210294Ssam return; 22310294Ssam } 22410294Ssam for (p = types; p->t_name; p++) 22510294Ssam if (strcmp(argv[1], p->t_name) == 0) 22610294Ssam break; 22710294Ssam if (p->t_name == 0) { 22810294Ssam printf("%s: unknown mode\n", argv[1]); 22926049Sminshall code = -1; 23010294Ssam return; 23110294Ssam } 23211218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 23311218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 23411218Ssam else 23511218Ssam comret = command("TYPE %s", p->t_mode); 23611218Ssam if (comret == COMPLETE) { 23726497Sminshall (void) strcpy(typename, p->t_name); 23838032Skarels curtype = type = p->t_type; 23910294Ssam } 24010294Ssam } 24110294Ssam 24210294Ssam /* 24338032Skarels * Internal form of settype; changes current type in use with server 24438032Skarels * without changing our notion of the type for data transfers. 24538032Skarels * Used to change to and from ascii for listings. 24638032Skarels */ 24766670Spendry void 24838032Skarels changetype(newtype, show) 24938032Skarels int newtype, show; 25038032Skarels { 25166670Spendry struct types *p; 25238032Skarels int comret, oldverbose = verbose; 25338032Skarels 25438032Skarels if (newtype == 0) 25538032Skarels newtype = TYPE_I; 25638032Skarels if (newtype == curtype) 25738032Skarels return; 25838032Skarels if (debug == 0 && show == 0) 25938032Skarels verbose = 0; 26038032Skarels for (p = types; p->t_name; p++) 26138032Skarels if (newtype == p->t_type) 26238032Skarels break; 26338032Skarels if (p->t_name == 0) { 26438032Skarels printf("ftp: internal error: unknown type %d\n", newtype); 26538032Skarels return; 26638032Skarels } 26738032Skarels if (newtype == TYPE_L && bytename[0] != '\0') 26838032Skarels comret = command("TYPE %s %s", p->t_mode, bytename); 26938032Skarels else 27038032Skarels comret = command("TYPE %s", p->t_mode); 27138032Skarels if (comret == COMPLETE) 27238032Skarels curtype = newtype; 27338032Skarels verbose = oldverbose; 27438032Skarels } 27538032Skarels 27638132Srick char *stype[] = { 27738132Srick "type", 27838132Srick "", 27938132Srick 0 28038132Srick }; 28138132Srick 28238032Skarels /* 28310294Ssam * Set binary transfer type. 28410294Ssam */ 28510294Ssam /*VARARGS*/ 28666670Spendry void 28766670Spendry setbinary(argc, argv) 28866670Spendry int argc; 28966670Spendry char **argv; 29010294Ssam { 29166670Spendry 29238132Srick stype[1] = "binary"; 29338132Srick settype(2, stype); 29410294Ssam } 29510294Ssam 29610294Ssam /* 29710294Ssam * Set ascii transfer type. 29810294Ssam */ 29910294Ssam /*VARARGS*/ 30066670Spendry void 30166670Spendry setascii(argc, argv) 30266670Spendry int argc; 30366670Spendry char *argv[]; 30410294Ssam { 30566670Spendry 30638132Srick stype[1] = "ascii"; 30738132Srick settype(2, stype); 30810294Ssam } 30910294Ssam 31010294Ssam /* 31110294Ssam * Set tenex transfer type. 31210294Ssam */ 31310294Ssam /*VARARGS*/ 31466670Spendry void 31566670Spendry settenex(argc, argv) 31666670Spendry int argc; 31766670Spendry char *argv[]; 31810294Ssam { 31966670Spendry 32038132Srick stype[1] = "tenex"; 32138132Srick settype(2, stype); 32210294Ssam } 32310294Ssam 32410294Ssam /* 32510294Ssam * Set file transfer mode. 32610294Ssam */ 32726497Sminshall /*ARGSUSED*/ 32866670Spendry void 32966670Spendry setftmode(argc, argv) 33045260Sbostic int argc; 33110294Ssam char *argv[]; 33210294Ssam { 33310294Ssam 33410294Ssam printf("We only support %s mode, sorry.\n", modename); 33526049Sminshall code = -1; 33610294Ssam } 33710294Ssam 33810294Ssam /* 33910294Ssam * Set file transfer format. 34010294Ssam */ 34126497Sminshall /*ARGSUSED*/ 34266670Spendry void 34310294Ssam setform(argc, argv) 34445260Sbostic int argc; 34510294Ssam char *argv[]; 34610294Ssam { 34710294Ssam 34810294Ssam printf("We only support %s format, sorry.\n", formname); 34926049Sminshall code = -1; 35010294Ssam } 35110294Ssam 35210294Ssam /* 35310294Ssam * Set file transfer structure. 35410294Ssam */ 35526497Sminshall /*ARGSUSED*/ 35666670Spendry void 35710294Ssam setstruct(argc, argv) 35845260Sbostic int argc; 35910294Ssam char *argv[]; 36010294Ssam { 36110294Ssam 36210294Ssam printf("We only support %s structure, sorry.\n", structname); 36326049Sminshall code = -1; 36410294Ssam } 36510294Ssam 36618286Sralph /* 36718286Sralph * Send a single file. 36818286Sralph */ 36966670Spendry void 37010294Ssam put(argc, argv) 37111756Ssam int argc; 37210294Ssam char *argv[]; 37310294Ssam { 37411650Ssam char *cmd; 37526049Sminshall int loc = 0; 37637225Skarels char *oldargv1, *oldargv2; 37711650Ssam 37826049Sminshall if (argc == 2) { 37926049Sminshall argc++; 38026049Sminshall argv[2] = argv[1]; 38126049Sminshall loc++; 38226049Sminshall } 38345260Sbostic if (argc < 2 && !another(&argc, &argv, "local-file")) 38445260Sbostic goto usage; 38545260Sbostic if (argc < 3 && !another(&argc, &argv, "remote-file")) { 38610294Ssam usage: 38745260Sbostic printf("usage: %s local-file remote-file\n", argv[0]); 38826049Sminshall code = -1; 38910294Ssam return; 39010294Ssam } 39125908Smckusick oldargv1 = argv[1]; 39237225Skarels oldargv2 = argv[2]; 39326049Sminshall if (!globulize(&argv[1])) { 39426049Sminshall code = -1; 39511353Ssam return; 39626049Sminshall } 39725908Smckusick /* 39825908Smckusick * If "globulize" modifies argv[1], and argv[2] is a copy of 39925908Smckusick * the old argv[1], make it a copy of the new argv[1]. 40025908Smckusick */ 40126049Sminshall if (argv[1] != oldargv1 && argv[2] == oldargv1) { 40225908Smckusick argv[2] = argv[1]; 40326049Sminshall } 40426049Sminshall cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); 40526049Sminshall if (loc && ntflag) { 40626049Sminshall argv[2] = dotrans(argv[2]); 40726049Sminshall } 40826049Sminshall if (loc && mapflag) { 40926049Sminshall argv[2] = domap(argv[2]); 41026049Sminshall } 41137225Skarels sendrequest(cmd, argv[1], argv[2], 41237225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 41310294Ssam } 41410294Ssam 41510294Ssam /* 41611756Ssam * Send multiple files. 41710294Ssam */ 41866670Spendry void 41911353Ssam mput(argc, argv) 42039252Sbostic int argc; 42139252Sbostic char **argv; 42211353Ssam { 42366670Spendry int i; 42439252Sbostic sig_t oldintr; 42538132Srick int ointer; 42626049Sminshall char *tp; 42711353Ssam 42845260Sbostic if (argc < 2 && !another(&argc, &argv, "local-files")) { 42945260Sbostic printf("usage: %s local-files\n", argv[0]); 43026049Sminshall code = -1; 43111353Ssam return; 43211353Ssam } 43326049Sminshall mname = argv[0]; 43426049Sminshall mflag = 1; 43526049Sminshall oldintr = signal(SIGINT, mabort); 43626049Sminshall (void) setjmp(jabort); 43726049Sminshall if (proxy) { 43826049Sminshall char *cp, *tp2, tmpbuf[MAXPATHLEN]; 43926049Sminshall 44026497Sminshall while ((cp = remglob(argv,0)) != NULL) { 44126049Sminshall if (*cp == 0) { 44226049Sminshall mflag = 0; 44326049Sminshall continue; 44426049Sminshall } 44526049Sminshall if (mflag && confirm(argv[0], cp)) { 44626049Sminshall tp = cp; 44726049Sminshall if (mcase) { 44826049Sminshall while (*tp && !islower(*tp)) { 44926049Sminshall tp++; 45026049Sminshall } 45126049Sminshall if (!*tp) { 45226049Sminshall tp = cp; 45326049Sminshall tp2 = tmpbuf; 45426049Sminshall while ((*tp2 = *tp) != NULL) { 45526049Sminshall if (isupper(*tp2)) { 45626049Sminshall *tp2 = 'a' + *tp2 - 'A'; 45726049Sminshall } 45826049Sminshall tp++; 45926049Sminshall tp2++; 46026049Sminshall } 46126049Sminshall } 46226049Sminshall tp = tmpbuf; 46326049Sminshall } 46426049Sminshall if (ntflag) { 46526049Sminshall tp = dotrans(tp); 46626049Sminshall } 46726049Sminshall if (mapflag) { 46826049Sminshall tp = domap(tp); 46926049Sminshall } 47037225Skarels sendrequest((sunique) ? "STOU" : "STOR", 47137225Skarels cp, tp, cp != tp || !interactive); 47226049Sminshall if (!mflag && fromatty) { 47326049Sminshall ointer = interactive; 47426049Sminshall interactive = 1; 47526049Sminshall if (confirm("Continue with","mput")) { 47626049Sminshall mflag++; 47726049Sminshall } 47826049Sminshall interactive = ointer; 47926049Sminshall } 48026049Sminshall } 48126049Sminshall } 48226049Sminshall (void) signal(SIGINT, oldintr); 48326049Sminshall mflag = 0; 48426049Sminshall return; 48526049Sminshall } 48613212Ssam for (i = 1; i < argc; i++) { 48766670Spendry char **cpp, **gargs; 48866692Spendry glob_t gl; 489*66723Spendry int flags; 49013212Ssam 49113212Ssam if (!doglob) { 49226049Sminshall if (mflag && confirm(argv[0], argv[i])) { 49326049Sminshall tp = (ntflag) ? dotrans(argv[i]) : argv[i]; 49426049Sminshall tp = (mapflag) ? domap(tp) : tp; 49526049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 49637225Skarels argv[i], tp, tp != argv[i] || !interactive); 49726049Sminshall if (!mflag && fromatty) { 49826049Sminshall ointer = interactive; 49926049Sminshall interactive = 1; 50026049Sminshall if (confirm("Continue with","mput")) { 50126049Sminshall mflag++; 50226049Sminshall } 50326049Sminshall interactive = ointer; 50426049Sminshall } 50526049Sminshall } 50613212Ssam continue; 50713212Ssam } 50866692Spendry 50966692Spendry memset(&gl, 0, sizeof(gl)); 510*66723Spendry flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 511*66723Spendry if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) { 51266692Spendry warnx("%s: not found", argv[i]); 51366692Spendry globfree(&gl); 51413212Ssam continue; 51511353Ssam } 51666692Spendry for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) { 51726049Sminshall if (mflag && confirm(argv[0], *cpp)) { 51826049Sminshall tp = (ntflag) ? dotrans(*cpp) : *cpp; 51926049Sminshall tp = (mapflag) ? domap(tp) : tp; 52026049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 52137225Skarels *cpp, tp, *cpp != tp || !interactive); 52226049Sminshall if (!mflag && fromatty) { 52326049Sminshall ointer = interactive; 52426049Sminshall interactive = 1; 52526049Sminshall if (confirm("Continue with","mput")) { 52626049Sminshall mflag++; 52726049Sminshall } 52826049Sminshall interactive = ointer; 52926049Sminshall } 53026049Sminshall } 53126049Sminshall } 53266692Spendry globfree(&gl); 53311353Ssam } 53426049Sminshall (void) signal(SIGINT, oldintr); 53526049Sminshall mflag = 0; 53611353Ssam } 53711353Ssam 53866670Spendry void 53937224Skarels reget(argc, argv) 54045260Sbostic int argc; 54137224Skarels char *argv[]; 54237224Skarels { 54366670Spendry 54437224Skarels (void) getit(argc, argv, 1, "r+w"); 54537224Skarels } 54636935Skarels 54766670Spendry void 54837224Skarels get(argc, argv) 54945260Sbostic int argc; 55037224Skarels char *argv[]; 55137224Skarels { 55266670Spendry 55337224Skarels (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" ); 55437224Skarels } 55537224Skarels 55611353Ssam /* 55711353Ssam * Receive one file. 55811353Ssam */ 55966670Spendry int 56037224Skarels getit(argc, argv, restartit, mode) 56145260Sbostic int argc; 56210294Ssam char *argv[]; 56337224Skarels char *mode; 56466670Spendry 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) { 61866670Spendry 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 66666670Spendry /* ARGSUSED */ 66739252Sbostic void 66866670Spendry mabort(signo) 66966670Spendry 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 */ 69166670Spendry 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; 70766670Spendry 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 } 76566670Spendry 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 } 79966670Spendry 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*/ 81666670Spendry 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*/ 87266670Spendry void 87366670Spendry setbell(argc, argv) 87466670Spendry int argc; 87566670Spendry 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*/ 88766670Spendry void 88866670Spendry settrace(argc, argv) 88966670Spendry int argc; 89066670Spendry 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*/ 90266670Spendry void 90366670Spendry sethash(argc, argv) 90466670Spendry int argc; 90566670Spendry 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*/ 92066670Spendry void 92166670Spendry setverbose(argc, argv) 92266670Spendry int argc; 92366670Spendry 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*/ 93566670Spendry void 93666670Spendry setport(argc, argv) 93766670Spendry int argc; 93866670Spendry 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*/ 95166670Spendry void 95266670Spendry setprompt(argc, argv) 95366670Spendry int argc; 95466670Spendry 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*/ 96766670Spendry void 96866670Spendry setglob(argc, argv) 96966670Spendry int argc; 97066670Spendry 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*/ 98366670Spendry 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 */ 101266670Spendry 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 */ 103466670Spendry 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) { 105366670Spendry warn("local: %s", argv[1]); 105426049Sminshall code = -1; 105511353Ssam return; 105611353Ssam } 105766692Spendry if (getwd(buf) != NULL) 105866692Spendry printf("Local directory now %s\n", buf); 105966692Spendry else 106066692Spendry warnx("getwd: %s", buf); 106126049Sminshall code = 0; 106210294Ssam } 106310294Ssam 106410294Ssam /* 106510294Ssam * Delete a single file. 106610294Ssam */ 106766670Spendry void 106810294Ssam delete(argc, argv) 106945260Sbostic int argc; 107010294Ssam char *argv[]; 107110294Ssam { 107210294Ssam 107345260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-file")) { 107445260Sbostic printf("usage: %s remote-file\n", argv[0]); 107526049Sminshall code = -1; 107610294Ssam return; 107710294Ssam } 107810294Ssam (void) command("DELE %s", argv[1]); 107910294Ssam } 108010294Ssam 108110294Ssam /* 108211650Ssam * Delete multiple files. 108311650Ssam */ 108466670Spendry void 108511650Ssam mdelete(argc, argv) 108639252Sbostic int argc; 108739252Sbostic char **argv; 108811650Ssam { 108939252Sbostic sig_t oldintr; 109039252Sbostic int ointer; 109111650Ssam char *cp; 109211650Ssam 109345260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) { 109445260Sbostic printf("usage: %s remote-files\n", argv[0]); 109526049Sminshall code = -1; 109611650Ssam return; 109711650Ssam } 109826049Sminshall mname = argv[0]; 109926049Sminshall mflag = 1; 110026049Sminshall oldintr = signal(SIGINT, mabort); 110126049Sminshall (void) setjmp(jabort); 110226497Sminshall while ((cp = remglob(argv,0)) != NULL) { 110326049Sminshall if (*cp == '\0') { 110426049Sminshall mflag = 0; 110526049Sminshall continue; 110626049Sminshall } 110726049Sminshall if (mflag && confirm(argv[0], cp)) { 110811650Ssam (void) command("DELE %s", cp); 110926049Sminshall if (!mflag && fromatty) { 111026049Sminshall ointer = interactive; 111126049Sminshall interactive = 1; 111226049Sminshall if (confirm("Continue with", "mdelete")) { 111326049Sminshall mflag++; 111426049Sminshall } 111526049Sminshall interactive = ointer; 111626049Sminshall } 111726049Sminshall } 111826049Sminshall } 111926049Sminshall (void) signal(SIGINT, oldintr); 112026049Sminshall mflag = 0; 112111650Ssam } 112211756Ssam 112311650Ssam /* 112410294Ssam * Rename a remote file. 112510294Ssam */ 112666670Spendry void 112710294Ssam renamefile(argc, argv) 112845260Sbostic int argc; 112910294Ssam char *argv[]; 113010294Ssam { 113110294Ssam 113245260Sbostic if (argc < 2 && !another(&argc, &argv, "from-name")) 113345260Sbostic goto usage; 113445260Sbostic if (argc < 3 && !another(&argc, &argv, "to-name")) { 113510294Ssam usage: 113610294Ssam printf("%s from-name to-name\n", argv[0]); 113726049Sminshall code = -1; 113810294Ssam return; 113910294Ssam } 114010294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 114110294Ssam (void) command("RNTO %s", argv[2]); 114210294Ssam } 114310294Ssam 114410294Ssam /* 114510294Ssam * Get a directory listing 114610294Ssam * of remote files. 114710294Ssam */ 114866670Spendry void 114910294Ssam ls(argc, argv) 115045260Sbostic int argc; 115110294Ssam char *argv[]; 115210294Ssam { 115311756Ssam char *cmd; 115410294Ssam 115510294Ssam if (argc < 2) 115610294Ssam argc++, argv[1] = NULL; 115710294Ssam if (argc < 3) 115810294Ssam argc++, argv[2] = "-"; 115911756Ssam if (argc > 3) { 116011756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 116126049Sminshall code = -1; 116211756Ssam return; 116311756Ssam } 116436935Skarels cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 116526049Sminshall if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 116626049Sminshall code = -1; 116711353Ssam return; 116826049Sminshall } 116932344Scsvsj if (strcmp(argv[2], "-") && *argv[2] != '|') 117032344Scsvsj if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { 117132344Scsvsj code = -1; 117232344Scsvsj return; 117332344Scsvsj } 117437225Skarels recvrequest(cmd, argv[2], argv[1], "w", 0); 117510294Ssam } 117610294Ssam 117710294Ssam /* 117811756Ssam * Get a directory listing 117911756Ssam * of multiple remote files. 118011756Ssam */ 118166670Spendry void 118211756Ssam mls(argc, argv) 118339252Sbostic int argc; 118439252Sbostic char **argv; 118511756Ssam { 118639252Sbostic sig_t oldintr; 118739252Sbostic int ointer, i; 118826049Sminshall char *cmd, mode[1], *dest; 118911756Ssam 119045260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) 119145260Sbostic goto usage; 119245260Sbostic if (argc < 3 && !another(&argc, &argv, "local-file")) { 119345260Sbostic usage: 119445260Sbostic printf("usage: %s remote-files local-file\n", argv[0]); 119526049Sminshall code = -1; 119613212Ssam return; 119713212Ssam } 119813212Ssam dest = argv[argc - 1]; 119913212Ssam argv[argc - 1] = NULL; 120026049Sminshall if (strcmp(dest, "-") && *dest != '|') 120145260Sbostic if (!globulize(&dest) || 120245260Sbostic !confirm("output to local-file:", dest)) { 120326049Sminshall code = -1; 120413212Ssam return; 120526049Sminshall } 120636940Skarels cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 120726049Sminshall mname = argv[0]; 120826049Sminshall mflag = 1; 120926049Sminshall oldintr = signal(SIGINT, mabort); 121026049Sminshall (void) setjmp(jabort); 121126049Sminshall for (i = 1; mflag && i < argc-1; ++i) { 121226049Sminshall *mode = (i == 1) ? 'w' : 'a'; 121337225Skarels recvrequest(cmd, dest, argv[i], mode, 0); 121426049Sminshall if (!mflag && fromatty) { 121526049Sminshall ointer = interactive; 121626049Sminshall interactive = 1; 121726049Sminshall if (confirm("Continue with", argv[0])) { 121826049Sminshall mflag ++; 121926049Sminshall } 122026049Sminshall interactive = ointer; 122126049Sminshall } 122226049Sminshall } 122326049Sminshall (void) signal(SIGINT, oldintr); 122426049Sminshall mflag = 0; 122511756Ssam } 122611756Ssam 122711756Ssam /* 122810294Ssam * Do a shell escape 122910294Ssam */ 123026497Sminshall /*ARGSUSED*/ 123166670Spendry void 123210294Ssam shell(argc, argv) 123339252Sbostic int argc; 123439252Sbostic char **argv; 123510294Ssam { 123666670Spendry pid_t pid; 123739252Sbostic sig_t old1, old2; 123826049Sminshall char shellnam[40], *shell, *namep; 123926497Sminshall union wait status; 124010294Ssam 124111756Ssam old1 = signal (SIGINT, SIG_IGN); 124211756Ssam old2 = signal (SIGQUIT, SIG_IGN); 124311756Ssam if ((pid = fork()) == 0) { 124411756Ssam for (pid = 3; pid < 20; pid++) 124526497Sminshall (void) close(pid); 124626497Sminshall (void) signal(SIGINT, SIG_DFL); 124726497Sminshall (void) signal(SIGQUIT, SIG_DFL); 124825908Smckusick shell = getenv("SHELL"); 124925908Smckusick if (shell == NULL) 125037458Skarels shell = _PATH_BSHELL; 125166670Spendry namep = strrchr(shell,'/'); 125225908Smckusick if (namep == NULL) 125325908Smckusick namep = shell; 125426497Sminshall (void) strcpy(shellnam,"-"); 125526497Sminshall (void) strcat(shellnam, ++namep); 125626049Sminshall if (strcmp(namep, "sh") != 0) 125726049Sminshall shellnam[0] = '+'; 125826049Sminshall if (debug) { 125926049Sminshall printf ("%s\n", shell); 126026497Sminshall (void) fflush (stdout); 126111756Ssam } 126226049Sminshall if (argc > 1) { 126326049Sminshall execl(shell,shellnam,"-c",altarg,(char *)0); 126426049Sminshall } 126526049Sminshall else { 126626049Sminshall execl(shell,shellnam,(char *)0); 126726049Sminshall } 126866670Spendry warn("%s", shell); 126926049Sminshall code = -1; 127011756Ssam exit(1); 127166670Spendry } 127211756Ssam if (pid > 0) 127346828Sbostic while (wait((int *)&status) != pid) 127411756Ssam ; 127526497Sminshall (void) signal(SIGINT, old1); 127626497Sminshall (void) signal(SIGQUIT, old2); 127726049Sminshall if (pid == -1) { 127866670Spendry warn("%s", "Try again later"); 127926049Sminshall code = -1; 128026049Sminshall } 128126049Sminshall else { 128226049Sminshall code = 0; 128326049Sminshall } 128410294Ssam } 128510294Ssam 128610294Ssam /* 128710294Ssam * Send new user information (re-login) 128810294Ssam */ 128966670Spendry void 129010294Ssam user(argc, argv) 129110294Ssam int argc; 129210294Ssam char **argv; 129310294Ssam { 129466670Spendry char acct[80]; 129526049Sminshall int n, aflag = 0; 129610294Ssam 129745260Sbostic if (argc < 2) 129845260Sbostic (void) another(&argc, &argv, "username"); 129945260Sbostic if (argc < 2 || argc > 4) { 130010294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 130126049Sminshall code = -1; 130266670Spendry return; 130310294Ssam } 130410294Ssam n = command("USER %s", argv[1]); 130510294Ssam if (n == CONTINUE) { 130610294Ssam if (argc < 3 ) 130735658Sbostic argv[2] = getpass("Password: "), argc++; 130810294Ssam n = command("PASS %s", argv[2]); 130910294Ssam } 131010294Ssam if (n == CONTINUE) { 131110294Ssam if (argc < 4) { 131210294Ssam printf("Account: "); (void) fflush(stdout); 131310294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 131410294Ssam acct[strlen(acct) - 1] = '\0'; 131510294Ssam argv[3] = acct; argc++; 131610294Ssam } 131726049Sminshall n = command("ACCT %s", argv[3]); 131826049Sminshall aflag++; 131910294Ssam } 132010294Ssam if (n != COMPLETE) { 132126497Sminshall fprintf(stdout, "Login failed.\n"); 132266670Spendry return; 132310294Ssam } 132426049Sminshall if (!aflag && argc == 4) { 132526049Sminshall (void) command("ACCT %s", argv[3]); 132626049Sminshall } 132710294Ssam } 132810294Ssam 132910294Ssam /* 133010294Ssam * Print working directory. 133110294Ssam */ 133210294Ssam /*VARARGS*/ 133366670Spendry void 133466670Spendry pwd(argc, argv) 133566670Spendry int argc; 133666670Spendry char *argv[]; 133710294Ssam { 133837224Skarels int oldverbose = verbose; 133911756Ssam 134037224Skarels /* 134137224Skarels * If we aren't verbose, this doesn't do anything! 134237224Skarels */ 134337224Skarels verbose = 1; 134437224Skarels if (command("PWD") == ERROR && code == 500) { 134537224Skarels printf("PWD command not recognized, trying XPWD\n"); 134637224Skarels (void) command("XPWD"); 134737224Skarels } 134837224Skarels verbose = oldverbose; 134910294Ssam } 135010294Ssam 135110294Ssam /* 135210294Ssam * Make a directory. 135310294Ssam */ 135466670Spendry void 135510294Ssam makedir(argc, argv) 135645260Sbostic int argc; 135710294Ssam char *argv[]; 135810294Ssam { 135910294Ssam 136045260Sbostic if (argc < 2 && !another(&argc, &argv, "directory-name")) { 136126049Sminshall printf("usage: %s directory-name\n", argv[0]); 136226049Sminshall code = -1; 136310294Ssam return; 136410294Ssam } 136537224Skarels if (command("MKD %s", argv[1]) == ERROR && code == 500) { 136637224Skarels if (verbose) 136737224Skarels printf("MKD command not recognized, trying XMKD\n"); 136837224Skarels (void) command("XMKD %s", argv[1]); 136937224Skarels } 137010294Ssam } 137110294Ssam 137210294Ssam /* 137310294Ssam * Remove a directory. 137410294Ssam */ 137566670Spendry void 137610294Ssam removedir(argc, argv) 137745260Sbostic int argc; 137810294Ssam char *argv[]; 137910294Ssam { 138010294Ssam 138145260Sbostic if (argc < 2 && !another(&argc, &argv, "directory-name")) { 138226049Sminshall printf("usage: %s directory-name\n", argv[0]); 138326049Sminshall code = -1; 138410294Ssam return; 138510294Ssam } 138637224Skarels if (command("RMD %s", argv[1]) == ERROR && code == 500) { 138737224Skarels if (verbose) 138837224Skarels printf("RMD command not recognized, trying XRMD\n"); 138937224Skarels (void) command("XRMD %s", argv[1]); 139037224Skarels } 139110294Ssam } 139210294Ssam 139310294Ssam /* 139410294Ssam * Send a line, verbatim, to the remote machine. 139510294Ssam */ 139666670Spendry void 139710294Ssam quote(argc, argv) 139845260Sbostic int argc; 139910294Ssam char *argv[]; 140010294Ssam { 140110294Ssam 140245260Sbostic if (argc < 2 && !another(&argc, &argv, "command line to send")) { 140310294Ssam printf("usage: %s line-to-send\n", argv[0]); 140426049Sminshall code = -1; 140510294Ssam return; 140610294Ssam } 140745260Sbostic quote1("", argc, argv); 140810294Ssam } 140910294Ssam 141010294Ssam /* 141137224Skarels * Send a SITE command to the remote machine. The line 141245260Sbostic * is sent verbatim to the remote machine, except that the 141345260Sbostic * word "SITE" is added at the front. 141437224Skarels */ 141566670Spendry void 141637224Skarels site(argc, argv) 141745260Sbostic int argc; 141837224Skarels char *argv[]; 141937224Skarels { 142037224Skarels 142145260Sbostic if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) { 142237224Skarels printf("usage: %s line-to-send\n", argv[0]); 142337224Skarels code = -1; 142437224Skarels return; 142537224Skarels } 142645260Sbostic quote1("SITE ", argc, argv); 142745260Sbostic } 142845260Sbostic 142945260Sbostic /* 143045260Sbostic * Turn argv[1..argc) into a space-separated string, then prepend initial text. 143145260Sbostic * Send the result as a one-line command and get response. 143245260Sbostic */ 143366670Spendry void 143445260Sbostic quote1(initial, argc, argv) 143545260Sbostic char *initial; 143645260Sbostic int argc; 143745260Sbostic char **argv; 143845260Sbostic { 143966670Spendry int i, len; 144045260Sbostic char buf[BUFSIZ]; /* must be >= sizeof(line) */ 144145260Sbostic 144245260Sbostic (void) strcpy(buf, initial); 144345260Sbostic if (argc > 1) { 144445260Sbostic len = strlen(buf); 144545260Sbostic len += strlen(strcpy(&buf[len], argv[1])); 144645260Sbostic for (i = 2; i < argc; i++) { 144745260Sbostic buf[len++] = ' '; 144845260Sbostic len += strlen(strcpy(&buf[len], argv[i])); 144945260Sbostic } 145037224Skarels } 145137224Skarels if (command(buf) == PRELIM) { 145266670Spendry while (getreply(0) == PRELIM) 145366670Spendry continue; 145437224Skarels } 145537224Skarels } 145637224Skarels 145766670Spendry void 145837224Skarels do_chmod(argc, argv) 145945260Sbostic int argc; 146037224Skarels char *argv[]; 146137224Skarels { 146245260Sbostic 146345260Sbostic if (argc < 2 && !another(&argc, &argv, "mode")) 146445260Sbostic goto usage; 146545260Sbostic if (argc < 3 && !another(&argc, &argv, "file-name")) { 146645260Sbostic usage: 146737224Skarels printf("usage: %s mode file-name\n", argv[0]); 146837224Skarels code = -1; 146937224Skarels return; 147037224Skarels } 147145260Sbostic (void) command("SITE CHMOD %s %s", argv[1], argv[2]); 147237224Skarels } 147337224Skarels 147466670Spendry void 147537224Skarels do_umask(argc, argv) 147645260Sbostic int argc; 147737224Skarels char *argv[]; 147837224Skarels { 147937224Skarels int oldverbose = verbose; 148037224Skarels 148137224Skarels verbose = 1; 148237224Skarels (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 148337224Skarels verbose = oldverbose; 148437224Skarels } 148537224Skarels 148666670Spendry void 148737224Skarels idle(argc, argv) 148845260Sbostic int argc; 148937224Skarels char *argv[]; 149037224Skarels { 149137224Skarels int oldverbose = verbose; 149237224Skarels 149337224Skarels verbose = 1; 149437224Skarels (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 149537224Skarels verbose = oldverbose; 149637224Skarels } 149737224Skarels 149837224Skarels /* 149910294Ssam * Ask the other side for help. 150010294Ssam */ 150166670Spendry void 150210294Ssam rmthelp(argc, argv) 150345260Sbostic int argc; 150410294Ssam char *argv[]; 150510294Ssam { 150610294Ssam int oldverbose = verbose; 150710294Ssam 150810294Ssam verbose = 1; 150910294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 151010294Ssam verbose = oldverbose; 151110294Ssam } 151210294Ssam 151310294Ssam /* 151410294Ssam * Terminate session and exit. 151510294Ssam */ 151610294Ssam /*VARARGS*/ 151766670Spendry void 151866670Spendry quit(argc, argv) 151966670Spendry int argc; 152066670Spendry char *argv[]; 152110294Ssam { 152210294Ssam 152318286Sralph if (connected) 152466670Spendry disconnect(0, 0); 152526049Sminshall pswitch(1); 152626049Sminshall if (connected) { 152766670Spendry disconnect(0, 0); 152826049Sminshall } 152910294Ssam exit(0); 153010294Ssam } 153110294Ssam 153210294Ssam /* 153310294Ssam * Terminate session, but don't exit. 153410294Ssam */ 153566670Spendry void 153666670Spendry disconnect(argc, argv) 153766670Spendry int argc; 153866670Spendry char *argv[]; 153910294Ssam { 154010294Ssam 154110294Ssam if (!connected) 154210294Ssam return; 154310294Ssam (void) command("QUIT"); 154426049Sminshall if (cout) { 154526049Sminshall (void) fclose(cout); 154626049Sminshall } 154710294Ssam cout = NULL; 154810294Ssam connected = 0; 154910294Ssam data = -1; 155026049Sminshall if (!proxy) { 155126049Sminshall macnum = 0; 155226049Sminshall } 155310294Ssam } 155411353Ssam 155566670Spendry int 155611650Ssam confirm(cmd, file) 155711353Ssam char *cmd, *file; 155811353Ssam { 155911353Ssam char line[BUFSIZ]; 156011353Ssam 156111353Ssam if (!interactive) 156211650Ssam return (1); 156311353Ssam printf("%s %s? ", cmd, file); 156426497Sminshall (void) fflush(stdout); 156545260Sbostic if (fgets(line, sizeof line, stdin) == NULL) 156645260Sbostic return (0); 156711650Ssam return (*line != 'n' && *line != 'N'); 156811353Ssam } 156911353Ssam 157066670Spendry void 157111353Ssam fatal(msg) 157211353Ssam char *msg; 157311353Ssam { 157411353Ssam 157566670Spendry errx(1, "%s", msg); 157611353Ssam } 157711353Ssam 157811353Ssam /* 157911353Ssam * Glob a local file name specification with 158011353Ssam * the expectation of a single return value. 158111353Ssam * Can't control multiple values being expanded 158211353Ssam * from the expression, we return only the first. 158311353Ssam */ 158466670Spendry int 158511353Ssam globulize(cpp) 158611353Ssam char **cpp; 158711353Ssam { 158866692Spendry glob_t gl; 1589*66723Spendry int flags; 159011353Ssam 159111353Ssam if (!doglob) 159211353Ssam return (1); 159366692Spendry 1594*66723Spendry flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; 159566692Spendry memset(&gl, 0, sizeof(gl)); 1596*66723Spendry if (glob(*cpp, flags, NULL, &gl) || 159766692Spendry gl.gl_pathc == 0) { 159866692Spendry warnx("%s: not found", *cpp); 159966692Spendry globfree(&gl); 160011353Ssam return (0); 160111353Ssam } 160266692Spendry *cpp = strdup(gl.gl_pathv[0]); /* XXX - wasted memory */ 160366692Spendry globfree(&gl); 160411353Ssam return (1); 160511353Ssam } 160626049Sminshall 160766670Spendry void 160826049Sminshall account(argc,argv) 160926049Sminshall int argc; 161026049Sminshall char **argv; 161126049Sminshall { 161266692Spendry char acct[50], *ap; 161326049Sminshall 161426049Sminshall if (argc > 1) { 161526049Sminshall ++argv; 161626049Sminshall --argc; 161726049Sminshall (void) strncpy(acct,*argv,49); 161836268Sbostic acct[49] = '\0'; 161926049Sminshall while (argc > 1) { 162026049Sminshall --argc; 162126049Sminshall ++argv; 162226049Sminshall (void) strncat(acct,*argv, 49-strlen(acct)); 162326049Sminshall } 162426049Sminshall ap = acct; 162526049Sminshall } 162626049Sminshall else { 162735658Sbostic ap = getpass("Account:"); 162826049Sminshall } 162926049Sminshall (void) command("ACCT %s", ap); 163026049Sminshall } 163126049Sminshall 163226049Sminshall jmp_buf abortprox; 163326049Sminshall 163439252Sbostic void 163526049Sminshall proxabort() 163626049Sminshall { 163726049Sminshall 163826049Sminshall if (!proxy) { 163926049Sminshall pswitch(1); 164026049Sminshall } 164126049Sminshall if (connected) { 164226049Sminshall proxflag = 1; 164326049Sminshall } 164426049Sminshall else { 164526049Sminshall proxflag = 0; 164626049Sminshall } 164726049Sminshall pswitch(0); 164826049Sminshall longjmp(abortprox,1); 164926049Sminshall } 165026049Sminshall 165166670Spendry void 165266670Spendry doproxy(argc, argv) 165326049Sminshall int argc; 165426049Sminshall char *argv[]; 165526049Sminshall { 165666670Spendry struct cmd *c; 165739252Sbostic sig_t oldintr; 165826049Sminshall 165945260Sbostic if (argc < 2 && !another(&argc, &argv, "command")) { 166045260Sbostic printf("usage: %s command\n", argv[0]); 166126049Sminshall code = -1; 166226049Sminshall return; 166326049Sminshall } 166426049Sminshall c = getcmd(argv[1]); 166526049Sminshall if (c == (struct cmd *) -1) { 166626049Sminshall printf("?Ambiguous command\n"); 166726497Sminshall (void) fflush(stdout); 166826049Sminshall code = -1; 166926049Sminshall return; 167026049Sminshall } 167126049Sminshall if (c == 0) { 167226049Sminshall printf("?Invalid command\n"); 167326497Sminshall (void) fflush(stdout); 167426049Sminshall code = -1; 167526049Sminshall return; 167626049Sminshall } 167726049Sminshall if (!c->c_proxy) { 167826049Sminshall printf("?Invalid proxy command\n"); 167926497Sminshall (void) fflush(stdout); 168026049Sminshall code = -1; 168126049Sminshall return; 168226049Sminshall } 168326049Sminshall if (setjmp(abortprox)) { 168426049Sminshall code = -1; 168526049Sminshall return; 168626049Sminshall } 168726049Sminshall oldintr = signal(SIGINT, proxabort); 168826049Sminshall pswitch(1); 168926049Sminshall if (c->c_conn && !connected) { 169026049Sminshall printf("Not connected\n"); 169126497Sminshall (void) fflush(stdout); 169226049Sminshall pswitch(0); 169326049Sminshall (void) signal(SIGINT, oldintr); 169426049Sminshall code = -1; 169526049Sminshall return; 169626049Sminshall } 169726049Sminshall (*c->c_handler)(argc-1, argv+1); 169826049Sminshall if (connected) { 169926049Sminshall proxflag = 1; 170026049Sminshall } 170126049Sminshall else { 170226049Sminshall proxflag = 0; 170326049Sminshall } 170426049Sminshall pswitch(0); 170526049Sminshall (void) signal(SIGINT, oldintr); 170626049Sminshall } 170726049Sminshall 170866670Spendry void 170966670Spendry setcase(argc, argv) 171066670Spendry int argc; 171166670Spendry char *argv[]; 171226049Sminshall { 171366670Spendry 171426049Sminshall mcase = !mcase; 171526049Sminshall printf("Case mapping %s.\n", onoff(mcase)); 171626049Sminshall code = mcase; 171726049Sminshall } 171826049Sminshall 171966670Spendry void 172066670Spendry setcr(argc, argv) 172166670Spendry int argc; 172266670Spendry char *argv[]; 172326049Sminshall { 172466670Spendry 172526049Sminshall crflag = !crflag; 172626049Sminshall printf("Carriage Return stripping %s.\n", onoff(crflag)); 172726049Sminshall code = crflag; 172826049Sminshall } 172926049Sminshall 173066670Spendry void 173126049Sminshall setntrans(argc,argv) 173226049Sminshall int argc; 173326049Sminshall char *argv[]; 173426049Sminshall { 173526049Sminshall if (argc == 1) { 173626049Sminshall ntflag = 0; 173726049Sminshall printf("Ntrans off.\n"); 173826049Sminshall code = ntflag; 173926049Sminshall return; 174026049Sminshall } 174126049Sminshall ntflag++; 174226049Sminshall code = ntflag; 174326049Sminshall (void) strncpy(ntin, argv[1], 16); 174426049Sminshall ntin[16] = '\0'; 174526049Sminshall if (argc == 2) { 174626049Sminshall ntout[0] = '\0'; 174726049Sminshall return; 174826049Sminshall } 174926049Sminshall (void) strncpy(ntout, argv[2], 16); 175026049Sminshall ntout[16] = '\0'; 175126049Sminshall } 175226049Sminshall 175326049Sminshall char * 175426049Sminshall dotrans(name) 175526049Sminshall char *name; 175626049Sminshall { 175726049Sminshall static char new[MAXPATHLEN]; 175826049Sminshall char *cp1, *cp2 = new; 175966670Spendry int i, ostop, found; 176026049Sminshall 176166670Spendry for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++) 176266670Spendry continue; 176326049Sminshall for (cp1 = name; *cp1; cp1++) { 176426049Sminshall found = 0; 176526049Sminshall for (i = 0; *(ntin + i) && i < 16; i++) { 176626049Sminshall if (*cp1 == *(ntin + i)) { 176726049Sminshall found++; 176826049Sminshall if (i < ostop) { 176926049Sminshall *cp2++ = *(ntout + i); 177026049Sminshall } 177126049Sminshall break; 177226049Sminshall } 177326049Sminshall } 177426049Sminshall if (!found) { 177526049Sminshall *cp2++ = *cp1; 177626049Sminshall } 177726049Sminshall } 177826049Sminshall *cp2 = '\0'; 177966670Spendry return (new); 178026049Sminshall } 178126049Sminshall 178266670Spendry void 178326049Sminshall setnmap(argc, argv) 178426049Sminshall int argc; 178526049Sminshall char *argv[]; 178626049Sminshall { 178726049Sminshall char *cp; 178826049Sminshall 178926049Sminshall if (argc == 1) { 179026049Sminshall mapflag = 0; 179126049Sminshall printf("Nmap off.\n"); 179226049Sminshall code = mapflag; 179326049Sminshall return; 179426049Sminshall } 179545260Sbostic if (argc < 3 && !another(&argc, &argv, "mapout")) { 179626049Sminshall printf("Usage: %s [mapin mapout]\n",argv[0]); 179726049Sminshall code = -1; 179826049Sminshall return; 179926049Sminshall } 180026049Sminshall mapflag = 1; 180126049Sminshall code = 1; 180266670Spendry cp = strchr(altarg, ' '); 180326049Sminshall if (proxy) { 180466670Spendry while(*++cp == ' ') 180566670Spendry continue; 180626049Sminshall altarg = cp; 180766670Spendry cp = strchr(altarg, ' '); 180826049Sminshall } 180926049Sminshall *cp = '\0'; 181026049Sminshall (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 181166670Spendry while (*++cp == ' ') 181266670Spendry continue; 181326049Sminshall (void) strncpy(mapout, cp, MAXPATHLEN - 1); 181426049Sminshall } 181526049Sminshall 181626049Sminshall char * 181726049Sminshall domap(name) 181826049Sminshall char *name; 181926049Sminshall { 182026049Sminshall static char new[MAXPATHLEN]; 182166670Spendry char *cp1 = name, *cp2 = mapin; 182226049Sminshall char *tp[9], *te[9]; 182336689Scsvsj int i, toks[9], toknum = 0, match = 1; 182426049Sminshall 182526049Sminshall for (i=0; i < 9; ++i) { 182626049Sminshall toks[i] = 0; 182726049Sminshall } 182826049Sminshall while (match && *cp1 && *cp2) { 182926049Sminshall switch (*cp2) { 183026049Sminshall case '\\': 183126049Sminshall if (*++cp2 != *cp1) { 183226049Sminshall match = 0; 183326049Sminshall } 183426049Sminshall break; 183526049Sminshall case '$': 183626049Sminshall if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 183726049Sminshall if (*cp1 != *(++cp2+1)) { 183826049Sminshall toks[toknum = *cp2 - '1']++; 183926049Sminshall tp[toknum] = cp1; 184026049Sminshall while (*++cp1 && *(cp2+1) 184126049Sminshall != *cp1); 184226049Sminshall te[toknum] = cp1; 184326049Sminshall } 184426049Sminshall cp2++; 184526049Sminshall break; 184626049Sminshall } 184736935Skarels /* FALLTHROUGH */ 184826049Sminshall default: 184926049Sminshall if (*cp2 != *cp1) { 185026049Sminshall match = 0; 185126049Sminshall } 185226049Sminshall break; 185326049Sminshall } 185436689Scsvsj if (match && *cp1) { 185526049Sminshall cp1++; 185626049Sminshall } 185736689Scsvsj if (match && *cp2) { 185826049Sminshall cp2++; 185926049Sminshall } 186026049Sminshall } 186136689Scsvsj if (!match && *cp1) /* last token mismatch */ 186236689Scsvsj { 186336689Scsvsj toks[toknum] = 0; 186436689Scsvsj } 186526049Sminshall cp1 = new; 186626049Sminshall *cp1 = '\0'; 186726049Sminshall cp2 = mapout; 186826049Sminshall while (*cp2) { 186926049Sminshall match = 0; 187026049Sminshall switch (*cp2) { 187126049Sminshall case '\\': 187226049Sminshall if (*(cp2 + 1)) { 187326049Sminshall *cp1++ = *++cp2; 187426049Sminshall } 187526049Sminshall break; 187626049Sminshall case '[': 187726049Sminshall LOOP: 187826049Sminshall if (*++cp2 == '$' && isdigit(*(cp2+1))) { 187926049Sminshall if (*++cp2 == '0') { 188026049Sminshall char *cp3 = name; 188126049Sminshall 188226049Sminshall while (*cp3) { 188326049Sminshall *cp1++ = *cp3++; 188426049Sminshall } 188526049Sminshall match = 1; 188626049Sminshall } 188726049Sminshall else if (toks[toknum = *cp2 - '1']) { 188826049Sminshall char *cp3 = tp[toknum]; 188926049Sminshall 189026049Sminshall while (cp3 != te[toknum]) { 189126049Sminshall *cp1++ = *cp3++; 189226049Sminshall } 189326049Sminshall match = 1; 189426049Sminshall } 189526049Sminshall } 189626049Sminshall else { 189726049Sminshall while (*cp2 && *cp2 != ',' && 189826049Sminshall *cp2 != ']') { 189926049Sminshall if (*cp2 == '\\') { 190026049Sminshall cp2++; 190126049Sminshall } 190226049Sminshall else if (*cp2 == '$' && 190326049Sminshall isdigit(*(cp2+1))) { 190426049Sminshall if (*++cp2 == '0') { 190526049Sminshall char *cp3 = name; 190626049Sminshall 190726049Sminshall while (*cp3) { 190826049Sminshall *cp1++ = *cp3++; 190926049Sminshall } 191026049Sminshall } 191126049Sminshall else if (toks[toknum = 191226049Sminshall *cp2 - '1']) { 191326049Sminshall char *cp3=tp[toknum]; 191426049Sminshall 191526049Sminshall while (cp3 != 191626049Sminshall te[toknum]) { 191726049Sminshall *cp1++ = *cp3++; 191826049Sminshall } 191926049Sminshall } 192026049Sminshall } 192126049Sminshall else if (*cp2) { 192226049Sminshall *cp1++ = *cp2++; 192326049Sminshall } 192426049Sminshall } 192526049Sminshall if (!*cp2) { 192626049Sminshall printf("nmap: unbalanced brackets\n"); 192766670Spendry return (name); 192826049Sminshall } 192926049Sminshall match = 1; 193026049Sminshall cp2--; 193126049Sminshall } 193226049Sminshall if (match) { 193326049Sminshall while (*++cp2 && *cp2 != ']') { 193426049Sminshall if (*cp2 == '\\' && *(cp2 + 1)) { 193526049Sminshall cp2++; 193626049Sminshall } 193726049Sminshall } 193826049Sminshall if (!*cp2) { 193926049Sminshall printf("nmap: unbalanced brackets\n"); 194066670Spendry return (name); 194126049Sminshall } 194226049Sminshall break; 194326049Sminshall } 194426049Sminshall switch (*++cp2) { 194526049Sminshall case ',': 194626049Sminshall goto LOOP; 194726049Sminshall case ']': 194826049Sminshall break; 194926049Sminshall default: 195026049Sminshall cp2--; 195126049Sminshall goto LOOP; 195226049Sminshall } 195326049Sminshall break; 195426049Sminshall case '$': 195526049Sminshall if (isdigit(*(cp2 + 1))) { 195626049Sminshall if (*++cp2 == '0') { 195726049Sminshall char *cp3 = name; 195826049Sminshall 195926049Sminshall while (*cp3) { 196026049Sminshall *cp1++ = *cp3++; 196126049Sminshall } 196226049Sminshall } 196326049Sminshall else if (toks[toknum = *cp2 - '1']) { 196426049Sminshall char *cp3 = tp[toknum]; 196526049Sminshall 196626049Sminshall while (cp3 != te[toknum]) { 196726049Sminshall *cp1++ = *cp3++; 196826049Sminshall } 196926049Sminshall } 197026049Sminshall break; 197126049Sminshall } 197226049Sminshall /* intentional drop through */ 197326049Sminshall default: 197426049Sminshall *cp1++ = *cp2; 197526049Sminshall break; 197626049Sminshall } 197726049Sminshall cp2++; 197826049Sminshall } 197926049Sminshall *cp1 = '\0'; 198026049Sminshall if (!*new) { 198166670Spendry return (name); 198226049Sminshall } 198366670Spendry return (new); 198426049Sminshall } 198526049Sminshall 198666670Spendry void 198766670Spendry setsunique(argc, argv) 198866670Spendry int argc; 198966670Spendry char *argv[]; 199026049Sminshall { 199166670Spendry 199226049Sminshall sunique = !sunique; 199326049Sminshall printf("Store unique %s.\n", onoff(sunique)); 199426049Sminshall code = sunique; 199526049Sminshall } 199626049Sminshall 199766670Spendry void 199866670Spendry setrunique(argc, argv) 199966670Spendry int argc; 200066670Spendry char *argv[]; 200126049Sminshall { 200266670Spendry 200326049Sminshall runique = !runique; 200426049Sminshall printf("Receive unique %s.\n", onoff(runique)); 200526049Sminshall code = runique; 200626049Sminshall } 200726049Sminshall 200826049Sminshall /* change directory to perent directory */ 200966670Spendry void 201066670Spendry cdup(argc, argv) 201166670Spendry int argc; 201266670Spendry char *argv[]; 201326049Sminshall { 201466670Spendry 201537224Skarels if (command("CDUP") == ERROR && code == 500) { 201637224Skarels if (verbose) 201737224Skarels printf("CDUP command not recognized, trying XCUP\n"); 201837224Skarels (void) command("XCUP"); 201937224Skarels } 202026049Sminshall } 202126049Sminshall 202237224Skarels /* restart transfer at specific point */ 202366670Spendry void 202437224Skarels restart(argc, argv) 202537224Skarels int argc; 202637224Skarels char *argv[]; 202737224Skarels { 202866670Spendry 202937224Skarels if (argc != 2) 203037224Skarels printf("restart: offset not specified\n"); 203137224Skarels else { 203237224Skarels restart_point = atol(argv[1]); 203366670Spendry printf("restarting at %qd. %s\n", restart_point, 203437224Skarels "execute get, put or append to initiate transfer"); 203537224Skarels } 203637224Skarels } 203736935Skarels 203836935Skarels /* show remote system type */ 203966670Spendry void 204066670Spendry syst(argc, argv) 204166670Spendry int argc; 204266670Spendry char *argv[]; 204336935Skarels { 204466670Spendry 204536935Skarels (void) command("SYST"); 204636935Skarels } 204736935Skarels 204866670Spendry void 204926049Sminshall macdef(argc, argv) 205026049Sminshall int argc; 205126049Sminshall char *argv[]; 205226049Sminshall { 205326049Sminshall char *tmp; 205426049Sminshall int c; 205526049Sminshall 205626049Sminshall if (macnum == 16) { 205726049Sminshall printf("Limit of 16 macros have already been defined\n"); 205826049Sminshall code = -1; 205926049Sminshall return; 206026049Sminshall } 206145260Sbostic if (argc < 2 && !another(&argc, &argv, "macro name")) { 206226049Sminshall printf("Usage: %s macro_name\n",argv[0]); 206326049Sminshall code = -1; 206426049Sminshall return; 206526049Sminshall } 206626049Sminshall if (interactive) { 206726049Sminshall printf("Enter macro line by line, terminating it with a null line\n"); 206826049Sminshall } 206926497Sminshall (void) strncpy(macros[macnum].mac_name, argv[1], 8); 207026049Sminshall if (macnum == 0) { 207126049Sminshall macros[macnum].mac_start = macbuf; 207226049Sminshall } 207326049Sminshall else { 207426049Sminshall macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 207526049Sminshall } 207626049Sminshall tmp = macros[macnum].mac_start; 207726049Sminshall while (tmp != macbuf+4096) { 207826049Sminshall if ((c = getchar()) == EOF) { 207926049Sminshall printf("macdef:end of file encountered\n"); 208026049Sminshall code = -1; 208126049Sminshall return; 208226049Sminshall } 208326049Sminshall if ((*tmp = c) == '\n') { 208426049Sminshall if (tmp == macros[macnum].mac_start) { 208526049Sminshall macros[macnum++].mac_end = tmp; 208626049Sminshall code = 0; 208726049Sminshall return; 208826049Sminshall } 208926049Sminshall if (*(tmp-1) == '\0') { 209026049Sminshall macros[macnum++].mac_end = tmp - 1; 209126049Sminshall code = 0; 209226049Sminshall return; 209326049Sminshall } 209426049Sminshall *tmp = '\0'; 209526049Sminshall } 209626049Sminshall tmp++; 209726049Sminshall } 209826049Sminshall while (1) { 209936935Skarels while ((c = getchar()) != '\n' && c != EOF) 210036935Skarels /* LOOP */; 210126049Sminshall if (c == EOF || getchar() == '\n') { 210226049Sminshall printf("Macro not defined - 4k buffer exceeded\n"); 210326049Sminshall code = -1; 210426049Sminshall return; 210526049Sminshall } 210626049Sminshall } 210726049Sminshall } 210836935Skarels 210936935Skarels /* 211036935Skarels * get size of file on remote machine 211136935Skarels */ 211266670Spendry void 211336935Skarels sizecmd(argc, argv) 211445260Sbostic int argc; 211536935Skarels char *argv[]; 211636935Skarels { 211736935Skarels 211845260Sbostic if (argc < 2 && !another(&argc, &argv, "filename")) { 211945260Sbostic printf("usage: %s filename\n", argv[0]); 212036935Skarels code = -1; 212136935Skarels return; 212236935Skarels } 212336935Skarels (void) command("SIZE %s", argv[1]); 212436935Skarels } 212536935Skarels 212636935Skarels /* 212736935Skarels * get last modification time of file on remote machine 212836935Skarels */ 212966670Spendry void 213036935Skarels modtime(argc, argv) 213145260Sbostic int argc; 213236935Skarels char *argv[]; 213336935Skarels { 213436935Skarels int overbose; 213536935Skarels 213645260Sbostic if (argc < 2 && !another(&argc, &argv, "filename")) { 213745260Sbostic printf("usage: %s filename\n", argv[0]); 213836935Skarels code = -1; 213936935Skarels return; 214036935Skarels } 214136940Skarels overbose = verbose; 214236940Skarels if (debug == 0) 214336940Skarels verbose = -1; 214436935Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 214536935Skarels int yy, mo, day, hour, min, sec; 214636935Skarels sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 214736935Skarels &day, &hour, &min, &sec); 214836935Skarels /* might want to print this in local time */ 214936935Skarels printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 215036935Skarels mo, day, yy, hour, min, sec); 215136935Skarels } else 215238132Srick printf("%s\n", reply_string); 215336935Skarels verbose = overbose; 215436935Skarels } 215536935Skarels 215636935Skarels /* 215737224Skarels * show status on reomte machine 215836935Skarels */ 215966670Spendry void 216036935Skarels rmtstatus(argc, argv) 216145260Sbostic int argc; 216236935Skarels char *argv[]; 216336935Skarels { 216466670Spendry 216536935Skarels (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 216636935Skarels } 216737224Skarels 216837224Skarels /* 216937224Skarels * get file if modtime is more recent than current file 217037224Skarels */ 217166670Spendry void 217237224Skarels newer(argc, argv) 217345260Sbostic int argc; 217437224Skarels char *argv[]; 217537224Skarels { 217666670Spendry 217737224Skarels if (getit(argc, argv, -1, "w")) 217837224Skarels printf("Local file \"%s\" is newer than remote file \"%s\"\n", 217954742Sandrew argv[2], argv[1]); 218037224Skarels } 2181