121737Sdist /* 236942Skarels * Copyright (c) 1985, 1989 Regents of the University of California. 333737Sbostic * All rights reserved. 433737Sbostic * 533737Sbostic * Redistribution and use in source and binary forms are permitted 634901Sbostic * provided that the above copyright notice and this paragraph are 734901Sbostic * duplicated in all such forms and that any documentation, 834901Sbostic * advertising materials, and other materials related to such 934901Sbostic * distribution and use acknowledge that the software was developed 1034901Sbostic * by the University of California, Berkeley. The name of the 1134901Sbostic * University may not be used to endorse or promote products derived 1234901Sbostic * from this software without specific prior written permission. 1334901Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434901Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1536935Skarels * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621737Sdist */ 1721737Sdist 1810294Ssam #ifndef lint 19*38132Srick static char sccsid[] = "@(#)cmds.c 5.20 (Berkeley) 05/26/89"; 2033737Sbostic #endif /* not lint */ 2110294Ssam 2210294Ssam /* 2310294Ssam * FTP User Program -- Command Routines. 2410294Ssam */ 2536940Skarels #include <sys/param.h> 2636940Skarels #include <sys/wait.h> 2736940Skarels #include <sys/stat.h> 2810294Ssam #include <sys/socket.h> 2910294Ssam 3012396Ssam #include <arpa/ftp.h> 3112396Ssam 3210294Ssam #include <signal.h> 3310294Ssam #include <stdio.h> 3410294Ssam #include <errno.h> 3510294Ssam #include <netdb.h> 3626049Sminshall #include <ctype.h> 3736935Skarels #include <time.h> 38*38132Srick #include <netinet/in.h> 3910294Ssam 4036940Skarels #include "ftp_var.h" 4137458Skarels #include "pathnames.h" 4210294Ssam 4311353Ssam extern char *globerr; 4411353Ssam extern char **glob(); 4511756Ssam extern char *home; 4611756Ssam extern char *remglob(); 4711756Ssam extern char *getenv(); 4811756Ssam extern char *index(); 4911756Ssam extern char *rindex(); 5037224Skarels extern off_t restart_point; 5136935Skarels extern char reply_string[]; 5236935Skarels 5326049Sminshall char *mname; 5426049Sminshall jmp_buf jabort; 5526049Sminshall char *dotrans(), *domap(); 5610294Ssam 5710294Ssam /* 5810294Ssam * Connect to peer server and 5910294Ssam * auto-login, if possible. 6010294Ssam */ 6110294Ssam setpeer(argc, argv) 6210294Ssam int argc; 6310294Ssam char *argv[]; 6410294Ssam { 6525903Skarels char *host, *hookup(); 66*38132Srick short port; 6710294Ssam 6810294Ssam if (connected) { 6926049Sminshall printf("Already connected to %s, use close first.\n", 7010294Ssam hostname); 7126049Sminshall code = -1; 7210294Ssam return; 7310294Ssam } 7410294Ssam if (argc < 2) { 7526497Sminshall (void) strcat(line, " "); 7610294Ssam printf("(to) "); 7726497Sminshall (void) gets(&line[strlen(line)]); 7810294Ssam makeargv(); 7910294Ssam argc = margc; 8010294Ssam argv = margv; 8110294Ssam } 8210294Ssam if (argc > 3) { 8310294Ssam printf("usage: %s host-name [port]\n", argv[0]); 8426049Sminshall code = -1; 8510294Ssam return; 8610294Ssam } 8710294Ssam port = sp->s_port; 8810294Ssam if (argc > 2) { 8911218Ssam port = atoi(argv[2]); 9010294Ssam if (port <= 0) { 9111218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 9211218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 9326049Sminshall code = -1; 9410294Ssam return; 9510294Ssam } 9610294Ssam port = htons(port); 9710294Ssam } 9810294Ssam host = hookup(argv[1], port); 9910294Ssam if (host) { 10037228Skarels int overbose; 10137228Skarels 10210294Ssam connected = 1; 10338032Skarels /* 10438032Skarels * Set up defaults for FTP. 10538032Skarels */ 10638032Skarels (void) strcpy(typename, "ascii"), type = TYPE_A; 10738032Skarels curtype = TYPE_A; 10838032Skarels (void) strcpy(formname, "non-print"), form = FORM_N; 10938032Skarels (void) strcpy(modename, "stream"), mode = MODE_S; 11038032Skarels (void) strcpy(structname, "file"), stru = STRU_F; 11138032Skarels (void) strcpy(bytename, "8"), bytesize = 8; 11237228Skarels if (autologin) 11337228Skarels (void) login(argv[1]); 11436940Skarels 11536935Skarels #if defined(unix) && NBBY == 8 11636935Skarels /* 11736935Skarels * this ifdef is to keep someone form "porting" this to an incompatible 11836935Skarels * system and not checking this out. This way they have to think about it. 11936935Skarels */ 12037228Skarels overbose = verbose; 12137228Skarels if (debug == 0) 12237228Skarels verbose = -1; 12337228Skarels if (command("SYST") == COMPLETE && overbose) { 12437228Skarels register char *cp, c; 12537228Skarels cp = index(reply_string+4, ' '); 12637228Skarels if (cp == NULL) 12737228Skarels cp = index(reply_string+4, '\r'); 12837228Skarels if (cp) { 12937228Skarels if (cp[-1] == '.') 13037228Skarels cp--; 13137228Skarels c = *cp; 13237228Skarels *cp = '\0'; 13337228Skarels } 13436935Skarels 13537228Skarels printf("Remote system type is %s.\n", 13637228Skarels reply_string+4); 13737228Skarels if (cp) 13837228Skarels *cp = c; 13937228Skarels } 14037228Skarels if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { 14138032Skarels if (proxy) 14238032Skarels unix_proxy = 1; 14338032Skarels else 14438032Skarels unix_server = 1; 14538032Skarels /* 14638032Skarels * Set type to 0 (not specified by user), 14738032Skarels * meaning binary by default, but don't bother 14838032Skarels * telling server. We can use binary 14938032Skarels * for text files unless changed by the user. 15038032Skarels */ 15138032Skarels type = 0; 15238032Skarels (void) strcpy(typename, "binary"); 15337228Skarels if (overbose) 15437228Skarels printf("Using %s mode to transfer files.\n", 15537228Skarels typename); 15638032Skarels } else { 15738032Skarels if (proxy) 15838032Skarels unix_proxy = 0; 15938032Skarels else 16038032Skarels unix_server = 0; 16138032Skarels if (overbose && 16238032Skarels !strncmp(reply_string, "215 TOPS20", 10)) 16338032Skarels printf( 16436940Skarels "Remember to set tenex mode when transfering binary files from this machine.\n"); 16537228Skarels } 16637228Skarels verbose = overbose; 16736935Skarels #endif /* unix */ 16810294Ssam } 16910294Ssam } 17010294Ssam 17110294Ssam struct types { 17210294Ssam char *t_name; 17310294Ssam char *t_mode; 17410294Ssam int t_type; 17511218Ssam char *t_arg; 17610294Ssam } types[] = { 17711218Ssam { "ascii", "A", TYPE_A, 0 }, 17811218Ssam { "binary", "I", TYPE_I, 0 }, 17911218Ssam { "image", "I", TYPE_I, 0 }, 18011218Ssam { "ebcdic", "E", TYPE_E, 0 }, 18111218Ssam { "tenex", "L", TYPE_L, bytename }, 18210294Ssam 0 18310294Ssam }; 18410294Ssam 18510294Ssam /* 18610294Ssam * Set transfer type. 18710294Ssam */ 18810294Ssam settype(argc, argv) 18910294Ssam char *argv[]; 19010294Ssam { 19110294Ssam register struct types *p; 19211218Ssam int comret; 19310294Ssam 19410294Ssam if (argc > 2) { 19510294Ssam char *sep; 19610294Ssam 19710294Ssam printf("usage: %s [", argv[0]); 19810294Ssam sep = " "; 19910294Ssam for (p = types; p->t_name; p++) { 20010294Ssam printf("%s%s", sep, p->t_name); 20138032Skarels sep = " | "; 20210294Ssam } 20310294Ssam printf(" ]\n"); 20426049Sminshall code = -1; 20510294Ssam return; 20610294Ssam } 20710294Ssam if (argc < 2) { 20810294Ssam printf("Using %s mode to transfer files.\n", typename); 20926049Sminshall code = 0; 21010294Ssam return; 21110294Ssam } 21210294Ssam for (p = types; p->t_name; p++) 21310294Ssam if (strcmp(argv[1], p->t_name) == 0) 21410294Ssam break; 21510294Ssam if (p->t_name == 0) { 21610294Ssam printf("%s: unknown mode\n", argv[1]); 21726049Sminshall code = -1; 21810294Ssam return; 21910294Ssam } 22011218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 22111218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 22211218Ssam else 22311218Ssam comret = command("TYPE %s", p->t_mode); 22411218Ssam if (comret == COMPLETE) { 22526497Sminshall (void) strcpy(typename, p->t_name); 22638032Skarels curtype = type = p->t_type; 22710294Ssam } 22810294Ssam } 22910294Ssam 23010294Ssam /* 23138032Skarels * Internal form of settype; changes current type in use with server 23238032Skarels * without changing our notion of the type for data transfers. 23338032Skarels * Used to change to and from ascii for listings. 23438032Skarels */ 23538032Skarels changetype(newtype, show) 23638032Skarels int newtype, show; 23738032Skarels { 23838032Skarels register struct types *p; 23938032Skarels int comret, oldverbose = verbose; 24038032Skarels 24138032Skarels if (newtype == 0) 24238032Skarels newtype = TYPE_I; 24338032Skarels if (newtype == curtype) 24438032Skarels return; 24538032Skarels if (debug == 0 && show == 0) 24638032Skarels verbose = 0; 24738032Skarels for (p = types; p->t_name; p++) 24838032Skarels if (newtype == p->t_type) 24938032Skarels break; 25038032Skarels if (p->t_name == 0) { 25138032Skarels printf("ftp: internal error: unknown type %d\n", newtype); 25238032Skarels return; 25338032Skarels } 25438032Skarels if (newtype == TYPE_L && bytename[0] != '\0') 25538032Skarels comret = command("TYPE %s %s", p->t_mode, bytename); 25638032Skarels else 25738032Skarels comret = command("TYPE %s", p->t_mode); 25838032Skarels if (comret == COMPLETE) 25938032Skarels curtype = newtype; 26038032Skarels verbose = oldverbose; 26138032Skarels } 26238032Skarels 263*38132Srick char *stype[] = { 264*38132Srick "type", 265*38132Srick "", 266*38132Srick 0 267*38132Srick }; 268*38132Srick 26938032Skarels /* 27010294Ssam * Set binary transfer type. 27110294Ssam */ 27210294Ssam /*VARARGS*/ 27310294Ssam setbinary() 27410294Ssam { 275*38132Srick stype[1] = "binary"; 276*38132Srick settype(2, stype); 27710294Ssam } 27810294Ssam 27910294Ssam /* 28010294Ssam * Set ascii transfer type. 28110294Ssam */ 28210294Ssam /*VARARGS*/ 28310294Ssam setascii() 28410294Ssam { 285*38132Srick stype[1] = "ascii"; 286*38132Srick settype(2, stype); 28710294Ssam } 28810294Ssam 28910294Ssam /* 29010294Ssam * Set tenex transfer type. 29110294Ssam */ 29210294Ssam /*VARARGS*/ 29310294Ssam settenex() 29410294Ssam { 295*38132Srick stype[1] = "tenex"; 296*38132Srick settype(2, stype); 29710294Ssam } 29810294Ssam 29910294Ssam /* 30010294Ssam * Set ebcdic transfer type. 30110294Ssam */ 30210294Ssam /*VARARGS*/ 30310294Ssam setebcdic() 30410294Ssam { 305*38132Srick stype[1] = "ebcdic"; 306*38132Srick settype(2, stype); 30710294Ssam } 30810294Ssam 30910294Ssam /* 31010294Ssam * Set file transfer mode. 31110294Ssam */ 31226497Sminshall /*ARGSUSED*/ 31310294Ssam setmode(argc, argv) 31410294Ssam char *argv[]; 31510294Ssam { 31610294Ssam 31710294Ssam printf("We only support %s mode, sorry.\n", modename); 31826049Sminshall code = -1; 31910294Ssam } 32010294Ssam 32110294Ssam /* 32210294Ssam * Set file transfer format. 32310294Ssam */ 32426497Sminshall /*ARGSUSED*/ 32510294Ssam setform(argc, argv) 32610294Ssam char *argv[]; 32710294Ssam { 32810294Ssam 32910294Ssam printf("We only support %s format, sorry.\n", formname); 33026049Sminshall code = -1; 33110294Ssam } 33210294Ssam 33310294Ssam /* 33410294Ssam * Set file transfer structure. 33510294Ssam */ 33626497Sminshall /*ARGSUSED*/ 33710294Ssam setstruct(argc, argv) 33810294Ssam char *argv[]; 33910294Ssam { 34010294Ssam 34110294Ssam printf("We only support %s structure, sorry.\n", structname); 34226049Sminshall code = -1; 34310294Ssam } 34410294Ssam 34518286Sralph /* 34618286Sralph * Send a single file. 34718286Sralph */ 34810294Ssam put(argc, argv) 34911756Ssam int argc; 35010294Ssam char *argv[]; 35110294Ssam { 35211650Ssam char *cmd; 35326049Sminshall int loc = 0; 35437225Skarels char *oldargv1, *oldargv2; 35511650Ssam 35626049Sminshall if (argc == 2) { 35726049Sminshall argc++; 35826049Sminshall argv[2] = argv[1]; 35926049Sminshall loc++; 36026049Sminshall } 36110294Ssam if (argc < 2) { 36226497Sminshall (void) strcat(line, " "); 36310294Ssam printf("(local-file) "); 36426497Sminshall (void) gets(&line[strlen(line)]); 36510294Ssam makeargv(); 36610294Ssam argc = margc; 36710294Ssam argv = margv; 36810294Ssam } 36910294Ssam if (argc < 2) { 37010294Ssam usage: 37126049Sminshall printf("usage:%s local-file remote-file\n", argv[0]); 37226049Sminshall code = -1; 37310294Ssam return; 37410294Ssam } 37510294Ssam if (argc < 3) { 37626497Sminshall (void) strcat(line, " "); 37710294Ssam printf("(remote-file) "); 37826497Sminshall (void) gets(&line[strlen(line)]); 37910294Ssam makeargv(); 38010294Ssam argc = margc; 38110294Ssam argv = margv; 38210294Ssam } 38310294Ssam if (argc < 3) 38410294Ssam goto usage; 38525908Smckusick oldargv1 = argv[1]; 38637225Skarels oldargv2 = argv[2]; 38726049Sminshall if (!globulize(&argv[1])) { 38826049Sminshall code = -1; 38911353Ssam return; 39026049Sminshall } 39125908Smckusick /* 39225908Smckusick * If "globulize" modifies argv[1], and argv[2] is a copy of 39325908Smckusick * the old argv[1], make it a copy of the new argv[1]. 39425908Smckusick */ 39526049Sminshall if (argv[1] != oldargv1 && argv[2] == oldargv1) { 39625908Smckusick argv[2] = argv[1]; 39726049Sminshall } 39826049Sminshall cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); 39926049Sminshall if (loc && ntflag) { 40026049Sminshall argv[2] = dotrans(argv[2]); 40126049Sminshall } 40226049Sminshall if (loc && mapflag) { 40326049Sminshall argv[2] = domap(argv[2]); 40426049Sminshall } 40537225Skarels sendrequest(cmd, argv[1], argv[2], 40637225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 40710294Ssam } 40810294Ssam 40910294Ssam /* 41011756Ssam * Send multiple files. 41110294Ssam */ 41211353Ssam mput(argc, argv) 41311353Ssam char *argv[]; 41411353Ssam { 41513212Ssam register int i; 416*38132Srick int ointer; 417*38132Srick sig_t (*oldintr)(), mabort(); 41826049Sminshall extern jmp_buf jabort; 41926049Sminshall char *tp; 42011353Ssam 42111650Ssam if (argc < 2) { 42226497Sminshall (void) strcat(line, " "); 42311650Ssam printf("(local-files) "); 42426497Sminshall (void) gets(&line[strlen(line)]); 42511650Ssam makeargv(); 42611650Ssam argc = margc; 42711650Ssam argv = margv; 42811353Ssam } 42911353Ssam if (argc < 2) { 43026049Sminshall printf("usage:%s local-files\n", argv[0]); 43126049Sminshall code = -1; 43211353Ssam return; 43311353Ssam } 43426049Sminshall mname = argv[0]; 43526049Sminshall mflag = 1; 43626049Sminshall oldintr = signal(SIGINT, mabort); 43726049Sminshall (void) setjmp(jabort); 43826049Sminshall if (proxy) { 43926049Sminshall char *cp, *tp2, tmpbuf[MAXPATHLEN]; 44026049Sminshall 44126497Sminshall while ((cp = remglob(argv,0)) != NULL) { 44226049Sminshall if (*cp == 0) { 44326049Sminshall mflag = 0; 44426049Sminshall continue; 44526049Sminshall } 44626049Sminshall if (mflag && confirm(argv[0], cp)) { 44726049Sminshall tp = cp; 44826049Sminshall if (mcase) { 44926049Sminshall while (*tp && !islower(*tp)) { 45026049Sminshall tp++; 45126049Sminshall } 45226049Sminshall if (!*tp) { 45326049Sminshall tp = cp; 45426049Sminshall tp2 = tmpbuf; 45526049Sminshall while ((*tp2 = *tp) != NULL) { 45626049Sminshall if (isupper(*tp2)) { 45726049Sminshall *tp2 = 'a' + *tp2 - 'A'; 45826049Sminshall } 45926049Sminshall tp++; 46026049Sminshall tp2++; 46126049Sminshall } 46226049Sminshall } 46326049Sminshall tp = tmpbuf; 46426049Sminshall } 46526049Sminshall if (ntflag) { 46626049Sminshall tp = dotrans(tp); 46726049Sminshall } 46826049Sminshall if (mapflag) { 46926049Sminshall tp = domap(tp); 47026049Sminshall } 47137225Skarels sendrequest((sunique) ? "STOU" : "STOR", 47237225Skarels cp, tp, cp != tp || !interactive); 47326049Sminshall if (!mflag && fromatty) { 47426049Sminshall ointer = interactive; 47526049Sminshall interactive = 1; 47626049Sminshall if (confirm("Continue with","mput")) { 47726049Sminshall mflag++; 47826049Sminshall } 47926049Sminshall interactive = ointer; 48026049Sminshall } 48126049Sminshall } 48226049Sminshall } 48326049Sminshall (void) signal(SIGINT, oldintr); 48426049Sminshall mflag = 0; 48526049Sminshall return; 48626049Sminshall } 48713212Ssam for (i = 1; i < argc; i++) { 48813212Ssam register char **cpp, **gargs; 48913212Ssam 49013212Ssam if (!doglob) { 49126049Sminshall if (mflag && confirm(argv[0], argv[i])) { 49226049Sminshall tp = (ntflag) ? dotrans(argv[i]) : argv[i]; 49326049Sminshall tp = (mapflag) ? domap(tp) : tp; 49426049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 49537225Skarels argv[i], tp, tp != argv[i] || !interactive); 49626049Sminshall if (!mflag && fromatty) { 49726049Sminshall ointer = interactive; 49826049Sminshall interactive = 1; 49926049Sminshall if (confirm("Continue with","mput")) { 50026049Sminshall mflag++; 50126049Sminshall } 50226049Sminshall interactive = ointer; 50326049Sminshall } 50426049Sminshall } 50513212Ssam continue; 50613212Ssam } 50713212Ssam gargs = glob(argv[i]); 50811650Ssam if (globerr != NULL) { 50911650Ssam printf("%s\n", globerr); 51036421Sbostic if (gargs) { 51111650Ssam blkfree(gargs); 512*38132Srick free((char *)gargs); 51336421Sbostic } 51413212Ssam continue; 51511353Ssam } 51626049Sminshall for (cpp = gargs; cpp && *cpp != NULL; cpp++) { 51726049Sminshall if (mflag && confirm(argv[0], *cpp)) { 51826049Sminshall tp = (ntflag) ? dotrans(*cpp) : *cpp; 51926049Sminshall tp = (mapflag) ? domap(tp) : tp; 52026049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 52137225Skarels *cpp, tp, *cpp != tp || !interactive); 52226049Sminshall if (!mflag && fromatty) { 52326049Sminshall ointer = interactive; 52426049Sminshall interactive = 1; 52526049Sminshall if (confirm("Continue with","mput")) { 52626049Sminshall mflag++; 52726049Sminshall } 52826049Sminshall interactive = ointer; 52926049Sminshall } 53026049Sminshall } 53126049Sminshall } 53236421Sbostic if (gargs != NULL) { 53313212Ssam blkfree(gargs); 534*38132Srick free((char *)gargs); 53536421Sbostic } 53611353Ssam } 53726049Sminshall (void) signal(SIGINT, oldintr); 53826049Sminshall mflag = 0; 53911353Ssam } 54011353Ssam 54137224Skarels reget(argc, argv) 54237224Skarels char *argv[]; 54337224Skarels { 54437224Skarels (void) getit(argc, argv, 1, "r+w"); 54537224Skarels } 54636935Skarels 54737224Skarels get(argc, argv) 54837224Skarels char *argv[]; 54937224Skarels { 55037224Skarels (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" ); 55137224Skarels } 55237224Skarels 55311353Ssam /* 55411353Ssam * Receive one file. 55511353Ssam */ 55637224Skarels getit(argc, argv, restartit, mode) 55710294Ssam char *argv[]; 55837224Skarels char *mode; 55910294Ssam { 56026049Sminshall int loc = 0; 56137225Skarels char *oldargv1, *oldargv2; 56210294Ssam 56326049Sminshall if (argc == 2) { 56426049Sminshall argc++; 56526049Sminshall argv[2] = argv[1]; 56626049Sminshall loc++; 56726049Sminshall } 56810294Ssam if (argc < 2) { 56926497Sminshall (void) strcat(line, " "); 57010294Ssam printf("(remote-file) "); 57126497Sminshall (void) gets(&line[strlen(line)]); 57210294Ssam makeargv(); 57310294Ssam argc = margc; 57410294Ssam argv = margv; 57510294Ssam } 57610294Ssam if (argc < 2) { 57710294Ssam usage: 57826049Sminshall printf("usage: %s remote-file [ local-file ]\n", argv[0]); 57926049Sminshall code = -1; 58037224Skarels return (0); 58110294Ssam } 58210294Ssam if (argc < 3) { 58326497Sminshall (void) strcat(line, " "); 58410294Ssam printf("(local-file) "); 58526497Sminshall (void) gets(&line[strlen(line)]); 58610294Ssam makeargv(); 58710294Ssam argc = margc; 58810294Ssam argv = margv; 58910294Ssam } 59010294Ssam if (argc < 3) 59110294Ssam goto usage; 59237225Skarels oldargv1 = argv[1]; 59337225Skarels oldargv2 = argv[2]; 59426049Sminshall if (!globulize(&argv[2])) { 59526049Sminshall code = -1; 59637224Skarels return (0); 59726049Sminshall } 59826049Sminshall if (loc && mcase) { 59926049Sminshall char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; 60026049Sminshall 60126049Sminshall while (*tp && !islower(*tp)) { 60226049Sminshall tp++; 60326049Sminshall } 60426049Sminshall if (!*tp) { 60526049Sminshall tp = argv[2]; 60626049Sminshall tp2 = tmpbuf; 60726049Sminshall while ((*tp2 = *tp) != NULL) { 60826049Sminshall if (isupper(*tp2)) { 60926049Sminshall *tp2 = 'a' + *tp2 - 'A'; 61026049Sminshall } 61126049Sminshall tp++; 61226049Sminshall tp2++; 61326049Sminshall } 61426049Sminshall argv[2] = tmpbuf; 61526049Sminshall } 61626049Sminshall } 61736940Skarels if (loc && ntflag) 61826049Sminshall argv[2] = dotrans(argv[2]); 61936940Skarels if (loc && mapflag) 62026049Sminshall argv[2] = domap(argv[2]); 62137224Skarels if (restartit) { 62237224Skarels struct stat stbuf; 62337224Skarels int ret; 62437224Skarels 62537224Skarels ret = stat(argv[2], &stbuf); 62637224Skarels if (restartit == 1) { 62737224Skarels if (ret < 0) { 62837224Skarels perror(argv[2]); 62937224Skarels return (0); 63037224Skarels } 63137224Skarels restart_point = stbuf.st_size; 63237224Skarels } else { 63337224Skarels if (ret == 0) { 63437224Skarels int overbose; 63537224Skarels 63637224Skarels overbose = verbose; 63737224Skarels if (debug == 0) 63837224Skarels verbose = -1; 63937224Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 64037224Skarels int yy, mo, day, hour, min, sec; 64137224Skarels struct tm *tm; 64237224Skarels verbose = overbose; 64337224Skarels sscanf(reply_string, 64437224Skarels "%*s %04d%02d%02d%02d%02d%02d", 64537224Skarels &yy, &mo, &day, &hour, &min, &sec); 64637224Skarels tm = gmtime(&stbuf.st_mtime); 64737224Skarels tm->tm_mon++; 64837224Skarels if (tm->tm_year > yy%100) 64937224Skarels return (1); 65037224Skarels else if (tm->tm_year == yy%100) { 65137224Skarels if (tm->tm_mon > mo) 65237224Skarels return (1); 65337224Skarels } else if (tm->tm_mon == mo) { 65437224Skarels if (tm->tm_mday > day) 65537224Skarels return (1); 65637224Skarels } else if (tm->tm_mday == day) { 65737224Skarels if (tm->tm_hour > hour) 65837224Skarels return (1); 65937224Skarels } else if (tm->tm_hour == hour) { 66037224Skarels if (tm->tm_min > min) 66137224Skarels return (1); 66237224Skarels } else if (tm->tm_min == min) { 66337224Skarels if (tm->tm_sec > sec) 66437224Skarels return (1); 66537224Skarels } 66637224Skarels } else { 667*38132Srick printf("%s\n", reply_string); 66837224Skarels verbose = overbose; 66937224Skarels return (0); 67037224Skarels } 67137224Skarels } 67237224Skarels } 67337224Skarels } 67437224Skarels 67537225Skarels recvrequest("RETR", argv[2], argv[1], mode, 67637225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 67737224Skarels restart_point = 0; 67837224Skarels return (0); 67910294Ssam } 68010294Ssam 681*38132Srick sig_t 68226049Sminshall mabort() 68326049Sminshall { 68426049Sminshall int ointer; 68526049Sminshall extern jmp_buf jabort; 68626049Sminshall 68726049Sminshall printf("\n"); 68826049Sminshall (void) fflush(stdout); 68926049Sminshall if (mflag && fromatty) { 69026049Sminshall ointer = interactive; 69126049Sminshall interactive = 1; 69226049Sminshall if (confirm("Continue with", mname)) { 69326049Sminshall interactive = ointer; 69426049Sminshall longjmp(jabort,0); 69526049Sminshall } 69626049Sminshall interactive = ointer; 69726049Sminshall } 69826049Sminshall mflag = 0; 69926049Sminshall longjmp(jabort,0); 70026049Sminshall } 70126049Sminshall 70211353Ssam /* 70311353Ssam * Get multiple files. 70411353Ssam */ 70511353Ssam mget(argc, argv) 70611353Ssam char *argv[]; 70711353Ssam { 70826049Sminshall char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; 709*38132Srick int ointer; 710*38132Srick sig_t (*oldintr)(), mabort(); 71126049Sminshall extern jmp_buf jabort; 71211353Ssam 71311353Ssam if (argc < 2) { 71426497Sminshall (void) strcat(line, " "); 71511756Ssam printf("(remote-files) "); 71626497Sminshall (void) gets(&line[strlen(line)]); 71711353Ssam makeargv(); 71811353Ssam argc = margc; 71911353Ssam argv = margv; 72011353Ssam } 72111353Ssam if (argc < 2) { 72226049Sminshall printf("usage:%s remote-files\n", argv[0]); 72326049Sminshall code = -1; 72411353Ssam return; 72511353Ssam } 72626049Sminshall mname = argv[0]; 72726049Sminshall mflag = 1; 72826049Sminshall oldintr = signal(SIGINT,mabort); 72926049Sminshall (void) setjmp(jabort); 73026497Sminshall while ((cp = remglob(argv,proxy)) != NULL) { 73126049Sminshall if (*cp == '\0') { 73226049Sminshall mflag = 0; 73326049Sminshall continue; 73426049Sminshall } 73526049Sminshall if (mflag && confirm(argv[0], cp)) { 73626049Sminshall tp = cp; 73726049Sminshall if (mcase) { 73826049Sminshall while (*tp && !islower(*tp)) { 73926049Sminshall tp++; 74026049Sminshall } 74126049Sminshall if (!*tp) { 74226049Sminshall tp = cp; 74326049Sminshall tp2 = tmpbuf; 74426049Sminshall while ((*tp2 = *tp) != NULL) { 74526049Sminshall if (isupper(*tp2)) { 74626049Sminshall *tp2 = 'a' + *tp2 - 'A'; 74726049Sminshall } 74826049Sminshall tp++; 74926049Sminshall tp2++; 75026049Sminshall } 75126049Sminshall } 75226049Sminshall tp = tmpbuf; 75326049Sminshall } 75426049Sminshall if (ntflag) { 75526049Sminshall tp = dotrans(tp); 75626049Sminshall } 75726049Sminshall if (mapflag) { 75826049Sminshall tp = domap(tp); 75926049Sminshall } 76037225Skarels recvrequest("RETR", tp, cp, "w", 76137225Skarels tp != cp || !interactive); 76226049Sminshall if (!mflag && fromatty) { 76326049Sminshall ointer = interactive; 76426049Sminshall interactive = 1; 76526049Sminshall if (confirm("Continue with","mget")) { 76626049Sminshall mflag++; 76726049Sminshall } 76826049Sminshall interactive = ointer; 76926049Sminshall } 77026049Sminshall } 77126049Sminshall } 77226049Sminshall (void) signal(SIGINT,oldintr); 77326049Sminshall mflag = 0; 77411650Ssam } 77511650Ssam 77611650Ssam char * 77726497Sminshall remglob(argv,doswitch) 77811650Ssam char *argv[]; 77926497Sminshall int doswitch; 78011650Ssam { 78111756Ssam char temp[16]; 78211650Ssam static char buf[MAXPATHLEN]; 78311650Ssam static FILE *ftemp = NULL; 78411650Ssam static char **args; 78513212Ssam int oldverbose, oldhash; 78611756Ssam char *cp, *mode; 78711650Ssam 78826049Sminshall if (!mflag) { 78926049Sminshall if (!doglob) { 79026049Sminshall args = NULL; 79126049Sminshall } 79226049Sminshall else { 79326049Sminshall if (ftemp) { 79426497Sminshall (void) fclose(ftemp); 79526049Sminshall ftemp = NULL; 79626049Sminshall } 79726049Sminshall } 79826049Sminshall return(NULL); 79926049Sminshall } 80011650Ssam if (!doglob) { 80111756Ssam if (args == NULL) 80211650Ssam args = argv; 80311650Ssam if ((cp = *++args) == NULL) 80411650Ssam args = NULL; 80511650Ssam return (cp); 80611353Ssam } 80711650Ssam if (ftemp == NULL) { 80837458Skarels (void) strcpy(temp, _PATH_TMP); 80926497Sminshall (void) mktemp(temp); 81011650Ssam oldverbose = verbose, verbose = 0; 81113212Ssam oldhash = hash, hash = 0; 81226049Sminshall if (doswitch) { 81326049Sminshall pswitch(!proxy); 81426049Sminshall } 81511756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 81637225Skarels recvrequest ("NLST", temp, *argv, mode, 0); 81726049Sminshall if (doswitch) { 81826049Sminshall pswitch(!proxy); 81926049Sminshall } 82013212Ssam verbose = oldverbose; hash = oldhash; 82111650Ssam ftemp = fopen(temp, "r"); 82226497Sminshall (void) unlink(temp); 82311650Ssam if (ftemp == NULL) { 82411650Ssam printf("can't find list of remote files, oops\n"); 82511756Ssam return (NULL); 82611353Ssam } 82711353Ssam } 82811650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 82926497Sminshall (void) fclose(ftemp), ftemp = NULL; 83011650Ssam return (NULL); 83111353Ssam } 83211650Ssam if ((cp = index(buf, '\n')) != NULL) 83311650Ssam *cp = '\0'; 83411650Ssam return (buf); 83511353Ssam } 83611353Ssam 83710294Ssam char * 83810294Ssam onoff(bool) 83910294Ssam int bool; 84010294Ssam { 84110294Ssam 84210294Ssam return (bool ? "on" : "off"); 84310294Ssam } 84410294Ssam 84510294Ssam /* 84610294Ssam * Show status. 84710294Ssam */ 84826497Sminshall /*ARGSUSED*/ 84910294Ssam status(argc, argv) 85010294Ssam char *argv[]; 85110294Ssam { 85226049Sminshall int i; 85310294Ssam 85410294Ssam if (connected) 85510294Ssam printf("Connected to %s.\n", hostname); 85610294Ssam else 85710294Ssam printf("Not connected.\n"); 85826049Sminshall if (!proxy) { 85926049Sminshall pswitch(1); 86026049Sminshall if (connected) { 86126049Sminshall printf("Connected for proxy commands to %s.\n", hostname); 86226049Sminshall } 86326049Sminshall else { 86426049Sminshall printf("No proxy connection.\n"); 86526049Sminshall } 86626049Sminshall pswitch(0); 86726049Sminshall } 86810294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 86910294Ssam modename, typename, formname, structname); 87011353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 87111353Ssam onoff(verbose), onoff(bell), onoff(interactive), 87211353Ssam onoff(doglob)); 87326049Sminshall printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), 87426049Sminshall onoff(runique)); 87526049Sminshall printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); 87626049Sminshall if (ntflag) { 87726049Sminshall printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); 87826049Sminshall } 87926049Sminshall else { 88026049Sminshall printf("Ntrans: off\n"); 88126049Sminshall } 88226049Sminshall if (mapflag) { 88326049Sminshall printf("Nmap: (in) %s (out) %s\n", mapin, mapout); 88426049Sminshall } 88526049Sminshall else { 88626049Sminshall printf("Nmap: off\n"); 88726049Sminshall } 88814143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 88914143Ssam onoff(hash), onoff(sendport)); 89026049Sminshall if (macnum > 0) { 89126049Sminshall printf("Macros:\n"); 89226049Sminshall for (i=0; i<macnum; i++) { 89326049Sminshall printf("\t%s\n",macros[i].mac_name); 89426049Sminshall } 89526049Sminshall } 89626049Sminshall code = 0; 89710294Ssam } 89810294Ssam 89910294Ssam /* 90010294Ssam * Set beep on cmd completed mode. 90110294Ssam */ 90210294Ssam /*VARARGS*/ 90310294Ssam setbell() 90410294Ssam { 90510294Ssam 90610294Ssam bell = !bell; 90710294Ssam printf("Bell mode %s.\n", onoff(bell)); 90826049Sminshall code = bell; 90910294Ssam } 91010294Ssam 91110294Ssam /* 91210294Ssam * Turn on packet tracing. 91310294Ssam */ 91410294Ssam /*VARARGS*/ 91510294Ssam settrace() 91610294Ssam { 91710294Ssam 91810294Ssam trace = !trace; 91910294Ssam printf("Packet tracing %s.\n", onoff(trace)); 92026049Sminshall code = trace; 92110294Ssam } 92210294Ssam 92310294Ssam /* 92411650Ssam * Toggle hash mark printing during transfers. 92511650Ssam */ 92611650Ssam /*VARARGS*/ 92711650Ssam sethash() 92811650Ssam { 92911650Ssam 93011650Ssam hash = !hash; 93111650Ssam printf("Hash mark printing %s", onoff(hash)); 93226049Sminshall code = hash; 93311650Ssam if (hash) 93437224Skarels printf(" (%d bytes/hash mark)", 1024); 93511650Ssam printf(".\n"); 93611650Ssam } 93711650Ssam 93811650Ssam /* 93910294Ssam * Turn on printing of server echo's. 94010294Ssam */ 94110294Ssam /*VARARGS*/ 94210294Ssam setverbose() 94310294Ssam { 94410294Ssam 94510294Ssam verbose = !verbose; 94610294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 94726049Sminshall code = verbose; 94810294Ssam } 94910294Ssam 95010294Ssam /* 95111650Ssam * Toggle PORT cmd use before each data connection. 95211650Ssam */ 95311650Ssam /*VARARGS*/ 95411650Ssam setport() 95511650Ssam { 95611650Ssam 95711650Ssam sendport = !sendport; 95811650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 95926049Sminshall code = sendport; 96011650Ssam } 96111650Ssam 96211650Ssam /* 96310294Ssam * Turn on interactive prompting 96410294Ssam * during mget, mput, and mdelete. 96510294Ssam */ 96610294Ssam /*VARARGS*/ 96710294Ssam setprompt() 96810294Ssam { 96910294Ssam 97010294Ssam interactive = !interactive; 97110294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 97226049Sminshall code = interactive; 97310294Ssam } 97410294Ssam 97510294Ssam /* 97611353Ssam * Toggle metacharacter interpretation 97711353Ssam * on local file names. 97811353Ssam */ 97911353Ssam /*VARARGS*/ 98011353Ssam setglob() 98111353Ssam { 98211353Ssam 98311353Ssam doglob = !doglob; 98411353Ssam printf("Globbing %s.\n", onoff(doglob)); 98526049Sminshall code = doglob; 98611353Ssam } 98711353Ssam 98811353Ssam /* 98910294Ssam * Set debugging mode on/off and/or 99010294Ssam * set level of debugging. 99110294Ssam */ 99211756Ssam /*VARARGS*/ 99310294Ssam setdebug(argc, argv) 99410294Ssam char *argv[]; 99510294Ssam { 99610294Ssam int val; 99710294Ssam 99810294Ssam if (argc > 1) { 99910294Ssam val = atoi(argv[1]); 100010294Ssam if (val < 0) { 100110294Ssam printf("%s: bad debugging value.\n", argv[1]); 100226049Sminshall code = -1; 100310294Ssam return; 100410294Ssam } 100510294Ssam } else 100610294Ssam val = !debug; 100710294Ssam debug = val; 100810294Ssam if (debug) 100910294Ssam options |= SO_DEBUG; 101010294Ssam else 101110294Ssam options &= ~SO_DEBUG; 101210294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 101326049Sminshall code = debug > 0; 101410294Ssam } 101510294Ssam 101610294Ssam /* 101710294Ssam * Set current working directory 101810294Ssam * on remote machine. 101910294Ssam */ 102010294Ssam cd(argc, argv) 102110294Ssam char *argv[]; 102210294Ssam { 102310294Ssam 102410294Ssam if (argc < 2) { 102526497Sminshall (void) strcat(line, " "); 102610294Ssam printf("(remote-directory) "); 102726497Sminshall (void) gets(&line[strlen(line)]); 102810294Ssam makeargv(); 102910294Ssam argc = margc; 103010294Ssam argv = margv; 103110294Ssam } 103210294Ssam if (argc < 2) { 103326049Sminshall printf("usage:%s remote-directory\n", argv[0]); 103426049Sminshall code = -1; 103510294Ssam return; 103610294Ssam } 103737224Skarels if (command("CWD %s", argv[1]) == ERROR && code == 500) { 103837224Skarels if (verbose) 103937224Skarels printf("CWD command not recognized, trying XCWD\n"); 104037224Skarels (void) command("XCWD %s", argv[1]); 104137224Skarels } 104210294Ssam } 104310294Ssam 104410294Ssam /* 104510294Ssam * Set current working directory 104610294Ssam * on local machine. 104710294Ssam */ 104810294Ssam lcd(argc, argv) 104910294Ssam char *argv[]; 105010294Ssam { 105111353Ssam char buf[MAXPATHLEN]; 1052*38132Srick extern char *getwd(); 105310294Ssam 105411353Ssam if (argc < 2) 105511353Ssam argc++, argv[1] = home; 105610294Ssam if (argc != 2) { 105726049Sminshall printf("usage:%s local-directory\n", argv[0]); 105826049Sminshall code = -1; 105910294Ssam return; 106010294Ssam } 106126049Sminshall if (!globulize(&argv[1])) { 106226049Sminshall code = -1; 106311353Ssam return; 106426049Sminshall } 106511353Ssam if (chdir(argv[1]) < 0) { 106610294Ssam perror(argv[1]); 106726049Sminshall code = -1; 106811353Ssam return; 106911353Ssam } 107011353Ssam printf("Local directory now %s\n", getwd(buf)); 107126049Sminshall code = 0; 107210294Ssam } 107310294Ssam 107410294Ssam /* 107510294Ssam * Delete a single file. 107610294Ssam */ 107710294Ssam delete(argc, argv) 107810294Ssam char *argv[]; 107910294Ssam { 108010294Ssam 108110294Ssam if (argc < 2) { 108226497Sminshall (void) strcat(line, " "); 108310294Ssam printf("(remote-file) "); 108426497Sminshall (void) gets(&line[strlen(line)]); 108510294Ssam makeargv(); 108610294Ssam argc = margc; 108710294Ssam argv = margv; 108810294Ssam } 108910294Ssam if (argc < 2) { 109026049Sminshall printf("usage:%s remote-file\n", argv[0]); 109126049Sminshall code = -1; 109210294Ssam return; 109310294Ssam } 109410294Ssam (void) command("DELE %s", argv[1]); 109510294Ssam } 109610294Ssam 109710294Ssam /* 109811650Ssam * Delete multiple files. 109911650Ssam */ 110011650Ssam mdelete(argc, argv) 110111650Ssam char *argv[]; 110211650Ssam { 110311650Ssam char *cp; 1104*38132Srick int ointer; 1105*38132Srick sig_t (*oldintr)(), mabort(); 110626049Sminshall extern jmp_buf jabort; 110711650Ssam 110811650Ssam if (argc < 2) { 110926497Sminshall (void) strcat(line, " "); 111011650Ssam printf("(remote-files) "); 111126497Sminshall (void) gets(&line[strlen(line)]); 111211650Ssam makeargv(); 111311650Ssam argc = margc; 111411650Ssam argv = margv; 111511650Ssam } 111611650Ssam if (argc < 2) { 111726049Sminshall printf("usage:%s remote-files\n", argv[0]); 111826049Sminshall code = -1; 111911650Ssam return; 112011650Ssam } 112126049Sminshall mname = argv[0]; 112226049Sminshall mflag = 1; 112326049Sminshall oldintr = signal(SIGINT, mabort); 112426049Sminshall (void) setjmp(jabort); 112526497Sminshall while ((cp = remglob(argv,0)) != NULL) { 112626049Sminshall if (*cp == '\0') { 112726049Sminshall mflag = 0; 112826049Sminshall continue; 112926049Sminshall } 113026049Sminshall if (mflag && confirm(argv[0], cp)) { 113111650Ssam (void) command("DELE %s", cp); 113226049Sminshall if (!mflag && fromatty) { 113326049Sminshall ointer = interactive; 113426049Sminshall interactive = 1; 113526049Sminshall if (confirm("Continue with", "mdelete")) { 113626049Sminshall mflag++; 113726049Sminshall } 113826049Sminshall interactive = ointer; 113926049Sminshall } 114026049Sminshall } 114126049Sminshall } 114226049Sminshall (void) signal(SIGINT, oldintr); 114326049Sminshall mflag = 0; 114411650Ssam } 114511756Ssam 114611650Ssam /* 114710294Ssam * Rename a remote file. 114810294Ssam */ 114910294Ssam renamefile(argc, argv) 115010294Ssam char *argv[]; 115110294Ssam { 115210294Ssam 115310294Ssam if (argc < 2) { 115426497Sminshall (void) strcat(line, " "); 115510294Ssam printf("(from-name) "); 115626497Sminshall (void) gets(&line[strlen(line)]); 115710294Ssam makeargv(); 115810294Ssam argc = margc; 115910294Ssam argv = margv; 116010294Ssam } 116110294Ssam if (argc < 2) { 116210294Ssam usage: 116310294Ssam printf("%s from-name to-name\n", argv[0]); 116426049Sminshall code = -1; 116510294Ssam return; 116610294Ssam } 116710294Ssam if (argc < 3) { 116826497Sminshall (void) strcat(line, " "); 116910294Ssam printf("(to-name) "); 117026497Sminshall (void) gets(&line[strlen(line)]); 117110294Ssam makeargv(); 117210294Ssam argc = margc; 117310294Ssam argv = margv; 117410294Ssam } 117510294Ssam if (argc < 3) 117610294Ssam goto usage; 117710294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 117810294Ssam (void) command("RNTO %s", argv[2]); 117910294Ssam } 118010294Ssam 118110294Ssam /* 118210294Ssam * Get a directory listing 118310294Ssam * of remote files. 118410294Ssam */ 118510294Ssam ls(argc, argv) 118610294Ssam char *argv[]; 118710294Ssam { 118811756Ssam char *cmd; 118910294Ssam 119010294Ssam if (argc < 2) 119110294Ssam argc++, argv[1] = NULL; 119210294Ssam if (argc < 3) 119310294Ssam argc++, argv[2] = "-"; 119411756Ssam if (argc > 3) { 119511756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 119626049Sminshall code = -1; 119711756Ssam return; 119811756Ssam } 119936935Skarels cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 120026049Sminshall if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 120126049Sminshall code = -1; 120211353Ssam return; 120326049Sminshall } 120432344Scsvsj if (strcmp(argv[2], "-") && *argv[2] != '|') 120532344Scsvsj if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { 120632344Scsvsj code = -1; 120732344Scsvsj return; 120832344Scsvsj } 120937225Skarels recvrequest(cmd, argv[2], argv[1], "w", 0); 121010294Ssam } 121110294Ssam 121210294Ssam /* 121311756Ssam * Get a directory listing 121411756Ssam * of multiple remote files. 121511756Ssam */ 121611756Ssam mls(argc, argv) 121711756Ssam char *argv[]; 121811756Ssam { 121926049Sminshall char *cmd, mode[1], *dest; 1220*38132Srick int ointer, i; 1221*38132Srick sig_t (*oldintr)(), mabort(); 122226049Sminshall extern jmp_buf jabort; 122311756Ssam 122413212Ssam if (argc < 2) { 122526497Sminshall (void) strcat(line, " "); 122613212Ssam printf("(remote-files) "); 122726497Sminshall (void) gets(&line[strlen(line)]); 122813212Ssam makeargv(); 122913212Ssam argc = margc; 123013212Ssam argv = margv; 123113212Ssam } 123213212Ssam if (argc < 3) { 123326497Sminshall (void) strcat(line, " "); 123413212Ssam printf("(local-file) "); 123526497Sminshall (void) gets(&line[strlen(line)]); 123613212Ssam makeargv(); 123713212Ssam argc = margc; 123813212Ssam argv = margv; 123913212Ssam } 124013212Ssam if (argc < 3) { 124126049Sminshall printf("usage:%s remote-files local-file\n", argv[0]); 124226049Sminshall code = -1; 124313212Ssam return; 124413212Ssam } 124513212Ssam dest = argv[argc - 1]; 124613212Ssam argv[argc - 1] = NULL; 124726049Sminshall if (strcmp(dest, "-") && *dest != '|') 124826049Sminshall if (!globulize(&dest) || !confirm("output to local-file:", dest)) { 124926049Sminshall code = -1; 125013212Ssam return; 125126049Sminshall } 125236940Skarels cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 125326049Sminshall mname = argv[0]; 125426049Sminshall mflag = 1; 125526049Sminshall oldintr = signal(SIGINT, mabort); 125626049Sminshall (void) setjmp(jabort); 125726049Sminshall for (i = 1; mflag && i < argc-1; ++i) { 125826049Sminshall *mode = (i == 1) ? 'w' : 'a'; 125937225Skarels recvrequest(cmd, dest, argv[i], mode, 0); 126026049Sminshall if (!mflag && fromatty) { 126126049Sminshall ointer = interactive; 126226049Sminshall interactive = 1; 126326049Sminshall if (confirm("Continue with", argv[0])) { 126426049Sminshall mflag ++; 126526049Sminshall } 126626049Sminshall interactive = ointer; 126726049Sminshall } 126826049Sminshall } 126926049Sminshall (void) signal(SIGINT, oldintr); 127026049Sminshall mflag = 0; 127111756Ssam } 127211756Ssam 127311756Ssam /* 127410294Ssam * Do a shell escape 127510294Ssam */ 127626497Sminshall /*ARGSUSED*/ 127710294Ssam shell(argc, argv) 127810294Ssam char *argv[]; 127910294Ssam { 1280*38132Srick int pid; 1281*38132Srick sig_t (*old1)(), (*old2)(); 128226049Sminshall char shellnam[40], *shell, *namep; 128326497Sminshall union wait status; 128410294Ssam 128511756Ssam old1 = signal (SIGINT, SIG_IGN); 128611756Ssam old2 = signal (SIGQUIT, SIG_IGN); 128711756Ssam if ((pid = fork()) == 0) { 128811756Ssam for (pid = 3; pid < 20; pid++) 128926497Sminshall (void) close(pid); 129026497Sminshall (void) signal(SIGINT, SIG_DFL); 129126497Sminshall (void) signal(SIGQUIT, SIG_DFL); 129225908Smckusick shell = getenv("SHELL"); 129325908Smckusick if (shell == NULL) 129437458Skarels shell = _PATH_BSHELL; 129525908Smckusick namep = rindex(shell,'/'); 129625908Smckusick if (namep == NULL) 129725908Smckusick namep = shell; 129826497Sminshall (void) strcpy(shellnam,"-"); 129926497Sminshall (void) strcat(shellnam, ++namep); 130026049Sminshall if (strcmp(namep, "sh") != 0) 130126049Sminshall shellnam[0] = '+'; 130226049Sminshall if (debug) { 130326049Sminshall printf ("%s\n", shell); 130426497Sminshall (void) fflush (stdout); 130511756Ssam } 130626049Sminshall if (argc > 1) { 130726049Sminshall execl(shell,shellnam,"-c",altarg,(char *)0); 130826049Sminshall } 130926049Sminshall else { 131026049Sminshall execl(shell,shellnam,(char *)0); 131126049Sminshall } 131225908Smckusick perror(shell); 131326049Sminshall code = -1; 131411756Ssam exit(1); 131526049Sminshall } 131611756Ssam if (pid > 0) 131711756Ssam while (wait(&status) != pid) 131811756Ssam ; 131926497Sminshall (void) signal(SIGINT, old1); 132026497Sminshall (void) signal(SIGQUIT, old2); 132126049Sminshall if (pid == -1) { 132211756Ssam perror("Try again later"); 132326049Sminshall code = -1; 132426049Sminshall } 132526049Sminshall else { 132626049Sminshall code = 0; 132726049Sminshall } 132811756Ssam return (0); 132910294Ssam } 133010294Ssam 133110294Ssam /* 133210294Ssam * Send new user information (re-login) 133310294Ssam */ 133410294Ssam user(argc, argv) 133510294Ssam int argc; 133610294Ssam char **argv; 133710294Ssam { 133835658Sbostic char acct[80], *getpass(); 133926049Sminshall int n, aflag = 0; 134010294Ssam 134110294Ssam if (argc < 2) { 134226497Sminshall (void) strcat(line, " "); 134310294Ssam printf("(username) "); 134426497Sminshall (void) gets(&line[strlen(line)]); 134510294Ssam makeargv(); 134610294Ssam argc = margc; 134710294Ssam argv = margv; 134810294Ssam } 134910294Ssam if (argc > 4) { 135010294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 135126049Sminshall code = -1; 135211756Ssam return (0); 135310294Ssam } 135410294Ssam n = command("USER %s", argv[1]); 135510294Ssam if (n == CONTINUE) { 135610294Ssam if (argc < 3 ) 135735658Sbostic argv[2] = getpass("Password: "), argc++; 135810294Ssam n = command("PASS %s", argv[2]); 135910294Ssam } 136010294Ssam if (n == CONTINUE) { 136110294Ssam if (argc < 4) { 136210294Ssam printf("Account: "); (void) fflush(stdout); 136310294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 136410294Ssam acct[strlen(acct) - 1] = '\0'; 136510294Ssam argv[3] = acct; argc++; 136610294Ssam } 136726049Sminshall n = command("ACCT %s", argv[3]); 136826049Sminshall aflag++; 136910294Ssam } 137010294Ssam if (n != COMPLETE) { 137126497Sminshall fprintf(stdout, "Login failed.\n"); 137210294Ssam return (0); 137310294Ssam } 137426049Sminshall if (!aflag && argc == 4) { 137526049Sminshall (void) command("ACCT %s", argv[3]); 137626049Sminshall } 137710294Ssam return (1); 137810294Ssam } 137910294Ssam 138010294Ssam /* 138110294Ssam * Print working directory. 138210294Ssam */ 138310294Ssam /*VARARGS*/ 138410294Ssam pwd() 138510294Ssam { 138637224Skarels int oldverbose = verbose; 138711756Ssam 138837224Skarels /* 138937224Skarels * If we aren't verbose, this doesn't do anything! 139037224Skarels */ 139137224Skarels verbose = 1; 139237224Skarels if (command("PWD") == ERROR && code == 500) { 139337224Skarels printf("PWD command not recognized, trying XPWD\n"); 139437224Skarels (void) command("XPWD"); 139537224Skarels } 139637224Skarels verbose = oldverbose; 139710294Ssam } 139810294Ssam 139910294Ssam /* 140010294Ssam * Make a directory. 140110294Ssam */ 140210294Ssam makedir(argc, argv) 140310294Ssam char *argv[]; 140410294Ssam { 140510294Ssam 140610294Ssam if (argc < 2) { 140726497Sminshall (void) strcat(line, " "); 140810294Ssam printf("(directory-name) "); 140926497Sminshall (void) gets(&line[strlen(line)]); 141010294Ssam makeargv(); 141110294Ssam argc = margc; 141210294Ssam argv = margv; 141310294Ssam } 141410294Ssam if (argc < 2) { 141526049Sminshall printf("usage: %s directory-name\n", argv[0]); 141626049Sminshall code = -1; 141710294Ssam return; 141810294Ssam } 141937224Skarels if (command("MKD %s", argv[1]) == ERROR && code == 500) { 142037224Skarels if (verbose) 142137224Skarels printf("MKD command not recognized, trying XMKD\n"); 142237224Skarels (void) command("XMKD %s", argv[1]); 142337224Skarels } 142410294Ssam } 142510294Ssam 142610294Ssam /* 142710294Ssam * Remove a directory. 142810294Ssam */ 142910294Ssam removedir(argc, argv) 143010294Ssam char *argv[]; 143110294Ssam { 143210294Ssam 143310294Ssam if (argc < 2) { 143426497Sminshall (void) strcat(line, " "); 143510294Ssam printf("(directory-name) "); 143626497Sminshall (void) gets(&line[strlen(line)]); 143710294Ssam makeargv(); 143810294Ssam argc = margc; 143910294Ssam argv = margv; 144010294Ssam } 144110294Ssam if (argc < 2) { 144226049Sminshall printf("usage: %s directory-name\n", argv[0]); 144326049Sminshall code = -1; 144410294Ssam return; 144510294Ssam } 144637224Skarels if (command("RMD %s", argv[1]) == ERROR && code == 500) { 144737224Skarels if (verbose) 144837224Skarels printf("RMD command not recognized, trying XRMD\n"); 144937224Skarels (void) command("XRMD %s", argv[1]); 145037224Skarels } 145110294Ssam } 145210294Ssam 145310294Ssam /* 145410294Ssam * Send a line, verbatim, to the remote machine. 145510294Ssam */ 145610294Ssam quote(argc, argv) 145710294Ssam char *argv[]; 145810294Ssam { 145910294Ssam int i; 146010294Ssam char buf[BUFSIZ]; 146110294Ssam 146210294Ssam if (argc < 2) { 146326497Sminshall (void) strcat(line, " "); 146410294Ssam printf("(command line to send) "); 146526497Sminshall (void) gets(&line[strlen(line)]); 146610294Ssam makeargv(); 146710294Ssam argc = margc; 146810294Ssam argv = margv; 146910294Ssam } 147010294Ssam if (argc < 2) { 147110294Ssam printf("usage: %s line-to-send\n", argv[0]); 147226049Sminshall code = -1; 147310294Ssam return; 147410294Ssam } 147526497Sminshall (void) strcpy(buf, argv[1]); 147610294Ssam for (i = 2; i < argc; i++) { 147726497Sminshall (void) strcat(buf, " "); 147826497Sminshall (void) strcat(buf, argv[i]); 147910294Ssam } 148026049Sminshall if (command(buf) == PRELIM) { 148126049Sminshall while (getreply(0) == PRELIM); 148226049Sminshall } 148310294Ssam } 148410294Ssam 148510294Ssam /* 148637224Skarels * Send a SITE command to the remote machine. The line 148737224Skarels * is sent almost verbatim to the remote machine, the 148837224Skarels * first argument is changed to SITE. 148937224Skarels */ 149037224Skarels 149137224Skarels site(argc, argv) 149237224Skarels char *argv[]; 149337224Skarels { 149437224Skarels int i; 149537224Skarels char buf[BUFSIZ]; 149637224Skarels 149737224Skarels if (argc < 2) { 149837224Skarels (void) strcat(line, " "); 149937224Skarels printf("(arguments to SITE command) "); 150037224Skarels (void) gets(&line[strlen(line)]); 150137224Skarels makeargv(); 150237224Skarels argc = margc; 150337224Skarels argv = margv; 150437224Skarels } 150537224Skarels if (argc < 2) { 150637224Skarels printf("usage: %s line-to-send\n", argv[0]); 150737224Skarels code = -1; 150837224Skarels return; 150937224Skarels } 151037224Skarels (void) strcpy(buf, "SITE "); 151137224Skarels (void) strcat(buf, argv[1]); 151237224Skarels for (i = 2; i < argc; i++) { 151337224Skarels (void) strcat(buf, " "); 151437224Skarels (void) strcat(buf, argv[i]); 151537224Skarels } 151637224Skarels if (command(buf) == PRELIM) { 151737224Skarels while (getreply(0) == PRELIM); 151837224Skarels } 151937224Skarels } 152037224Skarels 152137224Skarels do_chmod(argc, argv) 152237224Skarels char *argv[]; 152337224Skarels { 152437224Skarels if (argc == 2) { 152537224Skarels printf("usage: %s mode file-name\n", argv[0]); 152637224Skarels code = -1; 152737224Skarels return; 152837224Skarels } 152937224Skarels if (argc < 3) { 153037224Skarels (void) strcat(line, " "); 153137224Skarels printf("(mode and file-name) "); 153237224Skarels (void) gets(&line[strlen(line)]); 153337224Skarels makeargv(); 153437224Skarels argc = margc; 153537224Skarels argv = margv; 153637224Skarels } 153737224Skarels if (argc != 3) { 153837224Skarels printf("usage: %s mode file-name\n", argv[0]); 153937224Skarels code = -1; 154037224Skarels return; 154137224Skarels } 154237224Skarels (void)command("SITE CHMOD %s %s", argv[1], argv[2]); 154337224Skarels } 154437224Skarels 154537224Skarels do_umask(argc, argv) 154637224Skarels char *argv[]; 154737224Skarels { 154837224Skarels int oldverbose = verbose; 154937224Skarels 155037224Skarels verbose = 1; 155137224Skarels (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 155237224Skarels verbose = oldverbose; 155337224Skarels } 155437224Skarels 155537224Skarels idle(argc, argv) 155637224Skarels char *argv[]; 155737224Skarels { 155837224Skarels int oldverbose = verbose; 155937224Skarels 156037224Skarels verbose = 1; 156137224Skarels (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 156237224Skarels verbose = oldverbose; 156337224Skarels } 156437224Skarels 156537224Skarels /* 156610294Ssam * Ask the other side for help. 156710294Ssam */ 156810294Ssam rmthelp(argc, argv) 156910294Ssam char *argv[]; 157010294Ssam { 157110294Ssam int oldverbose = verbose; 157210294Ssam 157310294Ssam verbose = 1; 157410294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 157510294Ssam verbose = oldverbose; 157610294Ssam } 157710294Ssam 157810294Ssam /* 157910294Ssam * Terminate session and exit. 158010294Ssam */ 158110294Ssam /*VARARGS*/ 158210294Ssam quit() 158310294Ssam { 158410294Ssam 158518286Sralph if (connected) 158618286Sralph disconnect(); 158726049Sminshall pswitch(1); 158826049Sminshall if (connected) { 158926049Sminshall disconnect(); 159026049Sminshall } 159110294Ssam exit(0); 159210294Ssam } 159310294Ssam 159410294Ssam /* 159510294Ssam * Terminate session, but don't exit. 159610294Ssam */ 159710294Ssam disconnect() 159810294Ssam { 159910294Ssam extern FILE *cout; 160010294Ssam extern int data; 160110294Ssam 160210294Ssam if (!connected) 160310294Ssam return; 160410294Ssam (void) command("QUIT"); 160526049Sminshall if (cout) { 160626049Sminshall (void) fclose(cout); 160726049Sminshall } 160810294Ssam cout = NULL; 160910294Ssam connected = 0; 161010294Ssam data = -1; 161126049Sminshall if (!proxy) { 161226049Sminshall macnum = 0; 161326049Sminshall } 161410294Ssam } 161511353Ssam 161611650Ssam confirm(cmd, file) 161711353Ssam char *cmd, *file; 161811353Ssam { 161911353Ssam char line[BUFSIZ]; 162011353Ssam 162111353Ssam if (!interactive) 162211650Ssam return (1); 162311353Ssam printf("%s %s? ", cmd, file); 162426497Sminshall (void) fflush(stdout); 162526497Sminshall (void) gets(line); 162611650Ssam return (*line != 'n' && *line != 'N'); 162711353Ssam } 162811353Ssam 162911353Ssam fatal(msg) 163011353Ssam char *msg; 163111353Ssam { 163211353Ssam 163326497Sminshall fprintf(stderr, "ftp: %s\n", msg); 163411353Ssam exit(1); 163511353Ssam } 163611353Ssam 163711353Ssam /* 163811353Ssam * Glob a local file name specification with 163911353Ssam * the expectation of a single return value. 164011353Ssam * Can't control multiple values being expanded 164111353Ssam * from the expression, we return only the first. 164211353Ssam */ 164311353Ssam globulize(cpp) 164411353Ssam char **cpp; 164511353Ssam { 164611353Ssam char **globbed; 164711353Ssam 164811353Ssam if (!doglob) 164911353Ssam return (1); 165011353Ssam globbed = glob(*cpp); 165111353Ssam if (globerr != NULL) { 165211353Ssam printf("%s: %s\n", *cpp, globerr); 165336421Sbostic if (globbed) { 165411353Ssam blkfree(globbed); 1655*38132Srick free((char *)globbed); 165636421Sbostic } 165711353Ssam return (0); 165811353Ssam } 165911353Ssam if (globbed) { 166011353Ssam *cpp = *globbed++; 166111353Ssam /* don't waste too much memory */ 166236421Sbostic if (*globbed) { 166311353Ssam blkfree(globbed); 1664*38132Srick free((char *)globbed); 166536421Sbostic } 166611353Ssam } 166711353Ssam return (1); 166811353Ssam } 166926049Sminshall 167026049Sminshall account(argc,argv) 167126049Sminshall int argc; 167226049Sminshall char **argv; 167326049Sminshall { 167435658Sbostic char acct[50], *getpass(), *ap; 167526049Sminshall 167626049Sminshall if (argc > 1) { 167726049Sminshall ++argv; 167826049Sminshall --argc; 167926049Sminshall (void) strncpy(acct,*argv,49); 168036268Sbostic acct[49] = '\0'; 168126049Sminshall while (argc > 1) { 168226049Sminshall --argc; 168326049Sminshall ++argv; 168426049Sminshall (void) strncat(acct,*argv, 49-strlen(acct)); 168526049Sminshall } 168626049Sminshall ap = acct; 168726049Sminshall } 168826049Sminshall else { 168935658Sbostic ap = getpass("Account:"); 169026049Sminshall } 169126049Sminshall (void) command("ACCT %s", ap); 169226049Sminshall } 169326049Sminshall 169426049Sminshall jmp_buf abortprox; 169526049Sminshall 1696*38132Srick sig_t 169726049Sminshall proxabort() 169826049Sminshall { 169926049Sminshall extern int proxy; 170026049Sminshall 170126049Sminshall if (!proxy) { 170226049Sminshall pswitch(1); 170326049Sminshall } 170426049Sminshall if (connected) { 170526049Sminshall proxflag = 1; 170626049Sminshall } 170726049Sminshall else { 170826049Sminshall proxflag = 0; 170926049Sminshall } 171026049Sminshall pswitch(0); 171126049Sminshall longjmp(abortprox,1); 171226049Sminshall } 171326049Sminshall 171426049Sminshall doproxy(argc,argv) 171526049Sminshall int argc; 171626049Sminshall char *argv[]; 171726049Sminshall { 1718*38132Srick sig_t (*oldintr)(), proxabort(); 171926049Sminshall register struct cmd *c; 172026049Sminshall struct cmd *getcmd(); 172126049Sminshall extern struct cmd cmdtab[]; 172226049Sminshall extern jmp_buf abortprox; 172326049Sminshall 172426049Sminshall if (argc < 2) { 172526497Sminshall (void) strcat(line, " "); 172626049Sminshall printf("(command) "); 172726497Sminshall (void) gets(&line[strlen(line)]); 172826049Sminshall makeargv(); 172926049Sminshall argc = margc; 173026049Sminshall argv = margv; 173126049Sminshall } 173226049Sminshall if (argc < 2) { 173326049Sminshall printf("usage:%s command\n", argv[0]); 173426049Sminshall code = -1; 173526049Sminshall return; 173626049Sminshall } 173726049Sminshall c = getcmd(argv[1]); 173826049Sminshall if (c == (struct cmd *) -1) { 173926049Sminshall printf("?Ambiguous command\n"); 174026497Sminshall (void) fflush(stdout); 174126049Sminshall code = -1; 174226049Sminshall return; 174326049Sminshall } 174426049Sminshall if (c == 0) { 174526049Sminshall printf("?Invalid command\n"); 174626497Sminshall (void) fflush(stdout); 174726049Sminshall code = -1; 174826049Sminshall return; 174926049Sminshall } 175026049Sminshall if (!c->c_proxy) { 175126049Sminshall printf("?Invalid proxy command\n"); 175226497Sminshall (void) fflush(stdout); 175326049Sminshall code = -1; 175426049Sminshall return; 175526049Sminshall } 175626049Sminshall if (setjmp(abortprox)) { 175726049Sminshall code = -1; 175826049Sminshall return; 175926049Sminshall } 176026049Sminshall oldintr = signal(SIGINT, proxabort); 176126049Sminshall pswitch(1); 176226049Sminshall if (c->c_conn && !connected) { 176326049Sminshall printf("Not connected\n"); 176426497Sminshall (void) fflush(stdout); 176526049Sminshall pswitch(0); 176626049Sminshall (void) signal(SIGINT, oldintr); 176726049Sminshall code = -1; 176826049Sminshall return; 176926049Sminshall } 177026049Sminshall (*c->c_handler)(argc-1, argv+1); 177126049Sminshall if (connected) { 177226049Sminshall proxflag = 1; 177326049Sminshall } 177426049Sminshall else { 177526049Sminshall proxflag = 0; 177626049Sminshall } 177726049Sminshall pswitch(0); 177826049Sminshall (void) signal(SIGINT, oldintr); 177926049Sminshall } 178026049Sminshall 178126049Sminshall setcase() 178226049Sminshall { 178326049Sminshall mcase = !mcase; 178426049Sminshall printf("Case mapping %s.\n", onoff(mcase)); 178526049Sminshall code = mcase; 178626049Sminshall } 178726049Sminshall 178826049Sminshall setcr() 178926049Sminshall { 179026049Sminshall crflag = !crflag; 179126049Sminshall printf("Carriage Return stripping %s.\n", onoff(crflag)); 179226049Sminshall code = crflag; 179326049Sminshall } 179426049Sminshall 179526049Sminshall setntrans(argc,argv) 179626049Sminshall int argc; 179726049Sminshall char *argv[]; 179826049Sminshall { 179926049Sminshall if (argc == 1) { 180026049Sminshall ntflag = 0; 180126049Sminshall printf("Ntrans off.\n"); 180226049Sminshall code = ntflag; 180326049Sminshall return; 180426049Sminshall } 180526049Sminshall ntflag++; 180626049Sminshall code = ntflag; 180726049Sminshall (void) strncpy(ntin, argv[1], 16); 180826049Sminshall ntin[16] = '\0'; 180926049Sminshall if (argc == 2) { 181026049Sminshall ntout[0] = '\0'; 181126049Sminshall return; 181226049Sminshall } 181326049Sminshall (void) strncpy(ntout, argv[2], 16); 181426049Sminshall ntout[16] = '\0'; 181526049Sminshall } 181626049Sminshall 181726049Sminshall char * 181826049Sminshall dotrans(name) 181926049Sminshall char *name; 182026049Sminshall { 182126049Sminshall static char new[MAXPATHLEN]; 182226049Sminshall char *cp1, *cp2 = new; 182326049Sminshall register int i, ostop, found; 182426049Sminshall 182526049Sminshall for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++); 182626049Sminshall for (cp1 = name; *cp1; cp1++) { 182726049Sminshall found = 0; 182826049Sminshall for (i = 0; *(ntin + i) && i < 16; i++) { 182926049Sminshall if (*cp1 == *(ntin + i)) { 183026049Sminshall found++; 183126049Sminshall if (i < ostop) { 183226049Sminshall *cp2++ = *(ntout + i); 183326049Sminshall } 183426049Sminshall break; 183526049Sminshall } 183626049Sminshall } 183726049Sminshall if (!found) { 183826049Sminshall *cp2++ = *cp1; 183926049Sminshall } 184026049Sminshall } 184126049Sminshall *cp2 = '\0'; 184226049Sminshall return(new); 184326049Sminshall } 184426049Sminshall 184526049Sminshall setnmap(argc, argv) 184626049Sminshall int argc; 184726049Sminshall char *argv[]; 184826049Sminshall { 184926049Sminshall char *cp; 185026049Sminshall 185126049Sminshall if (argc == 1) { 185226049Sminshall mapflag = 0; 185326049Sminshall printf("Nmap off.\n"); 185426049Sminshall code = mapflag; 185526049Sminshall return; 185626049Sminshall } 185726049Sminshall if (argc < 3) { 185826497Sminshall (void) strcat(line, " "); 185926049Sminshall printf("(mapout) "); 186026497Sminshall (void) gets(&line[strlen(line)]); 186126049Sminshall makeargv(); 186226049Sminshall argc = margc; 186326049Sminshall argv = margv; 186426049Sminshall } 186526049Sminshall if (argc < 3) { 186626049Sminshall printf("Usage: %s [mapin mapout]\n",argv[0]); 186726049Sminshall code = -1; 186826049Sminshall return; 186926049Sminshall } 187026049Sminshall mapflag = 1; 187126049Sminshall code = 1; 187226049Sminshall cp = index(altarg, ' '); 187326049Sminshall if (proxy) { 187426049Sminshall while(*++cp == ' '); 187526049Sminshall altarg = cp; 187626049Sminshall cp = index(altarg, ' '); 187726049Sminshall } 187826049Sminshall *cp = '\0'; 187926049Sminshall (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 188026049Sminshall while (*++cp == ' '); 188126049Sminshall (void) strncpy(mapout, cp, MAXPATHLEN - 1); 188226049Sminshall } 188326049Sminshall 188426049Sminshall char * 188526049Sminshall domap(name) 188626049Sminshall char *name; 188726049Sminshall { 188826049Sminshall static char new[MAXPATHLEN]; 188926049Sminshall register char *cp1 = name, *cp2 = mapin; 189026049Sminshall char *tp[9], *te[9]; 189136689Scsvsj int i, toks[9], toknum = 0, match = 1; 189226049Sminshall 189326049Sminshall for (i=0; i < 9; ++i) { 189426049Sminshall toks[i] = 0; 189526049Sminshall } 189626049Sminshall while (match && *cp1 && *cp2) { 189726049Sminshall switch (*cp2) { 189826049Sminshall case '\\': 189926049Sminshall if (*++cp2 != *cp1) { 190026049Sminshall match = 0; 190126049Sminshall } 190226049Sminshall break; 190326049Sminshall case '$': 190426049Sminshall if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 190526049Sminshall if (*cp1 != *(++cp2+1)) { 190626049Sminshall toks[toknum = *cp2 - '1']++; 190726049Sminshall tp[toknum] = cp1; 190826049Sminshall while (*++cp1 && *(cp2+1) 190926049Sminshall != *cp1); 191026049Sminshall te[toknum] = cp1; 191126049Sminshall } 191226049Sminshall cp2++; 191326049Sminshall break; 191426049Sminshall } 191536935Skarels /* FALLTHROUGH */ 191626049Sminshall default: 191726049Sminshall if (*cp2 != *cp1) { 191826049Sminshall match = 0; 191926049Sminshall } 192026049Sminshall break; 192126049Sminshall } 192236689Scsvsj if (match && *cp1) { 192326049Sminshall cp1++; 192426049Sminshall } 192536689Scsvsj if (match && *cp2) { 192626049Sminshall cp2++; 192726049Sminshall } 192826049Sminshall } 192936689Scsvsj if (!match && *cp1) /* last token mismatch */ 193036689Scsvsj { 193136689Scsvsj toks[toknum] = 0; 193236689Scsvsj } 193326049Sminshall cp1 = new; 193426049Sminshall *cp1 = '\0'; 193526049Sminshall cp2 = mapout; 193626049Sminshall while (*cp2) { 193726049Sminshall match = 0; 193826049Sminshall switch (*cp2) { 193926049Sminshall case '\\': 194026049Sminshall if (*(cp2 + 1)) { 194126049Sminshall *cp1++ = *++cp2; 194226049Sminshall } 194326049Sminshall break; 194426049Sminshall case '[': 194526049Sminshall LOOP: 194626049Sminshall if (*++cp2 == '$' && isdigit(*(cp2+1))) { 194726049Sminshall if (*++cp2 == '0') { 194826049Sminshall char *cp3 = name; 194926049Sminshall 195026049Sminshall while (*cp3) { 195126049Sminshall *cp1++ = *cp3++; 195226049Sminshall } 195326049Sminshall match = 1; 195426049Sminshall } 195526049Sminshall else if (toks[toknum = *cp2 - '1']) { 195626049Sminshall char *cp3 = tp[toknum]; 195726049Sminshall 195826049Sminshall while (cp3 != te[toknum]) { 195926049Sminshall *cp1++ = *cp3++; 196026049Sminshall } 196126049Sminshall match = 1; 196226049Sminshall } 196326049Sminshall } 196426049Sminshall else { 196526049Sminshall while (*cp2 && *cp2 != ',' && 196626049Sminshall *cp2 != ']') { 196726049Sminshall if (*cp2 == '\\') { 196826049Sminshall cp2++; 196926049Sminshall } 197026049Sminshall else if (*cp2 == '$' && 197126049Sminshall isdigit(*(cp2+1))) { 197226049Sminshall if (*++cp2 == '0') { 197326049Sminshall char *cp3 = name; 197426049Sminshall 197526049Sminshall while (*cp3) { 197626049Sminshall *cp1++ = *cp3++; 197726049Sminshall } 197826049Sminshall } 197926049Sminshall else if (toks[toknum = 198026049Sminshall *cp2 - '1']) { 198126049Sminshall char *cp3=tp[toknum]; 198226049Sminshall 198326049Sminshall while (cp3 != 198426049Sminshall te[toknum]) { 198526049Sminshall *cp1++ = *cp3++; 198626049Sminshall } 198726049Sminshall } 198826049Sminshall } 198926049Sminshall else if (*cp2) { 199026049Sminshall *cp1++ = *cp2++; 199126049Sminshall } 199226049Sminshall } 199326049Sminshall if (!*cp2) { 199426049Sminshall printf("nmap: unbalanced brackets\n"); 199526049Sminshall return(name); 199626049Sminshall } 199726049Sminshall match = 1; 199826049Sminshall cp2--; 199926049Sminshall } 200026049Sminshall if (match) { 200126049Sminshall while (*++cp2 && *cp2 != ']') { 200226049Sminshall if (*cp2 == '\\' && *(cp2 + 1)) { 200326049Sminshall cp2++; 200426049Sminshall } 200526049Sminshall } 200626049Sminshall if (!*cp2) { 200726049Sminshall printf("nmap: unbalanced brackets\n"); 200826049Sminshall return(name); 200926049Sminshall } 201026049Sminshall break; 201126049Sminshall } 201226049Sminshall switch (*++cp2) { 201326049Sminshall case ',': 201426049Sminshall goto LOOP; 201526049Sminshall case ']': 201626049Sminshall break; 201726049Sminshall default: 201826049Sminshall cp2--; 201926049Sminshall goto LOOP; 202026049Sminshall } 202126049Sminshall break; 202226049Sminshall case '$': 202326049Sminshall if (isdigit(*(cp2 + 1))) { 202426049Sminshall if (*++cp2 == '0') { 202526049Sminshall char *cp3 = name; 202626049Sminshall 202726049Sminshall while (*cp3) { 202826049Sminshall *cp1++ = *cp3++; 202926049Sminshall } 203026049Sminshall } 203126049Sminshall else if (toks[toknum = *cp2 - '1']) { 203226049Sminshall char *cp3 = tp[toknum]; 203326049Sminshall 203426049Sminshall while (cp3 != te[toknum]) { 203526049Sminshall *cp1++ = *cp3++; 203626049Sminshall } 203726049Sminshall } 203826049Sminshall break; 203926049Sminshall } 204026049Sminshall /* intentional drop through */ 204126049Sminshall default: 204226049Sminshall *cp1++ = *cp2; 204326049Sminshall break; 204426049Sminshall } 204526049Sminshall cp2++; 204626049Sminshall } 204726049Sminshall *cp1 = '\0'; 204826049Sminshall if (!*new) { 204926049Sminshall return(name); 205026049Sminshall } 205126049Sminshall return(new); 205226049Sminshall } 205326049Sminshall 205426049Sminshall setsunique() 205526049Sminshall { 205626049Sminshall sunique = !sunique; 205726049Sminshall printf("Store unique %s.\n", onoff(sunique)); 205826049Sminshall code = sunique; 205926049Sminshall } 206026049Sminshall 206126049Sminshall setrunique() 206226049Sminshall { 206326049Sminshall runique = !runique; 206426049Sminshall printf("Receive unique %s.\n", onoff(runique)); 206526049Sminshall code = runique; 206626049Sminshall } 206726049Sminshall 206826049Sminshall /* change directory to perent directory */ 206926049Sminshall cdup() 207026049Sminshall { 207137224Skarels if (command("CDUP") == ERROR && code == 500) { 207237224Skarels if (verbose) 207337224Skarels printf("CDUP command not recognized, trying XCUP\n"); 207437224Skarels (void) command("XCUP"); 207537224Skarels } 207626049Sminshall } 207726049Sminshall 207837224Skarels /* restart transfer at specific point */ 207937224Skarels restart(argc, argv) 208037224Skarels int argc; 208137224Skarels char *argv[]; 208237224Skarels { 208337224Skarels extern long atol(); 208437224Skarels if (argc != 2) 208537224Skarels printf("restart: offset not specified\n"); 208637224Skarels else { 208737224Skarels restart_point = atol(argv[1]); 208837224Skarels printf("restarting at %ld. %s\n", restart_point, 208937224Skarels "execute get, put or append to initiate transfer"); 209037224Skarels } 209137224Skarels } 209236935Skarels 209336935Skarels /* show remote system type */ 209436935Skarels syst() 209536935Skarels { 209636935Skarels (void) command("SYST"); 209736935Skarels } 209836935Skarels 209926049Sminshall macdef(argc, argv) 210026049Sminshall int argc; 210126049Sminshall char *argv[]; 210226049Sminshall { 210326049Sminshall char *tmp; 210426049Sminshall int c; 210526049Sminshall 210626049Sminshall if (macnum == 16) { 210726049Sminshall printf("Limit of 16 macros have already been defined\n"); 210826049Sminshall code = -1; 210926049Sminshall return; 211026049Sminshall } 211126049Sminshall if (argc < 2) { 211226497Sminshall (void) strcat(line, " "); 211326049Sminshall printf("(macro name) "); 211426497Sminshall (void) gets(&line[strlen(line)]); 211526049Sminshall makeargv(); 211626049Sminshall argc = margc; 211726049Sminshall argv = margv; 211826049Sminshall } 211926049Sminshall if (argc != 2) { 212026049Sminshall printf("Usage: %s macro_name\n",argv[0]); 212126049Sminshall code = -1; 212226049Sminshall return; 212326049Sminshall } 212426049Sminshall if (interactive) { 212526049Sminshall printf("Enter macro line by line, terminating it with a null line\n"); 212626049Sminshall } 212726497Sminshall (void) strncpy(macros[macnum].mac_name, argv[1], 8); 212826049Sminshall if (macnum == 0) { 212926049Sminshall macros[macnum].mac_start = macbuf; 213026049Sminshall } 213126049Sminshall else { 213226049Sminshall macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 213326049Sminshall } 213426049Sminshall tmp = macros[macnum].mac_start; 213526049Sminshall while (tmp != macbuf+4096) { 213626049Sminshall if ((c = getchar()) == EOF) { 213726049Sminshall printf("macdef:end of file encountered\n"); 213826049Sminshall code = -1; 213926049Sminshall return; 214026049Sminshall } 214126049Sminshall if ((*tmp = c) == '\n') { 214226049Sminshall if (tmp == macros[macnum].mac_start) { 214326049Sminshall macros[macnum++].mac_end = tmp; 214426049Sminshall code = 0; 214526049Sminshall return; 214626049Sminshall } 214726049Sminshall if (*(tmp-1) == '\0') { 214826049Sminshall macros[macnum++].mac_end = tmp - 1; 214926049Sminshall code = 0; 215026049Sminshall return; 215126049Sminshall } 215226049Sminshall *tmp = '\0'; 215326049Sminshall } 215426049Sminshall tmp++; 215526049Sminshall } 215626049Sminshall while (1) { 215736935Skarels while ((c = getchar()) != '\n' && c != EOF) 215836935Skarels /* LOOP */; 215926049Sminshall if (c == EOF || getchar() == '\n') { 216026049Sminshall printf("Macro not defined - 4k buffer exceeded\n"); 216126049Sminshall code = -1; 216226049Sminshall return; 216326049Sminshall } 216426049Sminshall } 216526049Sminshall } 216636935Skarels 216736935Skarels /* 216836935Skarels * get size of file on remote machine 216936935Skarels */ 217036935Skarels sizecmd(argc, argv) 217136935Skarels char *argv[]; 217236935Skarels { 217336935Skarels 217436935Skarels if (argc < 2) { 217536935Skarels (void) strcat(line, " "); 217636935Skarels printf("(filename) "); 217736935Skarels (void) gets(&line[strlen(line)]); 217836935Skarels makeargv(); 217936935Skarels argc = margc; 218036935Skarels argv = margv; 218136935Skarels } 218236935Skarels if (argc < 2) { 218336935Skarels printf("usage:%s filename\n", argv[0]); 218436935Skarels code = -1; 218536935Skarels return; 218636935Skarels } 218736935Skarels (void) command("SIZE %s", argv[1]); 218836935Skarels } 218936935Skarels 219036935Skarels /* 219136935Skarels * get last modification time of file on remote machine 219236935Skarels */ 219336935Skarels modtime(argc, argv) 219436935Skarels char *argv[]; 219536935Skarels { 219636935Skarels int overbose; 219736935Skarels 219836935Skarels if (argc < 2) { 219936935Skarels (void) strcat(line, " "); 220036935Skarels printf("(filename) "); 220136935Skarels (void) gets(&line[strlen(line)]); 220236935Skarels makeargv(); 220336935Skarels argc = margc; 220436935Skarels argv = margv; 220536935Skarels } 220636935Skarels if (argc < 2) { 220736935Skarels printf("usage:%s filename\n", argv[0]); 220836935Skarels code = -1; 220936935Skarels return; 221036935Skarels } 221136940Skarels overbose = verbose; 221236940Skarels if (debug == 0) 221336940Skarels verbose = -1; 221436935Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 221536935Skarels int yy, mo, day, hour, min, sec; 221636935Skarels sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 221736935Skarels &day, &hour, &min, &sec); 221836935Skarels /* might want to print this in local time */ 221936935Skarels printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 222036935Skarels mo, day, yy, hour, min, sec); 222136935Skarels } else 2222*38132Srick printf("%s\n", reply_string); 222336935Skarels verbose = overbose; 222436935Skarels } 222536935Skarels 222636935Skarels /* 222737224Skarels * show status on reomte machine 222836935Skarels */ 222936935Skarels rmtstatus(argc, argv) 223036935Skarels char *argv[]; 223136935Skarels { 223236935Skarels (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 223336935Skarels } 223437224Skarels 223537224Skarels /* 223637224Skarels * get file if modtime is more recent than current file 223737224Skarels */ 223837224Skarels newer(argc, argv) 223937224Skarels char *argv[]; 224037224Skarels { 224137224Skarels if (getit(argc, argv, -1, "w")) 224237224Skarels printf("Local file \"%s\" is newer than remote file \"%s\"\n", 224337224Skarels argv[1], argv[2]); 224437224Skarels } 2245