121737Sdist /* 2*62007Sbostic * Copyright (c) 1985, 1989, 1993 3*62007Sbostic * The Regents of the University of California. All rights reserved. 433737Sbostic * 542665Sbostic * %sccs.include.redist.c% 621737Sdist */ 721737Sdist 810294Ssam #ifndef lint 9*62007Sbostic static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 06/06/93"; 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; 3447024Sbostic extern char **ftpglob(); 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 } 49747024Sbostic gargs = ftpglob(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); 62854056Sandrew if ((tm->tm_year == yy%100 && 62954056Sandrew tm->tm_mon > mo) || 63054056Sandrew (tm->tm_mon == mo && 63154056Sandrew tm->tm_mday > day) || 63254056Sandrew (tm->tm_mday == day && 63354056Sandrew tm->tm_hour > hour) || 63454056Sandrew (tm->tm_hour == hour && 63554056Sandrew tm->tm_min > min) || 63654056Sandrew (tm->tm_min == min && 63754056Sandrew tm->tm_sec > sec)) 63854056Sandrew return (1); 63937224Skarels } else { 64038132Srick printf("%s\n", reply_string); 64137224Skarels verbose = overbose; 64237224Skarels return (0); 64337224Skarels } 64437224Skarels } 64537224Skarels } 64637224Skarels } 64737224Skarels 64837225Skarels recvrequest("RETR", argv[2], argv[1], mode, 64937225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 65037224Skarels restart_point = 0; 65137224Skarels return (0); 65210294Ssam } 65310294Ssam 65439252Sbostic void 65526049Sminshall mabort() 65626049Sminshall { 65726049Sminshall int ointer; 65826049Sminshall extern jmp_buf jabort; 65926049Sminshall 66026049Sminshall printf("\n"); 66126049Sminshall (void) fflush(stdout); 66226049Sminshall if (mflag && fromatty) { 66326049Sminshall ointer = interactive; 66426049Sminshall interactive = 1; 66526049Sminshall if (confirm("Continue with", mname)) { 66626049Sminshall interactive = ointer; 66726049Sminshall longjmp(jabort,0); 66826049Sminshall } 66926049Sminshall interactive = ointer; 67026049Sminshall } 67126049Sminshall mflag = 0; 67226049Sminshall longjmp(jabort,0); 67326049Sminshall } 67426049Sminshall 67511353Ssam /* 67611353Ssam * Get multiple files. 67711353Ssam */ 67811353Ssam mget(argc, argv) 67939252Sbostic int argc; 68039252Sbostic char **argv; 68111353Ssam { 68239252Sbostic extern jmp_buf jabort; 68339252Sbostic sig_t oldintr; 68454056Sandrew int ch, ointer; 68526049Sminshall char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; 68639252Sbostic void mabort(); 68711353Ssam 68845260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) { 68945260Sbostic printf("usage: %s remote-files\n", argv[0]); 69026049Sminshall code = -1; 69111353Ssam return; 69211353Ssam } 69326049Sminshall mname = argv[0]; 69426049Sminshall mflag = 1; 69526049Sminshall oldintr = signal(SIGINT,mabort); 69626049Sminshall (void) setjmp(jabort); 69726497Sminshall while ((cp = remglob(argv,proxy)) != NULL) { 69826049Sminshall if (*cp == '\0') { 69926049Sminshall mflag = 0; 70026049Sminshall continue; 70126049Sminshall } 70226049Sminshall if (mflag && confirm(argv[0], cp)) { 70326049Sminshall tp = cp; 70426049Sminshall if (mcase) { 70554056Sandrew for (tp2 = tmpbuf; ch = *tp++;) 70654056Sandrew *tp2++ = isupper(ch) ? tolower(ch) : ch; 70726049Sminshall tp = tmpbuf; 70826049Sminshall } 70926049Sminshall if (ntflag) { 71026049Sminshall tp = dotrans(tp); 71126049Sminshall } 71226049Sminshall if (mapflag) { 71326049Sminshall tp = domap(tp); 71426049Sminshall } 71537225Skarels recvrequest("RETR", tp, cp, "w", 71637225Skarels tp != cp || !interactive); 71726049Sminshall if (!mflag && fromatty) { 71826049Sminshall ointer = interactive; 71926049Sminshall interactive = 1; 72026049Sminshall if (confirm("Continue with","mget")) { 72126049Sminshall mflag++; 72226049Sminshall } 72326049Sminshall interactive = ointer; 72426049Sminshall } 72526049Sminshall } 72626049Sminshall } 72726049Sminshall (void) signal(SIGINT,oldintr); 72826049Sminshall mflag = 0; 72911650Ssam } 73011650Ssam 73111650Ssam char * 73226497Sminshall remglob(argv,doswitch) 73311650Ssam char *argv[]; 73426497Sminshall int doswitch; 73511650Ssam { 73611756Ssam char temp[16]; 73711650Ssam static char buf[MAXPATHLEN]; 73811650Ssam static FILE *ftemp = NULL; 73911650Ssam static char **args; 74013212Ssam int oldverbose, oldhash; 74111756Ssam char *cp, *mode; 74211650Ssam 74326049Sminshall if (!mflag) { 74426049Sminshall if (!doglob) { 74526049Sminshall args = NULL; 74626049Sminshall } 74726049Sminshall else { 74826049Sminshall if (ftemp) { 74926497Sminshall (void) fclose(ftemp); 75026049Sminshall ftemp = NULL; 75126049Sminshall } 75226049Sminshall } 75326049Sminshall return(NULL); 75426049Sminshall } 75511650Ssam if (!doglob) { 75611756Ssam if (args == NULL) 75711650Ssam args = argv; 75811650Ssam if ((cp = *++args) == NULL) 75911650Ssam args = NULL; 76011650Ssam return (cp); 76111353Ssam } 76211650Ssam if (ftemp == NULL) { 76337458Skarels (void) strcpy(temp, _PATH_TMP); 76426497Sminshall (void) mktemp(temp); 76511650Ssam oldverbose = verbose, verbose = 0; 76613212Ssam oldhash = hash, hash = 0; 76726049Sminshall if (doswitch) { 76826049Sminshall pswitch(!proxy); 76926049Sminshall } 77011756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 77137225Skarels recvrequest ("NLST", temp, *argv, mode, 0); 77226049Sminshall if (doswitch) { 77326049Sminshall pswitch(!proxy); 77426049Sminshall } 77513212Ssam verbose = oldverbose; hash = oldhash; 77611650Ssam ftemp = fopen(temp, "r"); 77726497Sminshall (void) unlink(temp); 77811650Ssam if (ftemp == NULL) { 77911650Ssam printf("can't find list of remote files, oops\n"); 78011756Ssam return (NULL); 78111353Ssam } 78211353Ssam } 78311650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 78426497Sminshall (void) fclose(ftemp), ftemp = NULL; 78511650Ssam return (NULL); 78611353Ssam } 78711650Ssam if ((cp = index(buf, '\n')) != NULL) 78811650Ssam *cp = '\0'; 78911650Ssam return (buf); 79011353Ssam } 79111353Ssam 79210294Ssam char * 79310294Ssam onoff(bool) 79410294Ssam int bool; 79510294Ssam { 79610294Ssam 79710294Ssam return (bool ? "on" : "off"); 79810294Ssam } 79910294Ssam 80010294Ssam /* 80110294Ssam * Show status. 80210294Ssam */ 80326497Sminshall /*ARGSUSED*/ 80410294Ssam status(argc, argv) 80545260Sbostic int argc; 80610294Ssam char *argv[]; 80710294Ssam { 80826049Sminshall int i; 80910294Ssam 81010294Ssam if (connected) 81110294Ssam printf("Connected to %s.\n", hostname); 81210294Ssam else 81310294Ssam printf("Not connected.\n"); 81426049Sminshall if (!proxy) { 81526049Sminshall pswitch(1); 81626049Sminshall if (connected) { 81726049Sminshall printf("Connected for proxy commands to %s.\n", hostname); 81826049Sminshall } 81926049Sminshall else { 82026049Sminshall printf("No proxy connection.\n"); 82126049Sminshall } 82226049Sminshall pswitch(0); 82326049Sminshall } 82410294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 82510294Ssam modename, typename, formname, structname); 82611353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 82711353Ssam onoff(verbose), onoff(bell), onoff(interactive), 82811353Ssam onoff(doglob)); 82926049Sminshall printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), 83026049Sminshall onoff(runique)); 83126049Sminshall printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); 83226049Sminshall if (ntflag) { 83326049Sminshall printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); 83426049Sminshall } 83526049Sminshall else { 83626049Sminshall printf("Ntrans: off\n"); 83726049Sminshall } 83826049Sminshall if (mapflag) { 83926049Sminshall printf("Nmap: (in) %s (out) %s\n", mapin, mapout); 84026049Sminshall } 84126049Sminshall else { 84226049Sminshall printf("Nmap: off\n"); 84326049Sminshall } 84414143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 84514143Ssam onoff(hash), onoff(sendport)); 84626049Sminshall if (macnum > 0) { 84726049Sminshall printf("Macros:\n"); 84826049Sminshall for (i=0; i<macnum; i++) { 84926049Sminshall printf("\t%s\n",macros[i].mac_name); 85026049Sminshall } 85126049Sminshall } 85226049Sminshall code = 0; 85310294Ssam } 85410294Ssam 85510294Ssam /* 85610294Ssam * Set beep on cmd completed mode. 85710294Ssam */ 85810294Ssam /*VARARGS*/ 85910294Ssam setbell() 86010294Ssam { 86110294Ssam 86210294Ssam bell = !bell; 86310294Ssam printf("Bell mode %s.\n", onoff(bell)); 86426049Sminshall code = bell; 86510294Ssam } 86610294Ssam 86710294Ssam /* 86810294Ssam * Turn on packet tracing. 86910294Ssam */ 87010294Ssam /*VARARGS*/ 87110294Ssam settrace() 87210294Ssam { 87310294Ssam 87410294Ssam trace = !trace; 87510294Ssam printf("Packet tracing %s.\n", onoff(trace)); 87626049Sminshall code = trace; 87710294Ssam } 87810294Ssam 87910294Ssam /* 88011650Ssam * Toggle hash mark printing during transfers. 88111650Ssam */ 88211650Ssam /*VARARGS*/ 88311650Ssam sethash() 88411650Ssam { 88511650Ssam 88611650Ssam hash = !hash; 88711650Ssam printf("Hash mark printing %s", onoff(hash)); 88826049Sminshall code = hash; 88911650Ssam if (hash) 89037224Skarels printf(" (%d bytes/hash mark)", 1024); 89111650Ssam printf(".\n"); 89211650Ssam } 89311650Ssam 89411650Ssam /* 89510294Ssam * Turn on printing of server echo's. 89610294Ssam */ 89710294Ssam /*VARARGS*/ 89810294Ssam setverbose() 89910294Ssam { 90010294Ssam 90110294Ssam verbose = !verbose; 90210294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 90326049Sminshall code = verbose; 90410294Ssam } 90510294Ssam 90610294Ssam /* 90711650Ssam * Toggle PORT cmd use before each data connection. 90811650Ssam */ 90911650Ssam /*VARARGS*/ 91011650Ssam setport() 91111650Ssam { 91211650Ssam 91311650Ssam sendport = !sendport; 91411650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 91526049Sminshall code = sendport; 91611650Ssam } 91711650Ssam 91811650Ssam /* 91910294Ssam * Turn on interactive prompting 92010294Ssam * during mget, mput, and mdelete. 92110294Ssam */ 92210294Ssam /*VARARGS*/ 92310294Ssam setprompt() 92410294Ssam { 92510294Ssam 92610294Ssam interactive = !interactive; 92710294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 92826049Sminshall code = interactive; 92910294Ssam } 93010294Ssam 93110294Ssam /* 93211353Ssam * Toggle metacharacter interpretation 93311353Ssam * on local file names. 93411353Ssam */ 93511353Ssam /*VARARGS*/ 93611353Ssam setglob() 93711353Ssam { 93811353Ssam 93911353Ssam doglob = !doglob; 94011353Ssam printf("Globbing %s.\n", onoff(doglob)); 94126049Sminshall code = doglob; 94211353Ssam } 94311353Ssam 94411353Ssam /* 94510294Ssam * Set debugging mode on/off and/or 94610294Ssam * set level of debugging. 94710294Ssam */ 94811756Ssam /*VARARGS*/ 94910294Ssam setdebug(argc, argv) 95045260Sbostic int argc; 95110294Ssam char *argv[]; 95210294Ssam { 95310294Ssam int val; 95410294Ssam 95510294Ssam if (argc > 1) { 95610294Ssam val = atoi(argv[1]); 95710294Ssam if (val < 0) { 95810294Ssam printf("%s: bad debugging value.\n", argv[1]); 95926049Sminshall code = -1; 96010294Ssam return; 96110294Ssam } 96210294Ssam } else 96310294Ssam val = !debug; 96410294Ssam debug = val; 96510294Ssam if (debug) 96610294Ssam options |= SO_DEBUG; 96710294Ssam else 96810294Ssam options &= ~SO_DEBUG; 96910294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 97026049Sminshall code = debug > 0; 97110294Ssam } 97210294Ssam 97310294Ssam /* 97410294Ssam * Set current working directory 97510294Ssam * on remote machine. 97610294Ssam */ 97710294Ssam cd(argc, argv) 97845260Sbostic int argc; 97910294Ssam char *argv[]; 98010294Ssam { 98110294Ssam 98245260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-directory")) { 98345260Sbostic printf("usage: %s remote-directory\n", argv[0]); 98426049Sminshall code = -1; 98510294Ssam return; 98610294Ssam } 98737224Skarels if (command("CWD %s", argv[1]) == ERROR && code == 500) { 98837224Skarels if (verbose) 98937224Skarels printf("CWD command not recognized, trying XCWD\n"); 99037224Skarels (void) command("XCWD %s", argv[1]); 99137224Skarels } 99210294Ssam } 99310294Ssam 99410294Ssam /* 99510294Ssam * Set current working directory 99610294Ssam * on local machine. 99710294Ssam */ 99810294Ssam lcd(argc, argv) 99945260Sbostic int argc; 100010294Ssam char *argv[]; 100110294Ssam { 100211353Ssam char buf[MAXPATHLEN]; 100338132Srick extern char *getwd(); 100410294Ssam 100511353Ssam if (argc < 2) 100611353Ssam argc++, argv[1] = home; 100710294Ssam if (argc != 2) { 100845260Sbostic printf("usage: %s local-directory\n", argv[0]); 100926049Sminshall code = -1; 101010294Ssam return; 101110294Ssam } 101226049Sminshall if (!globulize(&argv[1])) { 101326049Sminshall code = -1; 101411353Ssam return; 101526049Sminshall } 101611353Ssam if (chdir(argv[1]) < 0) { 101738202Srick fprintf(stderr, "local: %s: %s\n", argv[1], strerror(errno)); 101826049Sminshall code = -1; 101911353Ssam return; 102011353Ssam } 102111353Ssam printf("Local directory now %s\n", getwd(buf)); 102226049Sminshall code = 0; 102310294Ssam } 102410294Ssam 102510294Ssam /* 102610294Ssam * Delete a single file. 102710294Ssam */ 102810294Ssam delete(argc, argv) 102945260Sbostic int argc; 103010294Ssam char *argv[]; 103110294Ssam { 103210294Ssam 103345260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-file")) { 103445260Sbostic printf("usage: %s remote-file\n", argv[0]); 103526049Sminshall code = -1; 103610294Ssam return; 103710294Ssam } 103810294Ssam (void) command("DELE %s", argv[1]); 103910294Ssam } 104010294Ssam 104110294Ssam /* 104211650Ssam * Delete multiple files. 104311650Ssam */ 104411650Ssam mdelete(argc, argv) 104539252Sbostic int argc; 104639252Sbostic char **argv; 104711650Ssam { 104839252Sbostic extern jmp_buf jabort; 104939252Sbostic sig_t oldintr; 105039252Sbostic int ointer; 105111650Ssam char *cp; 105239252Sbostic void mabort(); 105311650Ssam 105445260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) { 105545260Sbostic printf("usage: %s remote-files\n", argv[0]); 105626049Sminshall code = -1; 105711650Ssam return; 105811650Ssam } 105926049Sminshall mname = argv[0]; 106026049Sminshall mflag = 1; 106126049Sminshall oldintr = signal(SIGINT, mabort); 106226049Sminshall (void) setjmp(jabort); 106326497Sminshall while ((cp = remglob(argv,0)) != NULL) { 106426049Sminshall if (*cp == '\0') { 106526049Sminshall mflag = 0; 106626049Sminshall continue; 106726049Sminshall } 106826049Sminshall if (mflag && confirm(argv[0], cp)) { 106911650Ssam (void) command("DELE %s", cp); 107026049Sminshall if (!mflag && fromatty) { 107126049Sminshall ointer = interactive; 107226049Sminshall interactive = 1; 107326049Sminshall if (confirm("Continue with", "mdelete")) { 107426049Sminshall mflag++; 107526049Sminshall } 107626049Sminshall interactive = ointer; 107726049Sminshall } 107826049Sminshall } 107926049Sminshall } 108026049Sminshall (void) signal(SIGINT, oldintr); 108126049Sminshall mflag = 0; 108211650Ssam } 108311756Ssam 108411650Ssam /* 108510294Ssam * Rename a remote file. 108610294Ssam */ 108710294Ssam renamefile(argc, argv) 108845260Sbostic int argc; 108910294Ssam char *argv[]; 109010294Ssam { 109110294Ssam 109245260Sbostic if (argc < 2 && !another(&argc, &argv, "from-name")) 109345260Sbostic goto usage; 109445260Sbostic if (argc < 3 && !another(&argc, &argv, "to-name")) { 109510294Ssam usage: 109610294Ssam printf("%s from-name to-name\n", argv[0]); 109726049Sminshall code = -1; 109810294Ssam return; 109910294Ssam } 110010294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 110110294Ssam (void) command("RNTO %s", argv[2]); 110210294Ssam } 110310294Ssam 110410294Ssam /* 110510294Ssam * Get a directory listing 110610294Ssam * of remote files. 110710294Ssam */ 110810294Ssam ls(argc, argv) 110945260Sbostic int argc; 111010294Ssam char *argv[]; 111110294Ssam { 111211756Ssam char *cmd; 111310294Ssam 111410294Ssam if (argc < 2) 111510294Ssam argc++, argv[1] = NULL; 111610294Ssam if (argc < 3) 111710294Ssam argc++, argv[2] = "-"; 111811756Ssam if (argc > 3) { 111911756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 112026049Sminshall code = -1; 112111756Ssam return; 112211756Ssam } 112336935Skarels cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 112426049Sminshall if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 112526049Sminshall code = -1; 112611353Ssam return; 112726049Sminshall } 112832344Scsvsj if (strcmp(argv[2], "-") && *argv[2] != '|') 112932344Scsvsj if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { 113032344Scsvsj code = -1; 113132344Scsvsj return; 113232344Scsvsj } 113337225Skarels recvrequest(cmd, argv[2], argv[1], "w", 0); 113410294Ssam } 113510294Ssam 113610294Ssam /* 113711756Ssam * Get a directory listing 113811756Ssam * of multiple remote files. 113911756Ssam */ 114011756Ssam mls(argc, argv) 114139252Sbostic int argc; 114239252Sbostic char **argv; 114311756Ssam { 114439252Sbostic extern jmp_buf jabort; 114539252Sbostic sig_t oldintr; 114639252Sbostic int ointer, i; 114726049Sminshall char *cmd, mode[1], *dest; 114839252Sbostic void mabort(); 114911756Ssam 115045260Sbostic if (argc < 2 && !another(&argc, &argv, "remote-files")) 115145260Sbostic goto usage; 115245260Sbostic if (argc < 3 && !another(&argc, &argv, "local-file")) { 115345260Sbostic usage: 115445260Sbostic printf("usage: %s remote-files local-file\n", argv[0]); 115526049Sminshall code = -1; 115613212Ssam return; 115713212Ssam } 115813212Ssam dest = argv[argc - 1]; 115913212Ssam argv[argc - 1] = NULL; 116026049Sminshall if (strcmp(dest, "-") && *dest != '|') 116145260Sbostic if (!globulize(&dest) || 116245260Sbostic !confirm("output to local-file:", dest)) { 116326049Sminshall code = -1; 116413212Ssam return; 116526049Sminshall } 116636940Skarels cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 116726049Sminshall mname = argv[0]; 116826049Sminshall mflag = 1; 116926049Sminshall oldintr = signal(SIGINT, mabort); 117026049Sminshall (void) setjmp(jabort); 117126049Sminshall for (i = 1; mflag && i < argc-1; ++i) { 117226049Sminshall *mode = (i == 1) ? 'w' : 'a'; 117337225Skarels recvrequest(cmd, dest, argv[i], mode, 0); 117426049Sminshall if (!mflag && fromatty) { 117526049Sminshall ointer = interactive; 117626049Sminshall interactive = 1; 117726049Sminshall if (confirm("Continue with", argv[0])) { 117826049Sminshall mflag ++; 117926049Sminshall } 118026049Sminshall interactive = ointer; 118126049Sminshall } 118226049Sminshall } 118326049Sminshall (void) signal(SIGINT, oldintr); 118426049Sminshall mflag = 0; 118511756Ssam } 118611756Ssam 118711756Ssam /* 118810294Ssam * Do a shell escape 118910294Ssam */ 119026497Sminshall /*ARGSUSED*/ 119110294Ssam shell(argc, argv) 119239252Sbostic int argc; 119339252Sbostic char **argv; 119410294Ssam { 119538132Srick int pid; 119639252Sbostic sig_t old1, old2; 119726049Sminshall char shellnam[40], *shell, *namep; 119826497Sminshall union wait status; 119910294Ssam 120011756Ssam old1 = signal (SIGINT, SIG_IGN); 120111756Ssam old2 = signal (SIGQUIT, SIG_IGN); 120211756Ssam if ((pid = fork()) == 0) { 120311756Ssam for (pid = 3; pid < 20; pid++) 120426497Sminshall (void) close(pid); 120526497Sminshall (void) signal(SIGINT, SIG_DFL); 120626497Sminshall (void) signal(SIGQUIT, SIG_DFL); 120725908Smckusick shell = getenv("SHELL"); 120825908Smckusick if (shell == NULL) 120937458Skarels shell = _PATH_BSHELL; 121025908Smckusick namep = rindex(shell,'/'); 121125908Smckusick if (namep == NULL) 121225908Smckusick namep = shell; 121326497Sminshall (void) strcpy(shellnam,"-"); 121426497Sminshall (void) strcat(shellnam, ++namep); 121526049Sminshall if (strcmp(namep, "sh") != 0) 121626049Sminshall shellnam[0] = '+'; 121726049Sminshall if (debug) { 121826049Sminshall printf ("%s\n", shell); 121926497Sminshall (void) fflush (stdout); 122011756Ssam } 122126049Sminshall if (argc > 1) { 122226049Sminshall execl(shell,shellnam,"-c",altarg,(char *)0); 122326049Sminshall } 122426049Sminshall else { 122526049Sminshall execl(shell,shellnam,(char *)0); 122626049Sminshall } 122725908Smckusick perror(shell); 122826049Sminshall code = -1; 122911756Ssam exit(1); 123026049Sminshall } 123111756Ssam if (pid > 0) 123246828Sbostic while (wait((int *)&status) != pid) 123311756Ssam ; 123426497Sminshall (void) signal(SIGINT, old1); 123526497Sminshall (void) signal(SIGQUIT, old2); 123626049Sminshall if (pid == -1) { 123711756Ssam perror("Try again later"); 123826049Sminshall code = -1; 123926049Sminshall } 124026049Sminshall else { 124126049Sminshall code = 0; 124226049Sminshall } 124311756Ssam return (0); 124410294Ssam } 124510294Ssam 124610294Ssam /* 124710294Ssam * Send new user information (re-login) 124810294Ssam */ 124910294Ssam user(argc, argv) 125010294Ssam int argc; 125110294Ssam char **argv; 125210294Ssam { 125335658Sbostic char acct[80], *getpass(); 125426049Sminshall int n, aflag = 0; 125510294Ssam 125645260Sbostic if (argc < 2) 125745260Sbostic (void) another(&argc, &argv, "username"); 125845260Sbostic if (argc < 2 || argc > 4) { 125910294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 126026049Sminshall code = -1; 126111756Ssam return (0); 126210294Ssam } 126310294Ssam n = command("USER %s", argv[1]); 126410294Ssam if (n == CONTINUE) { 126510294Ssam if (argc < 3 ) 126635658Sbostic argv[2] = getpass("Password: "), argc++; 126710294Ssam n = command("PASS %s", argv[2]); 126810294Ssam } 126910294Ssam if (n == CONTINUE) { 127010294Ssam if (argc < 4) { 127110294Ssam printf("Account: "); (void) fflush(stdout); 127210294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 127310294Ssam acct[strlen(acct) - 1] = '\0'; 127410294Ssam argv[3] = acct; argc++; 127510294Ssam } 127626049Sminshall n = command("ACCT %s", argv[3]); 127726049Sminshall aflag++; 127810294Ssam } 127910294Ssam if (n != COMPLETE) { 128026497Sminshall fprintf(stdout, "Login failed.\n"); 128110294Ssam return (0); 128210294Ssam } 128326049Sminshall if (!aflag && argc == 4) { 128426049Sminshall (void) command("ACCT %s", argv[3]); 128526049Sminshall } 128610294Ssam return (1); 128710294Ssam } 128810294Ssam 128910294Ssam /* 129010294Ssam * Print working directory. 129110294Ssam */ 129210294Ssam /*VARARGS*/ 129310294Ssam pwd() 129410294Ssam { 129537224Skarels int oldverbose = verbose; 129611756Ssam 129737224Skarels /* 129837224Skarels * If we aren't verbose, this doesn't do anything! 129937224Skarels */ 130037224Skarels verbose = 1; 130137224Skarels if (command("PWD") == ERROR && code == 500) { 130237224Skarels printf("PWD command not recognized, trying XPWD\n"); 130337224Skarels (void) command("XPWD"); 130437224Skarels } 130537224Skarels verbose = oldverbose; 130610294Ssam } 130710294Ssam 130810294Ssam /* 130910294Ssam * Make a directory. 131010294Ssam */ 131110294Ssam makedir(argc, argv) 131245260Sbostic int argc; 131310294Ssam char *argv[]; 131410294Ssam { 131510294Ssam 131645260Sbostic if (argc < 2 && !another(&argc, &argv, "directory-name")) { 131726049Sminshall printf("usage: %s directory-name\n", argv[0]); 131826049Sminshall code = -1; 131910294Ssam return; 132010294Ssam } 132137224Skarels if (command("MKD %s", argv[1]) == ERROR && code == 500) { 132237224Skarels if (verbose) 132337224Skarels printf("MKD command not recognized, trying XMKD\n"); 132437224Skarels (void) command("XMKD %s", argv[1]); 132537224Skarels } 132610294Ssam } 132710294Ssam 132810294Ssam /* 132910294Ssam * Remove a directory. 133010294Ssam */ 133110294Ssam removedir(argc, argv) 133245260Sbostic int argc; 133310294Ssam char *argv[]; 133410294Ssam { 133510294Ssam 133645260Sbostic if (argc < 2 && !another(&argc, &argv, "directory-name")) { 133726049Sminshall printf("usage: %s directory-name\n", argv[0]); 133826049Sminshall code = -1; 133910294Ssam return; 134010294Ssam } 134137224Skarels if (command("RMD %s", argv[1]) == ERROR && code == 500) { 134237224Skarels if (verbose) 134337224Skarels printf("RMD command not recognized, trying XRMD\n"); 134437224Skarels (void) command("XRMD %s", argv[1]); 134537224Skarels } 134610294Ssam } 134710294Ssam 134810294Ssam /* 134910294Ssam * Send a line, verbatim, to the remote machine. 135010294Ssam */ 135110294Ssam quote(argc, argv) 135245260Sbostic int argc; 135310294Ssam char *argv[]; 135410294Ssam { 135510294Ssam 135645260Sbostic if (argc < 2 && !another(&argc, &argv, "command line to send")) { 135710294Ssam printf("usage: %s line-to-send\n", argv[0]); 135826049Sminshall code = -1; 135910294Ssam return; 136010294Ssam } 136145260Sbostic quote1("", argc, argv); 136210294Ssam } 136310294Ssam 136410294Ssam /* 136537224Skarels * Send a SITE command to the remote machine. The line 136645260Sbostic * is sent verbatim to the remote machine, except that the 136745260Sbostic * word "SITE" is added at the front. 136837224Skarels */ 136937224Skarels site(argc, argv) 137045260Sbostic int argc; 137137224Skarels char *argv[]; 137237224Skarels { 137337224Skarels 137445260Sbostic if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) { 137537224Skarels printf("usage: %s line-to-send\n", argv[0]); 137637224Skarels code = -1; 137737224Skarels return; 137837224Skarels } 137945260Sbostic quote1("SITE ", argc, argv); 138045260Sbostic } 138145260Sbostic 138245260Sbostic /* 138345260Sbostic * Turn argv[1..argc) into a space-separated string, then prepend initial text. 138445260Sbostic * Send the result as a one-line command and get response. 138545260Sbostic */ 138645260Sbostic quote1(initial, argc, argv) 138745260Sbostic char *initial; 138845260Sbostic int argc; 138945260Sbostic char **argv; 139045260Sbostic { 139145260Sbostic register int i, len; 139245260Sbostic char buf[BUFSIZ]; /* must be >= sizeof(line) */ 139345260Sbostic 139445260Sbostic (void) strcpy(buf, initial); 139545260Sbostic if (argc > 1) { 139645260Sbostic len = strlen(buf); 139745260Sbostic len += strlen(strcpy(&buf[len], argv[1])); 139845260Sbostic for (i = 2; i < argc; i++) { 139945260Sbostic buf[len++] = ' '; 140045260Sbostic len += strlen(strcpy(&buf[len], argv[i])); 140145260Sbostic } 140237224Skarels } 140337224Skarels if (command(buf) == PRELIM) { 140437224Skarels while (getreply(0) == PRELIM); 140537224Skarels } 140637224Skarels } 140737224Skarels 140837224Skarels do_chmod(argc, argv) 140945260Sbostic int argc; 141037224Skarels char *argv[]; 141137224Skarels { 141245260Sbostic 141345260Sbostic if (argc < 2 && !another(&argc, &argv, "mode")) 141445260Sbostic goto usage; 141545260Sbostic if (argc < 3 && !another(&argc, &argv, "file-name")) { 141645260Sbostic usage: 141737224Skarels printf("usage: %s mode file-name\n", argv[0]); 141837224Skarels code = -1; 141937224Skarels return; 142037224Skarels } 142145260Sbostic (void) command("SITE CHMOD %s %s", argv[1], argv[2]); 142237224Skarels } 142337224Skarels 142437224Skarels do_umask(argc, argv) 142545260Sbostic int argc; 142637224Skarels char *argv[]; 142737224Skarels { 142837224Skarels int oldverbose = verbose; 142937224Skarels 143037224Skarels verbose = 1; 143137224Skarels (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 143237224Skarels verbose = oldverbose; 143337224Skarels } 143437224Skarels 143537224Skarels idle(argc, argv) 143645260Sbostic int argc; 143737224Skarels char *argv[]; 143837224Skarels { 143937224Skarels int oldverbose = verbose; 144037224Skarels 144137224Skarels verbose = 1; 144237224Skarels (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 144337224Skarels verbose = oldverbose; 144437224Skarels } 144537224Skarels 144637224Skarels /* 144710294Ssam * Ask the other side for help. 144810294Ssam */ 144910294Ssam rmthelp(argc, argv) 145045260Sbostic int argc; 145110294Ssam char *argv[]; 145210294Ssam { 145310294Ssam int oldverbose = verbose; 145410294Ssam 145510294Ssam verbose = 1; 145610294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 145710294Ssam verbose = oldverbose; 145810294Ssam } 145910294Ssam 146010294Ssam /* 146110294Ssam * Terminate session and exit. 146210294Ssam */ 146310294Ssam /*VARARGS*/ 146410294Ssam quit() 146510294Ssam { 146610294Ssam 146718286Sralph if (connected) 146818286Sralph disconnect(); 146926049Sminshall pswitch(1); 147026049Sminshall if (connected) { 147126049Sminshall disconnect(); 147226049Sminshall } 147310294Ssam exit(0); 147410294Ssam } 147510294Ssam 147610294Ssam /* 147710294Ssam * Terminate session, but don't exit. 147810294Ssam */ 147910294Ssam disconnect() 148010294Ssam { 148110294Ssam extern FILE *cout; 148210294Ssam extern int data; 148310294Ssam 148410294Ssam if (!connected) 148510294Ssam return; 148610294Ssam (void) command("QUIT"); 148726049Sminshall if (cout) { 148826049Sminshall (void) fclose(cout); 148926049Sminshall } 149010294Ssam cout = NULL; 149110294Ssam connected = 0; 149210294Ssam data = -1; 149326049Sminshall if (!proxy) { 149426049Sminshall macnum = 0; 149526049Sminshall } 149610294Ssam } 149711353Ssam 149811650Ssam confirm(cmd, file) 149911353Ssam char *cmd, *file; 150011353Ssam { 150111353Ssam char line[BUFSIZ]; 150211353Ssam 150311353Ssam if (!interactive) 150411650Ssam return (1); 150511353Ssam printf("%s %s? ", cmd, file); 150626497Sminshall (void) fflush(stdout); 150745260Sbostic if (fgets(line, sizeof line, stdin) == NULL) 150845260Sbostic return (0); 150911650Ssam return (*line != 'n' && *line != 'N'); 151011353Ssam } 151111353Ssam 151211353Ssam fatal(msg) 151311353Ssam char *msg; 151411353Ssam { 151511353Ssam 151626497Sminshall fprintf(stderr, "ftp: %s\n", msg); 151711353Ssam exit(1); 151811353Ssam } 151911353Ssam 152011353Ssam /* 152111353Ssam * Glob a local file name specification with 152211353Ssam * the expectation of a single return value. 152311353Ssam * Can't control multiple values being expanded 152411353Ssam * from the expression, we return only the first. 152511353Ssam */ 152611353Ssam globulize(cpp) 152711353Ssam char **cpp; 152811353Ssam { 152911353Ssam char **globbed; 153011353Ssam 153111353Ssam if (!doglob) 153211353Ssam return (1); 153347024Sbostic globbed = ftpglob(*cpp); 153411353Ssam if (globerr != NULL) { 153511353Ssam printf("%s: %s\n", *cpp, globerr); 153636421Sbostic if (globbed) { 153711353Ssam blkfree(globbed); 153838132Srick free((char *)globbed); 153936421Sbostic } 154011353Ssam return (0); 154111353Ssam } 154211353Ssam if (globbed) { 154311353Ssam *cpp = *globbed++; 154411353Ssam /* don't waste too much memory */ 154536421Sbostic if (*globbed) { 154651444Srick blkfree(*globbed); 154751444Srick free((char *)*globbed); 154836421Sbostic } 154911353Ssam } 155011353Ssam return (1); 155111353Ssam } 155226049Sminshall 155326049Sminshall account(argc,argv) 155426049Sminshall int argc; 155526049Sminshall char **argv; 155626049Sminshall { 155735658Sbostic char acct[50], *getpass(), *ap; 155826049Sminshall 155926049Sminshall if (argc > 1) { 156026049Sminshall ++argv; 156126049Sminshall --argc; 156226049Sminshall (void) strncpy(acct,*argv,49); 156336268Sbostic acct[49] = '\0'; 156426049Sminshall while (argc > 1) { 156526049Sminshall --argc; 156626049Sminshall ++argv; 156726049Sminshall (void) strncat(acct,*argv, 49-strlen(acct)); 156826049Sminshall } 156926049Sminshall ap = acct; 157026049Sminshall } 157126049Sminshall else { 157235658Sbostic ap = getpass("Account:"); 157326049Sminshall } 157426049Sminshall (void) command("ACCT %s", ap); 157526049Sminshall } 157626049Sminshall 157726049Sminshall jmp_buf abortprox; 157826049Sminshall 157939252Sbostic void 158026049Sminshall proxabort() 158126049Sminshall { 158226049Sminshall extern int proxy; 158326049Sminshall 158426049Sminshall if (!proxy) { 158526049Sminshall pswitch(1); 158626049Sminshall } 158726049Sminshall if (connected) { 158826049Sminshall proxflag = 1; 158926049Sminshall } 159026049Sminshall else { 159126049Sminshall proxflag = 0; 159226049Sminshall } 159326049Sminshall pswitch(0); 159426049Sminshall longjmp(abortprox,1); 159526049Sminshall } 159626049Sminshall 159726049Sminshall doproxy(argc,argv) 159826049Sminshall int argc; 159926049Sminshall char *argv[]; 160026049Sminshall { 160139252Sbostic extern struct cmd cmdtab[]; 160239252Sbostic extern jmp_buf abortprox; 160326049Sminshall register struct cmd *c; 160426049Sminshall struct cmd *getcmd(); 160539252Sbostic sig_t oldintr; 160639252Sbostic void proxabort(); 160726049Sminshall 160845260Sbostic if (argc < 2 && !another(&argc, &argv, "command")) { 160945260Sbostic printf("usage: %s command\n", argv[0]); 161026049Sminshall code = -1; 161126049Sminshall return; 161226049Sminshall } 161326049Sminshall c = getcmd(argv[1]); 161426049Sminshall if (c == (struct cmd *) -1) { 161526049Sminshall printf("?Ambiguous command\n"); 161626497Sminshall (void) fflush(stdout); 161726049Sminshall code = -1; 161826049Sminshall return; 161926049Sminshall } 162026049Sminshall if (c == 0) { 162126049Sminshall printf("?Invalid command\n"); 162226497Sminshall (void) fflush(stdout); 162326049Sminshall code = -1; 162426049Sminshall return; 162526049Sminshall } 162626049Sminshall if (!c->c_proxy) { 162726049Sminshall printf("?Invalid proxy command\n"); 162826497Sminshall (void) fflush(stdout); 162926049Sminshall code = -1; 163026049Sminshall return; 163126049Sminshall } 163226049Sminshall if (setjmp(abortprox)) { 163326049Sminshall code = -1; 163426049Sminshall return; 163526049Sminshall } 163626049Sminshall oldintr = signal(SIGINT, proxabort); 163726049Sminshall pswitch(1); 163826049Sminshall if (c->c_conn && !connected) { 163926049Sminshall printf("Not connected\n"); 164026497Sminshall (void) fflush(stdout); 164126049Sminshall pswitch(0); 164226049Sminshall (void) signal(SIGINT, oldintr); 164326049Sminshall code = -1; 164426049Sminshall return; 164526049Sminshall } 164626049Sminshall (*c->c_handler)(argc-1, argv+1); 164726049Sminshall if (connected) { 164826049Sminshall proxflag = 1; 164926049Sminshall } 165026049Sminshall else { 165126049Sminshall proxflag = 0; 165226049Sminshall } 165326049Sminshall pswitch(0); 165426049Sminshall (void) signal(SIGINT, oldintr); 165526049Sminshall } 165626049Sminshall 165726049Sminshall setcase() 165826049Sminshall { 165926049Sminshall mcase = !mcase; 166026049Sminshall printf("Case mapping %s.\n", onoff(mcase)); 166126049Sminshall code = mcase; 166226049Sminshall } 166326049Sminshall 166426049Sminshall setcr() 166526049Sminshall { 166626049Sminshall crflag = !crflag; 166726049Sminshall printf("Carriage Return stripping %s.\n", onoff(crflag)); 166826049Sminshall code = crflag; 166926049Sminshall } 167026049Sminshall 167126049Sminshall setntrans(argc,argv) 167226049Sminshall int argc; 167326049Sminshall char *argv[]; 167426049Sminshall { 167526049Sminshall if (argc == 1) { 167626049Sminshall ntflag = 0; 167726049Sminshall printf("Ntrans off.\n"); 167826049Sminshall code = ntflag; 167926049Sminshall return; 168026049Sminshall } 168126049Sminshall ntflag++; 168226049Sminshall code = ntflag; 168326049Sminshall (void) strncpy(ntin, argv[1], 16); 168426049Sminshall ntin[16] = '\0'; 168526049Sminshall if (argc == 2) { 168626049Sminshall ntout[0] = '\0'; 168726049Sminshall return; 168826049Sminshall } 168926049Sminshall (void) strncpy(ntout, argv[2], 16); 169026049Sminshall ntout[16] = '\0'; 169126049Sminshall } 169226049Sminshall 169326049Sminshall char * 169426049Sminshall dotrans(name) 169526049Sminshall char *name; 169626049Sminshall { 169726049Sminshall static char new[MAXPATHLEN]; 169826049Sminshall char *cp1, *cp2 = new; 169926049Sminshall register int i, ostop, found; 170026049Sminshall 170126049Sminshall for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++); 170226049Sminshall for (cp1 = name; *cp1; cp1++) { 170326049Sminshall found = 0; 170426049Sminshall for (i = 0; *(ntin + i) && i < 16; i++) { 170526049Sminshall if (*cp1 == *(ntin + i)) { 170626049Sminshall found++; 170726049Sminshall if (i < ostop) { 170826049Sminshall *cp2++ = *(ntout + i); 170926049Sminshall } 171026049Sminshall break; 171126049Sminshall } 171226049Sminshall } 171326049Sminshall if (!found) { 171426049Sminshall *cp2++ = *cp1; 171526049Sminshall } 171626049Sminshall } 171726049Sminshall *cp2 = '\0'; 171826049Sminshall return(new); 171926049Sminshall } 172026049Sminshall 172126049Sminshall setnmap(argc, argv) 172226049Sminshall int argc; 172326049Sminshall char *argv[]; 172426049Sminshall { 172526049Sminshall char *cp; 172626049Sminshall 172726049Sminshall if (argc == 1) { 172826049Sminshall mapflag = 0; 172926049Sminshall printf("Nmap off.\n"); 173026049Sminshall code = mapflag; 173126049Sminshall return; 173226049Sminshall } 173345260Sbostic if (argc < 3 && !another(&argc, &argv, "mapout")) { 173426049Sminshall printf("Usage: %s [mapin mapout]\n",argv[0]); 173526049Sminshall code = -1; 173626049Sminshall return; 173726049Sminshall } 173826049Sminshall mapflag = 1; 173926049Sminshall code = 1; 174026049Sminshall cp = index(altarg, ' '); 174126049Sminshall if (proxy) { 174226049Sminshall while(*++cp == ' '); 174326049Sminshall altarg = cp; 174426049Sminshall cp = index(altarg, ' '); 174526049Sminshall } 174626049Sminshall *cp = '\0'; 174726049Sminshall (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 174826049Sminshall while (*++cp == ' '); 174926049Sminshall (void) strncpy(mapout, cp, MAXPATHLEN - 1); 175026049Sminshall } 175126049Sminshall 175226049Sminshall char * 175326049Sminshall domap(name) 175426049Sminshall char *name; 175526049Sminshall { 175626049Sminshall static char new[MAXPATHLEN]; 175726049Sminshall register char *cp1 = name, *cp2 = mapin; 175826049Sminshall char *tp[9], *te[9]; 175936689Scsvsj int i, toks[9], toknum = 0, match = 1; 176026049Sminshall 176126049Sminshall for (i=0; i < 9; ++i) { 176226049Sminshall toks[i] = 0; 176326049Sminshall } 176426049Sminshall while (match && *cp1 && *cp2) { 176526049Sminshall switch (*cp2) { 176626049Sminshall case '\\': 176726049Sminshall if (*++cp2 != *cp1) { 176826049Sminshall match = 0; 176926049Sminshall } 177026049Sminshall break; 177126049Sminshall case '$': 177226049Sminshall if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 177326049Sminshall if (*cp1 != *(++cp2+1)) { 177426049Sminshall toks[toknum = *cp2 - '1']++; 177526049Sminshall tp[toknum] = cp1; 177626049Sminshall while (*++cp1 && *(cp2+1) 177726049Sminshall != *cp1); 177826049Sminshall te[toknum] = cp1; 177926049Sminshall } 178026049Sminshall cp2++; 178126049Sminshall break; 178226049Sminshall } 178336935Skarels /* FALLTHROUGH */ 178426049Sminshall default: 178526049Sminshall if (*cp2 != *cp1) { 178626049Sminshall match = 0; 178726049Sminshall } 178826049Sminshall break; 178926049Sminshall } 179036689Scsvsj if (match && *cp1) { 179126049Sminshall cp1++; 179226049Sminshall } 179336689Scsvsj if (match && *cp2) { 179426049Sminshall cp2++; 179526049Sminshall } 179626049Sminshall } 179736689Scsvsj if (!match && *cp1) /* last token mismatch */ 179836689Scsvsj { 179936689Scsvsj toks[toknum] = 0; 180036689Scsvsj } 180126049Sminshall cp1 = new; 180226049Sminshall *cp1 = '\0'; 180326049Sminshall cp2 = mapout; 180426049Sminshall while (*cp2) { 180526049Sminshall match = 0; 180626049Sminshall switch (*cp2) { 180726049Sminshall case '\\': 180826049Sminshall if (*(cp2 + 1)) { 180926049Sminshall *cp1++ = *++cp2; 181026049Sminshall } 181126049Sminshall break; 181226049Sminshall case '[': 181326049Sminshall LOOP: 181426049Sminshall if (*++cp2 == '$' && isdigit(*(cp2+1))) { 181526049Sminshall if (*++cp2 == '0') { 181626049Sminshall char *cp3 = name; 181726049Sminshall 181826049Sminshall while (*cp3) { 181926049Sminshall *cp1++ = *cp3++; 182026049Sminshall } 182126049Sminshall match = 1; 182226049Sminshall } 182326049Sminshall else if (toks[toknum = *cp2 - '1']) { 182426049Sminshall char *cp3 = tp[toknum]; 182526049Sminshall 182626049Sminshall while (cp3 != te[toknum]) { 182726049Sminshall *cp1++ = *cp3++; 182826049Sminshall } 182926049Sminshall match = 1; 183026049Sminshall } 183126049Sminshall } 183226049Sminshall else { 183326049Sminshall while (*cp2 && *cp2 != ',' && 183426049Sminshall *cp2 != ']') { 183526049Sminshall if (*cp2 == '\\') { 183626049Sminshall cp2++; 183726049Sminshall } 183826049Sminshall else if (*cp2 == '$' && 183926049Sminshall isdigit(*(cp2+1))) { 184026049Sminshall if (*++cp2 == '0') { 184126049Sminshall char *cp3 = name; 184226049Sminshall 184326049Sminshall while (*cp3) { 184426049Sminshall *cp1++ = *cp3++; 184526049Sminshall } 184626049Sminshall } 184726049Sminshall else if (toks[toknum = 184826049Sminshall *cp2 - '1']) { 184926049Sminshall char *cp3=tp[toknum]; 185026049Sminshall 185126049Sminshall while (cp3 != 185226049Sminshall te[toknum]) { 185326049Sminshall *cp1++ = *cp3++; 185426049Sminshall } 185526049Sminshall } 185626049Sminshall } 185726049Sminshall else if (*cp2) { 185826049Sminshall *cp1++ = *cp2++; 185926049Sminshall } 186026049Sminshall } 186126049Sminshall if (!*cp2) { 186226049Sminshall printf("nmap: unbalanced brackets\n"); 186326049Sminshall return(name); 186426049Sminshall } 186526049Sminshall match = 1; 186626049Sminshall cp2--; 186726049Sminshall } 186826049Sminshall if (match) { 186926049Sminshall while (*++cp2 && *cp2 != ']') { 187026049Sminshall if (*cp2 == '\\' && *(cp2 + 1)) { 187126049Sminshall cp2++; 187226049Sminshall } 187326049Sminshall } 187426049Sminshall if (!*cp2) { 187526049Sminshall printf("nmap: unbalanced brackets\n"); 187626049Sminshall return(name); 187726049Sminshall } 187826049Sminshall break; 187926049Sminshall } 188026049Sminshall switch (*++cp2) { 188126049Sminshall case ',': 188226049Sminshall goto LOOP; 188326049Sminshall case ']': 188426049Sminshall break; 188526049Sminshall default: 188626049Sminshall cp2--; 188726049Sminshall goto LOOP; 188826049Sminshall } 188926049Sminshall break; 189026049Sminshall case '$': 189126049Sminshall if (isdigit(*(cp2 + 1))) { 189226049Sminshall if (*++cp2 == '0') { 189326049Sminshall char *cp3 = name; 189426049Sminshall 189526049Sminshall while (*cp3) { 189626049Sminshall *cp1++ = *cp3++; 189726049Sminshall } 189826049Sminshall } 189926049Sminshall else if (toks[toknum = *cp2 - '1']) { 190026049Sminshall char *cp3 = tp[toknum]; 190126049Sminshall 190226049Sminshall while (cp3 != te[toknum]) { 190326049Sminshall *cp1++ = *cp3++; 190426049Sminshall } 190526049Sminshall } 190626049Sminshall break; 190726049Sminshall } 190826049Sminshall /* intentional drop through */ 190926049Sminshall default: 191026049Sminshall *cp1++ = *cp2; 191126049Sminshall break; 191226049Sminshall } 191326049Sminshall cp2++; 191426049Sminshall } 191526049Sminshall *cp1 = '\0'; 191626049Sminshall if (!*new) { 191726049Sminshall return(name); 191826049Sminshall } 191926049Sminshall return(new); 192026049Sminshall } 192126049Sminshall 192226049Sminshall setsunique() 192326049Sminshall { 192426049Sminshall sunique = !sunique; 192526049Sminshall printf("Store unique %s.\n", onoff(sunique)); 192626049Sminshall code = sunique; 192726049Sminshall } 192826049Sminshall 192926049Sminshall setrunique() 193026049Sminshall { 193126049Sminshall runique = !runique; 193226049Sminshall printf("Receive unique %s.\n", onoff(runique)); 193326049Sminshall code = runique; 193426049Sminshall } 193526049Sminshall 193626049Sminshall /* change directory to perent directory */ 193726049Sminshall cdup() 193826049Sminshall { 193937224Skarels if (command("CDUP") == ERROR && code == 500) { 194037224Skarels if (verbose) 194137224Skarels printf("CDUP command not recognized, trying XCUP\n"); 194237224Skarels (void) command("XCUP"); 194337224Skarels } 194426049Sminshall } 194526049Sminshall 194637224Skarels /* restart transfer at specific point */ 194737224Skarels restart(argc, argv) 194837224Skarels int argc; 194937224Skarels char *argv[]; 195037224Skarels { 195137224Skarels extern long atol(); 195237224Skarels if (argc != 2) 195337224Skarels printf("restart: offset not specified\n"); 195437224Skarels else { 195537224Skarels restart_point = atol(argv[1]); 195637224Skarels printf("restarting at %ld. %s\n", restart_point, 195737224Skarels "execute get, put or append to initiate transfer"); 195837224Skarels } 195937224Skarels } 196036935Skarels 196136935Skarels /* show remote system type */ 196236935Skarels syst() 196336935Skarels { 196436935Skarels (void) command("SYST"); 196536935Skarels } 196636935Skarels 196726049Sminshall macdef(argc, argv) 196826049Sminshall int argc; 196926049Sminshall char *argv[]; 197026049Sminshall { 197126049Sminshall char *tmp; 197226049Sminshall int c; 197326049Sminshall 197426049Sminshall if (macnum == 16) { 197526049Sminshall printf("Limit of 16 macros have already been defined\n"); 197626049Sminshall code = -1; 197726049Sminshall return; 197826049Sminshall } 197945260Sbostic if (argc < 2 && !another(&argc, &argv, "macro name")) { 198026049Sminshall printf("Usage: %s macro_name\n",argv[0]); 198126049Sminshall code = -1; 198226049Sminshall return; 198326049Sminshall } 198426049Sminshall if (interactive) { 198526049Sminshall printf("Enter macro line by line, terminating it with a null line\n"); 198626049Sminshall } 198726497Sminshall (void) strncpy(macros[macnum].mac_name, argv[1], 8); 198826049Sminshall if (macnum == 0) { 198926049Sminshall macros[macnum].mac_start = macbuf; 199026049Sminshall } 199126049Sminshall else { 199226049Sminshall macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 199326049Sminshall } 199426049Sminshall tmp = macros[macnum].mac_start; 199526049Sminshall while (tmp != macbuf+4096) { 199626049Sminshall if ((c = getchar()) == EOF) { 199726049Sminshall printf("macdef:end of file encountered\n"); 199826049Sminshall code = -1; 199926049Sminshall return; 200026049Sminshall } 200126049Sminshall if ((*tmp = c) == '\n') { 200226049Sminshall if (tmp == macros[macnum].mac_start) { 200326049Sminshall macros[macnum++].mac_end = tmp; 200426049Sminshall code = 0; 200526049Sminshall return; 200626049Sminshall } 200726049Sminshall if (*(tmp-1) == '\0') { 200826049Sminshall macros[macnum++].mac_end = tmp - 1; 200926049Sminshall code = 0; 201026049Sminshall return; 201126049Sminshall } 201226049Sminshall *tmp = '\0'; 201326049Sminshall } 201426049Sminshall tmp++; 201526049Sminshall } 201626049Sminshall while (1) { 201736935Skarels while ((c = getchar()) != '\n' && c != EOF) 201836935Skarels /* LOOP */; 201926049Sminshall if (c == EOF || getchar() == '\n') { 202026049Sminshall printf("Macro not defined - 4k buffer exceeded\n"); 202126049Sminshall code = -1; 202226049Sminshall return; 202326049Sminshall } 202426049Sminshall } 202526049Sminshall } 202636935Skarels 202736935Skarels /* 202836935Skarels * get size of file on remote machine 202936935Skarels */ 203036935Skarels sizecmd(argc, argv) 203145260Sbostic int argc; 203236935Skarels char *argv[]; 203336935Skarels { 203436935Skarels 203545260Sbostic if (argc < 2 && !another(&argc, &argv, "filename")) { 203645260Sbostic printf("usage: %s filename\n", argv[0]); 203736935Skarels code = -1; 203836935Skarels return; 203936935Skarels } 204036935Skarels (void) command("SIZE %s", argv[1]); 204136935Skarels } 204236935Skarels 204336935Skarels /* 204436935Skarels * get last modification time of file on remote machine 204536935Skarels */ 204636935Skarels modtime(argc, argv) 204745260Sbostic int argc; 204836935Skarels char *argv[]; 204936935Skarels { 205036935Skarels int overbose; 205136935Skarels 205245260Sbostic if (argc < 2 && !another(&argc, &argv, "filename")) { 205345260Sbostic printf("usage: %s filename\n", argv[0]); 205436935Skarels code = -1; 205536935Skarels return; 205636935Skarels } 205736940Skarels overbose = verbose; 205836940Skarels if (debug == 0) 205936940Skarels verbose = -1; 206036935Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 206136935Skarels int yy, mo, day, hour, min, sec; 206236935Skarels sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 206336935Skarels &day, &hour, &min, &sec); 206436935Skarels /* might want to print this in local time */ 206536935Skarels printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 206636935Skarels mo, day, yy, hour, min, sec); 206736935Skarels } else 206838132Srick printf("%s\n", reply_string); 206936935Skarels verbose = overbose; 207036935Skarels } 207136935Skarels 207236935Skarels /* 207337224Skarels * show status on reomte machine 207436935Skarels */ 207536935Skarels rmtstatus(argc, argv) 207645260Sbostic int argc; 207736935Skarels char *argv[]; 207836935Skarels { 207936935Skarels (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 208036935Skarels } 208137224Skarels 208237224Skarels /* 208337224Skarels * get file if modtime is more recent than current file 208437224Skarels */ 208537224Skarels newer(argc, argv) 208645260Sbostic int argc; 208737224Skarels char *argv[]; 208837224Skarels { 208937224Skarels if (getit(argc, argv, -1, "w")) 209037224Skarels printf("Local file \"%s\" is newer than remote file \"%s\"\n", 209154742Sandrew argv[2], argv[1]); 209237224Skarels } 2093