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*38202Srick static char sccsid[] = "@(#)cmds.c 5.21 (Berkeley) 05/30/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> 3838132Srick #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(); 50*38202Srick extern char *strerror(); 51*38202Srick extern int errno; 5237224Skarels extern off_t restart_point; 5336935Skarels extern char reply_string[]; 5436935Skarels 5526049Sminshall char *mname; 5626049Sminshall jmp_buf jabort; 5726049Sminshall char *dotrans(), *domap(); 5810294Ssam 5910294Ssam /* 6010294Ssam * Connect to peer server and 6110294Ssam * auto-login, if possible. 6210294Ssam */ 6310294Ssam setpeer(argc, argv) 6410294Ssam int argc; 6510294Ssam char *argv[]; 6610294Ssam { 6725903Skarels char *host, *hookup(); 6838132Srick short port; 6910294Ssam 7010294Ssam if (connected) { 7126049Sminshall printf("Already connected to %s, use close first.\n", 7210294Ssam hostname); 7326049Sminshall code = -1; 7410294Ssam return; 7510294Ssam } 7610294Ssam if (argc < 2) { 7726497Sminshall (void) strcat(line, " "); 7810294Ssam printf("(to) "); 7926497Sminshall (void) gets(&line[strlen(line)]); 8010294Ssam makeargv(); 8110294Ssam argc = margc; 8210294Ssam argv = margv; 8310294Ssam } 8410294Ssam if (argc > 3) { 8510294Ssam printf("usage: %s host-name [port]\n", argv[0]); 8626049Sminshall code = -1; 8710294Ssam return; 8810294Ssam } 8910294Ssam port = sp->s_port; 9010294Ssam if (argc > 2) { 9111218Ssam port = atoi(argv[2]); 9210294Ssam if (port <= 0) { 9311218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 9411218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 9526049Sminshall code = -1; 9610294Ssam return; 9710294Ssam } 9810294Ssam port = htons(port); 9910294Ssam } 10010294Ssam host = hookup(argv[1], port); 10110294Ssam if (host) { 10237228Skarels int overbose; 10337228Skarels 10410294Ssam connected = 1; 10538032Skarels /* 10638032Skarels * Set up defaults for FTP. 10738032Skarels */ 10838032Skarels (void) strcpy(typename, "ascii"), type = TYPE_A; 10938032Skarels curtype = TYPE_A; 11038032Skarels (void) strcpy(formname, "non-print"), form = FORM_N; 11138032Skarels (void) strcpy(modename, "stream"), mode = MODE_S; 11238032Skarels (void) strcpy(structname, "file"), stru = STRU_F; 11338032Skarels (void) strcpy(bytename, "8"), bytesize = 8; 11437228Skarels if (autologin) 11537228Skarels (void) login(argv[1]); 11636940Skarels 11736935Skarels #if defined(unix) && NBBY == 8 11836935Skarels /* 11936935Skarels * this ifdef is to keep someone form "porting" this to an incompatible 12036935Skarels * system and not checking this out. This way they have to think about it. 12136935Skarels */ 12237228Skarels overbose = verbose; 12337228Skarels if (debug == 0) 12437228Skarels verbose = -1; 12537228Skarels if (command("SYST") == COMPLETE && overbose) { 12637228Skarels register char *cp, c; 12737228Skarels cp = index(reply_string+4, ' '); 12837228Skarels if (cp == NULL) 12937228Skarels cp = index(reply_string+4, '\r'); 13037228Skarels if (cp) { 13137228Skarels if (cp[-1] == '.') 13237228Skarels cp--; 13337228Skarels c = *cp; 13437228Skarels *cp = '\0'; 13537228Skarels } 13636935Skarels 13737228Skarels printf("Remote system type is %s.\n", 13837228Skarels reply_string+4); 13937228Skarels if (cp) 14037228Skarels *cp = c; 14137228Skarels } 14237228Skarels if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { 14338032Skarels if (proxy) 14438032Skarels unix_proxy = 1; 14538032Skarels else 14638032Skarels unix_server = 1; 14738032Skarels /* 14838032Skarels * Set type to 0 (not specified by user), 14938032Skarels * meaning binary by default, but don't bother 15038032Skarels * telling server. We can use binary 15138032Skarels * for text files unless changed by the user. 15238032Skarels */ 15338032Skarels type = 0; 15438032Skarels (void) strcpy(typename, "binary"); 15537228Skarels if (overbose) 15637228Skarels printf("Using %s mode to transfer files.\n", 15737228Skarels typename); 15838032Skarels } else { 15938032Skarels if (proxy) 16038032Skarels unix_proxy = 0; 16138032Skarels else 16238032Skarels unix_server = 0; 16338032Skarels if (overbose && 16438032Skarels !strncmp(reply_string, "215 TOPS20", 10)) 16538032Skarels printf( 16636940Skarels "Remember to set tenex mode when transfering binary files from this machine.\n"); 16737228Skarels } 16837228Skarels verbose = overbose; 16936935Skarels #endif /* unix */ 17010294Ssam } 17110294Ssam } 17210294Ssam 17310294Ssam struct types { 17410294Ssam char *t_name; 17510294Ssam char *t_mode; 17610294Ssam int t_type; 17711218Ssam char *t_arg; 17810294Ssam } types[] = { 17911218Ssam { "ascii", "A", TYPE_A, 0 }, 18011218Ssam { "binary", "I", TYPE_I, 0 }, 18111218Ssam { "image", "I", TYPE_I, 0 }, 18211218Ssam { "ebcdic", "E", TYPE_E, 0 }, 18311218Ssam { "tenex", "L", TYPE_L, bytename }, 18410294Ssam 0 18510294Ssam }; 18610294Ssam 18710294Ssam /* 18810294Ssam * Set transfer type. 18910294Ssam */ 19010294Ssam settype(argc, argv) 19110294Ssam char *argv[]; 19210294Ssam { 19310294Ssam register struct types *p; 19411218Ssam int comret; 19510294Ssam 19610294Ssam if (argc > 2) { 19710294Ssam char *sep; 19810294Ssam 19910294Ssam printf("usage: %s [", argv[0]); 20010294Ssam sep = " "; 20110294Ssam for (p = types; p->t_name; p++) { 20210294Ssam printf("%s%s", sep, p->t_name); 20338032Skarels sep = " | "; 20410294Ssam } 20510294Ssam printf(" ]\n"); 20626049Sminshall code = -1; 20710294Ssam return; 20810294Ssam } 20910294Ssam if (argc < 2) { 21010294Ssam printf("Using %s mode to transfer files.\n", typename); 21126049Sminshall code = 0; 21210294Ssam return; 21310294Ssam } 21410294Ssam for (p = types; p->t_name; p++) 21510294Ssam if (strcmp(argv[1], p->t_name) == 0) 21610294Ssam break; 21710294Ssam if (p->t_name == 0) { 21810294Ssam printf("%s: unknown mode\n", argv[1]); 21926049Sminshall code = -1; 22010294Ssam return; 22110294Ssam } 22211218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 22311218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 22411218Ssam else 22511218Ssam comret = command("TYPE %s", p->t_mode); 22611218Ssam if (comret == COMPLETE) { 22726497Sminshall (void) strcpy(typename, p->t_name); 22838032Skarels curtype = type = p->t_type; 22910294Ssam } 23010294Ssam } 23110294Ssam 23210294Ssam /* 23338032Skarels * Internal form of settype; changes current type in use with server 23438032Skarels * without changing our notion of the type for data transfers. 23538032Skarels * Used to change to and from ascii for listings. 23638032Skarels */ 23738032Skarels changetype(newtype, show) 23838032Skarels int newtype, show; 23938032Skarels { 24038032Skarels register struct types *p; 24138032Skarels int comret, oldverbose = verbose; 24238032Skarels 24338032Skarels if (newtype == 0) 24438032Skarels newtype = TYPE_I; 24538032Skarels if (newtype == curtype) 24638032Skarels return; 24738032Skarels if (debug == 0 && show == 0) 24838032Skarels verbose = 0; 24938032Skarels for (p = types; p->t_name; p++) 25038032Skarels if (newtype == p->t_type) 25138032Skarels break; 25238032Skarels if (p->t_name == 0) { 25338032Skarels printf("ftp: internal error: unknown type %d\n", newtype); 25438032Skarels return; 25538032Skarels } 25638032Skarels if (newtype == TYPE_L && bytename[0] != '\0') 25738032Skarels comret = command("TYPE %s %s", p->t_mode, bytename); 25838032Skarels else 25938032Skarels comret = command("TYPE %s", p->t_mode); 26038032Skarels if (comret == COMPLETE) 26138032Skarels curtype = newtype; 26238032Skarels verbose = oldverbose; 26338032Skarels } 26438032Skarels 26538132Srick char *stype[] = { 26638132Srick "type", 26738132Srick "", 26838132Srick 0 26938132Srick }; 27038132Srick 27138032Skarels /* 27210294Ssam * Set binary transfer type. 27310294Ssam */ 27410294Ssam /*VARARGS*/ 27510294Ssam setbinary() 27610294Ssam { 27738132Srick stype[1] = "binary"; 27838132Srick settype(2, stype); 27910294Ssam } 28010294Ssam 28110294Ssam /* 28210294Ssam * Set ascii transfer type. 28310294Ssam */ 28410294Ssam /*VARARGS*/ 28510294Ssam setascii() 28610294Ssam { 28738132Srick stype[1] = "ascii"; 28838132Srick settype(2, stype); 28910294Ssam } 29010294Ssam 29110294Ssam /* 29210294Ssam * Set tenex transfer type. 29310294Ssam */ 29410294Ssam /*VARARGS*/ 29510294Ssam settenex() 29610294Ssam { 29738132Srick stype[1] = "tenex"; 29838132Srick settype(2, stype); 29910294Ssam } 30010294Ssam 30110294Ssam /* 30210294Ssam * Set file transfer mode. 30310294Ssam */ 30426497Sminshall /*ARGSUSED*/ 30510294Ssam setmode(argc, argv) 30610294Ssam char *argv[]; 30710294Ssam { 30810294Ssam 30910294Ssam printf("We only support %s mode, sorry.\n", modename); 31026049Sminshall code = -1; 31110294Ssam } 31210294Ssam 31310294Ssam /* 31410294Ssam * Set file transfer format. 31510294Ssam */ 31626497Sminshall /*ARGSUSED*/ 31710294Ssam setform(argc, argv) 31810294Ssam char *argv[]; 31910294Ssam { 32010294Ssam 32110294Ssam printf("We only support %s format, sorry.\n", formname); 32226049Sminshall code = -1; 32310294Ssam } 32410294Ssam 32510294Ssam /* 32610294Ssam * Set file transfer structure. 32710294Ssam */ 32826497Sminshall /*ARGSUSED*/ 32910294Ssam setstruct(argc, argv) 33010294Ssam char *argv[]; 33110294Ssam { 33210294Ssam 33310294Ssam printf("We only support %s structure, sorry.\n", structname); 33426049Sminshall code = -1; 33510294Ssam } 33610294Ssam 33718286Sralph /* 33818286Sralph * Send a single file. 33918286Sralph */ 34010294Ssam put(argc, argv) 34111756Ssam int argc; 34210294Ssam char *argv[]; 34310294Ssam { 34411650Ssam char *cmd; 34526049Sminshall int loc = 0; 34637225Skarels char *oldargv1, *oldargv2; 34711650Ssam 34826049Sminshall if (argc == 2) { 34926049Sminshall argc++; 35026049Sminshall argv[2] = argv[1]; 35126049Sminshall loc++; 35226049Sminshall } 35310294Ssam if (argc < 2) { 35426497Sminshall (void) strcat(line, " "); 35510294Ssam printf("(local-file) "); 35626497Sminshall (void) gets(&line[strlen(line)]); 35710294Ssam makeargv(); 35810294Ssam argc = margc; 35910294Ssam argv = margv; 36010294Ssam } 36110294Ssam if (argc < 2) { 36210294Ssam usage: 36326049Sminshall printf("usage:%s local-file remote-file\n", argv[0]); 36426049Sminshall code = -1; 36510294Ssam return; 36610294Ssam } 36710294Ssam if (argc < 3) { 36826497Sminshall (void) strcat(line, " "); 36910294Ssam printf("(remote-file) "); 37026497Sminshall (void) gets(&line[strlen(line)]); 37110294Ssam makeargv(); 37210294Ssam argc = margc; 37310294Ssam argv = margv; 37410294Ssam } 37510294Ssam if (argc < 3) 37610294Ssam goto usage; 37725908Smckusick oldargv1 = argv[1]; 37837225Skarels oldargv2 = argv[2]; 37926049Sminshall if (!globulize(&argv[1])) { 38026049Sminshall code = -1; 38111353Ssam return; 38226049Sminshall } 38325908Smckusick /* 38425908Smckusick * If "globulize" modifies argv[1], and argv[2] is a copy of 38525908Smckusick * the old argv[1], make it a copy of the new argv[1]. 38625908Smckusick */ 38726049Sminshall if (argv[1] != oldargv1 && argv[2] == oldargv1) { 38825908Smckusick argv[2] = argv[1]; 38926049Sminshall } 39026049Sminshall cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); 39126049Sminshall if (loc && ntflag) { 39226049Sminshall argv[2] = dotrans(argv[2]); 39326049Sminshall } 39426049Sminshall if (loc && mapflag) { 39526049Sminshall argv[2] = domap(argv[2]); 39626049Sminshall } 39737225Skarels sendrequest(cmd, argv[1], argv[2], 39837225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 39910294Ssam } 40010294Ssam 40110294Ssam /* 40211756Ssam * Send multiple files. 40310294Ssam */ 40411353Ssam mput(argc, argv) 40511353Ssam char *argv[]; 40611353Ssam { 40713212Ssam register int i; 40838132Srick int ointer; 40938132Srick sig_t (*oldintr)(), mabort(); 41026049Sminshall extern jmp_buf jabort; 41126049Sminshall char *tp; 41211353Ssam 41311650Ssam if (argc < 2) { 41426497Sminshall (void) strcat(line, " "); 41511650Ssam printf("(local-files) "); 41626497Sminshall (void) gets(&line[strlen(line)]); 41711650Ssam makeargv(); 41811650Ssam argc = margc; 41911650Ssam argv = margv; 42011353Ssam } 42111353Ssam if (argc < 2) { 42226049Sminshall printf("usage:%s local-files\n", argv[0]); 42326049Sminshall code = -1; 42411353Ssam return; 42511353Ssam } 42626049Sminshall mname = argv[0]; 42726049Sminshall mflag = 1; 42826049Sminshall oldintr = signal(SIGINT, mabort); 42926049Sminshall (void) setjmp(jabort); 43026049Sminshall if (proxy) { 43126049Sminshall char *cp, *tp2, tmpbuf[MAXPATHLEN]; 43226049Sminshall 43326497Sminshall while ((cp = remglob(argv,0)) != NULL) { 43426049Sminshall if (*cp == 0) { 43526049Sminshall mflag = 0; 43626049Sminshall continue; 43726049Sminshall } 43826049Sminshall if (mflag && confirm(argv[0], cp)) { 43926049Sminshall tp = cp; 44026049Sminshall if (mcase) { 44126049Sminshall while (*tp && !islower(*tp)) { 44226049Sminshall tp++; 44326049Sminshall } 44426049Sminshall if (!*tp) { 44526049Sminshall tp = cp; 44626049Sminshall tp2 = tmpbuf; 44726049Sminshall while ((*tp2 = *tp) != NULL) { 44826049Sminshall if (isupper(*tp2)) { 44926049Sminshall *tp2 = 'a' + *tp2 - 'A'; 45026049Sminshall } 45126049Sminshall tp++; 45226049Sminshall tp2++; 45326049Sminshall } 45426049Sminshall } 45526049Sminshall tp = tmpbuf; 45626049Sminshall } 45726049Sminshall if (ntflag) { 45826049Sminshall tp = dotrans(tp); 45926049Sminshall } 46026049Sminshall if (mapflag) { 46126049Sminshall tp = domap(tp); 46226049Sminshall } 46337225Skarels sendrequest((sunique) ? "STOU" : "STOR", 46437225Skarels cp, tp, cp != tp || !interactive); 46526049Sminshall if (!mflag && fromatty) { 46626049Sminshall ointer = interactive; 46726049Sminshall interactive = 1; 46826049Sminshall if (confirm("Continue with","mput")) { 46926049Sminshall mflag++; 47026049Sminshall } 47126049Sminshall interactive = ointer; 47226049Sminshall } 47326049Sminshall } 47426049Sminshall } 47526049Sminshall (void) signal(SIGINT, oldintr); 47626049Sminshall mflag = 0; 47726049Sminshall return; 47826049Sminshall } 47913212Ssam for (i = 1; i < argc; i++) { 48013212Ssam register char **cpp, **gargs; 48113212Ssam 48213212Ssam if (!doglob) { 48326049Sminshall if (mflag && confirm(argv[0], argv[i])) { 48426049Sminshall tp = (ntflag) ? dotrans(argv[i]) : argv[i]; 48526049Sminshall tp = (mapflag) ? domap(tp) : tp; 48626049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 48737225Skarels argv[i], tp, tp != argv[i] || !interactive); 48826049Sminshall if (!mflag && fromatty) { 48926049Sminshall ointer = interactive; 49026049Sminshall interactive = 1; 49126049Sminshall if (confirm("Continue with","mput")) { 49226049Sminshall mflag++; 49326049Sminshall } 49426049Sminshall interactive = ointer; 49526049Sminshall } 49626049Sminshall } 49713212Ssam continue; 49813212Ssam } 49913212Ssam gargs = glob(argv[i]); 50011650Ssam if (globerr != NULL) { 50111650Ssam printf("%s\n", globerr); 50236421Sbostic if (gargs) { 50311650Ssam blkfree(gargs); 50438132Srick free((char *)gargs); 50536421Sbostic } 50613212Ssam continue; 50711353Ssam } 50826049Sminshall for (cpp = gargs; cpp && *cpp != NULL; cpp++) { 50926049Sminshall if (mflag && confirm(argv[0], *cpp)) { 51026049Sminshall tp = (ntflag) ? dotrans(*cpp) : *cpp; 51126049Sminshall tp = (mapflag) ? domap(tp) : tp; 51226049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 51337225Skarels *cpp, tp, *cpp != tp || !interactive); 51426049Sminshall if (!mflag && fromatty) { 51526049Sminshall ointer = interactive; 51626049Sminshall interactive = 1; 51726049Sminshall if (confirm("Continue with","mput")) { 51826049Sminshall mflag++; 51926049Sminshall } 52026049Sminshall interactive = ointer; 52126049Sminshall } 52226049Sminshall } 52326049Sminshall } 52436421Sbostic if (gargs != NULL) { 52513212Ssam blkfree(gargs); 52638132Srick free((char *)gargs); 52736421Sbostic } 52811353Ssam } 52926049Sminshall (void) signal(SIGINT, oldintr); 53026049Sminshall mflag = 0; 53111353Ssam } 53211353Ssam 53337224Skarels reget(argc, argv) 53437224Skarels char *argv[]; 53537224Skarels { 53637224Skarels (void) getit(argc, argv, 1, "r+w"); 53737224Skarels } 53836935Skarels 53937224Skarels get(argc, argv) 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) 54910294Ssam char *argv[]; 55037224Skarels char *mode; 55110294Ssam { 55226049Sminshall int loc = 0; 55337225Skarels char *oldargv1, *oldargv2; 55410294Ssam 55526049Sminshall if (argc == 2) { 55626049Sminshall argc++; 55726049Sminshall argv[2] = argv[1]; 55826049Sminshall loc++; 55926049Sminshall } 56010294Ssam if (argc < 2) { 56126497Sminshall (void) strcat(line, " "); 56210294Ssam printf("(remote-file) "); 56326497Sminshall (void) gets(&line[strlen(line)]); 56410294Ssam makeargv(); 56510294Ssam argc = margc; 56610294Ssam argv = margv; 56710294Ssam } 56810294Ssam if (argc < 2) { 56910294Ssam usage: 57026049Sminshall printf("usage: %s remote-file [ local-file ]\n", argv[0]); 57126049Sminshall code = -1; 57237224Skarels return (0); 57310294Ssam } 57410294Ssam if (argc < 3) { 57526497Sminshall (void) strcat(line, " "); 57610294Ssam printf("(local-file) "); 57726497Sminshall (void) gets(&line[strlen(line)]); 57810294Ssam makeargv(); 57910294Ssam argc = margc; 58010294Ssam argv = margv; 58110294Ssam } 58210294Ssam if (argc < 3) 58310294Ssam goto usage; 58437225Skarels oldargv1 = argv[1]; 58537225Skarels oldargv2 = argv[2]; 58626049Sminshall if (!globulize(&argv[2])) { 58726049Sminshall code = -1; 58837224Skarels return (0); 58926049Sminshall } 59026049Sminshall if (loc && mcase) { 59126049Sminshall char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; 59226049Sminshall 59326049Sminshall while (*tp && !islower(*tp)) { 59426049Sminshall tp++; 59526049Sminshall } 59626049Sminshall if (!*tp) { 59726049Sminshall tp = argv[2]; 59826049Sminshall tp2 = tmpbuf; 59926049Sminshall while ((*tp2 = *tp) != NULL) { 60026049Sminshall if (isupper(*tp2)) { 60126049Sminshall *tp2 = 'a' + *tp2 - 'A'; 60226049Sminshall } 60326049Sminshall tp++; 60426049Sminshall tp2++; 60526049Sminshall } 60626049Sminshall argv[2] = tmpbuf; 60726049Sminshall } 60826049Sminshall } 60936940Skarels if (loc && ntflag) 61026049Sminshall argv[2] = dotrans(argv[2]); 61136940Skarels if (loc && mapflag) 61226049Sminshall argv[2] = domap(argv[2]); 61337224Skarels if (restartit) { 61437224Skarels struct stat stbuf; 61537224Skarels int ret; 61637224Skarels 61737224Skarels ret = stat(argv[2], &stbuf); 61837224Skarels if (restartit == 1) { 61937224Skarels if (ret < 0) { 620*38202Srick fprintf(stderr, "local: %s: %s\n", argv[2], 621*38202Srick strerror(errno)); 62237224Skarels return (0); 62337224Skarels } 62437224Skarels restart_point = stbuf.st_size; 62537224Skarels } else { 62637224Skarels if (ret == 0) { 62737224Skarels int overbose; 62837224Skarels 62937224Skarels overbose = verbose; 63037224Skarels if (debug == 0) 63137224Skarels verbose = -1; 63237224Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 63337224Skarels int yy, mo, day, hour, min, sec; 63437224Skarels struct tm *tm; 63537224Skarels verbose = overbose; 63637224Skarels sscanf(reply_string, 63737224Skarels "%*s %04d%02d%02d%02d%02d%02d", 63837224Skarels &yy, &mo, &day, &hour, &min, &sec); 63937224Skarels tm = gmtime(&stbuf.st_mtime); 64037224Skarels tm->tm_mon++; 64137224Skarels if (tm->tm_year > yy%100) 64237224Skarels return (1); 64337224Skarels else if (tm->tm_year == yy%100) { 64437224Skarels if (tm->tm_mon > mo) 64537224Skarels return (1); 64637224Skarels } else if (tm->tm_mon == mo) { 64737224Skarels if (tm->tm_mday > day) 64837224Skarels return (1); 64937224Skarels } else if (tm->tm_mday == day) { 65037224Skarels if (tm->tm_hour > hour) 65137224Skarels return (1); 65237224Skarels } else if (tm->tm_hour == hour) { 65337224Skarels if (tm->tm_min > min) 65437224Skarels return (1); 65537224Skarels } else if (tm->tm_min == min) { 65637224Skarels if (tm->tm_sec > sec) 65737224Skarels return (1); 65837224Skarels } 65937224Skarels } else { 66038132Srick printf("%s\n", reply_string); 66137224Skarels verbose = overbose; 66237224Skarels return (0); 66337224Skarels } 66437224Skarels } 66537224Skarels } 66637224Skarels } 66737224Skarels 66837225Skarels recvrequest("RETR", argv[2], argv[1], mode, 66937225Skarels argv[1] != oldargv1 || argv[2] != oldargv2); 67037224Skarels restart_point = 0; 67137224Skarels return (0); 67210294Ssam } 67310294Ssam 67438132Srick sig_t 67526049Sminshall mabort() 67626049Sminshall { 67726049Sminshall int ointer; 67826049Sminshall extern jmp_buf jabort; 67926049Sminshall 68026049Sminshall printf("\n"); 68126049Sminshall (void) fflush(stdout); 68226049Sminshall if (mflag && fromatty) { 68326049Sminshall ointer = interactive; 68426049Sminshall interactive = 1; 68526049Sminshall if (confirm("Continue with", mname)) { 68626049Sminshall interactive = ointer; 68726049Sminshall longjmp(jabort,0); 68826049Sminshall } 68926049Sminshall interactive = ointer; 69026049Sminshall } 69126049Sminshall mflag = 0; 69226049Sminshall longjmp(jabort,0); 69326049Sminshall } 69426049Sminshall 69511353Ssam /* 69611353Ssam * Get multiple files. 69711353Ssam */ 69811353Ssam mget(argc, argv) 69911353Ssam char *argv[]; 70011353Ssam { 70126049Sminshall char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; 70238132Srick int ointer; 70338132Srick sig_t (*oldintr)(), mabort(); 70426049Sminshall extern jmp_buf jabort; 70511353Ssam 70611353Ssam if (argc < 2) { 70726497Sminshall (void) strcat(line, " "); 70811756Ssam printf("(remote-files) "); 70926497Sminshall (void) gets(&line[strlen(line)]); 71011353Ssam makeargv(); 71111353Ssam argc = margc; 71211353Ssam argv = margv; 71311353Ssam } 71411353Ssam if (argc < 2) { 71526049Sminshall printf("usage:%s remote-files\n", argv[0]); 71626049Sminshall code = -1; 71711353Ssam return; 71811353Ssam } 71926049Sminshall mname = argv[0]; 72026049Sminshall mflag = 1; 72126049Sminshall oldintr = signal(SIGINT,mabort); 72226049Sminshall (void) setjmp(jabort); 72326497Sminshall while ((cp = remglob(argv,proxy)) != NULL) { 72426049Sminshall if (*cp == '\0') { 72526049Sminshall mflag = 0; 72626049Sminshall continue; 72726049Sminshall } 72826049Sminshall if (mflag && confirm(argv[0], cp)) { 72926049Sminshall tp = cp; 73026049Sminshall if (mcase) { 73126049Sminshall while (*tp && !islower(*tp)) { 73226049Sminshall tp++; 73326049Sminshall } 73426049Sminshall if (!*tp) { 73526049Sminshall tp = cp; 73626049Sminshall tp2 = tmpbuf; 73726049Sminshall while ((*tp2 = *tp) != NULL) { 73826049Sminshall if (isupper(*tp2)) { 73926049Sminshall *tp2 = 'a' + *tp2 - 'A'; 74026049Sminshall } 74126049Sminshall tp++; 74226049Sminshall tp2++; 74326049Sminshall } 74426049Sminshall } 74526049Sminshall tp = tmpbuf; 74626049Sminshall } 74726049Sminshall if (ntflag) { 74826049Sminshall tp = dotrans(tp); 74926049Sminshall } 75026049Sminshall if (mapflag) { 75126049Sminshall tp = domap(tp); 75226049Sminshall } 75337225Skarels recvrequest("RETR", tp, cp, "w", 75437225Skarels tp != cp || !interactive); 75526049Sminshall if (!mflag && fromatty) { 75626049Sminshall ointer = interactive; 75726049Sminshall interactive = 1; 75826049Sminshall if (confirm("Continue with","mget")) { 75926049Sminshall mflag++; 76026049Sminshall } 76126049Sminshall interactive = ointer; 76226049Sminshall } 76326049Sminshall } 76426049Sminshall } 76526049Sminshall (void) signal(SIGINT,oldintr); 76626049Sminshall mflag = 0; 76711650Ssam } 76811650Ssam 76911650Ssam char * 77026497Sminshall remglob(argv,doswitch) 77111650Ssam char *argv[]; 77226497Sminshall int doswitch; 77311650Ssam { 77411756Ssam char temp[16]; 77511650Ssam static char buf[MAXPATHLEN]; 77611650Ssam static FILE *ftemp = NULL; 77711650Ssam static char **args; 77813212Ssam int oldverbose, oldhash; 77911756Ssam char *cp, *mode; 78011650Ssam 78126049Sminshall if (!mflag) { 78226049Sminshall if (!doglob) { 78326049Sminshall args = NULL; 78426049Sminshall } 78526049Sminshall else { 78626049Sminshall if (ftemp) { 78726497Sminshall (void) fclose(ftemp); 78826049Sminshall ftemp = NULL; 78926049Sminshall } 79026049Sminshall } 79126049Sminshall return(NULL); 79226049Sminshall } 79311650Ssam if (!doglob) { 79411756Ssam if (args == NULL) 79511650Ssam args = argv; 79611650Ssam if ((cp = *++args) == NULL) 79711650Ssam args = NULL; 79811650Ssam return (cp); 79911353Ssam } 80011650Ssam if (ftemp == NULL) { 80137458Skarels (void) strcpy(temp, _PATH_TMP); 80226497Sminshall (void) mktemp(temp); 80311650Ssam oldverbose = verbose, verbose = 0; 80413212Ssam oldhash = hash, hash = 0; 80526049Sminshall if (doswitch) { 80626049Sminshall pswitch(!proxy); 80726049Sminshall } 80811756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 80937225Skarels recvrequest ("NLST", temp, *argv, mode, 0); 81026049Sminshall if (doswitch) { 81126049Sminshall pswitch(!proxy); 81226049Sminshall } 81313212Ssam verbose = oldverbose; hash = oldhash; 81411650Ssam ftemp = fopen(temp, "r"); 81526497Sminshall (void) unlink(temp); 81611650Ssam if (ftemp == NULL) { 81711650Ssam printf("can't find list of remote files, oops\n"); 81811756Ssam return (NULL); 81911353Ssam } 82011353Ssam } 82111650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 82226497Sminshall (void) fclose(ftemp), ftemp = NULL; 82311650Ssam return (NULL); 82411353Ssam } 82511650Ssam if ((cp = index(buf, '\n')) != NULL) 82611650Ssam *cp = '\0'; 82711650Ssam return (buf); 82811353Ssam } 82911353Ssam 83010294Ssam char * 83110294Ssam onoff(bool) 83210294Ssam int bool; 83310294Ssam { 83410294Ssam 83510294Ssam return (bool ? "on" : "off"); 83610294Ssam } 83710294Ssam 83810294Ssam /* 83910294Ssam * Show status. 84010294Ssam */ 84126497Sminshall /*ARGSUSED*/ 84210294Ssam status(argc, argv) 84310294Ssam char *argv[]; 84410294Ssam { 84526049Sminshall int i; 84610294Ssam 84710294Ssam if (connected) 84810294Ssam printf("Connected to %s.\n", hostname); 84910294Ssam else 85010294Ssam printf("Not connected.\n"); 85126049Sminshall if (!proxy) { 85226049Sminshall pswitch(1); 85326049Sminshall if (connected) { 85426049Sminshall printf("Connected for proxy commands to %s.\n", hostname); 85526049Sminshall } 85626049Sminshall else { 85726049Sminshall printf("No proxy connection.\n"); 85826049Sminshall } 85926049Sminshall pswitch(0); 86026049Sminshall } 86110294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 86210294Ssam modename, typename, formname, structname); 86311353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 86411353Ssam onoff(verbose), onoff(bell), onoff(interactive), 86511353Ssam onoff(doglob)); 86626049Sminshall printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), 86726049Sminshall onoff(runique)); 86826049Sminshall printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); 86926049Sminshall if (ntflag) { 87026049Sminshall printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); 87126049Sminshall } 87226049Sminshall else { 87326049Sminshall printf("Ntrans: off\n"); 87426049Sminshall } 87526049Sminshall if (mapflag) { 87626049Sminshall printf("Nmap: (in) %s (out) %s\n", mapin, mapout); 87726049Sminshall } 87826049Sminshall else { 87926049Sminshall printf("Nmap: off\n"); 88026049Sminshall } 88114143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 88214143Ssam onoff(hash), onoff(sendport)); 88326049Sminshall if (macnum > 0) { 88426049Sminshall printf("Macros:\n"); 88526049Sminshall for (i=0; i<macnum; i++) { 88626049Sminshall printf("\t%s\n",macros[i].mac_name); 88726049Sminshall } 88826049Sminshall } 88926049Sminshall code = 0; 89010294Ssam } 89110294Ssam 89210294Ssam /* 89310294Ssam * Set beep on cmd completed mode. 89410294Ssam */ 89510294Ssam /*VARARGS*/ 89610294Ssam setbell() 89710294Ssam { 89810294Ssam 89910294Ssam bell = !bell; 90010294Ssam printf("Bell mode %s.\n", onoff(bell)); 90126049Sminshall code = bell; 90210294Ssam } 90310294Ssam 90410294Ssam /* 90510294Ssam * Turn on packet tracing. 90610294Ssam */ 90710294Ssam /*VARARGS*/ 90810294Ssam settrace() 90910294Ssam { 91010294Ssam 91110294Ssam trace = !trace; 91210294Ssam printf("Packet tracing %s.\n", onoff(trace)); 91326049Sminshall code = trace; 91410294Ssam } 91510294Ssam 91610294Ssam /* 91711650Ssam * Toggle hash mark printing during transfers. 91811650Ssam */ 91911650Ssam /*VARARGS*/ 92011650Ssam sethash() 92111650Ssam { 92211650Ssam 92311650Ssam hash = !hash; 92411650Ssam printf("Hash mark printing %s", onoff(hash)); 92526049Sminshall code = hash; 92611650Ssam if (hash) 92737224Skarels printf(" (%d bytes/hash mark)", 1024); 92811650Ssam printf(".\n"); 92911650Ssam } 93011650Ssam 93111650Ssam /* 93210294Ssam * Turn on printing of server echo's. 93310294Ssam */ 93410294Ssam /*VARARGS*/ 93510294Ssam setverbose() 93610294Ssam { 93710294Ssam 93810294Ssam verbose = !verbose; 93910294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 94026049Sminshall code = verbose; 94110294Ssam } 94210294Ssam 94310294Ssam /* 94411650Ssam * Toggle PORT cmd use before each data connection. 94511650Ssam */ 94611650Ssam /*VARARGS*/ 94711650Ssam setport() 94811650Ssam { 94911650Ssam 95011650Ssam sendport = !sendport; 95111650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 95226049Sminshall code = sendport; 95311650Ssam } 95411650Ssam 95511650Ssam /* 95610294Ssam * Turn on interactive prompting 95710294Ssam * during mget, mput, and mdelete. 95810294Ssam */ 95910294Ssam /*VARARGS*/ 96010294Ssam setprompt() 96110294Ssam { 96210294Ssam 96310294Ssam interactive = !interactive; 96410294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 96526049Sminshall code = interactive; 96610294Ssam } 96710294Ssam 96810294Ssam /* 96911353Ssam * Toggle metacharacter interpretation 97011353Ssam * on local file names. 97111353Ssam */ 97211353Ssam /*VARARGS*/ 97311353Ssam setglob() 97411353Ssam { 97511353Ssam 97611353Ssam doglob = !doglob; 97711353Ssam printf("Globbing %s.\n", onoff(doglob)); 97826049Sminshall code = doglob; 97911353Ssam } 98011353Ssam 98111353Ssam /* 98210294Ssam * Set debugging mode on/off and/or 98310294Ssam * set level of debugging. 98410294Ssam */ 98511756Ssam /*VARARGS*/ 98610294Ssam setdebug(argc, argv) 98710294Ssam char *argv[]; 98810294Ssam { 98910294Ssam int val; 99010294Ssam 99110294Ssam if (argc > 1) { 99210294Ssam val = atoi(argv[1]); 99310294Ssam if (val < 0) { 99410294Ssam printf("%s: bad debugging value.\n", argv[1]); 99526049Sminshall code = -1; 99610294Ssam return; 99710294Ssam } 99810294Ssam } else 99910294Ssam val = !debug; 100010294Ssam debug = val; 100110294Ssam if (debug) 100210294Ssam options |= SO_DEBUG; 100310294Ssam else 100410294Ssam options &= ~SO_DEBUG; 100510294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 100626049Sminshall code = debug > 0; 100710294Ssam } 100810294Ssam 100910294Ssam /* 101010294Ssam * Set current working directory 101110294Ssam * on remote machine. 101210294Ssam */ 101310294Ssam cd(argc, argv) 101410294Ssam char *argv[]; 101510294Ssam { 101610294Ssam 101710294Ssam if (argc < 2) { 101826497Sminshall (void) strcat(line, " "); 101910294Ssam printf("(remote-directory) "); 102026497Sminshall (void) gets(&line[strlen(line)]); 102110294Ssam makeargv(); 102210294Ssam argc = margc; 102310294Ssam argv = margv; 102410294Ssam } 102510294Ssam if (argc < 2) { 102626049Sminshall printf("usage:%s remote-directory\n", argv[0]); 102726049Sminshall code = -1; 102810294Ssam return; 102910294Ssam } 103037224Skarels if (command("CWD %s", argv[1]) == ERROR && code == 500) { 103137224Skarels if (verbose) 103237224Skarels printf("CWD command not recognized, trying XCWD\n"); 103337224Skarels (void) command("XCWD %s", argv[1]); 103437224Skarels } 103510294Ssam } 103610294Ssam 103710294Ssam /* 103810294Ssam * Set current working directory 103910294Ssam * on local machine. 104010294Ssam */ 104110294Ssam lcd(argc, argv) 104210294Ssam char *argv[]; 104310294Ssam { 104411353Ssam char buf[MAXPATHLEN]; 104538132Srick extern char *getwd(); 104610294Ssam 104711353Ssam if (argc < 2) 104811353Ssam argc++, argv[1] = home; 104910294Ssam if (argc != 2) { 105026049Sminshall printf("usage:%s local-directory\n", argv[0]); 105126049Sminshall code = -1; 105210294Ssam return; 105310294Ssam } 105426049Sminshall if (!globulize(&argv[1])) { 105526049Sminshall code = -1; 105611353Ssam return; 105726049Sminshall } 105811353Ssam if (chdir(argv[1]) < 0) { 1059*38202Srick fprintf(stderr, "local: %s: %s\n", argv[1], strerror(errno)); 106026049Sminshall code = -1; 106111353Ssam return; 106211353Ssam } 106311353Ssam printf("Local directory now %s\n", getwd(buf)); 106426049Sminshall code = 0; 106510294Ssam } 106610294Ssam 106710294Ssam /* 106810294Ssam * Delete a single file. 106910294Ssam */ 107010294Ssam delete(argc, argv) 107110294Ssam char *argv[]; 107210294Ssam { 107310294Ssam 107410294Ssam if (argc < 2) { 107526497Sminshall (void) strcat(line, " "); 107610294Ssam printf("(remote-file) "); 107726497Sminshall (void) gets(&line[strlen(line)]); 107810294Ssam makeargv(); 107910294Ssam argc = margc; 108010294Ssam argv = margv; 108110294Ssam } 108210294Ssam if (argc < 2) { 108326049Sminshall printf("usage:%s remote-file\n", argv[0]); 108426049Sminshall code = -1; 108510294Ssam return; 108610294Ssam } 108710294Ssam (void) command("DELE %s", argv[1]); 108810294Ssam } 108910294Ssam 109010294Ssam /* 109111650Ssam * Delete multiple files. 109211650Ssam */ 109311650Ssam mdelete(argc, argv) 109411650Ssam char *argv[]; 109511650Ssam { 109611650Ssam char *cp; 109738132Srick int ointer; 109838132Srick sig_t (*oldintr)(), mabort(); 109926049Sminshall extern jmp_buf jabort; 110011650Ssam 110111650Ssam if (argc < 2) { 110226497Sminshall (void) strcat(line, " "); 110311650Ssam printf("(remote-files) "); 110426497Sminshall (void) gets(&line[strlen(line)]); 110511650Ssam makeargv(); 110611650Ssam argc = margc; 110711650Ssam argv = margv; 110811650Ssam } 110911650Ssam if (argc < 2) { 111026049Sminshall printf("usage:%s remote-files\n", argv[0]); 111126049Sminshall code = -1; 111211650Ssam return; 111311650Ssam } 111426049Sminshall mname = argv[0]; 111526049Sminshall mflag = 1; 111626049Sminshall oldintr = signal(SIGINT, mabort); 111726049Sminshall (void) setjmp(jabort); 111826497Sminshall while ((cp = remglob(argv,0)) != NULL) { 111926049Sminshall if (*cp == '\0') { 112026049Sminshall mflag = 0; 112126049Sminshall continue; 112226049Sminshall } 112326049Sminshall if (mflag && confirm(argv[0], cp)) { 112411650Ssam (void) command("DELE %s", cp); 112526049Sminshall if (!mflag && fromatty) { 112626049Sminshall ointer = interactive; 112726049Sminshall interactive = 1; 112826049Sminshall if (confirm("Continue with", "mdelete")) { 112926049Sminshall mflag++; 113026049Sminshall } 113126049Sminshall interactive = ointer; 113226049Sminshall } 113326049Sminshall } 113426049Sminshall } 113526049Sminshall (void) signal(SIGINT, oldintr); 113626049Sminshall mflag = 0; 113711650Ssam } 113811756Ssam 113911650Ssam /* 114010294Ssam * Rename a remote file. 114110294Ssam */ 114210294Ssam renamefile(argc, argv) 114310294Ssam char *argv[]; 114410294Ssam { 114510294Ssam 114610294Ssam if (argc < 2) { 114726497Sminshall (void) strcat(line, " "); 114810294Ssam printf("(from-name) "); 114926497Sminshall (void) gets(&line[strlen(line)]); 115010294Ssam makeargv(); 115110294Ssam argc = margc; 115210294Ssam argv = margv; 115310294Ssam } 115410294Ssam if (argc < 2) { 115510294Ssam usage: 115610294Ssam printf("%s from-name to-name\n", argv[0]); 115726049Sminshall code = -1; 115810294Ssam return; 115910294Ssam } 116010294Ssam if (argc < 3) { 116126497Sminshall (void) strcat(line, " "); 116210294Ssam printf("(to-name) "); 116326497Sminshall (void) gets(&line[strlen(line)]); 116410294Ssam makeargv(); 116510294Ssam argc = margc; 116610294Ssam argv = margv; 116710294Ssam } 116810294Ssam if (argc < 3) 116910294Ssam goto usage; 117010294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 117110294Ssam (void) command("RNTO %s", argv[2]); 117210294Ssam } 117310294Ssam 117410294Ssam /* 117510294Ssam * Get a directory listing 117610294Ssam * of remote files. 117710294Ssam */ 117810294Ssam ls(argc, argv) 117910294Ssam char *argv[]; 118010294Ssam { 118111756Ssam char *cmd; 118210294Ssam 118310294Ssam if (argc < 2) 118410294Ssam argc++, argv[1] = NULL; 118510294Ssam if (argc < 3) 118610294Ssam argc++, argv[2] = "-"; 118711756Ssam if (argc > 3) { 118811756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 118926049Sminshall code = -1; 119011756Ssam return; 119111756Ssam } 119236935Skarels cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; 119326049Sminshall if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 119426049Sminshall code = -1; 119511353Ssam return; 119626049Sminshall } 119732344Scsvsj if (strcmp(argv[2], "-") && *argv[2] != '|') 119832344Scsvsj if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { 119932344Scsvsj code = -1; 120032344Scsvsj return; 120132344Scsvsj } 120237225Skarels recvrequest(cmd, argv[2], argv[1], "w", 0); 120310294Ssam } 120410294Ssam 120510294Ssam /* 120611756Ssam * Get a directory listing 120711756Ssam * of multiple remote files. 120811756Ssam */ 120911756Ssam mls(argc, argv) 121011756Ssam char *argv[]; 121111756Ssam { 121226049Sminshall char *cmd, mode[1], *dest; 121338132Srick int ointer, i; 121438132Srick sig_t (*oldintr)(), mabort(); 121526049Sminshall extern jmp_buf jabort; 121611756Ssam 121713212Ssam if (argc < 2) { 121826497Sminshall (void) strcat(line, " "); 121913212Ssam printf("(remote-files) "); 122026497Sminshall (void) gets(&line[strlen(line)]); 122113212Ssam makeargv(); 122213212Ssam argc = margc; 122313212Ssam argv = margv; 122413212Ssam } 122513212Ssam if (argc < 3) { 122626497Sminshall (void) strcat(line, " "); 122713212Ssam printf("(local-file) "); 122826497Sminshall (void) gets(&line[strlen(line)]); 122913212Ssam makeargv(); 123013212Ssam argc = margc; 123113212Ssam argv = margv; 123213212Ssam } 123313212Ssam if (argc < 3) { 123426049Sminshall printf("usage:%s remote-files local-file\n", argv[0]); 123526049Sminshall code = -1; 123613212Ssam return; 123713212Ssam } 123813212Ssam dest = argv[argc - 1]; 123913212Ssam argv[argc - 1] = NULL; 124026049Sminshall if (strcmp(dest, "-") && *dest != '|') 124126049Sminshall if (!globulize(&dest) || !confirm("output to local-file:", dest)) { 124226049Sminshall code = -1; 124313212Ssam return; 124426049Sminshall } 124536940Skarels cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 124626049Sminshall mname = argv[0]; 124726049Sminshall mflag = 1; 124826049Sminshall oldintr = signal(SIGINT, mabort); 124926049Sminshall (void) setjmp(jabort); 125026049Sminshall for (i = 1; mflag && i < argc-1; ++i) { 125126049Sminshall *mode = (i == 1) ? 'w' : 'a'; 125237225Skarels recvrequest(cmd, dest, argv[i], mode, 0); 125326049Sminshall if (!mflag && fromatty) { 125426049Sminshall ointer = interactive; 125526049Sminshall interactive = 1; 125626049Sminshall if (confirm("Continue with", argv[0])) { 125726049Sminshall mflag ++; 125826049Sminshall } 125926049Sminshall interactive = ointer; 126026049Sminshall } 126126049Sminshall } 126226049Sminshall (void) signal(SIGINT, oldintr); 126326049Sminshall mflag = 0; 126411756Ssam } 126511756Ssam 126611756Ssam /* 126710294Ssam * Do a shell escape 126810294Ssam */ 126926497Sminshall /*ARGSUSED*/ 127010294Ssam shell(argc, argv) 127110294Ssam char *argv[]; 127210294Ssam { 127338132Srick int pid; 127438132Srick sig_t (*old1)(), (*old2)(); 127526049Sminshall char shellnam[40], *shell, *namep; 127626497Sminshall union wait status; 127710294Ssam 127811756Ssam old1 = signal (SIGINT, SIG_IGN); 127911756Ssam old2 = signal (SIGQUIT, SIG_IGN); 128011756Ssam if ((pid = fork()) == 0) { 128111756Ssam for (pid = 3; pid < 20; pid++) 128226497Sminshall (void) close(pid); 128326497Sminshall (void) signal(SIGINT, SIG_DFL); 128426497Sminshall (void) signal(SIGQUIT, SIG_DFL); 128525908Smckusick shell = getenv("SHELL"); 128625908Smckusick if (shell == NULL) 128737458Skarels shell = _PATH_BSHELL; 128825908Smckusick namep = rindex(shell,'/'); 128925908Smckusick if (namep == NULL) 129025908Smckusick namep = shell; 129126497Sminshall (void) strcpy(shellnam,"-"); 129226497Sminshall (void) strcat(shellnam, ++namep); 129326049Sminshall if (strcmp(namep, "sh") != 0) 129426049Sminshall shellnam[0] = '+'; 129526049Sminshall if (debug) { 129626049Sminshall printf ("%s\n", shell); 129726497Sminshall (void) fflush (stdout); 129811756Ssam } 129926049Sminshall if (argc > 1) { 130026049Sminshall execl(shell,shellnam,"-c",altarg,(char *)0); 130126049Sminshall } 130226049Sminshall else { 130326049Sminshall execl(shell,shellnam,(char *)0); 130426049Sminshall } 130525908Smckusick perror(shell); 130626049Sminshall code = -1; 130711756Ssam exit(1); 130826049Sminshall } 130911756Ssam if (pid > 0) 131011756Ssam while (wait(&status) != pid) 131111756Ssam ; 131226497Sminshall (void) signal(SIGINT, old1); 131326497Sminshall (void) signal(SIGQUIT, old2); 131426049Sminshall if (pid == -1) { 131511756Ssam perror("Try again later"); 131626049Sminshall code = -1; 131726049Sminshall } 131826049Sminshall else { 131926049Sminshall code = 0; 132026049Sminshall } 132111756Ssam return (0); 132210294Ssam } 132310294Ssam 132410294Ssam /* 132510294Ssam * Send new user information (re-login) 132610294Ssam */ 132710294Ssam user(argc, argv) 132810294Ssam int argc; 132910294Ssam char **argv; 133010294Ssam { 133135658Sbostic char acct[80], *getpass(); 133226049Sminshall int n, aflag = 0; 133310294Ssam 133410294Ssam if (argc < 2) { 133526497Sminshall (void) strcat(line, " "); 133610294Ssam printf("(username) "); 133726497Sminshall (void) gets(&line[strlen(line)]); 133810294Ssam makeargv(); 133910294Ssam argc = margc; 134010294Ssam argv = margv; 134110294Ssam } 134210294Ssam if (argc > 4) { 134310294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 134426049Sminshall code = -1; 134511756Ssam return (0); 134610294Ssam } 134710294Ssam n = command("USER %s", argv[1]); 134810294Ssam if (n == CONTINUE) { 134910294Ssam if (argc < 3 ) 135035658Sbostic argv[2] = getpass("Password: "), argc++; 135110294Ssam n = command("PASS %s", argv[2]); 135210294Ssam } 135310294Ssam if (n == CONTINUE) { 135410294Ssam if (argc < 4) { 135510294Ssam printf("Account: "); (void) fflush(stdout); 135610294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 135710294Ssam acct[strlen(acct) - 1] = '\0'; 135810294Ssam argv[3] = acct; argc++; 135910294Ssam } 136026049Sminshall n = command("ACCT %s", argv[3]); 136126049Sminshall aflag++; 136210294Ssam } 136310294Ssam if (n != COMPLETE) { 136426497Sminshall fprintf(stdout, "Login failed.\n"); 136510294Ssam return (0); 136610294Ssam } 136726049Sminshall if (!aflag && argc == 4) { 136826049Sminshall (void) command("ACCT %s", argv[3]); 136926049Sminshall } 137010294Ssam return (1); 137110294Ssam } 137210294Ssam 137310294Ssam /* 137410294Ssam * Print working directory. 137510294Ssam */ 137610294Ssam /*VARARGS*/ 137710294Ssam pwd() 137810294Ssam { 137937224Skarels int oldverbose = verbose; 138011756Ssam 138137224Skarels /* 138237224Skarels * If we aren't verbose, this doesn't do anything! 138337224Skarels */ 138437224Skarels verbose = 1; 138537224Skarels if (command("PWD") == ERROR && code == 500) { 138637224Skarels printf("PWD command not recognized, trying XPWD\n"); 138737224Skarels (void) command("XPWD"); 138837224Skarels } 138937224Skarels verbose = oldverbose; 139010294Ssam } 139110294Ssam 139210294Ssam /* 139310294Ssam * Make a directory. 139410294Ssam */ 139510294Ssam makedir(argc, argv) 139610294Ssam char *argv[]; 139710294Ssam { 139810294Ssam 139910294Ssam if (argc < 2) { 140026497Sminshall (void) strcat(line, " "); 140110294Ssam printf("(directory-name) "); 140226497Sminshall (void) gets(&line[strlen(line)]); 140310294Ssam makeargv(); 140410294Ssam argc = margc; 140510294Ssam argv = margv; 140610294Ssam } 140710294Ssam if (argc < 2) { 140826049Sminshall printf("usage: %s directory-name\n", argv[0]); 140926049Sminshall code = -1; 141010294Ssam return; 141110294Ssam } 141237224Skarels if (command("MKD %s", argv[1]) == ERROR && code == 500) { 141337224Skarels if (verbose) 141437224Skarels printf("MKD command not recognized, trying XMKD\n"); 141537224Skarels (void) command("XMKD %s", argv[1]); 141637224Skarels } 141710294Ssam } 141810294Ssam 141910294Ssam /* 142010294Ssam * Remove a directory. 142110294Ssam */ 142210294Ssam removedir(argc, argv) 142310294Ssam char *argv[]; 142410294Ssam { 142510294Ssam 142610294Ssam if (argc < 2) { 142726497Sminshall (void) strcat(line, " "); 142810294Ssam printf("(directory-name) "); 142926497Sminshall (void) gets(&line[strlen(line)]); 143010294Ssam makeargv(); 143110294Ssam argc = margc; 143210294Ssam argv = margv; 143310294Ssam } 143410294Ssam if (argc < 2) { 143526049Sminshall printf("usage: %s directory-name\n", argv[0]); 143626049Sminshall code = -1; 143710294Ssam return; 143810294Ssam } 143937224Skarels if (command("RMD %s", argv[1]) == ERROR && code == 500) { 144037224Skarels if (verbose) 144137224Skarels printf("RMD command not recognized, trying XRMD\n"); 144237224Skarels (void) command("XRMD %s", argv[1]); 144337224Skarels } 144410294Ssam } 144510294Ssam 144610294Ssam /* 144710294Ssam * Send a line, verbatim, to the remote machine. 144810294Ssam */ 144910294Ssam quote(argc, argv) 145010294Ssam char *argv[]; 145110294Ssam { 145210294Ssam int i; 145310294Ssam char buf[BUFSIZ]; 145410294Ssam 145510294Ssam if (argc < 2) { 145626497Sminshall (void) strcat(line, " "); 145710294Ssam printf("(command line to send) "); 145826497Sminshall (void) gets(&line[strlen(line)]); 145910294Ssam makeargv(); 146010294Ssam argc = margc; 146110294Ssam argv = margv; 146210294Ssam } 146310294Ssam if (argc < 2) { 146410294Ssam printf("usage: %s line-to-send\n", argv[0]); 146526049Sminshall code = -1; 146610294Ssam return; 146710294Ssam } 146826497Sminshall (void) strcpy(buf, argv[1]); 146910294Ssam for (i = 2; i < argc; i++) { 147026497Sminshall (void) strcat(buf, " "); 147126497Sminshall (void) strcat(buf, argv[i]); 147210294Ssam } 147326049Sminshall if (command(buf) == PRELIM) { 147426049Sminshall while (getreply(0) == PRELIM); 147526049Sminshall } 147610294Ssam } 147710294Ssam 147810294Ssam /* 147937224Skarels * Send a SITE command to the remote machine. The line 148037224Skarels * is sent almost verbatim to the remote machine, the 148137224Skarels * first argument is changed to SITE. 148237224Skarels */ 148337224Skarels 148437224Skarels site(argc, argv) 148537224Skarels char *argv[]; 148637224Skarels { 148737224Skarels int i; 148837224Skarels char buf[BUFSIZ]; 148937224Skarels 149037224Skarels if (argc < 2) { 149137224Skarels (void) strcat(line, " "); 149237224Skarels printf("(arguments to SITE command) "); 149337224Skarels (void) gets(&line[strlen(line)]); 149437224Skarels makeargv(); 149537224Skarels argc = margc; 149637224Skarels argv = margv; 149737224Skarels } 149837224Skarels if (argc < 2) { 149937224Skarels printf("usage: %s line-to-send\n", argv[0]); 150037224Skarels code = -1; 150137224Skarels return; 150237224Skarels } 150337224Skarels (void) strcpy(buf, "SITE "); 150437224Skarels (void) strcat(buf, argv[1]); 150537224Skarels for (i = 2; i < argc; i++) { 150637224Skarels (void) strcat(buf, " "); 150737224Skarels (void) strcat(buf, argv[i]); 150837224Skarels } 150937224Skarels if (command(buf) == PRELIM) { 151037224Skarels while (getreply(0) == PRELIM); 151137224Skarels } 151237224Skarels } 151337224Skarels 151437224Skarels do_chmod(argc, argv) 151537224Skarels char *argv[]; 151637224Skarels { 151737224Skarels if (argc == 2) { 151837224Skarels printf("usage: %s mode file-name\n", argv[0]); 151937224Skarels code = -1; 152037224Skarels return; 152137224Skarels } 152237224Skarels if (argc < 3) { 152337224Skarels (void) strcat(line, " "); 152437224Skarels printf("(mode and file-name) "); 152537224Skarels (void) gets(&line[strlen(line)]); 152637224Skarels makeargv(); 152737224Skarels argc = margc; 152837224Skarels argv = margv; 152937224Skarels } 153037224Skarels if (argc != 3) { 153137224Skarels printf("usage: %s mode file-name\n", argv[0]); 153237224Skarels code = -1; 153337224Skarels return; 153437224Skarels } 153537224Skarels (void)command("SITE CHMOD %s %s", argv[1], argv[2]); 153637224Skarels } 153737224Skarels 153837224Skarels do_umask(argc, argv) 153937224Skarels char *argv[]; 154037224Skarels { 154137224Skarels int oldverbose = verbose; 154237224Skarels 154337224Skarels verbose = 1; 154437224Skarels (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); 154537224Skarels verbose = oldverbose; 154637224Skarels } 154737224Skarels 154837224Skarels idle(argc, argv) 154937224Skarels char *argv[]; 155037224Skarels { 155137224Skarels int oldverbose = verbose; 155237224Skarels 155337224Skarels verbose = 1; 155437224Skarels (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); 155537224Skarels verbose = oldverbose; 155637224Skarels } 155737224Skarels 155837224Skarels /* 155910294Ssam * Ask the other side for help. 156010294Ssam */ 156110294Ssam rmthelp(argc, argv) 156210294Ssam char *argv[]; 156310294Ssam { 156410294Ssam int oldverbose = verbose; 156510294Ssam 156610294Ssam verbose = 1; 156710294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 156810294Ssam verbose = oldverbose; 156910294Ssam } 157010294Ssam 157110294Ssam /* 157210294Ssam * Terminate session and exit. 157310294Ssam */ 157410294Ssam /*VARARGS*/ 157510294Ssam quit() 157610294Ssam { 157710294Ssam 157818286Sralph if (connected) 157918286Sralph disconnect(); 158026049Sminshall pswitch(1); 158126049Sminshall if (connected) { 158226049Sminshall disconnect(); 158326049Sminshall } 158410294Ssam exit(0); 158510294Ssam } 158610294Ssam 158710294Ssam /* 158810294Ssam * Terminate session, but don't exit. 158910294Ssam */ 159010294Ssam disconnect() 159110294Ssam { 159210294Ssam extern FILE *cout; 159310294Ssam extern int data; 159410294Ssam 159510294Ssam if (!connected) 159610294Ssam return; 159710294Ssam (void) command("QUIT"); 159826049Sminshall if (cout) { 159926049Sminshall (void) fclose(cout); 160026049Sminshall } 160110294Ssam cout = NULL; 160210294Ssam connected = 0; 160310294Ssam data = -1; 160426049Sminshall if (!proxy) { 160526049Sminshall macnum = 0; 160626049Sminshall } 160710294Ssam } 160811353Ssam 160911650Ssam confirm(cmd, file) 161011353Ssam char *cmd, *file; 161111353Ssam { 161211353Ssam char line[BUFSIZ]; 161311353Ssam 161411353Ssam if (!interactive) 161511650Ssam return (1); 161611353Ssam printf("%s %s? ", cmd, file); 161726497Sminshall (void) fflush(stdout); 161826497Sminshall (void) gets(line); 161911650Ssam return (*line != 'n' && *line != 'N'); 162011353Ssam } 162111353Ssam 162211353Ssam fatal(msg) 162311353Ssam char *msg; 162411353Ssam { 162511353Ssam 162626497Sminshall fprintf(stderr, "ftp: %s\n", msg); 162711353Ssam exit(1); 162811353Ssam } 162911353Ssam 163011353Ssam /* 163111353Ssam * Glob a local file name specification with 163211353Ssam * the expectation of a single return value. 163311353Ssam * Can't control multiple values being expanded 163411353Ssam * from the expression, we return only the first. 163511353Ssam */ 163611353Ssam globulize(cpp) 163711353Ssam char **cpp; 163811353Ssam { 163911353Ssam char **globbed; 164011353Ssam 164111353Ssam if (!doglob) 164211353Ssam return (1); 164311353Ssam globbed = glob(*cpp); 164411353Ssam if (globerr != NULL) { 164511353Ssam printf("%s: %s\n", *cpp, globerr); 164636421Sbostic if (globbed) { 164711353Ssam blkfree(globbed); 164838132Srick free((char *)globbed); 164936421Sbostic } 165011353Ssam return (0); 165111353Ssam } 165211353Ssam if (globbed) { 165311353Ssam *cpp = *globbed++; 165411353Ssam /* don't waste too much memory */ 165536421Sbostic if (*globbed) { 165611353Ssam blkfree(globbed); 165738132Srick free((char *)globbed); 165836421Sbostic } 165911353Ssam } 166011353Ssam return (1); 166111353Ssam } 166226049Sminshall 166326049Sminshall account(argc,argv) 166426049Sminshall int argc; 166526049Sminshall char **argv; 166626049Sminshall { 166735658Sbostic char acct[50], *getpass(), *ap; 166826049Sminshall 166926049Sminshall if (argc > 1) { 167026049Sminshall ++argv; 167126049Sminshall --argc; 167226049Sminshall (void) strncpy(acct,*argv,49); 167336268Sbostic acct[49] = '\0'; 167426049Sminshall while (argc > 1) { 167526049Sminshall --argc; 167626049Sminshall ++argv; 167726049Sminshall (void) strncat(acct,*argv, 49-strlen(acct)); 167826049Sminshall } 167926049Sminshall ap = acct; 168026049Sminshall } 168126049Sminshall else { 168235658Sbostic ap = getpass("Account:"); 168326049Sminshall } 168426049Sminshall (void) command("ACCT %s", ap); 168526049Sminshall } 168626049Sminshall 168726049Sminshall jmp_buf abortprox; 168826049Sminshall 168938132Srick sig_t 169026049Sminshall proxabort() 169126049Sminshall { 169226049Sminshall extern int proxy; 169326049Sminshall 169426049Sminshall if (!proxy) { 169526049Sminshall pswitch(1); 169626049Sminshall } 169726049Sminshall if (connected) { 169826049Sminshall proxflag = 1; 169926049Sminshall } 170026049Sminshall else { 170126049Sminshall proxflag = 0; 170226049Sminshall } 170326049Sminshall pswitch(0); 170426049Sminshall longjmp(abortprox,1); 170526049Sminshall } 170626049Sminshall 170726049Sminshall doproxy(argc,argv) 170826049Sminshall int argc; 170926049Sminshall char *argv[]; 171026049Sminshall { 171138132Srick sig_t (*oldintr)(), proxabort(); 171226049Sminshall register struct cmd *c; 171326049Sminshall struct cmd *getcmd(); 171426049Sminshall extern struct cmd cmdtab[]; 171526049Sminshall extern jmp_buf abortprox; 171626049Sminshall 171726049Sminshall if (argc < 2) { 171826497Sminshall (void) strcat(line, " "); 171926049Sminshall printf("(command) "); 172026497Sminshall (void) gets(&line[strlen(line)]); 172126049Sminshall makeargv(); 172226049Sminshall argc = margc; 172326049Sminshall argv = margv; 172426049Sminshall } 172526049Sminshall if (argc < 2) { 172626049Sminshall printf("usage:%s command\n", argv[0]); 172726049Sminshall code = -1; 172826049Sminshall return; 172926049Sminshall } 173026049Sminshall c = getcmd(argv[1]); 173126049Sminshall if (c == (struct cmd *) -1) { 173226049Sminshall printf("?Ambiguous command\n"); 173326497Sminshall (void) fflush(stdout); 173426049Sminshall code = -1; 173526049Sminshall return; 173626049Sminshall } 173726049Sminshall if (c == 0) { 173826049Sminshall printf("?Invalid command\n"); 173926497Sminshall (void) fflush(stdout); 174026049Sminshall code = -1; 174126049Sminshall return; 174226049Sminshall } 174326049Sminshall if (!c->c_proxy) { 174426049Sminshall printf("?Invalid proxy command\n"); 174526497Sminshall (void) fflush(stdout); 174626049Sminshall code = -1; 174726049Sminshall return; 174826049Sminshall } 174926049Sminshall if (setjmp(abortprox)) { 175026049Sminshall code = -1; 175126049Sminshall return; 175226049Sminshall } 175326049Sminshall oldintr = signal(SIGINT, proxabort); 175426049Sminshall pswitch(1); 175526049Sminshall if (c->c_conn && !connected) { 175626049Sminshall printf("Not connected\n"); 175726497Sminshall (void) fflush(stdout); 175826049Sminshall pswitch(0); 175926049Sminshall (void) signal(SIGINT, oldintr); 176026049Sminshall code = -1; 176126049Sminshall return; 176226049Sminshall } 176326049Sminshall (*c->c_handler)(argc-1, argv+1); 176426049Sminshall if (connected) { 176526049Sminshall proxflag = 1; 176626049Sminshall } 176726049Sminshall else { 176826049Sminshall proxflag = 0; 176926049Sminshall } 177026049Sminshall pswitch(0); 177126049Sminshall (void) signal(SIGINT, oldintr); 177226049Sminshall } 177326049Sminshall 177426049Sminshall setcase() 177526049Sminshall { 177626049Sminshall mcase = !mcase; 177726049Sminshall printf("Case mapping %s.\n", onoff(mcase)); 177826049Sminshall code = mcase; 177926049Sminshall } 178026049Sminshall 178126049Sminshall setcr() 178226049Sminshall { 178326049Sminshall crflag = !crflag; 178426049Sminshall printf("Carriage Return stripping %s.\n", onoff(crflag)); 178526049Sminshall code = crflag; 178626049Sminshall } 178726049Sminshall 178826049Sminshall setntrans(argc,argv) 178926049Sminshall int argc; 179026049Sminshall char *argv[]; 179126049Sminshall { 179226049Sminshall if (argc == 1) { 179326049Sminshall ntflag = 0; 179426049Sminshall printf("Ntrans off.\n"); 179526049Sminshall code = ntflag; 179626049Sminshall return; 179726049Sminshall } 179826049Sminshall ntflag++; 179926049Sminshall code = ntflag; 180026049Sminshall (void) strncpy(ntin, argv[1], 16); 180126049Sminshall ntin[16] = '\0'; 180226049Sminshall if (argc == 2) { 180326049Sminshall ntout[0] = '\0'; 180426049Sminshall return; 180526049Sminshall } 180626049Sminshall (void) strncpy(ntout, argv[2], 16); 180726049Sminshall ntout[16] = '\0'; 180826049Sminshall } 180926049Sminshall 181026049Sminshall char * 181126049Sminshall dotrans(name) 181226049Sminshall char *name; 181326049Sminshall { 181426049Sminshall static char new[MAXPATHLEN]; 181526049Sminshall char *cp1, *cp2 = new; 181626049Sminshall register int i, ostop, found; 181726049Sminshall 181826049Sminshall for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++); 181926049Sminshall for (cp1 = name; *cp1; cp1++) { 182026049Sminshall found = 0; 182126049Sminshall for (i = 0; *(ntin + i) && i < 16; i++) { 182226049Sminshall if (*cp1 == *(ntin + i)) { 182326049Sminshall found++; 182426049Sminshall if (i < ostop) { 182526049Sminshall *cp2++ = *(ntout + i); 182626049Sminshall } 182726049Sminshall break; 182826049Sminshall } 182926049Sminshall } 183026049Sminshall if (!found) { 183126049Sminshall *cp2++ = *cp1; 183226049Sminshall } 183326049Sminshall } 183426049Sminshall *cp2 = '\0'; 183526049Sminshall return(new); 183626049Sminshall } 183726049Sminshall 183826049Sminshall setnmap(argc, argv) 183926049Sminshall int argc; 184026049Sminshall char *argv[]; 184126049Sminshall { 184226049Sminshall char *cp; 184326049Sminshall 184426049Sminshall if (argc == 1) { 184526049Sminshall mapflag = 0; 184626049Sminshall printf("Nmap off.\n"); 184726049Sminshall code = mapflag; 184826049Sminshall return; 184926049Sminshall } 185026049Sminshall if (argc < 3) { 185126497Sminshall (void) strcat(line, " "); 185226049Sminshall printf("(mapout) "); 185326497Sminshall (void) gets(&line[strlen(line)]); 185426049Sminshall makeargv(); 185526049Sminshall argc = margc; 185626049Sminshall argv = margv; 185726049Sminshall } 185826049Sminshall if (argc < 3) { 185926049Sminshall printf("Usage: %s [mapin mapout]\n",argv[0]); 186026049Sminshall code = -1; 186126049Sminshall return; 186226049Sminshall } 186326049Sminshall mapflag = 1; 186426049Sminshall code = 1; 186526049Sminshall cp = index(altarg, ' '); 186626049Sminshall if (proxy) { 186726049Sminshall while(*++cp == ' '); 186826049Sminshall altarg = cp; 186926049Sminshall cp = index(altarg, ' '); 187026049Sminshall } 187126049Sminshall *cp = '\0'; 187226049Sminshall (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 187326049Sminshall while (*++cp == ' '); 187426049Sminshall (void) strncpy(mapout, cp, MAXPATHLEN - 1); 187526049Sminshall } 187626049Sminshall 187726049Sminshall char * 187826049Sminshall domap(name) 187926049Sminshall char *name; 188026049Sminshall { 188126049Sminshall static char new[MAXPATHLEN]; 188226049Sminshall register char *cp1 = name, *cp2 = mapin; 188326049Sminshall char *tp[9], *te[9]; 188436689Scsvsj int i, toks[9], toknum = 0, match = 1; 188526049Sminshall 188626049Sminshall for (i=0; i < 9; ++i) { 188726049Sminshall toks[i] = 0; 188826049Sminshall } 188926049Sminshall while (match && *cp1 && *cp2) { 189026049Sminshall switch (*cp2) { 189126049Sminshall case '\\': 189226049Sminshall if (*++cp2 != *cp1) { 189326049Sminshall match = 0; 189426049Sminshall } 189526049Sminshall break; 189626049Sminshall case '$': 189726049Sminshall if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 189826049Sminshall if (*cp1 != *(++cp2+1)) { 189926049Sminshall toks[toknum = *cp2 - '1']++; 190026049Sminshall tp[toknum] = cp1; 190126049Sminshall while (*++cp1 && *(cp2+1) 190226049Sminshall != *cp1); 190326049Sminshall te[toknum] = cp1; 190426049Sminshall } 190526049Sminshall cp2++; 190626049Sminshall break; 190726049Sminshall } 190836935Skarels /* FALLTHROUGH */ 190926049Sminshall default: 191026049Sminshall if (*cp2 != *cp1) { 191126049Sminshall match = 0; 191226049Sminshall } 191326049Sminshall break; 191426049Sminshall } 191536689Scsvsj if (match && *cp1) { 191626049Sminshall cp1++; 191726049Sminshall } 191836689Scsvsj if (match && *cp2) { 191926049Sminshall cp2++; 192026049Sminshall } 192126049Sminshall } 192236689Scsvsj if (!match && *cp1) /* last token mismatch */ 192336689Scsvsj { 192436689Scsvsj toks[toknum] = 0; 192536689Scsvsj } 192626049Sminshall cp1 = new; 192726049Sminshall *cp1 = '\0'; 192826049Sminshall cp2 = mapout; 192926049Sminshall while (*cp2) { 193026049Sminshall match = 0; 193126049Sminshall switch (*cp2) { 193226049Sminshall case '\\': 193326049Sminshall if (*(cp2 + 1)) { 193426049Sminshall *cp1++ = *++cp2; 193526049Sminshall } 193626049Sminshall break; 193726049Sminshall case '[': 193826049Sminshall LOOP: 193926049Sminshall if (*++cp2 == '$' && isdigit(*(cp2+1))) { 194026049Sminshall if (*++cp2 == '0') { 194126049Sminshall char *cp3 = name; 194226049Sminshall 194326049Sminshall while (*cp3) { 194426049Sminshall *cp1++ = *cp3++; 194526049Sminshall } 194626049Sminshall match = 1; 194726049Sminshall } 194826049Sminshall else if (toks[toknum = *cp2 - '1']) { 194926049Sminshall char *cp3 = tp[toknum]; 195026049Sminshall 195126049Sminshall while (cp3 != te[toknum]) { 195226049Sminshall *cp1++ = *cp3++; 195326049Sminshall } 195426049Sminshall match = 1; 195526049Sminshall } 195626049Sminshall } 195726049Sminshall else { 195826049Sminshall while (*cp2 && *cp2 != ',' && 195926049Sminshall *cp2 != ']') { 196026049Sminshall if (*cp2 == '\\') { 196126049Sminshall cp2++; 196226049Sminshall } 196326049Sminshall else if (*cp2 == '$' && 196426049Sminshall isdigit(*(cp2+1))) { 196526049Sminshall if (*++cp2 == '0') { 196626049Sminshall char *cp3 = name; 196726049Sminshall 196826049Sminshall while (*cp3) { 196926049Sminshall *cp1++ = *cp3++; 197026049Sminshall } 197126049Sminshall } 197226049Sminshall else if (toks[toknum = 197326049Sminshall *cp2 - '1']) { 197426049Sminshall char *cp3=tp[toknum]; 197526049Sminshall 197626049Sminshall while (cp3 != 197726049Sminshall te[toknum]) { 197826049Sminshall *cp1++ = *cp3++; 197926049Sminshall } 198026049Sminshall } 198126049Sminshall } 198226049Sminshall else if (*cp2) { 198326049Sminshall *cp1++ = *cp2++; 198426049Sminshall } 198526049Sminshall } 198626049Sminshall if (!*cp2) { 198726049Sminshall printf("nmap: unbalanced brackets\n"); 198826049Sminshall return(name); 198926049Sminshall } 199026049Sminshall match = 1; 199126049Sminshall cp2--; 199226049Sminshall } 199326049Sminshall if (match) { 199426049Sminshall while (*++cp2 && *cp2 != ']') { 199526049Sminshall if (*cp2 == '\\' && *(cp2 + 1)) { 199626049Sminshall cp2++; 199726049Sminshall } 199826049Sminshall } 199926049Sminshall if (!*cp2) { 200026049Sminshall printf("nmap: unbalanced brackets\n"); 200126049Sminshall return(name); 200226049Sminshall } 200326049Sminshall break; 200426049Sminshall } 200526049Sminshall switch (*++cp2) { 200626049Sminshall case ',': 200726049Sminshall goto LOOP; 200826049Sminshall case ']': 200926049Sminshall break; 201026049Sminshall default: 201126049Sminshall cp2--; 201226049Sminshall goto LOOP; 201326049Sminshall } 201426049Sminshall break; 201526049Sminshall case '$': 201626049Sminshall if (isdigit(*(cp2 + 1))) { 201726049Sminshall if (*++cp2 == '0') { 201826049Sminshall char *cp3 = name; 201926049Sminshall 202026049Sminshall while (*cp3) { 202126049Sminshall *cp1++ = *cp3++; 202226049Sminshall } 202326049Sminshall } 202426049Sminshall else if (toks[toknum = *cp2 - '1']) { 202526049Sminshall char *cp3 = tp[toknum]; 202626049Sminshall 202726049Sminshall while (cp3 != te[toknum]) { 202826049Sminshall *cp1++ = *cp3++; 202926049Sminshall } 203026049Sminshall } 203126049Sminshall break; 203226049Sminshall } 203326049Sminshall /* intentional drop through */ 203426049Sminshall default: 203526049Sminshall *cp1++ = *cp2; 203626049Sminshall break; 203726049Sminshall } 203826049Sminshall cp2++; 203926049Sminshall } 204026049Sminshall *cp1 = '\0'; 204126049Sminshall if (!*new) { 204226049Sminshall return(name); 204326049Sminshall } 204426049Sminshall return(new); 204526049Sminshall } 204626049Sminshall 204726049Sminshall setsunique() 204826049Sminshall { 204926049Sminshall sunique = !sunique; 205026049Sminshall printf("Store unique %s.\n", onoff(sunique)); 205126049Sminshall code = sunique; 205226049Sminshall } 205326049Sminshall 205426049Sminshall setrunique() 205526049Sminshall { 205626049Sminshall runique = !runique; 205726049Sminshall printf("Receive unique %s.\n", onoff(runique)); 205826049Sminshall code = runique; 205926049Sminshall } 206026049Sminshall 206126049Sminshall /* change directory to perent directory */ 206226049Sminshall cdup() 206326049Sminshall { 206437224Skarels if (command("CDUP") == ERROR && code == 500) { 206537224Skarels if (verbose) 206637224Skarels printf("CDUP command not recognized, trying XCUP\n"); 206737224Skarels (void) command("XCUP"); 206837224Skarels } 206926049Sminshall } 207026049Sminshall 207137224Skarels /* restart transfer at specific point */ 207237224Skarels restart(argc, argv) 207337224Skarels int argc; 207437224Skarels char *argv[]; 207537224Skarels { 207637224Skarels extern long atol(); 207737224Skarels if (argc != 2) 207837224Skarels printf("restart: offset not specified\n"); 207937224Skarels else { 208037224Skarels restart_point = atol(argv[1]); 208137224Skarels printf("restarting at %ld. %s\n", restart_point, 208237224Skarels "execute get, put or append to initiate transfer"); 208337224Skarels } 208437224Skarels } 208536935Skarels 208636935Skarels /* show remote system type */ 208736935Skarels syst() 208836935Skarels { 208936935Skarels (void) command("SYST"); 209036935Skarels } 209136935Skarels 209226049Sminshall macdef(argc, argv) 209326049Sminshall int argc; 209426049Sminshall char *argv[]; 209526049Sminshall { 209626049Sminshall char *tmp; 209726049Sminshall int c; 209826049Sminshall 209926049Sminshall if (macnum == 16) { 210026049Sminshall printf("Limit of 16 macros have already been defined\n"); 210126049Sminshall code = -1; 210226049Sminshall return; 210326049Sminshall } 210426049Sminshall if (argc < 2) { 210526497Sminshall (void) strcat(line, " "); 210626049Sminshall printf("(macro name) "); 210726497Sminshall (void) gets(&line[strlen(line)]); 210826049Sminshall makeargv(); 210926049Sminshall argc = margc; 211026049Sminshall argv = margv; 211126049Sminshall } 211226049Sminshall if (argc != 2) { 211326049Sminshall printf("Usage: %s macro_name\n",argv[0]); 211426049Sminshall code = -1; 211526049Sminshall return; 211626049Sminshall } 211726049Sminshall if (interactive) { 211826049Sminshall printf("Enter macro line by line, terminating it with a null line\n"); 211926049Sminshall } 212026497Sminshall (void) strncpy(macros[macnum].mac_name, argv[1], 8); 212126049Sminshall if (macnum == 0) { 212226049Sminshall macros[macnum].mac_start = macbuf; 212326049Sminshall } 212426049Sminshall else { 212526049Sminshall macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 212626049Sminshall } 212726049Sminshall tmp = macros[macnum].mac_start; 212826049Sminshall while (tmp != macbuf+4096) { 212926049Sminshall if ((c = getchar()) == EOF) { 213026049Sminshall printf("macdef:end of file encountered\n"); 213126049Sminshall code = -1; 213226049Sminshall return; 213326049Sminshall } 213426049Sminshall if ((*tmp = c) == '\n') { 213526049Sminshall if (tmp == macros[macnum].mac_start) { 213626049Sminshall macros[macnum++].mac_end = tmp; 213726049Sminshall code = 0; 213826049Sminshall return; 213926049Sminshall } 214026049Sminshall if (*(tmp-1) == '\0') { 214126049Sminshall macros[macnum++].mac_end = tmp - 1; 214226049Sminshall code = 0; 214326049Sminshall return; 214426049Sminshall } 214526049Sminshall *tmp = '\0'; 214626049Sminshall } 214726049Sminshall tmp++; 214826049Sminshall } 214926049Sminshall while (1) { 215036935Skarels while ((c = getchar()) != '\n' && c != EOF) 215136935Skarels /* LOOP */; 215226049Sminshall if (c == EOF || getchar() == '\n') { 215326049Sminshall printf("Macro not defined - 4k buffer exceeded\n"); 215426049Sminshall code = -1; 215526049Sminshall return; 215626049Sminshall } 215726049Sminshall } 215826049Sminshall } 215936935Skarels 216036935Skarels /* 216136935Skarels * get size of file on remote machine 216236935Skarels */ 216336935Skarels sizecmd(argc, argv) 216436935Skarels char *argv[]; 216536935Skarels { 216636935Skarels 216736935Skarels if (argc < 2) { 216836935Skarels (void) strcat(line, " "); 216936935Skarels printf("(filename) "); 217036935Skarels (void) gets(&line[strlen(line)]); 217136935Skarels makeargv(); 217236935Skarels argc = margc; 217336935Skarels argv = margv; 217436935Skarels } 217536935Skarels if (argc < 2) { 217636935Skarels printf("usage:%s filename\n", argv[0]); 217736935Skarels code = -1; 217836935Skarels return; 217936935Skarels } 218036935Skarels (void) command("SIZE %s", argv[1]); 218136935Skarels } 218236935Skarels 218336935Skarels /* 218436935Skarels * get last modification time of file on remote machine 218536935Skarels */ 218636935Skarels modtime(argc, argv) 218736935Skarels char *argv[]; 218836935Skarels { 218936935Skarels int overbose; 219036935Skarels 219136935Skarels if (argc < 2) { 219236935Skarels (void) strcat(line, " "); 219336935Skarels printf("(filename) "); 219436935Skarels (void) gets(&line[strlen(line)]); 219536935Skarels makeargv(); 219636935Skarels argc = margc; 219736935Skarels argv = margv; 219836935Skarels } 219936935Skarels if (argc < 2) { 220036935Skarels printf("usage:%s filename\n", argv[0]); 220136935Skarels code = -1; 220236935Skarels return; 220336935Skarels } 220436940Skarels overbose = verbose; 220536940Skarels if (debug == 0) 220636940Skarels verbose = -1; 220736935Skarels if (command("MDTM %s", argv[1]) == COMPLETE) { 220836935Skarels int yy, mo, day, hour, min, sec; 220936935Skarels sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, 221036935Skarels &day, &hour, &min, &sec); 221136935Skarels /* might want to print this in local time */ 221236935Skarels printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], 221336935Skarels mo, day, yy, hour, min, sec); 221436935Skarels } else 221538132Srick printf("%s\n", reply_string); 221636935Skarels verbose = overbose; 221736935Skarels } 221836935Skarels 221936935Skarels /* 222037224Skarels * show status on reomte machine 222136935Skarels */ 222236935Skarels rmtstatus(argc, argv) 222336935Skarels char *argv[]; 222436935Skarels { 222536935Skarels (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); 222636935Skarels } 222737224Skarels 222837224Skarels /* 222937224Skarels * get file if modtime is more recent than current file 223037224Skarels */ 223137224Skarels newer(argc, argv) 223237224Skarels char *argv[]; 223337224Skarels { 223437224Skarels if (getit(argc, argv, -1, "w")) 223537224Skarels printf("Local file \"%s\" is newer than remote file \"%s\"\n", 223637224Skarels argv[1], argv[2]); 223737224Skarels } 2238