110294Ssam #ifndef lint 2*11218Ssam static char sccsid[] = "@(#)cmds.c 4.2 (Berkeley) 02/21/83"; 310294Ssam #endif 410294Ssam 510294Ssam /* 610294Ssam * FTP User Program -- Command Routines. 710294Ssam */ 810294Ssam #include <sys/types.h> 910294Ssam #include <sys/socket.h> 1010294Ssam 1110294Ssam #include <signal.h> 1210294Ssam #include <stdio.h> 1310294Ssam #include <errno.h> 1410294Ssam #include <netdb.h> 1510294Ssam 1610294Ssam #include "ftp.h" 1710294Ssam #include "ftp_var.h" 1810294Ssam 1910294Ssam int autologin = 1; 2010294Ssam 2110294Ssam /* 2210294Ssam * Connect to peer server and 2310294Ssam * auto-login, if possible. 2410294Ssam */ 2510294Ssam setpeer(argc, argv) 2610294Ssam int argc; 2710294Ssam char *argv[]; 2810294Ssam { 2910294Ssam struct hostent *host, *hookup(); 3010294Ssam int port; 3110294Ssam 3210294Ssam if (connected) { 3310294Ssam printf("Already connected to %s, use disconnect first.\n", 3410294Ssam hostname); 3510294Ssam return; 3610294Ssam } 3710294Ssam if (argc < 2) { 3810294Ssam strcat(line, " "); 3910294Ssam printf("(to) "); 4010294Ssam gets(&line[strlen(line)]); 4110294Ssam makeargv(); 4210294Ssam argc = margc; 4310294Ssam argv = margv; 4410294Ssam } 4510294Ssam if (argc > 3) { 4610294Ssam printf("usage: %s host-name [port]\n", argv[0]); 4710294Ssam return; 4810294Ssam } 4910294Ssam port = sp->s_port; 5010294Ssam if (argc > 2) { 51*11218Ssam port = atoi(argv[2]); 5210294Ssam if (port <= 0) { 53*11218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 54*11218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 5510294Ssam return; 5610294Ssam } 5710294Ssam port = htons(port); 5810294Ssam } 5910294Ssam host = hookup(argv[1], port); 6010294Ssam if (host) { 6110294Ssam connected = 1; 6210294Ssam if (autologin) 6310294Ssam login(host); 6410294Ssam } 6510294Ssam } 6610294Ssam 6710294Ssam struct types { 6810294Ssam char *t_name; 6910294Ssam char *t_mode; 7010294Ssam int t_type; 71*11218Ssam char *t_arg; 7210294Ssam } types[] = { 73*11218Ssam { "ascii", "A", TYPE_A, 0 }, 74*11218Ssam { "binary", "I", TYPE_I, 0 }, 75*11218Ssam { "image", "I", TYPE_I, 0 }, 76*11218Ssam { "ebcdic", "E", TYPE_E, 0 }, 77*11218Ssam { "tenex", "L", TYPE_L, bytename }, 7810294Ssam 0 7910294Ssam }; 8010294Ssam 8110294Ssam /* 8210294Ssam * Set transfer type. 8310294Ssam */ 8410294Ssam settype(argc, argv) 8510294Ssam char *argv[]; 8610294Ssam { 8710294Ssam register struct types *p; 88*11218Ssam int comret; 8910294Ssam 9010294Ssam if (argc > 2) { 9110294Ssam char *sep; 9210294Ssam 9310294Ssam printf("usage: %s [", argv[0]); 9410294Ssam sep = " "; 9510294Ssam for (p = types; p->t_name; p++) { 9610294Ssam printf("%s%s", sep, p->t_name); 9710294Ssam if (*sep == ' ') 9810294Ssam sep = " | "; 9910294Ssam } 10010294Ssam printf(" ]\n"); 10110294Ssam return; 10210294Ssam } 10310294Ssam if (argc < 2) { 10410294Ssam printf("Using %s mode to transfer files.\n", typename); 10510294Ssam return; 10610294Ssam } 10710294Ssam for (p = types; p->t_name; p++) 10810294Ssam if (strcmp(argv[1], p->t_name) == 0) 10910294Ssam break; 11010294Ssam if (p->t_name == 0) { 11110294Ssam printf("%s: unknown mode\n", argv[1]); 11210294Ssam return; 11310294Ssam } 114*11218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 115*11218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 116*11218Ssam else 117*11218Ssam comret = command("TYPE %s", p->t_mode); 118*11218Ssam if (comret == COMPLETE) { 11910294Ssam strcpy(typename, p->t_name); 12010294Ssam type = p->t_type; 12110294Ssam } 12210294Ssam } 12310294Ssam 12410294Ssam /* 12510294Ssam * Set binary transfer type. 12610294Ssam */ 12710294Ssam /*VARARGS*/ 12810294Ssam setbinary() 12910294Ssam { 13010294Ssam 13110294Ssam call(settype, "type", "binary", 0); 13210294Ssam } 13310294Ssam 13410294Ssam /* 13510294Ssam * Set ascii transfer type. 13610294Ssam */ 13710294Ssam /*VARARGS*/ 13810294Ssam setascii() 13910294Ssam { 14010294Ssam 14110294Ssam call(settype, "type", "ascii", 0); 14210294Ssam } 14310294Ssam 14410294Ssam /* 14510294Ssam * Set tenex transfer type. 14610294Ssam */ 14710294Ssam /*VARARGS*/ 14810294Ssam settenex() 14910294Ssam { 15010294Ssam 15110294Ssam call(settype, "type", "tenex", 0); 15210294Ssam } 15310294Ssam 15410294Ssam /* 15510294Ssam * Set ebcdic transfer type. 15610294Ssam */ 15710294Ssam /*VARARGS*/ 15810294Ssam setebcdic() 15910294Ssam { 16010294Ssam 16110294Ssam call(settype, "type", "ebcdic", 0); 16210294Ssam } 16310294Ssam 16410294Ssam /* 16510294Ssam * Set file transfer mode. 16610294Ssam */ 16710294Ssam setmode(argc, argv) 16810294Ssam char *argv[]; 16910294Ssam { 17010294Ssam 17110294Ssam printf("We only support %s mode, sorry.\n", modename); 17210294Ssam } 17310294Ssam 17410294Ssam /* 17510294Ssam * Set file transfer format. 17610294Ssam */ 17710294Ssam setform(argc, argv) 17810294Ssam char *argv[]; 17910294Ssam { 18010294Ssam 18110294Ssam printf("We only support %s format, sorry.\n", formname); 18210294Ssam } 18310294Ssam 18410294Ssam /* 18510294Ssam * Set file transfer structure. 18610294Ssam */ 18710294Ssam setstruct(argc, argv) 18810294Ssam char *argv[]; 18910294Ssam { 19010294Ssam 19110294Ssam printf("We only support %s structure, sorry.\n", structname); 19210294Ssam } 19310294Ssam 19410294Ssam /* 19510294Ssam * Send a single file. 19610294Ssam */ 19710294Ssam put(argc, argv) 19810294Ssam char *argv[]; 19910294Ssam { 20010294Ssam int fd; 20110294Ssam register int n, addr; 20210294Ssam register char *cp, *targ; 20310294Ssam 20410294Ssam if (!connected) { 20510294Ssam printf("Not connected.\n"); 20610294Ssam return; 20710294Ssam } 20810294Ssam if (argc == 2) 20910294Ssam argc++, argv[2] = argv[1]; 21010294Ssam if (argc < 2) { 21110294Ssam strcat(line, " "); 21210294Ssam printf("(local-file) "); 21310294Ssam gets(&line[strlen(line)]); 21410294Ssam makeargv(); 21510294Ssam argc = margc; 21610294Ssam argv = margv; 21710294Ssam } 21810294Ssam if (argc < 2) { 21910294Ssam usage: 22010294Ssam printf("%s local-file remote-file\n", argv[0]); 22110294Ssam return; 22210294Ssam } 22310294Ssam if (argc < 3) { 22410294Ssam strcat(line, " "); 22510294Ssam printf("(remote-file) "); 22610294Ssam gets(&line[strlen(line)]); 22710294Ssam makeargv(); 22810294Ssam argc = margc; 22910294Ssam argv = margv; 23010294Ssam } 23110294Ssam if (argc < 3) 23210294Ssam goto usage; 23310294Ssam sendrequest("STOR", argv[1], argv[2]); 23410294Ssam } 23510294Ssam 23610294Ssam /* 23710294Ssam * Receive a single file. 23810294Ssam */ 23910294Ssam get(argc, argv) 24010294Ssam char *argv[]; 24110294Ssam { 24210294Ssam int fd; 24310294Ssam register int n, addr; 24410294Ssam register char *cp; 24510294Ssam char *src; 24610294Ssam 24710294Ssam if (!connected) { 24810294Ssam printf("Not connected.\n"); 24910294Ssam return; 25010294Ssam } 25110294Ssam if (argc == 2) 25210294Ssam argc++, argv[2] = argv[1]; 25310294Ssam if (argc < 2) { 25410294Ssam strcat(line, " "); 25510294Ssam printf("(remote-file) "); 25610294Ssam gets(&line[strlen(line)]); 25710294Ssam makeargv(); 25810294Ssam argc = margc; 25910294Ssam argv = margv; 26010294Ssam } 26110294Ssam if (argc < 2) { 26210294Ssam usage: 26310294Ssam printf("%s remote-file local-file\n", argv[0]); 26410294Ssam return; 26510294Ssam } 26610294Ssam if (argc < 3) { 26710294Ssam strcat(line, " "); 26810294Ssam printf("(local-file) "); 26910294Ssam gets(&line[strlen(line)]); 27010294Ssam makeargv(); 27110294Ssam argc = margc; 27210294Ssam argv = margv; 27310294Ssam } 27410294Ssam if (argc < 3) 27510294Ssam goto usage; 27610294Ssam recvrequest("RETR", argv[2], argv[1]); 27710294Ssam } 27810294Ssam 27910294Ssam char * 28010294Ssam onoff(bool) 28110294Ssam int bool; 28210294Ssam { 28310294Ssam 28410294Ssam return (bool ? "on" : "off"); 28510294Ssam } 28610294Ssam 28710294Ssam /* 28810294Ssam * Show status. 28910294Ssam */ 29010294Ssam status(argc, argv) 29110294Ssam char *argv[]; 29210294Ssam { 29310294Ssam 29410294Ssam if (connected) 29510294Ssam printf("Connected to %s.\n", hostname); 29610294Ssam else 29710294Ssam printf("Not connected.\n"); 29810294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 29910294Ssam modename, typename, formname, structname); 30010294Ssam printf("Verbose: %s; Bell: %s; Prompting: %s\n", 30110294Ssam onoff(verbose), onoff(bell), onoff(interactive)); 30210294Ssam } 30310294Ssam 30410294Ssam /* 30510294Ssam * Set beep on cmd completed mode. 30610294Ssam */ 30710294Ssam /*VARARGS*/ 30810294Ssam setbell() 30910294Ssam { 31010294Ssam 31110294Ssam bell = !bell; 31210294Ssam printf("Bell mode %s.\n", onoff(bell)); 31310294Ssam } 31410294Ssam 31510294Ssam /* 31610294Ssam * Turn on packet tracing. 31710294Ssam */ 31810294Ssam /*VARARGS*/ 31910294Ssam settrace() 32010294Ssam { 32110294Ssam 32210294Ssam trace = !trace; 32310294Ssam printf("Packet tracing %s.\n", onoff(trace)); 32410294Ssam } 32510294Ssam 32610294Ssam /* 32710294Ssam * Turn on printing of server echo's. 32810294Ssam */ 32910294Ssam /*VARARGS*/ 33010294Ssam setverbose() 33110294Ssam { 33210294Ssam 33310294Ssam verbose = !verbose; 33410294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 33510294Ssam } 33610294Ssam 33710294Ssam /* 33810294Ssam * Turn on interactive prompting 33910294Ssam * during mget, mput, and mdelete. 34010294Ssam */ 34110294Ssam /*VARARGS*/ 34210294Ssam setprompt() 34310294Ssam { 34410294Ssam 34510294Ssam interactive = !interactive; 34610294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 34710294Ssam } 34810294Ssam 34910294Ssam /* 35010294Ssam * Set debugging mode on/off and/or 35110294Ssam * set level of debugging. 35210294Ssam */ 35310294Ssam /*VARARGS*/ 35410294Ssam setdebug(argc, argv) 35510294Ssam char *argv[]; 35610294Ssam { 35710294Ssam int val; 35810294Ssam 35910294Ssam if (argc > 1) { 36010294Ssam val = atoi(argv[1]); 36110294Ssam if (val < 0) { 36210294Ssam printf("%s: bad debugging value.\n", argv[1]); 36310294Ssam return; 36410294Ssam } 36510294Ssam } else 36610294Ssam val = !debug; 36710294Ssam debug = val; 36810294Ssam if (debug) 36910294Ssam options |= SO_DEBUG; 37010294Ssam else 37110294Ssam options &= ~SO_DEBUG; 37210294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 37310294Ssam } 37410294Ssam 37510294Ssam /* 37610294Ssam * Set current working directory 37710294Ssam * on remote machine. 37810294Ssam */ 37910294Ssam cd(argc, argv) 38010294Ssam char *argv[]; 38110294Ssam { 38210294Ssam 38310294Ssam if (!connected) { 38410294Ssam printf("Not connected.\n"); 38510294Ssam return; 38610294Ssam } 38710294Ssam if (argc < 2) { 38810294Ssam strcat(line, " "); 38910294Ssam printf("(remote-directory) "); 39010294Ssam gets(&line[strlen(line)]); 39110294Ssam makeargv(); 39210294Ssam argc = margc; 39310294Ssam argv = margv; 39410294Ssam } 39510294Ssam if (argc < 2) { 39610294Ssam printf("%s remote-directory\n", argv[0]); 39710294Ssam return; 39810294Ssam } 39910294Ssam (void) command("CWD %s", argv[1]); 40010294Ssam } 40110294Ssam 40210294Ssam #include <pwd.h> 40310294Ssam 40410294Ssam /* 40510294Ssam * Set current working directory 40610294Ssam * on local machine. 40710294Ssam */ 40810294Ssam lcd(argc, argv) 40910294Ssam char *argv[]; 41010294Ssam { 41110294Ssam static struct passwd *pw = NULL; 41210294Ssam 41310294Ssam if (argc < 2) { 41410294Ssam if (pw == NULL) { 41510294Ssam pw = getpwnam(getlogin()); 41610294Ssam if (pw == NULL) 41710294Ssam pw = getpwuid(getuid()); 41810294Ssam } 41910294Ssam if (pw == NULL) { 42010294Ssam printf("ftp: can't find home directory.\n"); 42110294Ssam return; 42210294Ssam } 42310294Ssam argc++, argv[1] = pw->pw_dir; 42410294Ssam } 42510294Ssam if (argc != 2) { 42610294Ssam printf("%s local-directory\n", argv[0]); 42710294Ssam return; 42810294Ssam } 42910294Ssam if (chdir(argv[1]) < 0) 43010294Ssam perror(argv[1]); 43110294Ssam } 43210294Ssam 43310294Ssam /* 43410294Ssam * Delete a single file. 43510294Ssam */ 43610294Ssam delete(argc, argv) 43710294Ssam char *argv[]; 43810294Ssam { 43910294Ssam 44010294Ssam if (argc < 2) { 44110294Ssam strcat(line, " "); 44210294Ssam printf("(remote-file) "); 44310294Ssam gets(&line[strlen(line)]); 44410294Ssam makeargv(); 44510294Ssam argc = margc; 44610294Ssam argv = margv; 44710294Ssam } 44810294Ssam if (argc < 2) { 44910294Ssam printf("%s remote-file\n", argv[0]); 45010294Ssam return; 45110294Ssam } 45210294Ssam (void) command("DELE %s", argv[1]); 45310294Ssam } 45410294Ssam 45510294Ssam /* 45610294Ssam * Rename a remote file. 45710294Ssam */ 45810294Ssam renamefile(argc, argv) 45910294Ssam char *argv[]; 46010294Ssam { 46110294Ssam 46210294Ssam if (argc < 2) { 46310294Ssam strcat(line, " "); 46410294Ssam printf("(from-name) "); 46510294Ssam gets(&line[strlen(line)]); 46610294Ssam makeargv(); 46710294Ssam argc = margc; 46810294Ssam argv = margv; 46910294Ssam } 47010294Ssam if (argc < 2) { 47110294Ssam usage: 47210294Ssam printf("%s from-name to-name\n", argv[0]); 47310294Ssam return; 47410294Ssam } 47510294Ssam if (argc < 3) { 47610294Ssam strcat(line, " "); 47710294Ssam printf("(to-name) "); 47810294Ssam gets(&line[strlen(line)]); 47910294Ssam makeargv(); 48010294Ssam argc = margc; 48110294Ssam argv = margv; 48210294Ssam } 48310294Ssam if (argc < 3) 48410294Ssam goto usage; 48510294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 48610294Ssam (void) command("RNTO %s", argv[2]); 48710294Ssam } 48810294Ssam 48910294Ssam /* 49010294Ssam * Get a directory listing 49110294Ssam * of remote files. 49210294Ssam */ 49310294Ssam ls(argc, argv) 49410294Ssam char *argv[]; 49510294Ssam { 49610294Ssam char *cmd; 49710294Ssam 49810294Ssam if (argc < 2) 49910294Ssam argc++, argv[1] = NULL; 50010294Ssam if (argc < 3) 50110294Ssam argc++, argv[2] = "-"; 50210294Ssam if (argc > 3) { 50310294Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 50410294Ssam return; 50510294Ssam } 50610294Ssam cmd = argv[0][0] == 'l' ? "NLST" : "LIST"; 50710294Ssam recvrequest(cmd, argv[2], argv[1]); 50810294Ssam } 50910294Ssam 51010294Ssam /* 51110294Ssam * Do a shell escape 51210294Ssam */ 51310294Ssam shell(argc, argv) 51410294Ssam char *argv[]; 51510294Ssam { 51610294Ssam 51710294Ssam printf("Sorry, this function is unimplemented.\n"); 51810294Ssam } 51910294Ssam 52010294Ssam /* 52110294Ssam * Send new user information (re-login) 52210294Ssam */ 52310294Ssam user(argc, argv) 52410294Ssam int argc; 52510294Ssam char **argv; 52610294Ssam { 52710294Ssam char acct[80], *getpass(); 52810294Ssam int n; 52910294Ssam 53010294Ssam if (argc < 2) { 53110294Ssam strcat(line, " "); 53210294Ssam printf("(username) "); 53310294Ssam gets(&line[strlen(line)]); 53410294Ssam makeargv(); 53510294Ssam argc = margc; 53610294Ssam argv = margv; 53710294Ssam } 53810294Ssam if (argc > 4) { 53910294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 54010294Ssam return; 54110294Ssam } 54210294Ssam n = command("USER %s", argv[1]); 54310294Ssam if (n == CONTINUE) { 54410294Ssam if (argc < 3 ) 54510294Ssam argv[2] = getpass("Password: "), argc++; 54610294Ssam n = command("PASS %s", argv[2]); 54710294Ssam } 54810294Ssam if (n == CONTINUE) { 54910294Ssam if (argc < 4) { 55010294Ssam printf("Account: "); (void) fflush(stdout); 55110294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 55210294Ssam acct[strlen(acct) - 1] = '\0'; 55310294Ssam argv[3] = acct; argc++; 55410294Ssam } 55510294Ssam n = command("ACCT %s", acct); 55610294Ssam } 55710294Ssam if (n != COMPLETE) { 55810294Ssam fprintf(stderr, "Login failed.\n"); 55910294Ssam return (0); 56010294Ssam } 56110294Ssam return (1); 56210294Ssam } 56310294Ssam 56410294Ssam /* 56510294Ssam * Print working directory. 56610294Ssam */ 56710294Ssam /*VARARGS*/ 56810294Ssam pwd() 56910294Ssam { 57010294Ssam if (!connected) { 57110294Ssam printf("Not connected.\n"); 57210294Ssam return; 57310294Ssam } 57410294Ssam (void) command("XPWD"); 57510294Ssam } 57610294Ssam 57710294Ssam /* 57810294Ssam * Make a directory. 57910294Ssam */ 58010294Ssam makedir(argc, argv) 58110294Ssam char *argv[]; 58210294Ssam { 58310294Ssam 58410294Ssam if (argc < 2) { 58510294Ssam strcat(line, " "); 58610294Ssam printf("(directory-name) "); 58710294Ssam gets(&line[strlen(line)]); 58810294Ssam makeargv(); 58910294Ssam argc = margc; 59010294Ssam argv = margv; 59110294Ssam } 59210294Ssam if (argc < 2) { 59310294Ssam printf("%s directory-name\n", argv[0]); 59410294Ssam return; 59510294Ssam } 59610294Ssam (void) command("XMKD %s", argv[1]); 59710294Ssam } 59810294Ssam 59910294Ssam /* 60010294Ssam * Remove a directory. 60110294Ssam */ 60210294Ssam removedir(argc, argv) 60310294Ssam char *argv[]; 60410294Ssam { 60510294Ssam 60610294Ssam if (argc < 2) { 60710294Ssam strcat(line, " "); 60810294Ssam printf("(directory-name) "); 60910294Ssam gets(&line[strlen(line)]); 61010294Ssam makeargv(); 61110294Ssam argc = margc; 61210294Ssam argv = margv; 61310294Ssam } 61410294Ssam if (argc < 2) { 61510294Ssam printf("%s directory-name\n", argv[0]); 61610294Ssam return; 61710294Ssam } 61810294Ssam (void) command("XRMD %s", argv[1]); 61910294Ssam } 62010294Ssam 62110294Ssam /* 62210294Ssam * Send a line, verbatim, to the remote machine. 62310294Ssam */ 62410294Ssam quote(argc, argv) 62510294Ssam char *argv[]; 62610294Ssam { 62710294Ssam int i; 62810294Ssam char buf[BUFSIZ]; 62910294Ssam 63010294Ssam if (argc < 2) { 63110294Ssam strcat(line, " "); 63210294Ssam printf("(command line to send) "); 63310294Ssam gets(&line[strlen(line)]); 63410294Ssam makeargv(); 63510294Ssam argc = margc; 63610294Ssam argv = margv; 63710294Ssam } 63810294Ssam if (argc < 2) { 63910294Ssam printf("usage: %s line-to-send\n", argv[0]); 64010294Ssam return; 64110294Ssam } 64210294Ssam strcpy(buf, argv[1]); 64310294Ssam for (i = 2; i < argc; i++) { 64410294Ssam strcat(buf, " "); 64510294Ssam strcat(buf, argv[i]); 64610294Ssam } 64710294Ssam (void) command(buf); 64810294Ssam } 64910294Ssam 65010294Ssam /* 65110294Ssam * Ask the other side for help. 65210294Ssam */ 65310294Ssam rmthelp(argc, argv) 65410294Ssam char *argv[]; 65510294Ssam { 65610294Ssam int oldverbose = verbose; 65710294Ssam 65810294Ssam verbose = 1; 65910294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 66010294Ssam verbose = oldverbose; 66110294Ssam } 66210294Ssam 66310294Ssam /* 66410294Ssam * Terminate session and exit. 66510294Ssam */ 66610294Ssam /*VARARGS*/ 66710294Ssam quit() 66810294Ssam { 66910294Ssam 67010294Ssam disconnect(); 67110294Ssam exit(0); 67210294Ssam } 67310294Ssam 67410294Ssam /* 67510294Ssam * Terminate session, but don't exit. 67610294Ssam */ 67710294Ssam disconnect() 67810294Ssam { 67910294Ssam extern FILE *cout; 68010294Ssam extern int data; 68110294Ssam 68210294Ssam if (!connected) 68310294Ssam return; 68410294Ssam (void) command("QUIT"); 68510294Ssam (void) fclose(cout); 68610294Ssam cout = NULL; 68710294Ssam connected = 0; 68810294Ssam data = -1; 68910294Ssam } 690