121737Sdist /* 221737Sdist * Copyright (c) 1983 Regents of the University of California. 321737Sdist * All rights reserved. The Berkeley software License Agreement 421737Sdist * specifies the terms and conditions for redistribution. 521737Sdist */ 621737Sdist 710294Ssam #ifndef lint 8*25908Smckusick static char sccsid[] = "@(#)cmds.c 5.3 (Berkeley) 01/13/86"; 921737Sdist #endif not lint 1010294Ssam 1110294Ssam /* 1210294Ssam * FTP User Program -- Command Routines. 1310294Ssam */ 1411353Ssam #include <sys/param.h> 1510294Ssam #include <sys/socket.h> 1610294Ssam 1712396Ssam #include <arpa/ftp.h> 1812396Ssam 1910294Ssam #include <signal.h> 2010294Ssam #include <stdio.h> 2110294Ssam #include <errno.h> 2210294Ssam #include <netdb.h> 2310294Ssam 2410294Ssam #include "ftp_var.h" 2510294Ssam 2611353Ssam extern char *globerr; 2711353Ssam extern char **glob(); 2811756Ssam extern char *home; 2911353Ssam extern short gflag; 3011756Ssam extern char *remglob(); 3111756Ssam extern char *getenv(); 3211756Ssam extern char *index(); 3311756Ssam extern char *rindex(); 3410294Ssam 3510294Ssam /* 3610294Ssam * Connect to peer server and 3710294Ssam * auto-login, if possible. 3810294Ssam */ 3910294Ssam setpeer(argc, argv) 4010294Ssam int argc; 4110294Ssam char *argv[]; 4210294Ssam { 4325903Skarels char *host, *hookup(); 4410294Ssam int port; 4510294Ssam 4610294Ssam if (connected) { 4710294Ssam printf("Already connected to %s, use disconnect first.\n", 4810294Ssam hostname); 4910294Ssam return; 5010294Ssam } 5110294Ssam if (argc < 2) { 5210294Ssam strcat(line, " "); 5310294Ssam printf("(to) "); 5410294Ssam gets(&line[strlen(line)]); 5510294Ssam makeargv(); 5610294Ssam argc = margc; 5710294Ssam argv = margv; 5810294Ssam } 5910294Ssam if (argc > 3) { 6010294Ssam printf("usage: %s host-name [port]\n", argv[0]); 6110294Ssam return; 6210294Ssam } 6310294Ssam port = sp->s_port; 6410294Ssam if (argc > 2) { 6511218Ssam port = atoi(argv[2]); 6610294Ssam if (port <= 0) { 6711218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 6811218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 6910294Ssam return; 7010294Ssam } 7110294Ssam port = htons(port); 7210294Ssam } 7310294Ssam host = hookup(argv[1], port); 7410294Ssam if (host) { 7510294Ssam connected = 1; 7610294Ssam if (autologin) 7710294Ssam login(host); 7810294Ssam } 7910294Ssam } 8010294Ssam 8110294Ssam struct types { 8210294Ssam char *t_name; 8310294Ssam char *t_mode; 8410294Ssam int t_type; 8511218Ssam char *t_arg; 8610294Ssam } types[] = { 8711218Ssam { "ascii", "A", TYPE_A, 0 }, 8811218Ssam { "binary", "I", TYPE_I, 0 }, 8911218Ssam { "image", "I", TYPE_I, 0 }, 9011218Ssam { "ebcdic", "E", TYPE_E, 0 }, 9111218Ssam { "tenex", "L", TYPE_L, bytename }, 9210294Ssam 0 9310294Ssam }; 9410294Ssam 9510294Ssam /* 9610294Ssam * Set transfer type. 9710294Ssam */ 9810294Ssam settype(argc, argv) 9910294Ssam char *argv[]; 10010294Ssam { 10110294Ssam register struct types *p; 10211218Ssam int comret; 10310294Ssam 10410294Ssam if (argc > 2) { 10510294Ssam char *sep; 10610294Ssam 10710294Ssam printf("usage: %s [", argv[0]); 10810294Ssam sep = " "; 10910294Ssam for (p = types; p->t_name; p++) { 11010294Ssam printf("%s%s", sep, p->t_name); 11110294Ssam if (*sep == ' ') 11210294Ssam sep = " | "; 11310294Ssam } 11410294Ssam printf(" ]\n"); 11510294Ssam return; 11610294Ssam } 11710294Ssam if (argc < 2) { 11810294Ssam printf("Using %s mode to transfer files.\n", typename); 11910294Ssam return; 12010294Ssam } 12110294Ssam for (p = types; p->t_name; p++) 12210294Ssam if (strcmp(argv[1], p->t_name) == 0) 12310294Ssam break; 12410294Ssam if (p->t_name == 0) { 12510294Ssam printf("%s: unknown mode\n", argv[1]); 12610294Ssam return; 12710294Ssam } 12811218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 12911218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 13011218Ssam else 13111218Ssam comret = command("TYPE %s", p->t_mode); 13211218Ssam if (comret == COMPLETE) { 13310294Ssam strcpy(typename, p->t_name); 13410294Ssam type = p->t_type; 13510294Ssam } 13610294Ssam } 13710294Ssam 13810294Ssam /* 13910294Ssam * Set binary transfer type. 14010294Ssam */ 14110294Ssam /*VARARGS*/ 14210294Ssam setbinary() 14310294Ssam { 14410294Ssam 14510294Ssam call(settype, "type", "binary", 0); 14610294Ssam } 14710294Ssam 14810294Ssam /* 14910294Ssam * Set ascii transfer type. 15010294Ssam */ 15110294Ssam /*VARARGS*/ 15210294Ssam setascii() 15310294Ssam { 15410294Ssam 15510294Ssam call(settype, "type", "ascii", 0); 15610294Ssam } 15710294Ssam 15810294Ssam /* 15910294Ssam * Set tenex transfer type. 16010294Ssam */ 16110294Ssam /*VARARGS*/ 16210294Ssam settenex() 16310294Ssam { 16410294Ssam 16510294Ssam call(settype, "type", "tenex", 0); 16610294Ssam } 16710294Ssam 16810294Ssam /* 16910294Ssam * Set ebcdic transfer type. 17010294Ssam */ 17110294Ssam /*VARARGS*/ 17210294Ssam setebcdic() 17310294Ssam { 17410294Ssam 17510294Ssam call(settype, "type", "ebcdic", 0); 17610294Ssam } 17710294Ssam 17810294Ssam /* 17910294Ssam * Set file transfer mode. 18010294Ssam */ 18110294Ssam setmode(argc, argv) 18210294Ssam char *argv[]; 18310294Ssam { 18410294Ssam 18510294Ssam printf("We only support %s mode, sorry.\n", modename); 18610294Ssam } 18710294Ssam 18810294Ssam /* 18910294Ssam * Set file transfer format. 19010294Ssam */ 19110294Ssam setform(argc, argv) 19210294Ssam char *argv[]; 19310294Ssam { 19410294Ssam 19510294Ssam printf("We only support %s format, sorry.\n", formname); 19610294Ssam } 19710294Ssam 19810294Ssam /* 19910294Ssam * Set file transfer structure. 20010294Ssam */ 20110294Ssam setstruct(argc, argv) 20210294Ssam char *argv[]; 20310294Ssam { 20410294Ssam 20510294Ssam printf("We only support %s structure, sorry.\n", structname); 20610294Ssam } 20710294Ssam 20818286Sralph /* 20918286Sralph * Send a single file. 21018286Sralph */ 21110294Ssam put(argc, argv) 21211756Ssam int argc; 21310294Ssam char *argv[]; 21410294Ssam { 21511650Ssam char *cmd; 216*25908Smckusick char *oldargv1; 21711650Ssam 21810294Ssam if (argc == 2) 21910294Ssam argc++, argv[2] = argv[1]; 22010294Ssam if (argc < 2) { 22110294Ssam strcat(line, " "); 22210294Ssam printf("(local-file) "); 22310294Ssam gets(&line[strlen(line)]); 22410294Ssam makeargv(); 22510294Ssam argc = margc; 22610294Ssam argv = margv; 22710294Ssam } 22810294Ssam if (argc < 2) { 22910294Ssam usage: 23010294Ssam printf("%s local-file remote-file\n", argv[0]); 23110294Ssam return; 23210294Ssam } 23310294Ssam if (argc < 3) { 23410294Ssam strcat(line, " "); 23510294Ssam printf("(remote-file) "); 23610294Ssam gets(&line[strlen(line)]); 23710294Ssam makeargv(); 23810294Ssam argc = margc; 23910294Ssam argv = margv; 24010294Ssam } 24110294Ssam if (argc < 3) 24210294Ssam goto usage; 243*25908Smckusick oldargv1 = argv[1]; 24411353Ssam if (!globulize(&argv[1])) 24511353Ssam return; 246*25908Smckusick /* 247*25908Smckusick * If "globulize" modifies argv[1], and argv[2] is a copy of 248*25908Smckusick * the old argv[1], make it a copy of the new argv[1]. 249*25908Smckusick */ 250*25908Smckusick if (argv[1] != oldargv1 && argv[2] == oldargv1) 251*25908Smckusick argv[2] = argv[1]; 25211756Ssam cmd = (argv[0][0] == 'a') ? "APPE" : "STOR"; 25311650Ssam sendrequest(cmd, argv[1], argv[2]); 25410294Ssam } 25510294Ssam 25610294Ssam /* 25711756Ssam * Send multiple files. 25810294Ssam */ 25911353Ssam mput(argc, argv) 26011353Ssam char *argv[]; 26111353Ssam { 26213212Ssam register int i; 26311353Ssam 26411650Ssam if (argc < 2) { 26511650Ssam strcat(line, " "); 26611650Ssam printf("(local-files) "); 26711650Ssam gets(&line[strlen(line)]); 26811650Ssam makeargv(); 26911650Ssam argc = margc; 27011650Ssam argv = margv; 27111353Ssam } 27211353Ssam if (argc < 2) { 27311353Ssam printf("%s local-files\n", argv[0]); 27411353Ssam return; 27511353Ssam } 27613212Ssam for (i = 1; i < argc; i++) { 27713212Ssam register char **cpp, **gargs; 27813212Ssam 27913212Ssam if (!doglob) { 28013212Ssam if (confirm(argv[0], argv[i])) 28113212Ssam sendrequest("STOR", argv[i], argv[i]); 28213212Ssam continue; 28313212Ssam } 28413212Ssam gargs = glob(argv[i]); 28511650Ssam if (globerr != NULL) { 28611650Ssam printf("%s\n", globerr); 28711650Ssam if (gargs) 28811650Ssam blkfree(gargs); 28913212Ssam continue; 29011353Ssam } 29113212Ssam for (cpp = gargs; cpp && *cpp != NULL; cpp++) 29213212Ssam if (confirm(argv[0], *cpp)) 29313212Ssam sendrequest("STOR", *cpp, *cpp); 29413212Ssam if (gargs != NULL) 29513212Ssam blkfree(gargs); 29611353Ssam } 29711353Ssam } 29811353Ssam 29911353Ssam /* 30011353Ssam * Receive one file. 30111353Ssam */ 30210294Ssam get(argc, argv) 30310294Ssam char *argv[]; 30410294Ssam { 30510294Ssam 30610294Ssam if (argc == 2) 30710294Ssam argc++, argv[2] = argv[1]; 30810294Ssam if (argc < 2) { 30910294Ssam strcat(line, " "); 31010294Ssam printf("(remote-file) "); 31110294Ssam gets(&line[strlen(line)]); 31210294Ssam makeargv(); 31310294Ssam argc = margc; 31410294Ssam argv = margv; 31510294Ssam } 31610294Ssam if (argc < 2) { 31710294Ssam usage: 31811353Ssam printf("%s remote-file [ local-file ]\n", argv[0]); 31910294Ssam return; 32010294Ssam } 32110294Ssam if (argc < 3) { 32210294Ssam strcat(line, " "); 32310294Ssam printf("(local-file) "); 32410294Ssam gets(&line[strlen(line)]); 32510294Ssam makeargv(); 32610294Ssam argc = margc; 32710294Ssam argv = margv; 32810294Ssam } 32910294Ssam if (argc < 3) 33010294Ssam goto usage; 33111353Ssam if (!globulize(&argv[2])) 33211353Ssam return; 33311650Ssam recvrequest("RETR", argv[2], argv[1], "w"); 33410294Ssam } 33510294Ssam 33611353Ssam /* 33711353Ssam * Get multiple files. 33811353Ssam */ 33911353Ssam mget(argc, argv) 34011353Ssam char *argv[]; 34111353Ssam { 34211756Ssam char *cp; 34311353Ssam 34411353Ssam if (argc < 2) { 34511353Ssam strcat(line, " "); 34611756Ssam printf("(remote-files) "); 34711353Ssam gets(&line[strlen(line)]); 34811353Ssam makeargv(); 34911353Ssam argc = margc; 35011353Ssam argv = margv; 35111353Ssam } 35211353Ssam if (argc < 2) { 35311650Ssam printf("%s remote-files\n", argv[0]); 35411353Ssam return; 35511353Ssam } 35611650Ssam while ((cp = remglob(argc, argv)) != NULL) 35711650Ssam if (confirm(argv[0], cp)) 35811650Ssam recvrequest("RETR", cp, cp, "w"); 35911650Ssam } 36011650Ssam 36111650Ssam char * 36211650Ssam remglob(argc, argv) 36311650Ssam char *argv[]; 36411650Ssam { 36511756Ssam char temp[16]; 36611650Ssam static char buf[MAXPATHLEN]; 36711650Ssam static FILE *ftemp = NULL; 36811650Ssam static char **args; 36913212Ssam int oldverbose, oldhash; 37011756Ssam char *cp, *mode; 37111650Ssam 37211650Ssam if (!doglob) { 37311756Ssam if (args == NULL) 37411650Ssam args = argv; 37511650Ssam if ((cp = *++args) == NULL) 37611650Ssam args = NULL; 37711650Ssam return (cp); 37811353Ssam } 37911650Ssam if (ftemp == NULL) { 38011650Ssam strcpy(temp, "/tmp/ftpXXXXXX"); 38111650Ssam mktemp(temp); 38211650Ssam oldverbose = verbose, verbose = 0; 38313212Ssam oldhash = hash, hash = 0; 38411756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 38511756Ssam recvrequest ("NLST", temp, *argv, mode); 38613212Ssam verbose = oldverbose; hash = oldhash; 38711650Ssam ftemp = fopen(temp, "r"); 38811650Ssam unlink(temp); 38911650Ssam if (ftemp == NULL) { 39011650Ssam printf("can't find list of remote files, oops\n"); 39111756Ssam return (NULL); 39211353Ssam } 39311353Ssam } 39411650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 39511650Ssam fclose(ftemp), ftemp = NULL; 39611650Ssam return (NULL); 39711353Ssam } 39811650Ssam if ((cp = index(buf, '\n')) != NULL) 39911650Ssam *cp = '\0'; 40011650Ssam return (buf); 40111353Ssam } 40211353Ssam 40310294Ssam char * 40410294Ssam onoff(bool) 40510294Ssam int bool; 40610294Ssam { 40710294Ssam 40810294Ssam return (bool ? "on" : "off"); 40910294Ssam } 41010294Ssam 41110294Ssam /* 41210294Ssam * Show status. 41310294Ssam */ 41410294Ssam status(argc, argv) 41510294Ssam char *argv[]; 41610294Ssam { 41710294Ssam 41810294Ssam if (connected) 41910294Ssam printf("Connected to %s.\n", hostname); 42010294Ssam else 42110294Ssam printf("Not connected.\n"); 42210294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 42310294Ssam modename, typename, formname, structname); 42411353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 42511353Ssam onoff(verbose), onoff(bell), onoff(interactive), 42611353Ssam onoff(doglob)); 42714143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 42814143Ssam onoff(hash), onoff(sendport)); 42910294Ssam } 43010294Ssam 43110294Ssam /* 43210294Ssam * Set beep on cmd completed mode. 43310294Ssam */ 43410294Ssam /*VARARGS*/ 43510294Ssam setbell() 43610294Ssam { 43710294Ssam 43810294Ssam bell = !bell; 43910294Ssam printf("Bell mode %s.\n", onoff(bell)); 44010294Ssam } 44110294Ssam 44210294Ssam /* 44310294Ssam * Turn on packet tracing. 44410294Ssam */ 44510294Ssam /*VARARGS*/ 44610294Ssam settrace() 44710294Ssam { 44810294Ssam 44910294Ssam trace = !trace; 45010294Ssam printf("Packet tracing %s.\n", onoff(trace)); 45110294Ssam } 45210294Ssam 45310294Ssam /* 45411650Ssam * Toggle hash mark printing during transfers. 45511650Ssam */ 45611650Ssam /*VARARGS*/ 45711650Ssam sethash() 45811650Ssam { 45911650Ssam 46011650Ssam hash = !hash; 46111650Ssam printf("Hash mark printing %s", onoff(hash)); 46211650Ssam if (hash) 46311650Ssam printf(" (%d bytes/hash mark)", BUFSIZ); 46411650Ssam printf(".\n"); 46511650Ssam } 46611650Ssam 46711650Ssam /* 46810294Ssam * Turn on printing of server echo's. 46910294Ssam */ 47010294Ssam /*VARARGS*/ 47110294Ssam setverbose() 47210294Ssam { 47310294Ssam 47410294Ssam verbose = !verbose; 47510294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 47610294Ssam } 47710294Ssam 47810294Ssam /* 47911650Ssam * Toggle PORT cmd use before each data connection. 48011650Ssam */ 48111650Ssam /*VARARGS*/ 48211650Ssam setport() 48311650Ssam { 48411650Ssam 48511650Ssam sendport = !sendport; 48611650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 48711650Ssam } 48811650Ssam 48911650Ssam /* 49010294Ssam * Turn on interactive prompting 49110294Ssam * during mget, mput, and mdelete. 49210294Ssam */ 49310294Ssam /*VARARGS*/ 49410294Ssam setprompt() 49510294Ssam { 49610294Ssam 49710294Ssam interactive = !interactive; 49810294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 49910294Ssam } 50010294Ssam 50110294Ssam /* 50211353Ssam * Toggle metacharacter interpretation 50311353Ssam * on local file names. 50411353Ssam */ 50511353Ssam /*VARARGS*/ 50611353Ssam setglob() 50711353Ssam { 50811353Ssam 50911353Ssam doglob = !doglob; 51011353Ssam printf("Globbing %s.\n", onoff(doglob)); 51111353Ssam } 51211353Ssam 51311353Ssam /* 51410294Ssam * Set debugging mode on/off and/or 51510294Ssam * set level of debugging. 51610294Ssam */ 51711756Ssam /*VARARGS*/ 51810294Ssam setdebug(argc, argv) 51910294Ssam char *argv[]; 52010294Ssam { 52110294Ssam int val; 52210294Ssam 52310294Ssam if (argc > 1) { 52410294Ssam val = atoi(argv[1]); 52510294Ssam if (val < 0) { 52610294Ssam printf("%s: bad debugging value.\n", argv[1]); 52710294Ssam return; 52810294Ssam } 52910294Ssam } else 53010294Ssam val = !debug; 53110294Ssam debug = val; 53210294Ssam if (debug) 53310294Ssam options |= SO_DEBUG; 53410294Ssam else 53510294Ssam options &= ~SO_DEBUG; 53610294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 53710294Ssam } 53810294Ssam 53910294Ssam /* 54010294Ssam * Set current working directory 54110294Ssam * on remote machine. 54210294Ssam */ 54310294Ssam cd(argc, argv) 54410294Ssam char *argv[]; 54510294Ssam { 54610294Ssam 54710294Ssam if (argc < 2) { 54810294Ssam strcat(line, " "); 54910294Ssam printf("(remote-directory) "); 55010294Ssam gets(&line[strlen(line)]); 55110294Ssam makeargv(); 55210294Ssam argc = margc; 55310294Ssam argv = margv; 55410294Ssam } 55510294Ssam if (argc < 2) { 55610294Ssam printf("%s remote-directory\n", argv[0]); 55710294Ssam return; 55810294Ssam } 55910294Ssam (void) command("CWD %s", argv[1]); 56010294Ssam } 56110294Ssam 56210294Ssam /* 56310294Ssam * Set current working directory 56410294Ssam * on local machine. 56510294Ssam */ 56610294Ssam lcd(argc, argv) 56710294Ssam char *argv[]; 56810294Ssam { 56911353Ssam char buf[MAXPATHLEN]; 57010294Ssam 57111353Ssam if (argc < 2) 57211353Ssam argc++, argv[1] = home; 57310294Ssam if (argc != 2) { 57410294Ssam printf("%s local-directory\n", argv[0]); 57510294Ssam return; 57610294Ssam } 57711353Ssam if (!globulize(&argv[1])) 57811353Ssam return; 57911353Ssam if (chdir(argv[1]) < 0) { 58010294Ssam perror(argv[1]); 58111353Ssam return; 58211353Ssam } 58311353Ssam printf("Local directory now %s\n", getwd(buf)); 58410294Ssam } 58510294Ssam 58610294Ssam /* 58710294Ssam * Delete a single file. 58810294Ssam */ 58910294Ssam delete(argc, argv) 59010294Ssam char *argv[]; 59110294Ssam { 59210294Ssam 59310294Ssam if (argc < 2) { 59410294Ssam strcat(line, " "); 59510294Ssam printf("(remote-file) "); 59610294Ssam gets(&line[strlen(line)]); 59710294Ssam makeargv(); 59810294Ssam argc = margc; 59910294Ssam argv = margv; 60010294Ssam } 60110294Ssam if (argc < 2) { 60210294Ssam printf("%s remote-file\n", argv[0]); 60310294Ssam return; 60410294Ssam } 60510294Ssam (void) command("DELE %s", argv[1]); 60610294Ssam } 60710294Ssam 60810294Ssam /* 60911650Ssam * Delete multiple files. 61011650Ssam */ 61111650Ssam mdelete(argc, argv) 61211650Ssam char *argv[]; 61311650Ssam { 61411650Ssam char *cp; 61511650Ssam 61611650Ssam if (argc < 2) { 61711650Ssam strcat(line, " "); 61811650Ssam printf("(remote-files) "); 61911650Ssam gets(&line[strlen(line)]); 62011650Ssam makeargv(); 62111650Ssam argc = margc; 62211650Ssam argv = margv; 62311650Ssam } 62411650Ssam if (argc < 2) { 62511650Ssam printf("%s remote-files\n", argv[0]); 62611650Ssam return; 62711650Ssam } 62811650Ssam while ((cp = remglob(argc, argv)) != NULL) 62911650Ssam if (confirm(argv[0], cp)) 63011650Ssam (void) command("DELE %s", cp); 63111650Ssam } 63211756Ssam 63311650Ssam /* 63410294Ssam * Rename a remote file. 63510294Ssam */ 63610294Ssam renamefile(argc, argv) 63710294Ssam char *argv[]; 63810294Ssam { 63910294Ssam 64010294Ssam if (argc < 2) { 64110294Ssam strcat(line, " "); 64210294Ssam printf("(from-name) "); 64310294Ssam gets(&line[strlen(line)]); 64410294Ssam makeargv(); 64510294Ssam argc = margc; 64610294Ssam argv = margv; 64710294Ssam } 64810294Ssam if (argc < 2) { 64910294Ssam usage: 65010294Ssam printf("%s from-name to-name\n", argv[0]); 65110294Ssam return; 65210294Ssam } 65310294Ssam if (argc < 3) { 65410294Ssam strcat(line, " "); 65510294Ssam printf("(to-name) "); 65610294Ssam gets(&line[strlen(line)]); 65710294Ssam makeargv(); 65810294Ssam argc = margc; 65910294Ssam argv = margv; 66010294Ssam } 66110294Ssam if (argc < 3) 66210294Ssam goto usage; 66310294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 66410294Ssam (void) command("RNTO %s", argv[2]); 66510294Ssam } 66610294Ssam 66710294Ssam /* 66810294Ssam * Get a directory listing 66910294Ssam * of remote files. 67010294Ssam */ 67110294Ssam ls(argc, argv) 67210294Ssam char *argv[]; 67310294Ssam { 67411756Ssam char *cmd; 67510294Ssam 67610294Ssam if (argc < 2) 67710294Ssam argc++, argv[1] = NULL; 67810294Ssam if (argc < 3) 67910294Ssam argc++, argv[2] = "-"; 68011756Ssam if (argc > 3) { 68111756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 68211756Ssam return; 68311756Ssam } 68410294Ssam cmd = argv[0][0] == 'l' ? "NLST" : "LIST"; 68511353Ssam if (strcmp(argv[2], "-") && !globulize(&argv[2])) 68611353Ssam return; 68711756Ssam recvrequest(cmd, argv[2], argv[1], "w"); 68810294Ssam } 68910294Ssam 69010294Ssam /* 69111756Ssam * Get a directory listing 69211756Ssam * of multiple remote files. 69311756Ssam */ 69411756Ssam mls(argc, argv) 69511756Ssam char *argv[]; 69611756Ssam { 69713212Ssam char *cmd, *mode, *cp, *dest; 69811756Ssam 69913212Ssam if (argc < 2) { 70013212Ssam strcat(line, " "); 70113212Ssam printf("(remote-files) "); 70213212Ssam gets(&line[strlen(line)]); 70313212Ssam makeargv(); 70413212Ssam argc = margc; 70513212Ssam argv = margv; 70613212Ssam } 70713212Ssam if (argc < 3) { 70813212Ssam strcat(line, " "); 70913212Ssam printf("(local-file) "); 71013212Ssam gets(&line[strlen(line)]); 71113212Ssam makeargv(); 71213212Ssam argc = margc; 71313212Ssam argv = margv; 71413212Ssam } 71513212Ssam if (argc < 3) { 71613212Ssam printf("%s remote-files local-file\n", argv[0]); 71713212Ssam return; 71813212Ssam } 71913212Ssam dest = argv[argc - 1]; 72013212Ssam argv[argc - 1] = NULL; 72113212Ssam if (strcmp(dest, "-")) 72216324Sralph if (!globulize(&dest) || !confirm("local-file", dest)) 72313212Ssam return; 72411756Ssam cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 72513212Ssam for (mode = "w"; cp = remglob(argc, argv); mode = "a") 72613212Ssam if (confirm(argv[0], cp)) 72713212Ssam recvrequest(cmd, dest, cp, mode); 72811756Ssam } 72911756Ssam 73011756Ssam /* 73110294Ssam * Do a shell escape 73210294Ssam */ 73310294Ssam shell(argc, argv) 73410294Ssam char *argv[]; 73510294Ssam { 73611756Ssam int pid, status, (*old1)(), (*old2)(); 73711756Ssam char shellnam[40], *shell, *namep; 73811756Ssam char **cpp, **gargs; 73910294Ssam 74011756Ssam old1 = signal (SIGINT, SIG_IGN); 74111756Ssam old2 = signal (SIGQUIT, SIG_IGN); 74211756Ssam if ((pid = fork()) == 0) { 74311756Ssam for (pid = 3; pid < 20; pid++) 74411756Ssam close(pid); 74511756Ssam signal(SIGINT, SIG_DFL); 74611756Ssam signal(SIGQUIT, SIG_DFL); 747*25908Smckusick shell = getenv("SHELL"); 748*25908Smckusick if (shell == NULL) 749*25908Smckusick shell = "/bin/sh"; 750*25908Smckusick namep = rindex(shell,'/'); 751*25908Smckusick if (namep == NULL) 752*25908Smckusick namep = shell; 75311756Ssam if (argc <= 1) { 75411756Ssam if (debug) { 75511756Ssam printf ("%s\n", shell); 75611756Ssam fflush (stdout); 75711756Ssam } 758*25908Smckusick execl(shell, shell, (char *)0); 759*25908Smckusick } else { 760*25908Smckusick char *args[4]; /* "sh" "-c" <command> NULL */ 761*25908Smckusick 762*25908Smckusick args[0] = shell; 763*25908Smckusick args[1] = "-c"; 764*25908Smckusick args[2] = argv[1]; 765*25908Smckusick args[3] = NULL; 766*25908Smckusick if (debug) { 767*25908Smckusick printf("%s -c %s\n", shell, argv[1]); 768*25908Smckusick fflush(stdout); 76911756Ssam } 770*25908Smckusick execv(shell, args); 77111756Ssam } 772*25908Smckusick perror(shell); 77311756Ssam exit(1); 77411756Ssam } 77511756Ssam if (pid > 0) 77611756Ssam while (wait(&status) != pid) 77711756Ssam ; 77811756Ssam signal(SIGINT, old1); 77911756Ssam signal(SIGQUIT, old2); 78011756Ssam if (pid == -1) 78111756Ssam perror("Try again later"); 78211756Ssam return (0); 78310294Ssam } 78410294Ssam 78510294Ssam /* 78610294Ssam * Send new user information (re-login) 78710294Ssam */ 78810294Ssam user(argc, argv) 78910294Ssam int argc; 79010294Ssam char **argv; 79110294Ssam { 79210294Ssam char acct[80], *getpass(); 79310294Ssam int n; 79410294Ssam 79510294Ssam if (argc < 2) { 79610294Ssam strcat(line, " "); 79710294Ssam printf("(username) "); 79810294Ssam gets(&line[strlen(line)]); 79910294Ssam makeargv(); 80010294Ssam argc = margc; 80110294Ssam argv = margv; 80210294Ssam } 80310294Ssam if (argc > 4) { 80410294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 80511756Ssam return (0); 80610294Ssam } 80710294Ssam n = command("USER %s", argv[1]); 80810294Ssam if (n == CONTINUE) { 80910294Ssam if (argc < 3 ) 81010294Ssam argv[2] = getpass("Password: "), argc++; 81110294Ssam n = command("PASS %s", argv[2]); 81210294Ssam } 81310294Ssam if (n == CONTINUE) { 81410294Ssam if (argc < 4) { 81510294Ssam printf("Account: "); (void) fflush(stdout); 81610294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 81710294Ssam acct[strlen(acct) - 1] = '\0'; 81810294Ssam argv[3] = acct; argc++; 81910294Ssam } 82010294Ssam n = command("ACCT %s", acct); 82110294Ssam } 82210294Ssam if (n != COMPLETE) { 82310294Ssam fprintf(stderr, "Login failed.\n"); 82410294Ssam return (0); 82510294Ssam } 82610294Ssam return (1); 82710294Ssam } 82810294Ssam 82910294Ssam /* 83010294Ssam * Print working directory. 83110294Ssam */ 83210294Ssam /*VARARGS*/ 83310294Ssam pwd() 83410294Ssam { 83511756Ssam 83610294Ssam (void) command("XPWD"); 83710294Ssam } 83810294Ssam 83910294Ssam /* 84010294Ssam * Make a directory. 84110294Ssam */ 84210294Ssam makedir(argc, argv) 84310294Ssam char *argv[]; 84410294Ssam { 84510294Ssam 84610294Ssam if (argc < 2) { 84710294Ssam strcat(line, " "); 84810294Ssam printf("(directory-name) "); 84910294Ssam gets(&line[strlen(line)]); 85010294Ssam makeargv(); 85110294Ssam argc = margc; 85210294Ssam argv = margv; 85310294Ssam } 85410294Ssam if (argc < 2) { 85510294Ssam printf("%s directory-name\n", argv[0]); 85610294Ssam return; 85710294Ssam } 85810294Ssam (void) command("XMKD %s", argv[1]); 85910294Ssam } 86010294Ssam 86110294Ssam /* 86210294Ssam * Remove a directory. 86310294Ssam */ 86410294Ssam removedir(argc, argv) 86510294Ssam char *argv[]; 86610294Ssam { 86710294Ssam 86810294Ssam if (argc < 2) { 86910294Ssam strcat(line, " "); 87010294Ssam printf("(directory-name) "); 87110294Ssam gets(&line[strlen(line)]); 87210294Ssam makeargv(); 87310294Ssam argc = margc; 87410294Ssam argv = margv; 87510294Ssam } 87610294Ssam if (argc < 2) { 87710294Ssam printf("%s directory-name\n", argv[0]); 87810294Ssam return; 87910294Ssam } 88010294Ssam (void) command("XRMD %s", argv[1]); 88110294Ssam } 88210294Ssam 88310294Ssam /* 88410294Ssam * Send a line, verbatim, to the remote machine. 88510294Ssam */ 88610294Ssam quote(argc, argv) 88710294Ssam char *argv[]; 88810294Ssam { 88910294Ssam int i; 89010294Ssam char buf[BUFSIZ]; 89110294Ssam 89210294Ssam if (argc < 2) { 89310294Ssam strcat(line, " "); 89410294Ssam printf("(command line to send) "); 89510294Ssam gets(&line[strlen(line)]); 89610294Ssam makeargv(); 89710294Ssam argc = margc; 89810294Ssam argv = margv; 89910294Ssam } 90010294Ssam if (argc < 2) { 90110294Ssam printf("usage: %s line-to-send\n", argv[0]); 90210294Ssam return; 90310294Ssam } 90410294Ssam strcpy(buf, argv[1]); 90510294Ssam for (i = 2; i < argc; i++) { 90610294Ssam strcat(buf, " "); 90710294Ssam strcat(buf, argv[i]); 90810294Ssam } 90910294Ssam (void) command(buf); 91010294Ssam } 91110294Ssam 91210294Ssam /* 91310294Ssam * Ask the other side for help. 91410294Ssam */ 91510294Ssam rmthelp(argc, argv) 91610294Ssam char *argv[]; 91710294Ssam { 91810294Ssam int oldverbose = verbose; 91910294Ssam 92010294Ssam verbose = 1; 92110294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 92210294Ssam verbose = oldverbose; 92310294Ssam } 92410294Ssam 92510294Ssam /* 92610294Ssam * Terminate session and exit. 92710294Ssam */ 92810294Ssam /*VARARGS*/ 92910294Ssam quit() 93010294Ssam { 93110294Ssam 93218286Sralph if (connected) 93318286Sralph disconnect(); 93410294Ssam exit(0); 93510294Ssam } 93610294Ssam 93710294Ssam /* 93810294Ssam * Terminate session, but don't exit. 93910294Ssam */ 94010294Ssam disconnect() 94110294Ssam { 94210294Ssam extern FILE *cout; 94310294Ssam extern int data; 94410294Ssam 94510294Ssam if (!connected) 94610294Ssam return; 94710294Ssam (void) command("QUIT"); 94810294Ssam (void) fclose(cout); 94910294Ssam cout = NULL; 95010294Ssam connected = 0; 95110294Ssam data = -1; 95210294Ssam } 95311353Ssam 95411650Ssam confirm(cmd, file) 95511353Ssam char *cmd, *file; 95611353Ssam { 95711353Ssam char line[BUFSIZ]; 95811353Ssam 95911353Ssam if (!interactive) 96011650Ssam return (1); 96111353Ssam printf("%s %s? ", cmd, file); 96211353Ssam fflush(stdout); 96311353Ssam gets(line); 96411650Ssam return (*line != 'n' && *line != 'N'); 96511353Ssam } 96611353Ssam 96711353Ssam fatal(msg) 96811353Ssam char *msg; 96911353Ssam { 97011353Ssam 97111353Ssam fprintf(stderr, "ftp: %s\n"); 97211353Ssam exit(1); 97311353Ssam } 97411353Ssam 97511353Ssam /* 97611353Ssam * Glob a local file name specification with 97711353Ssam * the expectation of a single return value. 97811353Ssam * Can't control multiple values being expanded 97911353Ssam * from the expression, we return only the first. 98011353Ssam */ 98111353Ssam globulize(cpp) 98211353Ssam char **cpp; 98311353Ssam { 98411353Ssam char **globbed; 98511353Ssam 98611353Ssam if (!doglob) 98711353Ssam return (1); 98811353Ssam globbed = glob(*cpp); 98911353Ssam if (globerr != NULL) { 99011353Ssam printf("%s: %s\n", *cpp, globerr); 99111353Ssam if (globbed) 99211353Ssam blkfree(globbed); 99311353Ssam return (0); 99411353Ssam } 99511353Ssam if (globbed) { 99611353Ssam *cpp = *globbed++; 99711353Ssam /* don't waste too much memory */ 99811353Ssam if (*globbed) 99911353Ssam blkfree(globbed); 100011353Ssam } 100111353Ssam return (1); 100211353Ssam } 1003