121737Sdist /* 236942Skarels * Copyright (c) 1985, 1989 Regents of the University of California. 333737Sbostic * All rights reserved. 433737Sbostic * 542665Sbostic * %sccs.include.redist.c% 621737Sdist */ 721737Sdist 810294Ssam #ifndef lint 9*46828Sbostic static char sccsid[] = "@(#)cmds.c 5.25 (Berkeley) 03/01/91"; 1033737Sbostic #endif /* not lint */ 1110294Ssam 1210294Ssam /* 1310294Ssam * FTP User Program -- Command Routines. 1410294Ssam */ 1536940Skarels #include <sys/param.h> 1636940Skarels #include <sys/wait.h> 1736940Skarels #include <sys/stat.h> 1810294Ssam #include <sys/socket.h> 1910294Ssam 2012396Ssam #include <arpa/ftp.h> 2112396Ssam 2210294Ssam #include <signal.h> 2310294Ssam #include <stdio.h> 2410294Ssam #include <errno.h> 2510294Ssam #include <netdb.h> 2626049Sminshall #include <ctype.h> 2736935Skarels #include <time.h> 2838132Srick #include <netinet/in.h> 2910294Ssam 3036940Skarels #include "ftp_var.h" 3137458Skarels #include "pathnames.h" 3210294Ssam 3311353Ssam extern char *globerr; 3411353Ssam extern char **glob(); 3511756Ssam extern char *home; 3611756Ssam extern char *remglob(); 3711756Ssam extern char *getenv(); 3811756Ssam extern char *index(); 3911756Ssam extern char *rindex(); 4038202Srick extern char *strerror(); 4138202Srick extern int errno; 4237224Skarels extern off_t restart_point; 4336935Skarels extern char reply_string[]; 4436935Skarels 4526049Sminshall char *mname; 4626049Sminshall jmp_buf jabort; 4726049Sminshall char *dotrans(), *domap(); 4810294Ssam 4910294Ssam /* 5045260Sbostic * `Another' gets another argument, and stores the new argc and argv. 5145260Sbostic * It reverts to the top level (via main.c's intr()) on EOF/error. 5245260Sbostic * 5345260Sbostic * Returns false if no new arguments have been added. 5445260Sbostic */ 5545260Sbostic another(pargc, pargv, prompt) 5645260Sbostic int *pargc; 5745260Sbostic char ***pargv; 5845260Sbostic char *prompt; 5945260Sbostic { 6045260Sbostic int len = strlen(line), ret; 6145260Sbostic extern sig_t intr(); 6245260Sbostic 6345260Sbostic if (len >= sizeof(line) - 3) { 6445260Sbostic printf("sorry, arguments too long\n"); 6545260Sbostic intr(); 6645260Sbostic } 6745260Sbostic printf("(%s) ", prompt); 6845260Sbostic line[len++] = ' '; 6945260Sbostic if (fgets(&line[len], sizeof(line) - len, stdin) == NULL) 7045260Sbostic intr(); 7145260Sbostic len += strlen(&line[len]); 7245260Sbostic if (len > 0 && line[len - 1] == '\n') 7345260Sbostic line[len - 1] = '\0'; 7445260Sbostic makeargv(); 7545260Sbostic ret = margc > *pargc; 7645260Sbostic *pargc = margc; 7745260Sbostic *pargv = margv; 7845260Sbostic return (ret); 7945260Sbostic } 8045260Sbostic 8145260Sbostic /* 8210294Ssam * Connect to peer server and 8310294Ssam * auto-login, if possible. 8410294Ssam */ 8510294Ssam setpeer(argc, argv) 8610294Ssam int argc; 8710294Ssam char *argv[]; 8810294Ssam { 8925903Skarels char *host, *hookup(); 9038132Srick short port; 9110294Ssam 9210294Ssam if (connected) { 9326049Sminshall printf("Already connected to %s, use close first.\n", 9410294Ssam hostname); 9526049Sminshall code = -1; 9610294Ssam return; 9710294Ssam } 9845260Sbostic if (argc < 2) 9945260Sbostic (void) another(&argc, &argv, "to"); 10045260Sbostic if (argc < 2 || argc > 3) { 10110294Ssam printf("usage: %s host-name [port]\n", argv[0]); 10226049Sminshall code = -1; 10310294Ssam return; 10410294Ssam } 10510294Ssam port = sp->s_port; 10610294Ssam if (argc > 2) { 10711218Ssam port = atoi(argv[2]); 10810294Ssam if (port <= 0) { 10911218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 11011218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 11126049Sminshall code = -1; 11210294Ssam return; 11310294Ssam } 11410294Ssam port = htons(port); 11510294Ssam } 11610294Ssam host = hookup(argv[1], port); 11710294Ssam if (host) { 11837228Skarels int overbose; 11937228Skarels 12010294Ssam connected = 1; 12138032Skarels /* 12238032Skarels * Set up defaults for FTP. 12338032Skarels */ 12438032Skarels (void) strcpy(typename, "ascii"), type = TYPE_A; 12538032Skarels curtype = TYPE_A; 12638032Skarels (void) strcpy(formname, "non-print"), form = FORM_N; 12738032Skarels (void) strcpy(modename, "stream"), mode = MODE_S; 12838032Skarels (void) strcpy(structname, "file"), stru = STRU_F; 12938032Skarels (void) strcpy(bytename, "8"), bytesize = 8; 13037228Skarels if (autologin) 13137228Skarels (void) login(argv[1]); 13236940Skarels 13336935Skarels #if defined(unix) && NBBY == 8 13436935Skarels /* 13536935Skarels * this ifdef is to keep someone form "porting" this to an incompatible 13636935Skarels * system and not checking this out. This way they have to think about it. 13736935Skarels */ 13837228Skarels overbose = verbose; 13937228Skarels if (debug == 0) 14037228Skarels verbose = -1; 14137228Skarels if (command("SYST") == COMPLETE && overbose) { 14237228Skarels register char *cp, c; 14337228Skarels cp = index(reply_string+4, ' '); 14437228Skarels if (cp == NULL) 14537228Skarels cp = index(reply_string+4, '\r'); 14637228Skarels if (cp) { 14737228Skarels if (cp[-1] == '.') 14837228Skarels cp--; 14937228Skarels c = *cp; 15037228Skarels *cp = '\0'; 15137228Skarels } 15236935Skarels 15337228Skarels printf("Remote system type is %s.\n", 15437228Skarels reply_string+4); 15537228Skarels if (cp) 15637228Skarels *cp = c; 15737228Skarels } 15837228Skarels if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { 15938032Skarels if (proxy) 16038032Skarels unix_proxy = 1; 16138032Skarels else 16238032Skarels unix_server = 1; 16338032Skarels /* 16438032Skarels * Set type to 0 (not specified by user), 16538032Skarels * meaning binary by default, but don't bother 16638032Skarels * telling server. We can use binary 16738032Skarels * for text files unless changed by the user. 16838032Skarels */ 16938032Skarels type = 0; 17038032Skarels (void) strcpy(typename, "binary"); 17137228Skarels if (overbose) 17237228Skarels printf("Using %s mode to transfer files.\n", 17337228Skarels typename); 17438032Skarels } else { 17538032Skarels if (proxy) 17638032Skarels unix_proxy = 0; 17738032Skarels else 17838032Skarels unix_server = 0; 17938032Skarels if (overbose && 18038032Skarels !strncmp(reply_string, "215 TOPS20", 10)) 18138032Skarels printf( 18236940Skarels "Remember to set tenex mode when transfering binary files from this machine.\n"); 18337228Skarels } 18437228Skarels verbose = overbose; 18536935Skarels #endif /* unix */ 18610294Ssam } 18710294Ssam } 18810294Ssam 18910294Ssam struct types { 19010294Ssam char *t_name; 19110294Ssam char *t_mode; 19210294Ssam int t_type; 19311218Ssam char *t_arg; 19410294Ssam } types[] = { 19511218Ssam { "ascii", "A", TYPE_A, 0 }, 19611218Ssam { "binary", "I", TYPE_I, 0 }, 19711218Ssam { "image", "I", TYPE_I, 0 }, 19811218Ssam { "ebcdic", "E", TYPE_E, 0 }, 19911218Ssam { "tenex", "L", TYPE_L, bytename }, 20010294Ssam 0 20110294Ssam }; 20210294Ssam 20310294Ssam /* 20410294Ssam * Set transfer type. 20510294Ssam */ 20610294Ssam settype(argc, argv) 20745260Sbostic int argc; 20810294Ssam char *argv[]; 20910294Ssam { 21010294Ssam register struct types *p; 21111218Ssam int comret; 21210294Ssam 21310294Ssam if (argc > 2) { 21410294Ssam char *sep; 21510294Ssam 21610294Ssam printf("usage: %s [", argv[0]); 21710294Ssam sep = " "; 21810294Ssam for (p = types; p->t_name; p++) { 21910294Ssam printf("%s%s", sep, p->t_name); 22038032Skarels sep = " | "; 22110294Ssam } 22210294Ssam printf(" ]\n"); 22326049Sminshall code = -1; 22410294Ssam return; 22510294Ssam } 22610294Ssam if (argc < 2) { 22710294Ssam printf("Using %s mode to transfer files.\n", typename); 22826049Sminshall code = 0; 22910294Ssam return; 23010294Ssam } 23110294Ssam for (p = types; p->t_name; p++) 23210294Ssam if (strcmp(argv[1], p->t_name) == 0) 23310294Ssam break; 23410294Ssam if (p->t_name == 0) { 23510294Ssam printf("%s: unknown mode\n", argv[1]); 23626049Sminshall code = -1; 23710294Ssam return; 23810294Ssam } 23911218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 24011218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 24111218Ssam else 24211218Ssam comret = command("TYPE %s", p->t_mode); 24311218Ssam if (comret == COMPLETE) { 24426497Sminshall (void) strcpy(typename, p->t_name); 24538032Skarels curtype = type = p->t_type; 24610294Ssam } 24710294Ssam } 24810294Ssam 24910294Ssam /* 25038032Skarels * Internal form of settype; changes current type in use with server 25138032Skarels * without changing our notion of the type for data transfers. 25238032Skarels * Used to change to and from ascii for listings. 25338032Skarels */ 25438032Skarels changetype(newtype, show) 25538032Skarels int newtype, show; 25638032Skarels { 25738032Skarels register struct types *p; 25838032Skarels int comret, oldverbose = verbose; 25938032Skarels 26038032Skarels if (newtype == 0) 26138032Skarels newtype = TYPE_I; 26238032Skarels if (newtype == curtype) 26338032Skarels return; 26438032Skarels if (debug == 0 && show == 0) 26538032Skarels verbose = 0; 26638032Skarels for (p = types; p->t_name; p++) 26738032Skarels if (newtype == p->t_type) 26838032Skarels break; 26938032Skarels if (p->t_name == 0) { 27038032Skarels printf("ftp: internal error: unknown type %d\n", newtype); 27138032Skarels return; 27238032Skarels } 27338032Skarels if (newtype == TYPE_L && bytename[0] != '\0') 27438032Skarels comret = command("TYPE %s %s", p->t_mode, bytename); 27538032Skarels else 27638032Skarels comret = command("TYPE %s", p->t_mode); 27738032Skarels if (comret == COMPLETE) 27838032Skarels curtype = newtype; 27938032Skarels verbose = oldverbose; 28038032Skarels } 28138032Skarels 28238132Srick char *stype[] = { 28338132Srick "type", 28438132Srick "", 28538132Srick 0 28638132Srick }; 28738132Srick 28838032Skarels /* 28910294Ssam * Set binary transfer type. 29010294Ssam */ 29110294Ssam /*VARARGS*/ 29210294Ssam setbinary() 29310294Ssam { 29438132Srick stype[1] = "binary"; 29538132Srick settype(2, stype); 29610294Ssam } 29710294Ssam 29810294Ssam /* 29910294Ssam * Set ascii transfer type. 30010294Ssam */ 30110294Ssam /*VARARGS*/ 30210294Ssam setascii() 30310294Ssam { 30438132Srick stype[1] = "ascii"; 30538132Srick settype(2, stype); 30610294Ssam } 30710294Ssam 30810294Ssam /* 30910294Ssam * Set tenex transfer type. 31010294Ssam */ 31110294Ssam /*VARARGS*/ 31210294Ssam settenex() 31310294Ssam { 31438132Srick stype[1] = "tenex"; 31538132Srick settype(2, stype); 31610294Ssam } 31710294Ssam 31810294Ssam /* 31910294Ssam * Set file transfer mode. 32010294Ssam */ 32126497Sminshall /*ARGSUSED*/ 32210294Ssam setmode(argc, argv) 32345260Sbostic int argc; 32410294Ssam char *argv[]; 32510294Ssam { 32610294Ssam 32710294Ssam printf("We only support %s mode, sorry.\n", modename); 32826049Sminshall code = -1; 32910294Ssam } 33010294Ssam 33110294Ssam /* 33210294Ssam * Set file transfer format. 33310294Ssam */ 33426497Sminshall /*ARGSUSED*/ 33510294Ssam setform(argc, argv) 33645260Sbostic int argc; 33710294Ssam char *argv[]; 33810294Ssam { 33910294Ssam 34010294Ssam printf("We only support %s format, sorry.\n", formname); 34126049Sminshall code = -1; 34210294Ssam } 34310294Ssam 34410294Ssam /* 34510294Ssam * Set file transfer structure. 34610294Ssam */ 34726497Sminshall /*ARGSUSED*/ 34810294Ssam setstruct(argc, argv) 34945260Sbostic int argc; 35010294Ssam char *argv[]; 35110294Ssam { 35210294Ssam 35310294Ssam printf("We only support %s structure, sorry.\n", structname); 35426049Sminshall code = -1; 35510294Ssam } 35610294Ssam 35718286Sralph /* 35818286Sralph * Send a single file. 35918286Sralph */ 36010294Ssam put(argc, argv) 36111756Ssam int argc; 36210294Ssam char *argv[]; 36310294Ssam { 36411650Ssam char *cmd; 36526049Sminshall int loc = 0; 36637225Skarels char *oldargv1, *oldargv2; 36711650Ssam 36826049Sminshall if (argc == 2) { 36926049Sminshall argc++; 37026049Sminshall argv[2] = argv[1]; 37126049Sminshall loc++; 37226049Sminshall } 37345260Sbostic if (argc < 2 && !another(&argc, &argv, "local-file")) 37445260Sbostic goto usage; 37545260Sbostic if (argc < 3 && !another(&argc, &argv, "remote-file")) { 37610294Ssam usage: 37745260Sbostic printf("usage: %s local-file remote-file\n", argv[0]); 37826049Sminshall code = -1; 37910294Ssam return; 38010294Ssam } 38125908Smckusick oldargv1 = argv[1]; 38237225Skarels oldargv2 = argv[2]; 38326049Sminshall if (!globulize(&argv[1])) { 38426049Sminshall code = -1; 38511353Ssam return; 38626049Sminshall } 38725908Smckusick /* 38825908Smckusick * If "globulize" modifies argv[1], and argv[2] is a copy of 38925908Smckusick * the old argv[1], make it a copy of the new argv[1]. 39025908Smckusick */ 39126049Sminshall if (argv[1] != oldargv1 && argv[2] == oldargv1) { 39225908Smckusick argv[2] = argv[1]; 39326049Sminshall } 39426049Sminshall cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); 39526049Sminshall if (loc && ntflag) { 39626049Sminshall argv[2] = dotrans(argv[2]); 39726049Sminshall } 39826049Sminshall if (loc && mapflag) { 39926049Sminshall argv[2] = domap(argv[2]); 40026049Sminshall } 40137225Skarels sendrequest(cmd, argv[1], argv[2], 40237225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 40310294Ssam } 40410294Ssam 40510294Ssam /* 40611756Ssam * Send multiple files. 40710294Ssam */ 40811353Ssam mput(argc, argv) 40939252Sbostic int argc; 41039252Sbostic char **argv; 41111353Ssam { 41239252Sbostic extern jmp_buf jabort; 41313212Ssam register int i; 41439252Sbostic sig_t oldintr; 41538132Srick int ointer; 41626049Sminshall char *tp; 41739252Sbostic void mabort(); 41811353Ssam 41945260Sbostic if (argc < 2 && !another(&argc, &argv, "local-files")) { 42045260Sbostic printf("usage: %s local-files\n", argv[0]); 42126049Sminshall code = -1; 42211353Ssam return; 42311353Ssam } 42426049Sminshall mname = argv[0]; 42526049Sminshall mflag = 1; 42626049Sminshall oldintr = signal(SIGINT, mabort); 42726049Sminshall (void) setjmp(jabort); 42826049Sminshall if (proxy) { 42926049Sminshall char *cp, *tp2, tmpbuf[MAXPATHLEN]; 43026049Sminshall 43126497Sminshall while ((cp = remglob(argv,0)) != NULL) { 43226049Sminshall if (*cp == 0) { 43326049Sminshall mflag = 0; 43426049Sminshall continue; 43526049Sminshall } 43626049Sminshall if (mflag && confirm(argv[0], cp)) { 43726049Sminshall tp = cp; 43826049Sminshall if (mcase) { 43926049Sminshall while (*tp && !islower(*tp)) { 44026049Sminshall tp++; 44126049Sminshall } 44226049Sminshall if (!*tp) { 44326049Sminshall tp = cp; 44426049Sminshall tp2 = tmpbuf; 44526049Sminshall while ((*tp2 = *tp) != NULL) { 44626049Sminshall if (isupper(*tp2)) { 44726049Sminshall *tp2 = 'a' + *tp2 - 'A'; 44826049Sminshall } 44926049Sminshall tp++; 45026049Sminshall tp2++; 45126049Sminshall } 45226049Sminshall } 45326049Sminshall tp = tmpbuf; 45426049Sminshall } 45526049Sminshall if (ntflag) { 45626049Sminshall tp = dotrans(tp); 45726049Sminshall } 45826049Sminshall if (mapflag) { 45926049Sminshall tp = domap(tp); 46026049Sminshall } 46137225Skarels sendrequest((sunique) ? "STOU" : "STOR", 46237225Skarels cp, tp, cp != tp || !interactive); 46326049Sminshall if (!mflag && fromatty) { 46426049Sminshall ointer = interactive; 46526049Sminshall interactive = 1; 46626049Sminshall if (confirm("Continue with","mput")) { 46726049Sminshall mflag++; 46826049Sminshall } 46926049Sminshall interactive = ointer; 47026049Sminshall } 47126049Sminshall } 47226049Sminshall } 47326049Sminshall (void) signal(SIGINT, oldintr); 47426049Sminshall mflag = 0; 47526049Sminshall return; 47626049Sminshall } 47713212Ssam for (i = 1; i < argc; i++) { 47813212Ssam register char **cpp, **gargs; 47913212Ssam 48013212Ssam if (!doglob) { 48126049Sminshall if (mflag && confirm(argv[0], argv[i])) { 48226049Sminshall tp = (ntflag) ? dotrans(argv[i]) : argv[i]; 48326049Sminshall tp = (mapflag) ? domap(tp) : tp; 48426049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 48537225Skarels argv[i], tp, tp != argv[i] || !interactive); 48626049Sminshall if (!mflag && fromatty) { 48726049Sminshall ointer = interactive; 48826049Sminshall interactive = 1; 48926049Sminshall if (confirm("Continue with","mput")) { 49026049Sminshall mflag++; 49126049Sminshall } 49226049Sminshall interactive = ointer; 49326049Sminshall } 49426049Sminshall } 49513212Ssam continue; 49613212Ssam } 49713212Ssam gargs = glob(argv[i]); 49811650Ssam if (globerr != NULL) { 49911650Ssam printf("%s\n", globerr); 50036421Sbostic if (gargs) { 50111650Ssam blkfree(gargs); 50238132Srick free((char *)gargs); 50336421Sbostic } 50413212Ssam continue; 50511353Ssam } 50626049Sminshall for (cpp = gargs; cpp && *cpp != NULL; cpp++) { 50726049Sminshall if (mflag && confirm(argv[0], *cpp)) { 50826049Sminshall tp = (ntflag) ? dotrans(*cpp) : *cpp; 50926049Sminshall tp = (mapflag) ? domap(tp) : tp; 51026049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 51137225Skarels *cpp, tp, *cpp != tp || !interactive); 51226049Sminshall if (!mflag && fromatty) { 51326049Sminshall ointer = interactive; 51426049Sminshall interactive = 1; 51526049Sminshall if (confirm("Continue with","mput")) { 51626049Sminshall mflag++; 51726049Sminshall } 51826049Sminshall interactive = ointer; 51926049Sminshall } 52026049Sminshall } 52126049Sminshall } 52236421Sbostic if (gargs != NULL) { 52313212Ssam blkfree(gargs); 52438132Srick free((char *)gargs); 52536421Sbostic } 52611353Ssam } 52726049Sminshall (void) signal(SIGINT, oldintr); 52826049Sminshall mflag = 0; 52911353Ssam } 53011353Ssam 53137224Skarels reget(argc, argv) 53245260Sbostic int argc; 53337224Skarels char *argv[]; 53437224Skarels { 53537224Skarels (void) getit(argc, argv, 1, "r+w"); 53637224Skarels } 53736935Skarels 53837224Skarels get(argc, argv) 53945260Sbostic int argc; 54037224Skarels char *argv[]; 54137224Skarels { 54237224Skarels (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" ); 54337224Skarels } 54437224Skarels 54511353Ssam /* 54611353Ssam * Receive one file. 54711353Ssam */ 54837224Skarels getit(argc, argv, restartit, mode) 54945260Sbostic int argc; 55010294Ssam char *argv[]; 55137224Skarels char *mode; 55210294Ssam { 55326049Sminshall int loc = 0; 55437225Skarels char *oldargv1, *oldargv2; 55510294Ssam 55626049Sminshall if (argc == 2) { 55726049Sminshall argc++; 55826049Sminshall argv[2] = argv[1]; 55926049Sminshall loc++; 56026049Sminshall } 56145260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-file")) 56245260Sbostic goto usage; 56345260Sbostic if (argc < 3 && !another(&argc, &argv, "local-file")) { 56410294Ssam usage: 56526049Sminshall printf("usage: %s remote-file [ local-file ]\n", argv[0]); 56626049Sminshall code = -1; 56737224Skarels return (0); 56810294Ssam } 56937225Skarels oldargv1 = argv[1]; 57037225Skarels oldargv2 = argv[2]; 57126049Sminshall if (!globulize(&argv[2])) { 57226049Sminshall code = -1; 57337224Skarels return (0); 57426049Sminshall } 57526049Sminshall if (loc && mcase) { 57626049Sminshall char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; 57726049Sminshall 57826049Sminshall while (*tp && !islower(*tp)) { 57926049Sminshall tp++; 58026049Sminshall } 58126049Sminshall if (!*tp) { 58226049Sminshall tp = argv[2]; 58326049Sminshall tp2 = tmpbuf; 58426049Sminshall while ((*tp2 = *tp) != NULL) { 58526049Sminshall if (isupper(*tp2)) { 58626049Sminshall *tp2 = 'a' + *tp2 - 'A'; 58726049Sminshall } 58826049Sminshall tp++; 58926049Sminshall tp2++; 59026049Sminshall } 59126049Sminshall argv[2] = tmpbuf; 59226049Sminshall } 59326049Sminshall } 59436940Skarels if (loc && ntflag) 59526049Sminshall argv[2] = dotrans(argv[2]); 59636940Skarels if (loc && mapflag) 59726049Sminshall argv[2] = domap(argv[2]); 59837224Skarels if (restartit) { 59937224Skarels struct stat stbuf; 60037224Skarels int ret; 60137224Skarels 60237224Skarels ret = stat(argv[2], &stbuf); 60337224Skarels if (restartit == 1) { 60437224Skarels if (ret < 0) { 60538202Srick fprintf(stderr, "local: %s: %s\n", argv[2], 60638202Srick strerror(errno)); 60737224Skarels return (0); 60837224Skarels } 60937224Skarels restart_point = stbuf.st_size; 61037224Skarels } else { 61137224Skarels if (ret == 0) { 61237224Skarels int overbose; 61337224Skarels 61437224Skarels overbose = verbose; 61537224Skarels if (debug == 0) 61637224Skarels verbose = -1; 61737224Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 61837224Skarels int yy, mo, day, hour, min, sec; 61937224Skarels struct tm *tm; 62037224Skarels verbose = overbose; 62137224Skarels sscanf(reply_string, 62237224Skarels "%*s %04d%02d%02d%02d%02d%02d", 62337224Skarels &yy, &mo, &day, &hour, &min, &sec); 62437224Skarels tm = gmtime(&stbuf.st_mtime); 62537224Skarels tm->tm_mon++; 62637224Skarels if (tm->tm_year > yy%100) 62737224Skarels return (1); 62837224Skarels else if (tm->tm_year == yy%100) { 62937224Skarels if (tm->tm_mon > mo) 63037224Skarels return (1); 63137224Skarels } else if (tm->tm_mon == mo) { 63237224Skarels if (tm->tm_mday > day) 63337224Skarels return (1); 63437224Skarels } else if (tm->tm_mday == day) { 63537224Skarels if (tm->tm_hour > hour) 63637224Skarels return (1); 63737224Skarels } else if (tm->tm_hour == hour) { 63837224Skarels if (tm->tm_min > min) 63937224Skarels return (1); 64037224Skarels } else if (tm->tm_min == min) { 64137224Skarels if (tm->tm_sec > sec) 64237224Skarels return (1); 64337224Skarels } 64437224Skarels } else { 64538132Srick printf("%s\n", reply_string); 64637224Skarels verbose = overbose; 64737224Skarels return (0); 64837224Skarels } 64937224Skarels } 65037224Skarels } 65137224Skarels } 65237224Skarels 65337225Skarels recvrequest("RETR", argv[2], argv[1], mode, 65437225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 65537224Skarels restart_point = 0; 65637224Skarels return (0); 65710294Ssam } 65810294Ssam 65939252Sbostic void 66026049Sminshall mabort() 66126049Sminshall { 66226049Sminshall int ointer; 66326049Sminshall extern jmp_buf jabort; 66426049Sminshall 66526049Sminshall printf("\n"); 66626049Sminshall (void) fflush(stdout); 66726049Sminshall if (mflag && fromatty) { 66826049Sminshall ointer = interactive; 66926049Sminshall interactive = 1; 67026049Sminshall if (confirm("Continue with", mname)) { 67126049Sminshall interactive = ointer; 67226049Sminshall longjmp(jabort,0); 67326049Sminshall } 67426049Sminshall interactive = ointer; 67526049Sminshall } 67626049Sminshall mflag = 0; 67726049Sminshall longjmp(jabort,0); 67826049Sminshall } 67926049Sminshall 68011353Ssam /* 68111353Ssam * Get multiple files. 68211353Ssam */ 68311353Ssam mget(argc, argv) 68439252Sbostic int argc; 68539252Sbostic char **argv; 68611353Ssam { 68739252Sbostic extern jmp_buf jabort; 68839252Sbostic sig_t oldintr; 68939252Sbostic int ointer; 69026049Sminshall char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; 69139252Sbostic void mabort(); 69211353Ssam 69345260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) { 69445260Sbostic printf("usage: %s remote-files\n", argv[0]); 69526049Sminshall code = -1; 69611353Ssam return; 69711353Ssam } 69826049Sminshall mname = argv[0]; 69926049Sminshall mflag = 1; 70026049Sminshall oldintr = signal(SIGINT,mabort); 70126049Sminshall (void) setjmp(jabort); 70226497Sminshall while ((cp = remglob(argv,proxy)) != NULL) { 70326049Sminshall if (*cp == '\0') { 70426049Sminshall mflag = 0; 70526049Sminshall continue; 70626049Sminshall } 70726049Sminshall if (mflag && confirm(argv[0], cp)) { 70826049Sminshall tp = cp; 70926049Sminshall if (mcase) { 71026049Sminshall while (*tp && !islower(*tp)) { 71126049Sminshall tp++; 71226049Sminshall } 71326049Sminshall if (!*tp) { 71426049Sminshall tp = cp; 71526049Sminshall tp2 = tmpbuf; 71626049Sminshall while ((*tp2 = *tp) != NULL) { 71726049Sminshall if (isupper(*tp2)) { 71826049Sminshall *tp2 = 'a' + *tp2 - 'A'; 71926049Sminshall } 72026049Sminshall tp++; 72126049Sminshall tp2++; 72226049Sminshall } 72326049Sminshall } 72426049Sminshall tp = tmpbuf; 72526049Sminshall } 72626049Sminshall if (ntflag) { 72726049Sminshall tp = dotrans(tp); 72826049Sminshall } 72926049Sminshall if (mapflag) { 73026049Sminshall tp = domap(tp); 73126049Sminshall } 73237225Skarels recvrequest("RETR", tp, cp, "w", 73337225Skarels tp != cp || !interactive); 73426049Sminshall if (!mflag && fromatty) { 73526049Sminshall ointer = interactive; 73626049Sminshall interactive = 1; 73726049Sminshall if (confirm("Continue with","mget")) { 73826049Sminshall mflag++; 73926049Sminshall } 74026049Sminshall interactive = ointer; 74126049Sminshall } 74226049Sminshall } 74326049Sminshall } 74426049Sminshall (void) signal(SIGINT,oldintr); 74526049Sminshall mflag = 0; 74611650Ssam } 74711650Ssam 74811650Ssam char * 74926497Sminshall remglob(argv,doswitch) 75011650Ssam char *argv[]; 75126497Sminshall int doswitch; 75211650Ssam { 75311756Ssam char temp[16]; 75411650Ssam static char buf[MAXPATHLEN]; 75511650Ssam static FILE *ftemp = NULL; 75611650Ssam static char **args; 75713212Ssam int oldverbose, oldhash; 75811756Ssam char *cp, *mode; 75911650Ssam 76026049Sminshall if (!mflag) { 76126049Sminshall if (!doglob) { 76226049Sminshall args = NULL; 76326049Sminshall } 76426049Sminshall else { 76526049Sminshall if (ftemp) { 76626497Sminshall (void) fclose(ftemp); 76726049Sminshall ftemp = NULL; 76826049Sminshall } 76926049Sminshall } 77026049Sminshall return(NULL); 77126049Sminshall } 77211650Ssam if (!doglob) { 77311756Ssam if (args == NULL) 77411650Ssam args = argv; 77511650Ssam if ((cp = *++args) == NULL) 77611650Ssam args = NULL; 77711650Ssam return (cp); 77811353Ssam } 77911650Ssam if (ftemp == NULL) { 78037458Skarels (void) strcpy(temp, _PATH_TMP); 78126497Sminshall (void) mktemp(temp); 78211650Ssam oldverbose = verbose, verbose = 0; 78313212Ssam oldhash = hash, hash = 0; 78426049Sminshall if (doswitch) { 78526049Sminshall pswitch(!proxy); 78626049Sminshall } 78711756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 78837225Skarels recvrequest ("NLST", temp, *argv, mode, 0); 78926049Sminshall if (doswitch) { 79026049Sminshall pswitch(!proxy); 79126049Sminshall } 79213212Ssam verbose = oldverbose; hash = oldhash; 79311650Ssam ftemp = fopen(temp, "r"); 79426497Sminshall (void) unlink(temp); 79511650Ssam if (ftemp == NULL) { 79611650Ssam printf("can't find list of remote files, oops\n"); 79711756Ssam return (NULL); 79811353Ssam } 79911353Ssam } 80011650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 80126497Sminshall (void) fclose(ftemp), ftemp = NULL; 80211650Ssam return (NULL); 80311353Ssam } 80411650Ssam if ((cp = index(buf, '\n')) != NULL) 80511650Ssam *cp = '\0'; 80611650Ssam return (buf); 80711353Ssam } 80811353Ssam 80910294Ssam char * 81010294Ssam onoff(bool) 81110294Ssam int bool; 81210294Ssam { 81310294Ssam 81410294Ssam return (bool ? "on" : "off"); 81510294Ssam } 81610294Ssam 81710294Ssam /* 81810294Ssam * Show status. 81910294Ssam */ 82026497Sminshall /*ARGSUSED*/ 82110294Ssam status(argc, argv) 82245260Sbostic int argc; 82310294Ssam char *argv[]; 82410294Ssam { 82526049Sminshall int i; 82610294Ssam 82710294Ssam if (connected) 82810294Ssam printf("Connected to %s.\n", hostname); 82910294Ssam else 83010294Ssam printf("Not connected.\n"); 83126049Sminshall if (!proxy) { 83226049Sminshall pswitch(1); 83326049Sminshall if (connected) { 83426049Sminshall printf("Connected for proxy commands to %s.\n", hostname); 83526049Sminshall } 83626049Sminshall else { 83726049Sminshall printf("No proxy connection.\n"); 83826049Sminshall } 83926049Sminshall pswitch(0); 84026049Sminshall } 84110294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 84210294Ssam modename, typename, formname, structname); 84311353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 84411353Ssam onoff(verbose), onoff(bell), onoff(interactive), 84511353Ssam onoff(doglob)); 84626049Sminshall printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), 84726049Sminshall onoff(runique)); 84826049Sminshall printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); 84926049Sminshall if (ntflag) { 85026049Sminshall printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); 85126049Sminshall } 85226049Sminshall else { 85326049Sminshall printf("Ntrans: off\n"); 85426049Sminshall } 85526049Sminshall if (mapflag) { 85626049Sminshall printf("Nmap: (in) %s (out) %s\n", mapin, mapout); 85726049Sminshall } 85826049Sminshall else { 85926049Sminshall printf("Nmap: off\n"); 86026049Sminshall } 86114143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 86214143Ssam onoff(hash), onoff(sendport)); 86326049Sminshall if (macnum > 0) { 86426049Sminshall printf("Macros:\n"); 86526049Sminshall for (i=0; i<macnum; i++) { 86626049Sminshall printf("\t%s\n",macros[i].mac_name); 86726049Sminshall } 86826049Sminshall } 86926049Sminshall code = 0; 87010294Ssam } 87110294Ssam 87210294Ssam /* 87310294Ssam * Set beep on cmd completed mode. 87410294Ssam */ 87510294Ssam /*VARARGS*/ 87610294Ssam setbell() 87710294Ssam { 87810294Ssam 87910294Ssam bell = !bell; 88010294Ssam printf("Bell mode %s.\n", onoff(bell)); 88126049Sminshall code = bell; 88210294Ssam } 88310294Ssam 88410294Ssam /* 88510294Ssam * Turn on packet tracing. 88610294Ssam */ 88710294Ssam /*VARARGS*/ 88810294Ssam settrace() 88910294Ssam { 89010294Ssam 89110294Ssam trace = !trace; 89210294Ssam printf("Packet tracing %s.\n", onoff(trace)); 89326049Sminshall code = trace; 89410294Ssam } 89510294Ssam 89610294Ssam /* 89711650Ssam * Toggle hash mark printing during transfers. 89811650Ssam */ 89911650Ssam /*VARARGS*/ 90011650Ssam sethash() 90111650Ssam { 90211650Ssam 90311650Ssam hash = !hash; 90411650Ssam printf("Hash mark printing %s", onoff(hash)); 90526049Sminshall code = hash; 90611650Ssam if (hash) 90737224Skarels printf(" (%d bytes/hash mark)", 1024); 90811650Ssam printf(".\n"); 90911650Ssam } 91011650Ssam 91111650Ssam /* 91210294Ssam * Turn on printing of server echo's. 91310294Ssam */ 91410294Ssam /*VARARGS*/ 91510294Ssam setverbose() 91610294Ssam { 91710294Ssam 91810294Ssam verbose = !verbose; 91910294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 92026049Sminshall code = verbose; 92110294Ssam } 92210294Ssam 92310294Ssam /* 92411650Ssam * Toggle PORT cmd use before each data connection. 92511650Ssam */ 92611650Ssam /*VARARGS*/ 92711650Ssam setport() 92811650Ssam { 92911650Ssam 93011650Ssam sendport = !sendport; 93111650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 93226049Sminshall code = sendport; 93311650Ssam } 93411650Ssam 93511650Ssam /* 93610294Ssam * Turn on interactive prompting 93710294Ssam * during mget, mput, and mdelete. 93810294Ssam */ 93910294Ssam /*VARARGS*/ 94010294Ssam setprompt() 94110294Ssam { 94210294Ssam 94310294Ssam interactive = !interactive; 94410294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 94526049Sminshall code = interactive; 94610294Ssam } 94710294Ssam 94810294Ssam /* 94911353Ssam * Toggle metacharacter interpretation 95011353Ssam * on local file names. 95111353Ssam */ 95211353Ssam /*VARARGS*/ 95311353Ssam setglob() 95411353Ssam { 95511353Ssam 95611353Ssam doglob = !doglob; 95711353Ssam printf("Globbing %s.\n", onoff(doglob)); 95826049Sminshall code = doglob; 95911353Ssam } 96011353Ssam 96111353Ssam /* 96210294Ssam * Set debugging mode on/off and/or 96310294Ssam * set level of debugging. 96410294Ssam */ 96511756Ssam /*VARARGS*/ 96610294Ssam setdebug(argc, argv) 96745260Sbostic int argc; 96810294Ssam char *argv[]; 96910294Ssam { 97010294Ssam int val; 97110294Ssam 97210294Ssam if (argc > 1) { 97310294Ssam val = atoi(argv[1]); 97410294Ssam if (val < 0) { 97510294Ssam printf("%s: bad debugging value.\n", argv[1]); 97626049Sminshall code = -1; 97710294Ssam return; 97810294Ssam } 97910294Ssam } else 98010294Ssam val = !debug; 98110294Ssam debug = val; 98210294Ssam if (debug) 98310294Ssam options |= SO_DEBUG; 98410294Ssam else 98510294Ssam options &= ~SO_DEBUG; 98610294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 98726049Sminshall code = debug > 0; 98810294Ssam } 98910294Ssam 99010294Ssam /* 99110294Ssam * Set current working directory 99210294Ssam * on remote machine. 99310294Ssam */ 99410294Ssam cd(argc, argv) 99545260Sbostic int argc; 99610294Ssam char *argv[]; 99710294Ssam { 99810294Ssam 99945260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-directory")) { 100045260Sbostic printf("usage: %s remote-directory\n", argv[0]); 100126049Sminshall code = -1; 100210294Ssam return; 100310294Ssam } 100437224Skarels if (command("CWD %s", argv[1]) == ERROR && code == 500) { 100537224Skarels if (verbose) 100637224Skarels printf("CWD command not recognized, trying XCWD\n"); 100737224Skarels (void) command("XCWD %s", argv[1]); 100837224Skarels } 100910294Ssam } 101010294Ssam 101110294Ssam /* 101210294Ssam * Set current working directory 101310294Ssam * on local machine. 101410294Ssam */ 101510294Ssam lcd(argc, argv) 101645260Sbostic int argc; 101710294Ssam char *argv[]; 101810294Ssam { 101911353Ssam char buf[MAXPATHLEN]; 102038132Srick extern char *getwd(); 102110294Ssam 102211353Ssam if (argc < 2) 102311353Ssam argc++, argv[1] = home; 102410294Ssam if (argc != 2) { 102545260Sbostic printf("usage: %s local-directory\n", argv[0]); 102626049Sminshall code = -1; 102710294Ssam return; 102810294Ssam } 102926049Sminshall if (!globulize(&argv[1])) { 103026049Sminshall code = -1; 103111353Ssam return; 103226049Sminshall } 103311353Ssam if (chdir(argv[1]) < 0) { 103438202Srick fprintf(stderr, "local: %s: %s\n", argv[1], strerror(errno)); 103526049Sminshall code = -1; 103611353Ssam return; 103711353Ssam } 103811353Ssam printf("Local directory now %s\n", getwd(buf)); 103926049Sminshall code = 0; 104010294Ssam } 104110294Ssam 104210294Ssam /* 104310294Ssam * Delete a single file. 104410294Ssam */ 104510294Ssam delete(argc, argv) 104645260Sbostic int argc; 104710294Ssam char *argv[]; 104810294Ssam { 104910294Ssam 105045260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-file")) { 105145260Sbostic printf("usage: %s remote-file\n", argv[0]); 105226049Sminshall code = -1; 105310294Ssam return; 105410294Ssam } 105510294Ssam (void) command("DELE %s", argv[1]); 105610294Ssam } 105710294Ssam 105810294Ssam /* 105911650Ssam * Delete multiple files. 106011650Ssam */ 106111650Ssam mdelete(argc, argv) 106239252Sbostic int argc; 106339252Sbostic char **argv; 106411650Ssam { 106539252Sbostic extern jmp_buf jabort; 106639252Sbostic sig_t oldintr; 106739252Sbostic int ointer; 106811650Ssam char *cp; 106939252Sbostic void mabort(); 107011650Ssam 107145260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) { 107245260Sbostic printf("usage: %s remote-files\n", argv[0]); 107326049Sminshall code = -1; 107411650Ssam return; 107511650Ssam } 107626049Sminshall mname = argv[0]; 107726049Sminshall mflag = 1; 107826049Sminshall oldintr = signal(SIGINT, mabort); 107926049Sminshall (void) setjmp(jabort); 108026497Sminshall while ((cp = remglob(argv,0)) != NULL) { 108126049Sminshall if (*cp == '\0') { 108226049Sminshall mflag = 0; 108326049Sminshall continue; 108426049Sminshall } 108526049Sminshall if (mflag && confirm(argv[0], cp)) { 108611650Ssam (void) command("DELE %s", cp); 108726049Sminshall if (!mflag && fromatty) { 108826049Sminshall ointer = interactive; 108926049Sminshall interactive = 1; 109026049Sminshall if (confirm("Continue with", "mdelete")) { 109126049Sminshall mflag++; 109226049Sminshall } 109326049Sminshall interactive = ointer; 109426049Sminshall } 109526049Sminshall } 109626049Sminshall } 109726049Sminshall (void) signal(SIGINT, oldintr); 109826049Sminshall mflag = 0; 109911650Ssam } 110011756Ssam 110111650Ssam /* 110210294Ssam * Rename a remote file. 110310294Ssam */ 110410294Ssam renamefile(argc, argv) 110545260Sbostic int argc; 110610294Ssam char *argv[]; 110710294Ssam { 110810294Ssam 110945260Sbostic if (argc < 2 && !another(&argc, &argv, "from-name")) 111045260Sbostic goto usage; 111145260Sbostic if (argc < 3 && !another(&argc, &argv, "to-name")) { 111210294Ssam usage: 111310294Ssam printf("%s from-name to-name\n", argv[0]); 111426049Sminshall code = -1; 111510294Ssam return; 111610294Ssam } 111710294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 111810294Ssam (void) command("RNTO %s", argv[2]); 111910294Ssam } 112010294Ssam 112110294Ssam /* 112210294Ssam * Get a directory listing 112310294Ssam * of remote files. 112410294Ssam */ 112510294Ssam ls(argc, argv) 112645260Sbostic int argc; 112710294Ssam char *argv[]; 112810294Ssam { 112911756Ssam char *cmd; 113010294Ssam 113110294Ssam if (argc < 2) 113210294Ssam argc++, argv[1] = NULL; 113310294Ssam if (argc < 3) 113410294Ssam argc++, argv[2] = "-"; 113511756Ssam if (argc > 3) { 113611756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 113726049Sminshall code = -1; 113811756Ssam return; 113911756Ssam } 114036935Skarels cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 114126049Sminshall if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 114226049Sminshall code = -1; 114311353Ssam return; 114426049Sminshall } 114532344Scsvsj if (strcmp(argv[2], "-") && *argv[2] != '|') 114632344Scsvsj if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { 114732344Scsvsj code = -1; 114832344Scsvsj return; 114932344Scsvsj } 115037225Skarels recvrequest(cmd, argv[2], argv[1], "w", 0); 115110294Ssam } 115210294Ssam 115310294Ssam /* 115411756Ssam * Get a directory listing 115511756Ssam * of multiple remote files. 115611756Ssam */ 115711756Ssam mls(argc, argv) 115839252Sbostic int argc; 115939252Sbostic char **argv; 116011756Ssam { 116139252Sbostic extern jmp_buf jabort; 116239252Sbostic sig_t oldintr; 116339252Sbostic int ointer, i; 116426049Sminshall char *cmd, mode[1], *dest; 116539252Sbostic void mabort(); 116611756Ssam 116745260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) 116845260Sbostic goto usage; 116945260Sbostic if (argc < 3 && !another(&argc, &argv, "local-file")) { 117045260Sbostic usage: 117145260Sbostic printf("usage: %s remote-files local-file\n", argv[0]); 117226049Sminshall code = -1; 117313212Ssam return; 117413212Ssam } 117513212Ssam dest = argv[argc - 1]; 117613212Ssam argv[argc - 1] = NULL; 117726049Sminshall if (strcmp(dest, "-") && *dest != '|') 117845260Sbostic if (!globulize(&dest) || 117945260Sbostic !confirm("output to local-file:", dest)) { 118026049Sminshall code = -1; 118113212Ssam return; 118226049Sminshall } 118336940Skarels cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 118426049Sminshall mname = argv[0]; 118526049Sminshall mflag = 1; 118626049Sminshall oldintr = signal(SIGINT, mabort); 118726049Sminshall (void) setjmp(jabort); 118826049Sminshall for (i = 1; mflag && i < argc-1; ++i) { 118926049Sminshall *mode = (i == 1) ? 'w' : 'a'; 119037225Skarels recvrequest(cmd, dest, argv[i], mode, 0); 119126049Sminshall if (!mflag && fromatty) { 119226049Sminshall ointer = interactive; 119326049Sminshall interactive = 1; 119426049Sminshall if (confirm("Continue with", argv[0])) { 119526049Sminshall mflag ++; 119626049Sminshall } 119726049Sminshall interactive = ointer; 119826049Sminshall } 119926049Sminshall } 120026049Sminshall (void) signal(SIGINT, oldintr); 120126049Sminshall mflag = 0; 120211756Ssam } 120311756Ssam 120411756Ssam /* 120510294Ssam * Do a shell escape 120610294Ssam */ 120726497Sminshall /*ARGSUSED*/ 120810294Ssam shell(argc, argv) 120939252Sbostic int argc; 121039252Sbostic char **argv; 121110294Ssam { 121238132Srick int pid; 121339252Sbostic sig_t old1, old2; 121426049Sminshall char shellnam[40], *shell, *namep; 121526497Sminshall union wait status; 121610294Ssam 121711756Ssam old1 = signal (SIGINT, SIG_IGN); 121811756Ssam old2 = signal (SIGQUIT, SIG_IGN); 121911756Ssam if ((pid = fork()) == 0) { 122011756Ssam for (pid = 3; pid < 20; pid++) 122126497Sminshall (void) close(pid); 122226497Sminshall (void) signal(SIGINT, SIG_DFL); 122326497Sminshall (void) signal(SIGQUIT, SIG_DFL); 122425908Smckusick shell = getenv("SHELL"); 122525908Smckusick if (shell == NULL) 122637458Skarels shell = _PATH_BSHELL; 122725908Smckusick namep = rindex(shell,'/'); 122825908Smckusick if (namep == NULL) 122925908Smckusick namep = shell; 123026497Sminshall (void) strcpy(shellnam,"-"); 123126497Sminshall (void) strcat(shellnam, ++namep); 123226049Sminshall if (strcmp(namep, "sh") != 0) 123326049Sminshall shellnam[0] = '+'; 123426049Sminshall if (debug) { 123526049Sminshall printf ("%s\n", shell); 123626497Sminshall (void) fflush (stdout); 123711756Ssam } 123826049Sminshall if (argc > 1) { 123926049Sminshall execl(shell,shellnam,"-c",altarg,(char *)0); 124026049Sminshall } 124126049Sminshall else { 124226049Sminshall execl(shell,shellnam,(char *)0); 124326049Sminshall } 124425908Smckusick perror(shell); 124526049Sminshall code = -1; 124611756Ssam exit(1); 124726049Sminshall } 124811756Ssam if (pid > 0) 1249*46828Sbostic while (wait((int *)&status) != pid) 125011756Ssam ; 125126497Sminshall (void) signal(SIGINT, old1); 125226497Sminshall (void) signal(SIGQUIT, old2); 125326049Sminshall if (pid == -1) { 125411756Ssam perror("Try again later"); 125526049Sminshall code = -1; 125626049Sminshall } 125726049Sminshall else { 125826049Sminshall code = 0; 125926049Sminshall } 126011756Ssam return (0); 126110294Ssam } 126210294Ssam 126310294Ssam /* 126410294Ssam * Send new user information (re-login) 126510294Ssam */ 126610294Ssam user(argc, argv) 126710294Ssam int argc; 126810294Ssam char **argv; 126910294Ssam { 127035658Sbostic char acct[80], *getpass(); 127126049Sminshall int n, aflag = 0; 127210294Ssam 127345260Sbostic if (argc < 2) 127445260Sbostic (void) another(&argc, &argv, "username"); 127545260Sbostic if (argc < 2 || argc > 4) { 127610294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 127726049Sminshall code = -1; 127811756Ssam return (0); 127910294Ssam } 128010294Ssam n = command("USER %s", argv[1]); 128110294Ssam if (n == CONTINUE) { 128210294Ssam if (argc < 3 ) 128335658Sbostic argv[2] = getpass("Password: "), argc++; 128410294Ssam n = command("PASS %s", argv[2]); 128510294Ssam } 128610294Ssam if (n == CONTINUE) { 128710294Ssam if (argc < 4) { 128810294Ssam printf("Account: "); (void) fflush(stdout); 128910294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 129010294Ssam acct[strlen(acct) - 1] = '\0'; 129110294Ssam argv[3] = acct; argc++; 129210294Ssam } 129326049Sminshall n = command("ACCT %s", argv[3]); 129426049Sminshall aflag++; 129510294Ssam } 129610294Ssam if (n != COMPLETE) { 129726497Sminshall fprintf(stdout, "Login failed.\n"); 129810294Ssam return (0); 129910294Ssam } 130026049Sminshall if (!aflag && argc == 4) { 130126049Sminshall (void) command("ACCT %s", argv[3]); 130226049Sminshall } 130310294Ssam return (1); 130410294Ssam } 130510294Ssam 130610294Ssam /* 130710294Ssam * Print working directory. 130810294Ssam */ 130910294Ssam /*VARARGS*/ 131010294Ssam pwd() 131110294Ssam { 131237224Skarels int oldverbose = verbose; 131311756Ssam 131437224Skarels /* 131537224Skarels * If we aren't verbose, this doesn't do anything! 131637224Skarels */ 131737224Skarels verbose = 1; 131837224Skarels if (command("PWD") == ERROR && code == 500) { 131937224Skarels printf("PWD command not recognized, trying XPWD\n"); 132037224Skarels (void) command("XPWD"); 132137224Skarels } 132237224Skarels verbose = oldverbose; 132310294Ssam } 132410294Ssam 132510294Ssam /* 132610294Ssam * Make a directory. 132710294Ssam */ 132810294Ssam makedir(argc, argv) 132945260Sbostic int argc; 133010294Ssam char *argv[]; 133110294Ssam { 133210294Ssam 133345260Sbostic if (argc < 2 && !another(&argc, &argv, "directory-name")) { 133426049Sminshall printf("usage: %s directory-name\n", argv[0]); 133526049Sminshall code = -1; 133610294Ssam return; 133710294Ssam } 133837224Skarels if (command("MKD %s", argv[1]) == ERROR && code == 500) { 133937224Skarels if (verbose) 134037224Skarels printf("MKD command not recognized, trying XMKD\n"); 134137224Skarels (void) command("XMKD %s", argv[1]); 134237224Skarels } 134310294Ssam } 134410294Ssam 134510294Ssam /* 134610294Ssam * Remove a directory. 134710294Ssam */ 134810294Ssam removedir(argc, argv) 134945260Sbostic int argc; 135010294Ssam char *argv[]; 135110294Ssam { 135210294Ssam 135345260Sbostic if (argc < 2 && !another(&argc, &argv, "directory-name")) { 135426049Sminshall printf("usage: %s directory-name\n", argv[0]); 135526049Sminshall code = -1; 135610294Ssam return; 135710294Ssam } 135837224Skarels if (command("RMD %s", argv[1]) == ERROR && code == 500) { 135937224Skarels if (verbose) 136037224Skarels printf("RMD command not recognized, trying XRMD\n"); 136137224Skarels (void) command("XRMD %s", argv[1]); 136237224Skarels } 136310294Ssam } 136410294Ssam 136510294Ssam /* 136610294Ssam * Send a line, verbatim, to the remote machine. 136710294Ssam */ 136810294Ssam quote(argc, argv) 136945260Sbostic int argc; 137010294Ssam char *argv[]; 137110294Ssam { 137210294Ssam 137345260Sbostic if (argc < 2 && !another(&argc, &argv, "command line to send")) { 137410294Ssam printf("usage: %s line-to-send\n", argv[0]); 137526049Sminshall code = -1; 137610294Ssam return; 137710294Ssam } 137845260Sbostic quote1("", argc, argv); 137910294Ssam } 138010294Ssam 138110294Ssam /* 138237224Skarels * Send a SITE command to the remote machine. The line 138345260Sbostic * is sent verbatim to the remote machine, except that the 138445260Sbostic * word "SITE" is added at the front. 138537224Skarels */ 138637224Skarels site(argc, argv) 138745260Sbostic int argc; 138837224Skarels char *argv[]; 138937224Skarels { 139037224Skarels 139145260Sbostic if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) { 139237224Skarels printf("usage: %s line-to-send\n", argv[0]); 139337224Skarels code = -1; 139437224Skarels return; 139537224Skarels } 139645260Sbostic quote1("SITE ", argc, argv); 139745260Sbostic } 139845260Sbostic 139945260Sbostic /* 140045260Sbostic * Turn argv[1..argc) into a space-separated string, then prepend initial text. 140145260Sbostic * Send the result as a one-line command and get response. 140245260Sbostic */ 140345260Sbostic quote1(initial, argc, argv) 140445260Sbostic char *initial; 140545260Sbostic int argc; 140645260Sbostic char **argv; 140745260Sbostic { 140845260Sbostic register int i, len; 140945260Sbostic char buf[BUFSIZ]; /* must be >= sizeof(line) */ 141045260Sbostic 141145260Sbostic (void) strcpy(buf, initial); 141245260Sbostic if (argc > 1) { 141345260Sbostic len = strlen(buf); 141445260Sbostic len += strlen(strcpy(&buf[len], argv[1])); 141545260Sbostic for (i = 2; i < argc; i++) { 141645260Sbostic buf[len++] = ' '; 141745260Sbostic len += strlen(strcpy(&buf[len], argv[i])); 141845260Sbostic } 141937224Skarels } 142037224Skarels if (command(buf) == PRELIM) { 142137224Skarels while (getreply(0) == PRELIM); 142237224Skarels } 142337224Skarels } 142437224Skarels 142537224Skarels do_chmod(argc, argv) 142645260Sbostic int argc; 142737224Skarels char *argv[]; 142837224Skarels { 142945260Sbostic 143045260Sbostic if (argc < 2 && !another(&argc, &argv, "mode")) 143145260Sbostic goto usage; 143245260Sbostic if (argc < 3 && !another(&argc, &argv, "file-name")) { 143345260Sbostic usage: 143437224Skarels printf("usage: %s mode file-name\n", argv[0]); 143537224Skarels code = -1; 143637224Skarels return; 143737224Skarels } 143845260Sbostic (void) command("SITE CHMOD %s %s", argv[1], argv[2]); 143937224Skarels } 144037224Skarels 144137224Skarels do_umask(argc, argv) 144245260Sbostic int argc; 144337224Skarels char *argv[]; 144437224Skarels { 144537224Skarels int oldverbose = verbose; 144637224Skarels 144737224Skarels verbose = 1; 144837224Skarels (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 144937224Skarels verbose = oldverbose; 145037224Skarels } 145137224Skarels 145237224Skarels idle(argc, argv) 145345260Sbostic int argc; 145437224Skarels char *argv[]; 145537224Skarels { 145637224Skarels int oldverbose = verbose; 145737224Skarels 145837224Skarels verbose = 1; 145937224Skarels (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 146037224Skarels verbose = oldverbose; 146137224Skarels } 146237224Skarels 146337224Skarels /* 146410294Ssam * Ask the other side for help. 146510294Ssam */ 146610294Ssam rmthelp(argc, argv) 146745260Sbostic int argc; 146810294Ssam char *argv[]; 146910294Ssam { 147010294Ssam int oldverbose = verbose; 147110294Ssam 147210294Ssam verbose = 1; 147310294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 147410294Ssam verbose = oldverbose; 147510294Ssam } 147610294Ssam 147710294Ssam /* 147810294Ssam * Terminate session and exit. 147910294Ssam */ 148010294Ssam /*VARARGS*/ 148110294Ssam quit() 148210294Ssam { 148310294Ssam 148418286Sralph if (connected) 148518286Sralph disconnect(); 148626049Sminshall pswitch(1); 148726049Sminshall if (connected) { 148826049Sminshall disconnect(); 148926049Sminshall } 149010294Ssam exit(0); 149110294Ssam } 149210294Ssam 149310294Ssam /* 149410294Ssam * Terminate session, but don't exit. 149510294Ssam */ 149610294Ssam disconnect() 149710294Ssam { 149810294Ssam extern FILE *cout; 149910294Ssam extern int data; 150010294Ssam 150110294Ssam if (!connected) 150210294Ssam return; 150310294Ssam (void) command("QUIT"); 150426049Sminshall if (cout) { 150526049Sminshall (void) fclose(cout); 150626049Sminshall } 150710294Ssam cout = NULL; 150810294Ssam connected = 0; 150910294Ssam data = -1; 151026049Sminshall if (!proxy) { 151126049Sminshall macnum = 0; 151226049Sminshall } 151310294Ssam } 151411353Ssam 151511650Ssam confirm(cmd, file) 151611353Ssam char *cmd, *file; 151711353Ssam { 151811353Ssam char line[BUFSIZ]; 151911353Ssam 152011353Ssam if (!interactive) 152111650Ssam return (1); 152211353Ssam printf("%s %s? ", cmd, file); 152326497Sminshall (void) fflush(stdout); 152445260Sbostic if (fgets(line, sizeof line, stdin) == NULL) 152545260Sbostic return (0); 152611650Ssam return (*line != 'n' && *line != 'N'); 152711353Ssam } 152811353Ssam 152911353Ssam fatal(msg) 153011353Ssam char *msg; 153111353Ssam { 153211353Ssam 153326497Sminshall fprintf(stderr, "ftp: %s\n", msg); 153411353Ssam exit(1); 153511353Ssam } 153611353Ssam 153711353Ssam /* 153811353Ssam * Glob a local file name specification with 153911353Ssam * the expectation of a single return value. 154011353Ssam * Can't control multiple values being expanded 154111353Ssam * from the expression, we return only the first. 154211353Ssam */ 154311353Ssam globulize(cpp) 154411353Ssam char **cpp; 154511353Ssam { 154611353Ssam char **globbed; 154711353Ssam 154811353Ssam if (!doglob) 154911353Ssam return (1); 155011353Ssam globbed = glob(*cpp); 155111353Ssam if (globerr != NULL) { 155211353Ssam printf("%s: %s\n", *cpp, globerr); 155336421Sbostic if (globbed) { 155411353Ssam blkfree(globbed); 155538132Srick free((char *)globbed); 155636421Sbostic } 155711353Ssam return (0); 155811353Ssam } 155911353Ssam if (globbed) { 156011353Ssam *cpp = *globbed++; 156111353Ssam /* don't waste too much memory */ 156236421Sbostic if (*globbed) { 156311353Ssam blkfree(globbed); 156438132Srick free((char *)globbed); 156536421Sbostic } 156611353Ssam } 156711353Ssam return (1); 156811353Ssam } 156926049Sminshall 157026049Sminshall account(argc,argv) 157126049Sminshall int argc; 157226049Sminshall char **argv; 157326049Sminshall { 157435658Sbostic char acct[50], *getpass(), *ap; 157526049Sminshall 157626049Sminshall if (argc > 1) { 157726049Sminshall ++argv; 157826049Sminshall --argc; 157926049Sminshall (void) strncpy(acct,*argv,49); 158036268Sbostic acct[49] = '\0'; 158126049Sminshall while (argc > 1) { 158226049Sminshall --argc; 158326049Sminshall ++argv; 158426049Sminshall (void) strncat(acct,*argv, 49-strlen(acct)); 158526049Sminshall } 158626049Sminshall ap = acct; 158726049Sminshall } 158826049Sminshall else { 158935658Sbostic ap = getpass("Account:"); 159026049Sminshall } 159126049Sminshall (void) command("ACCT %s", ap); 159226049Sminshall } 159326049Sminshall 159426049Sminshall jmp_buf abortprox; 159526049Sminshall 159639252Sbostic void 159726049Sminshall proxabort() 159826049Sminshall { 159926049Sminshall extern int proxy; 160026049Sminshall 160126049Sminshall if (!proxy) { 160226049Sminshall pswitch(1); 160326049Sminshall } 160426049Sminshall if (connected) { 160526049Sminshall proxflag = 1; 160626049Sminshall } 160726049Sminshall else { 160826049Sminshall proxflag = 0; 160926049Sminshall } 161026049Sminshall pswitch(0); 161126049Sminshall longjmp(abortprox,1); 161226049Sminshall } 161326049Sminshall 161426049Sminshall doproxy(argc,argv) 161526049Sminshall int argc; 161626049Sminshall char *argv[]; 161726049Sminshall { 161839252Sbostic extern struct cmd cmdtab[]; 161939252Sbostic extern jmp_buf abortprox; 162026049Sminshall register struct cmd *c; 162126049Sminshall struct cmd *getcmd(); 162239252Sbostic sig_t oldintr; 162339252Sbostic void proxabort(); 162426049Sminshall 162545260Sbostic if (argc < 2 && !another(&argc, &argv, "command")) { 162645260Sbostic printf("usage: %s command\n", argv[0]); 162726049Sminshall code = -1; 162826049Sminshall return; 162926049Sminshall } 163026049Sminshall c = getcmd(argv[1]); 163126049Sminshall if (c == (struct cmd *) -1) { 163226049Sminshall printf("?Ambiguous command\n"); 163326497Sminshall (void) fflush(stdout); 163426049Sminshall code = -1; 163526049Sminshall return; 163626049Sminshall } 163726049Sminshall if (c == 0) { 163826049Sminshall printf("?Invalid command\n"); 163926497Sminshall (void) fflush(stdout); 164026049Sminshall code = -1; 164126049Sminshall return; 164226049Sminshall } 164326049Sminshall if (!c->c_proxy) { 164426049Sminshall printf("?Invalid proxy command\n"); 164526497Sminshall (void) fflush(stdout); 164626049Sminshall code = -1; 164726049Sminshall return; 164826049Sminshall } 164926049Sminshall if (setjmp(abortprox)) { 165026049Sminshall code = -1; 165126049Sminshall return; 165226049Sminshall } 165326049Sminshall oldintr = signal(SIGINT, proxabort); 165426049Sminshall pswitch(1); 165526049Sminshall if (c->c_conn && !connected) { 165626049Sminshall printf("Not connected\n"); 165726497Sminshall (void) fflush(stdout); 165826049Sminshall pswitch(0); 165926049Sminshall (void) signal(SIGINT, oldintr); 166026049Sminshall code = -1; 166126049Sminshall return; 166226049Sminshall } 166326049Sminshall (*c->c_handler)(argc-1, argv+1); 166426049Sminshall if (connected) { 166526049Sminshall proxflag = 1; 166626049Sminshall } 166726049Sminshall else { 166826049Sminshall proxflag = 0; 166926049Sminshall } 167026049Sminshall pswitch(0); 167126049Sminshall (void) signal(SIGINT, oldintr); 167226049Sminshall } 167326049Sminshall 167426049Sminshall setcase() 167526049Sminshall { 167626049Sminshall mcase = !mcase; 167726049Sminshall printf("Case mapping %s.\n", onoff(mcase)); 167826049Sminshall code = mcase; 167926049Sminshall } 168026049Sminshall 168126049Sminshall setcr() 168226049Sminshall { 168326049Sminshall crflag = !crflag; 168426049Sminshall printf("Carriage Return stripping %s.\n", onoff(crflag)); 168526049Sminshall code = crflag; 168626049Sminshall } 168726049Sminshall 168826049Sminshall setntrans(argc,argv) 168926049Sminshall int argc; 169026049Sminshall char *argv[]; 169126049Sminshall { 169226049Sminshall if (argc == 1) { 169326049Sminshall ntflag = 0; 169426049Sminshall printf("Ntrans off.\n"); 169526049Sminshall code = ntflag; 169626049Sminshall return; 169726049Sminshall } 169826049Sminshall ntflag++; 169926049Sminshall code = ntflag; 170026049Sminshall (void) strncpy(ntin, argv[1], 16); 170126049Sminshall ntin[16] = '\0'; 170226049Sminshall if (argc == 2) { 170326049Sminshall ntout[0] = '\0'; 170426049Sminshall return; 170526049Sminshall } 170626049Sminshall (void) strncpy(ntout, argv[2], 16); 170726049Sminshall ntout[16] = '\0'; 170826049Sminshall } 170926049Sminshall 171026049Sminshall char * 171126049Sminshall dotrans(name) 171226049Sminshall char *name; 171326049Sminshall { 171426049Sminshall static char new[MAXPATHLEN]; 171526049Sminshall char *cp1, *cp2 = new; 171626049Sminshall register int i, ostop, found; 171726049Sminshall 171826049Sminshall for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++); 171926049Sminshall for (cp1 = name; *cp1; cp1++) { 172026049Sminshall found = 0; 172126049Sminshall for (i = 0; *(ntin + i) && i < 16; i++) { 172226049Sminshall if (*cp1 == *(ntin + i)) { 172326049Sminshall found++; 172426049Sminshall if (i < ostop) { 172526049Sminshall *cp2++ = *(ntout + i); 172626049Sminshall } 172726049Sminshall break; 172826049Sminshall } 172926049Sminshall } 173026049Sminshall if (!found) { 173126049Sminshall *cp2++ = *cp1; 173226049Sminshall } 173326049Sminshall } 173426049Sminshall *cp2 = '\0'; 173526049Sminshall return(new); 173626049Sminshall } 173726049Sminshall 173826049Sminshall setnmap(argc, argv) 173926049Sminshall int argc; 174026049Sminshall char *argv[]; 174126049Sminshall { 174226049Sminshall char *cp; 174326049Sminshall 174426049Sminshall if (argc == 1) { 174526049Sminshall mapflag = 0; 174626049Sminshall printf("Nmap off.\n"); 174726049Sminshall code = mapflag; 174826049Sminshall return; 174926049Sminshall } 175045260Sbostic if (argc < 3 && !another(&argc, &argv, "mapout")) { 175126049Sminshall printf("Usage: %s [mapin mapout]\n",argv[0]); 175226049Sminshall code = -1; 175326049Sminshall return; 175426049Sminshall } 175526049Sminshall mapflag = 1; 175626049Sminshall code = 1; 175726049Sminshall cp = index(altarg, ' '); 175826049Sminshall if (proxy) { 175926049Sminshall while(*++cp == ' '); 176026049Sminshall altarg = cp; 176126049Sminshall cp = index(altarg, ' '); 176226049Sminshall } 176326049Sminshall *cp = '\0'; 176426049Sminshall (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 176526049Sminshall while (*++cp == ' '); 176626049Sminshall (void) strncpy(mapout, cp, MAXPATHLEN - 1); 176726049Sminshall } 176826049Sminshall 176926049Sminshall char * 177026049Sminshall domap(name) 177126049Sminshall char *name; 177226049Sminshall { 177326049Sminshall static char new[MAXPATHLEN]; 177426049Sminshall register char *cp1 = name, *cp2 = mapin; 177526049Sminshall char *tp[9], *te[9]; 177636689Scsvsj int i, toks[9], toknum = 0, match = 1; 177726049Sminshall 177826049Sminshall for (i=0; i < 9; ++i) { 177926049Sminshall toks[i] = 0; 178026049Sminshall } 178126049Sminshall while (match && *cp1 && *cp2) { 178226049Sminshall switch (*cp2) { 178326049Sminshall case '\\': 178426049Sminshall if (*++cp2 != *cp1) { 178526049Sminshall match = 0; 178626049Sminshall } 178726049Sminshall break; 178826049Sminshall case '$': 178926049Sminshall if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 179026049Sminshall if (*cp1 != *(++cp2+1)) { 179126049Sminshall toks[toknum = *cp2 - '1']++; 179226049Sminshall tp[toknum] = cp1; 179326049Sminshall while (*++cp1 && *(cp2+1) 179426049Sminshall != *cp1); 179526049Sminshall te[toknum] = cp1; 179626049Sminshall } 179726049Sminshall cp2++; 179826049Sminshall break; 179926049Sminshall } 180036935Skarels /* FALLTHROUGH */ 180126049Sminshall default: 180226049Sminshall if (*cp2 != *cp1) { 180326049Sminshall match = 0; 180426049Sminshall } 180526049Sminshall break; 180626049Sminshall } 180736689Scsvsj if (match && *cp1) { 180826049Sminshall cp1++; 180926049Sminshall } 181036689Scsvsj if (match && *cp2) { 181126049Sminshall cp2++; 181226049Sminshall } 181326049Sminshall } 181436689Scsvsj if (!match && *cp1) /* last token mismatch */ 181536689Scsvsj { 181636689Scsvsj toks[toknum] = 0; 181736689Scsvsj } 181826049Sminshall cp1 = new; 181926049Sminshall *cp1 = '\0'; 182026049Sminshall cp2 = mapout; 182126049Sminshall while (*cp2) { 182226049Sminshall match = 0; 182326049Sminshall switch (*cp2) { 182426049Sminshall case '\\': 182526049Sminshall if (*(cp2 + 1)) { 182626049Sminshall *cp1++ = *++cp2; 182726049Sminshall } 182826049Sminshall break; 182926049Sminshall case '[': 183026049Sminshall LOOP: 183126049Sminshall if (*++cp2 == '$' && isdigit(*(cp2+1))) { 183226049Sminshall if (*++cp2 == '0') { 183326049Sminshall char *cp3 = name; 183426049Sminshall 183526049Sminshall while (*cp3) { 183626049Sminshall *cp1++ = *cp3++; 183726049Sminshall } 183826049Sminshall match = 1; 183926049Sminshall } 184026049Sminshall else if (toks[toknum = *cp2 - '1']) { 184126049Sminshall char *cp3 = tp[toknum]; 184226049Sminshall 184326049Sminshall while (cp3 != te[toknum]) { 184426049Sminshall *cp1++ = *cp3++; 184526049Sminshall } 184626049Sminshall match = 1; 184726049Sminshall } 184826049Sminshall } 184926049Sminshall else { 185026049Sminshall while (*cp2 && *cp2 != ',' && 185126049Sminshall *cp2 != ']') { 185226049Sminshall if (*cp2 == '\\') { 185326049Sminshall cp2++; 185426049Sminshall } 185526049Sminshall else if (*cp2 == '$' && 185626049Sminshall isdigit(*(cp2+1))) { 185726049Sminshall if (*++cp2 == '0') { 185826049Sminshall char *cp3 = name; 185926049Sminshall 186026049Sminshall while (*cp3) { 186126049Sminshall *cp1++ = *cp3++; 186226049Sminshall } 186326049Sminshall } 186426049Sminshall else if (toks[toknum = 186526049Sminshall *cp2 - '1']) { 186626049Sminshall char *cp3=tp[toknum]; 186726049Sminshall 186826049Sminshall while (cp3 != 186926049Sminshall te[toknum]) { 187026049Sminshall *cp1++ = *cp3++; 187126049Sminshall } 187226049Sminshall } 187326049Sminshall } 187426049Sminshall else if (*cp2) { 187526049Sminshall *cp1++ = *cp2++; 187626049Sminshall } 187726049Sminshall } 187826049Sminshall if (!*cp2) { 187926049Sminshall printf("nmap: unbalanced brackets\n"); 188026049Sminshall return(name); 188126049Sminshall } 188226049Sminshall match = 1; 188326049Sminshall cp2--; 188426049Sminshall } 188526049Sminshall if (match) { 188626049Sminshall while (*++cp2 && *cp2 != ']') { 188726049Sminshall if (*cp2 == '\\' && *(cp2 + 1)) { 188826049Sminshall cp2++; 188926049Sminshall } 189026049Sminshall } 189126049Sminshall if (!*cp2) { 189226049Sminshall printf("nmap: unbalanced brackets\n"); 189326049Sminshall return(name); 189426049Sminshall } 189526049Sminshall break; 189626049Sminshall } 189726049Sminshall switch (*++cp2) { 189826049Sminshall case ',': 189926049Sminshall goto LOOP; 190026049Sminshall case ']': 190126049Sminshall break; 190226049Sminshall default: 190326049Sminshall cp2--; 190426049Sminshall goto LOOP; 190526049Sminshall } 190626049Sminshall break; 190726049Sminshall case '$': 190826049Sminshall if (isdigit(*(cp2 + 1))) { 190926049Sminshall if (*++cp2 == '0') { 191026049Sminshall char *cp3 = name; 191126049Sminshall 191226049Sminshall while (*cp3) { 191326049Sminshall *cp1++ = *cp3++; 191426049Sminshall } 191526049Sminshall } 191626049Sminshall else if (toks[toknum = *cp2 - '1']) { 191726049Sminshall char *cp3 = tp[toknum]; 191826049Sminshall 191926049Sminshall while (cp3 != te[toknum]) { 192026049Sminshall *cp1++ = *cp3++; 192126049Sminshall } 192226049Sminshall } 192326049Sminshall break; 192426049Sminshall } 192526049Sminshall /* intentional drop through */ 192626049Sminshall default: 192726049Sminshall *cp1++ = *cp2; 192826049Sminshall break; 192926049Sminshall } 193026049Sminshall cp2++; 193126049Sminshall } 193226049Sminshall *cp1 = '\0'; 193326049Sminshall if (!*new) { 193426049Sminshall return(name); 193526049Sminshall } 193626049Sminshall return(new); 193726049Sminshall } 193826049Sminshall 193926049Sminshall setsunique() 194026049Sminshall { 194126049Sminshall sunique = !sunique; 194226049Sminshall printf("Store unique %s.\n", onoff(sunique)); 194326049Sminshall code = sunique; 194426049Sminshall } 194526049Sminshall 194626049Sminshall setrunique() 194726049Sminshall { 194826049Sminshall runique = !runique; 194926049Sminshall printf("Receive unique %s.\n", onoff(runique)); 195026049Sminshall code = runique; 195126049Sminshall } 195226049Sminshall 195326049Sminshall /* change directory to perent directory */ 195426049Sminshall cdup() 195526049Sminshall { 195637224Skarels if (command("CDUP") == ERROR && code == 500) { 195737224Skarels if (verbose) 195837224Skarels printf("CDUP command not recognized, trying XCUP\n"); 195937224Skarels (void) command("XCUP"); 196037224Skarels } 196126049Sminshall } 196226049Sminshall 196337224Skarels /* restart transfer at specific point */ 196437224Skarels restart(argc, argv) 196537224Skarels int argc; 196637224Skarels char *argv[]; 196737224Skarels { 196837224Skarels extern long atol(); 196937224Skarels if (argc != 2) 197037224Skarels printf("restart: offset not specified\n"); 197137224Skarels else { 197237224Skarels restart_point = atol(argv[1]); 197337224Skarels printf("restarting at %ld. %s\n", restart_point, 197437224Skarels "execute get, put or append to initiate transfer"); 197537224Skarels } 197637224Skarels } 197736935Skarels 197836935Skarels /* show remote system type */ 197936935Skarels syst() 198036935Skarels { 198136935Skarels (void) command("SYST"); 198236935Skarels } 198336935Skarels 198426049Sminshall macdef(argc, argv) 198526049Sminshall int argc; 198626049Sminshall char *argv[]; 198726049Sminshall { 198826049Sminshall char *tmp; 198926049Sminshall int c; 199026049Sminshall 199126049Sminshall if (macnum == 16) { 199226049Sminshall printf("Limit of 16 macros have already been defined\n"); 199326049Sminshall code = -1; 199426049Sminshall return; 199526049Sminshall } 199645260Sbostic if (argc < 2 && !another(&argc, &argv, "macro name")) { 199726049Sminshall printf("Usage: %s macro_name\n",argv[0]); 199826049Sminshall code = -1; 199926049Sminshall return; 200026049Sminshall } 200126049Sminshall if (interactive) { 200226049Sminshall printf("Enter macro line by line, terminating it with a null line\n"); 200326049Sminshall } 200426497Sminshall (void) strncpy(macros[macnum].mac_name, argv[1], 8); 200526049Sminshall if (macnum == 0) { 200626049Sminshall macros[macnum].mac_start = macbuf; 200726049Sminshall } 200826049Sminshall else { 200926049Sminshall macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 201026049Sminshall } 201126049Sminshall tmp = macros[macnum].mac_start; 201226049Sminshall while (tmp != macbuf+4096) { 201326049Sminshall if ((c = getchar()) == EOF) { 201426049Sminshall printf("macdef:end of file encountered\n"); 201526049Sminshall code = -1; 201626049Sminshall return; 201726049Sminshall } 201826049Sminshall if ((*tmp = c) == '\n') { 201926049Sminshall if (tmp == macros[macnum].mac_start) { 202026049Sminshall macros[macnum++].mac_end = tmp; 202126049Sminshall code = 0; 202226049Sminshall return; 202326049Sminshall } 202426049Sminshall if (*(tmp-1) == '\0') { 202526049Sminshall macros[macnum++].mac_end = tmp - 1; 202626049Sminshall code = 0; 202726049Sminshall return; 202826049Sminshall } 202926049Sminshall *tmp = '\0'; 203026049Sminshall } 203126049Sminshall tmp++; 203226049Sminshall } 203326049Sminshall while (1) { 203436935Skarels while ((c = getchar()) != '\n' && c != EOF) 203536935Skarels /* LOOP */; 203626049Sminshall if (c == EOF || getchar() == '\n') { 203726049Sminshall printf("Macro not defined - 4k buffer exceeded\n"); 203826049Sminshall code = -1; 203926049Sminshall return; 204026049Sminshall } 204126049Sminshall } 204226049Sminshall } 204336935Skarels 204436935Skarels /* 204536935Skarels * get size of file on remote machine 204636935Skarels */ 204736935Skarels sizecmd(argc, argv) 204845260Sbostic int argc; 204936935Skarels char *argv[]; 205036935Skarels { 205136935Skarels 205245260Sbostic if (argc < 2 && !another(&argc, &argv, "filename")) { 205345260Sbostic printf("usage: %s filename\n", argv[0]); 205436935Skarels code = -1; 205536935Skarels return; 205636935Skarels } 205736935Skarels (void) command("SIZE %s", argv[1]); 205836935Skarels } 205936935Skarels 206036935Skarels /* 206136935Skarels * get last modification time of file on remote machine 206236935Skarels */ 206336935Skarels modtime(argc, argv) 206445260Sbostic int argc; 206536935Skarels char *argv[]; 206636935Skarels { 206736935Skarels int overbose; 206836935Skarels 206945260Sbostic if (argc < 2 && !another(&argc, &argv, "filename")) { 207045260Sbostic printf("usage: %s filename\n", argv[0]); 207136935Skarels code = -1; 207236935Skarels return; 207336935Skarels } 207436940Skarels overbose = verbose; 207536940Skarels if (debug == 0) 207636940Skarels verbose = -1; 207736935Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 207836935Skarels int yy, mo, day, hour, min, sec; 207936935Skarels sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 208036935Skarels &day, &hour, &min, &sec); 208136935Skarels /* might want to print this in local time */ 208236935Skarels printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 208336935Skarels mo, day, yy, hour, min, sec); 208436935Skarels } else 208538132Srick printf("%s\n", reply_string); 208636935Skarels verbose = overbose; 208736935Skarels } 208836935Skarels 208936935Skarels /* 209037224Skarels * show status on reomte machine 209136935Skarels */ 209236935Skarels rmtstatus(argc, argv) 209345260Sbostic int argc; 209436935Skarels char *argv[]; 209536935Skarels { 209636935Skarels (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 209736935Skarels } 209837224Skarels 209937224Skarels /* 210037224Skarels * get file if modtime is more recent than current file 210137224Skarels */ 210237224Skarels newer(argc, argv) 210345260Sbostic int argc; 210437224Skarels char *argv[]; 210537224Skarels { 210637224Skarels if (getit(argc, argv, -1, "w")) 210737224Skarels printf("Local file \"%s\" is newer than remote file \"%s\"\n", 210837224Skarels argv[1], argv[2]); 210937224Skarels } 2110