110294Ssam #ifndef lint 2*18286Sralph static char sccsid[] = "@(#)cmds.c 4.11 (Berkeley) 03/11/85"; 310294Ssam #endif 410294Ssam 510294Ssam /* 610294Ssam * FTP User Program -- Command Routines. 710294Ssam */ 811353Ssam #include <sys/param.h> 910294Ssam #include <sys/socket.h> 1010294Ssam 1112396Ssam #include <arpa/ftp.h> 1212396Ssam 1310294Ssam #include <signal.h> 1410294Ssam #include <stdio.h> 1510294Ssam #include <errno.h> 1610294Ssam #include <netdb.h> 1710294Ssam 1810294Ssam #include "ftp_var.h" 1910294Ssam 2011353Ssam extern char *globerr; 2111353Ssam extern char **glob(); 2211756Ssam extern char *home; 2311353Ssam extern short gflag; 2411756Ssam extern char *remglob(); 2511756Ssam extern char *getenv(); 2611756Ssam extern char *index(); 2711756Ssam extern char *rindex(); 2810294Ssam 2910294Ssam /* 3010294Ssam * Connect to peer server and 3110294Ssam * auto-login, if possible. 3210294Ssam */ 3310294Ssam setpeer(argc, argv) 3410294Ssam int argc; 3510294Ssam char *argv[]; 3610294Ssam { 3710294Ssam struct hostent *host, *hookup(); 3810294Ssam int port; 3910294Ssam 4010294Ssam if (connected) { 4110294Ssam printf("Already connected to %s, use disconnect first.\n", 4210294Ssam hostname); 4310294Ssam return; 4410294Ssam } 4510294Ssam if (argc < 2) { 4610294Ssam strcat(line, " "); 4710294Ssam printf("(to) "); 4810294Ssam gets(&line[strlen(line)]); 4910294Ssam makeargv(); 5010294Ssam argc = margc; 5110294Ssam argv = margv; 5210294Ssam } 5310294Ssam if (argc > 3) { 5410294Ssam printf("usage: %s host-name [port]\n", argv[0]); 5510294Ssam return; 5610294Ssam } 5710294Ssam port = sp->s_port; 5810294Ssam if (argc > 2) { 5911218Ssam port = atoi(argv[2]); 6010294Ssam if (port <= 0) { 6111218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 6211218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 6310294Ssam return; 6410294Ssam } 6510294Ssam port = htons(port); 6610294Ssam } 6710294Ssam host = hookup(argv[1], port); 6810294Ssam if (host) { 6910294Ssam connected = 1; 7010294Ssam if (autologin) 7110294Ssam login(host); 7210294Ssam } 7310294Ssam } 7410294Ssam 7510294Ssam struct types { 7610294Ssam char *t_name; 7710294Ssam char *t_mode; 7810294Ssam int t_type; 7911218Ssam char *t_arg; 8010294Ssam } types[] = { 8111218Ssam { "ascii", "A", TYPE_A, 0 }, 8211218Ssam { "binary", "I", TYPE_I, 0 }, 8311218Ssam { "image", "I", TYPE_I, 0 }, 8411218Ssam { "ebcdic", "E", TYPE_E, 0 }, 8511218Ssam { "tenex", "L", TYPE_L, bytename }, 8610294Ssam 0 8710294Ssam }; 8810294Ssam 8910294Ssam /* 9010294Ssam * Set transfer type. 9110294Ssam */ 9210294Ssam settype(argc, argv) 9310294Ssam char *argv[]; 9410294Ssam { 9510294Ssam register struct types *p; 9611218Ssam int comret; 9710294Ssam 9810294Ssam if (argc > 2) { 9910294Ssam char *sep; 10010294Ssam 10110294Ssam printf("usage: %s [", argv[0]); 10210294Ssam sep = " "; 10310294Ssam for (p = types; p->t_name; p++) { 10410294Ssam printf("%s%s", sep, p->t_name); 10510294Ssam if (*sep == ' ') 10610294Ssam sep = " | "; 10710294Ssam } 10810294Ssam printf(" ]\n"); 10910294Ssam return; 11010294Ssam } 11110294Ssam if (argc < 2) { 11210294Ssam printf("Using %s mode to transfer files.\n", typename); 11310294Ssam return; 11410294Ssam } 11510294Ssam for (p = types; p->t_name; p++) 11610294Ssam if (strcmp(argv[1], p->t_name) == 0) 11710294Ssam break; 11810294Ssam if (p->t_name == 0) { 11910294Ssam printf("%s: unknown mode\n", argv[1]); 12010294Ssam return; 12110294Ssam } 12211218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 12311218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 12411218Ssam else 12511218Ssam comret = command("TYPE %s", p->t_mode); 12611218Ssam if (comret == COMPLETE) { 12710294Ssam strcpy(typename, p->t_name); 12810294Ssam type = p->t_type; 12910294Ssam } 13010294Ssam } 13110294Ssam 13210294Ssam /* 13310294Ssam * Set binary transfer type. 13410294Ssam */ 13510294Ssam /*VARARGS*/ 13610294Ssam setbinary() 13710294Ssam { 13810294Ssam 13910294Ssam call(settype, "type", "binary", 0); 14010294Ssam } 14110294Ssam 14210294Ssam /* 14310294Ssam * Set ascii transfer type. 14410294Ssam */ 14510294Ssam /*VARARGS*/ 14610294Ssam setascii() 14710294Ssam { 14810294Ssam 14910294Ssam call(settype, "type", "ascii", 0); 15010294Ssam } 15110294Ssam 15210294Ssam /* 15310294Ssam * Set tenex transfer type. 15410294Ssam */ 15510294Ssam /*VARARGS*/ 15610294Ssam settenex() 15710294Ssam { 15810294Ssam 15910294Ssam call(settype, "type", "tenex", 0); 16010294Ssam } 16110294Ssam 16210294Ssam /* 16310294Ssam * Set ebcdic transfer type. 16410294Ssam */ 16510294Ssam /*VARARGS*/ 16610294Ssam setebcdic() 16710294Ssam { 16810294Ssam 16910294Ssam call(settype, "type", "ebcdic", 0); 17010294Ssam } 17110294Ssam 17210294Ssam /* 17310294Ssam * Set file transfer mode. 17410294Ssam */ 17510294Ssam setmode(argc, argv) 17610294Ssam char *argv[]; 17710294Ssam { 17810294Ssam 17910294Ssam printf("We only support %s mode, sorry.\n", modename); 18010294Ssam } 18110294Ssam 18210294Ssam /* 18310294Ssam * Set file transfer format. 18410294Ssam */ 18510294Ssam setform(argc, argv) 18610294Ssam char *argv[]; 18710294Ssam { 18810294Ssam 18910294Ssam printf("We only support %s format, sorry.\n", formname); 19010294Ssam } 19110294Ssam 19210294Ssam /* 19310294Ssam * Set file transfer structure. 19410294Ssam */ 19510294Ssam setstruct(argc, argv) 19610294Ssam char *argv[]; 19710294Ssam { 19810294Ssam 19910294Ssam printf("We only support %s structure, sorry.\n", structname); 20010294Ssam } 20110294Ssam 202*18286Sralph /* 203*18286Sralph * Send a single file. 204*18286Sralph */ 20510294Ssam put(argc, argv) 20611756Ssam int argc; 20710294Ssam char *argv[]; 20810294Ssam { 20911650Ssam char *cmd; 21011650Ssam 21110294Ssam if (argc == 2) 21210294Ssam argc++, argv[2] = argv[1]; 21310294Ssam if (argc < 2) { 21410294Ssam strcat(line, " "); 21510294Ssam printf("(local-file) "); 21610294Ssam gets(&line[strlen(line)]); 21710294Ssam makeargv(); 21810294Ssam argc = margc; 21910294Ssam argv = margv; 22010294Ssam } 22110294Ssam if (argc < 2) { 22210294Ssam usage: 22310294Ssam printf("%s local-file remote-file\n", argv[0]); 22410294Ssam return; 22510294Ssam } 22610294Ssam if (argc < 3) { 22710294Ssam strcat(line, " "); 22810294Ssam printf("(remote-file) "); 22910294Ssam gets(&line[strlen(line)]); 23010294Ssam makeargv(); 23110294Ssam argc = margc; 23210294Ssam argv = margv; 23310294Ssam } 23410294Ssam if (argc < 3) 23510294Ssam goto usage; 23611353Ssam if (!globulize(&argv[1])) 23711353Ssam return; 23811756Ssam cmd = (argv[0][0] == 'a') ? "APPE" : "STOR"; 23911650Ssam sendrequest(cmd, argv[1], argv[2]); 24010294Ssam } 24110294Ssam 24210294Ssam /* 24311756Ssam * Send multiple files. 24410294Ssam */ 24511353Ssam mput(argc, argv) 24611353Ssam char *argv[]; 24711353Ssam { 24813212Ssam register int i; 24911353Ssam 25011650Ssam if (argc < 2) { 25111650Ssam strcat(line, " "); 25211650Ssam printf("(local-files) "); 25311650Ssam gets(&line[strlen(line)]); 25411650Ssam makeargv(); 25511650Ssam argc = margc; 25611650Ssam argv = margv; 25711353Ssam } 25811353Ssam if (argc < 2) { 25911353Ssam printf("%s local-files\n", argv[0]); 26011353Ssam return; 26111353Ssam } 26213212Ssam for (i = 1; i < argc; i++) { 26313212Ssam register char **cpp, **gargs; 26413212Ssam 26513212Ssam if (!doglob) { 26613212Ssam if (confirm(argv[0], argv[i])) 26713212Ssam sendrequest("STOR", argv[i], argv[i]); 26813212Ssam continue; 26913212Ssam } 27013212Ssam gargs = glob(argv[i]); 27111650Ssam if (globerr != NULL) { 27211650Ssam printf("%s\n", globerr); 27311650Ssam if (gargs) 27411650Ssam blkfree(gargs); 27513212Ssam continue; 27611353Ssam } 27713212Ssam for (cpp = gargs; cpp && *cpp != NULL; cpp++) 27813212Ssam if (confirm(argv[0], *cpp)) 27913212Ssam sendrequest("STOR", *cpp, *cpp); 28013212Ssam if (gargs != NULL) 28113212Ssam blkfree(gargs); 28211353Ssam } 28311353Ssam } 28411353Ssam 28511353Ssam /* 28611353Ssam * Receive one file. 28711353Ssam */ 28810294Ssam get(argc, argv) 28910294Ssam char *argv[]; 29010294Ssam { 29110294Ssam 29210294Ssam if (argc == 2) 29310294Ssam argc++, argv[2] = argv[1]; 29410294Ssam if (argc < 2) { 29510294Ssam strcat(line, " "); 29610294Ssam printf("(remote-file) "); 29710294Ssam gets(&line[strlen(line)]); 29810294Ssam makeargv(); 29910294Ssam argc = margc; 30010294Ssam argv = margv; 30110294Ssam } 30210294Ssam if (argc < 2) { 30310294Ssam usage: 30411353Ssam printf("%s remote-file [ local-file ]\n", argv[0]); 30510294Ssam return; 30610294Ssam } 30710294Ssam if (argc < 3) { 30810294Ssam strcat(line, " "); 30910294Ssam printf("(local-file) "); 31010294Ssam gets(&line[strlen(line)]); 31110294Ssam makeargv(); 31210294Ssam argc = margc; 31310294Ssam argv = margv; 31410294Ssam } 31510294Ssam if (argc < 3) 31610294Ssam goto usage; 31711353Ssam if (!globulize(&argv[2])) 31811353Ssam return; 31911650Ssam recvrequest("RETR", argv[2], argv[1], "w"); 32010294Ssam } 32110294Ssam 32211353Ssam /* 32311353Ssam * Get multiple files. 32411353Ssam */ 32511353Ssam mget(argc, argv) 32611353Ssam char *argv[]; 32711353Ssam { 32811756Ssam char *cp; 32911353Ssam 33011353Ssam if (argc < 2) { 33111353Ssam strcat(line, " "); 33211756Ssam printf("(remote-files) "); 33311353Ssam gets(&line[strlen(line)]); 33411353Ssam makeargv(); 33511353Ssam argc = margc; 33611353Ssam argv = margv; 33711353Ssam } 33811353Ssam if (argc < 2) { 33911650Ssam printf("%s remote-files\n", argv[0]); 34011353Ssam return; 34111353Ssam } 34211650Ssam while ((cp = remglob(argc, argv)) != NULL) 34311650Ssam if (confirm(argv[0], cp)) 34411650Ssam recvrequest("RETR", cp, cp, "w"); 34511650Ssam } 34611650Ssam 34711650Ssam char * 34811650Ssam remglob(argc, argv) 34911650Ssam char *argv[]; 35011650Ssam { 35111756Ssam char temp[16]; 35211650Ssam static char buf[MAXPATHLEN]; 35311650Ssam static FILE *ftemp = NULL; 35411650Ssam static char **args; 35513212Ssam int oldverbose, oldhash; 35611756Ssam char *cp, *mode; 35711650Ssam 35811650Ssam if (!doglob) { 35911756Ssam if (args == NULL) 36011650Ssam args = argv; 36111650Ssam if ((cp = *++args) == NULL) 36211650Ssam args = NULL; 36311650Ssam return (cp); 36411353Ssam } 36511650Ssam if (ftemp == NULL) { 36611650Ssam strcpy(temp, "/tmp/ftpXXXXXX"); 36711650Ssam mktemp(temp); 36811650Ssam oldverbose = verbose, verbose = 0; 36913212Ssam oldhash = hash, hash = 0; 37011756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 37111756Ssam recvrequest ("NLST", temp, *argv, mode); 37213212Ssam verbose = oldverbose; hash = oldhash; 37311650Ssam ftemp = fopen(temp, "r"); 37411650Ssam unlink(temp); 37511650Ssam if (ftemp == NULL) { 37611650Ssam printf("can't find list of remote files, oops\n"); 37711756Ssam return (NULL); 37811353Ssam } 37911353Ssam } 38011650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 38111650Ssam fclose(ftemp), ftemp = NULL; 38211650Ssam return (NULL); 38311353Ssam } 38411650Ssam if ((cp = index(buf, '\n')) != NULL) 38511650Ssam *cp = '\0'; 38611650Ssam return (buf); 38711353Ssam } 38811353Ssam 38910294Ssam char * 39010294Ssam onoff(bool) 39110294Ssam int bool; 39210294Ssam { 39310294Ssam 39410294Ssam return (bool ? "on" : "off"); 39510294Ssam } 39610294Ssam 39710294Ssam /* 39810294Ssam * Show status. 39910294Ssam */ 40010294Ssam status(argc, argv) 40110294Ssam char *argv[]; 40210294Ssam { 40310294Ssam 40410294Ssam if (connected) 40510294Ssam printf("Connected to %s.\n", hostname); 40610294Ssam else 40710294Ssam printf("Not connected.\n"); 40810294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 40910294Ssam modename, typename, formname, structname); 41011353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 41111353Ssam onoff(verbose), onoff(bell), onoff(interactive), 41211353Ssam onoff(doglob)); 41314143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 41414143Ssam onoff(hash), onoff(sendport)); 41510294Ssam } 41610294Ssam 41710294Ssam /* 41810294Ssam * Set beep on cmd completed mode. 41910294Ssam */ 42010294Ssam /*VARARGS*/ 42110294Ssam setbell() 42210294Ssam { 42310294Ssam 42410294Ssam bell = !bell; 42510294Ssam printf("Bell mode %s.\n", onoff(bell)); 42610294Ssam } 42710294Ssam 42810294Ssam /* 42910294Ssam * Turn on packet tracing. 43010294Ssam */ 43110294Ssam /*VARARGS*/ 43210294Ssam settrace() 43310294Ssam { 43410294Ssam 43510294Ssam trace = !trace; 43610294Ssam printf("Packet tracing %s.\n", onoff(trace)); 43710294Ssam } 43810294Ssam 43910294Ssam /* 44011650Ssam * Toggle hash mark printing during transfers. 44111650Ssam */ 44211650Ssam /*VARARGS*/ 44311650Ssam sethash() 44411650Ssam { 44511650Ssam 44611650Ssam hash = !hash; 44711650Ssam printf("Hash mark printing %s", onoff(hash)); 44811650Ssam if (hash) 44911650Ssam printf(" (%d bytes/hash mark)", BUFSIZ); 45011650Ssam printf(".\n"); 45111650Ssam } 45211650Ssam 45311650Ssam /* 45410294Ssam * Turn on printing of server echo's. 45510294Ssam */ 45610294Ssam /*VARARGS*/ 45710294Ssam setverbose() 45810294Ssam { 45910294Ssam 46010294Ssam verbose = !verbose; 46110294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 46210294Ssam } 46310294Ssam 46410294Ssam /* 46511650Ssam * Toggle PORT cmd use before each data connection. 46611650Ssam */ 46711650Ssam /*VARARGS*/ 46811650Ssam setport() 46911650Ssam { 47011650Ssam 47111650Ssam sendport = !sendport; 47211650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 47311650Ssam } 47411650Ssam 47511650Ssam /* 47610294Ssam * Turn on interactive prompting 47710294Ssam * during mget, mput, and mdelete. 47810294Ssam */ 47910294Ssam /*VARARGS*/ 48010294Ssam setprompt() 48110294Ssam { 48210294Ssam 48310294Ssam interactive = !interactive; 48410294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 48510294Ssam } 48610294Ssam 48710294Ssam /* 48811353Ssam * Toggle metacharacter interpretation 48911353Ssam * on local file names. 49011353Ssam */ 49111353Ssam /*VARARGS*/ 49211353Ssam setglob() 49311353Ssam { 49411353Ssam 49511353Ssam doglob = !doglob; 49611353Ssam printf("Globbing %s.\n", onoff(doglob)); 49711353Ssam } 49811353Ssam 49911353Ssam /* 50010294Ssam * Set debugging mode on/off and/or 50110294Ssam * set level of debugging. 50210294Ssam */ 50311756Ssam /*VARARGS*/ 50410294Ssam setdebug(argc, argv) 50510294Ssam char *argv[]; 50610294Ssam { 50710294Ssam int val; 50810294Ssam 50910294Ssam if (argc > 1) { 51010294Ssam val = atoi(argv[1]); 51110294Ssam if (val < 0) { 51210294Ssam printf("%s: bad debugging value.\n", argv[1]); 51310294Ssam return; 51410294Ssam } 51510294Ssam } else 51610294Ssam val = !debug; 51710294Ssam debug = val; 51810294Ssam if (debug) 51910294Ssam options |= SO_DEBUG; 52010294Ssam else 52110294Ssam options &= ~SO_DEBUG; 52210294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 52310294Ssam } 52410294Ssam 52510294Ssam /* 52610294Ssam * Set current working directory 52710294Ssam * on remote machine. 52810294Ssam */ 52910294Ssam cd(argc, argv) 53010294Ssam char *argv[]; 53110294Ssam { 53210294Ssam 53310294Ssam if (argc < 2) { 53410294Ssam strcat(line, " "); 53510294Ssam printf("(remote-directory) "); 53610294Ssam gets(&line[strlen(line)]); 53710294Ssam makeargv(); 53810294Ssam argc = margc; 53910294Ssam argv = margv; 54010294Ssam } 54110294Ssam if (argc < 2) { 54210294Ssam printf("%s remote-directory\n", argv[0]); 54310294Ssam return; 54410294Ssam } 54510294Ssam (void) command("CWD %s", argv[1]); 54610294Ssam } 54710294Ssam 54810294Ssam /* 54910294Ssam * Set current working directory 55010294Ssam * on local machine. 55110294Ssam */ 55210294Ssam lcd(argc, argv) 55310294Ssam char *argv[]; 55410294Ssam { 55511353Ssam char buf[MAXPATHLEN]; 55610294Ssam 55711353Ssam if (argc < 2) 55811353Ssam argc++, argv[1] = home; 55910294Ssam if (argc != 2) { 56010294Ssam printf("%s local-directory\n", argv[0]); 56110294Ssam return; 56210294Ssam } 56311353Ssam if (!globulize(&argv[1])) 56411353Ssam return; 56511353Ssam if (chdir(argv[1]) < 0) { 56610294Ssam perror(argv[1]); 56711353Ssam return; 56811353Ssam } 56911353Ssam printf("Local directory now %s\n", getwd(buf)); 57010294Ssam } 57110294Ssam 57210294Ssam /* 57310294Ssam * Delete a single file. 57410294Ssam */ 57510294Ssam delete(argc, argv) 57610294Ssam char *argv[]; 57710294Ssam { 57810294Ssam 57910294Ssam if (argc < 2) { 58010294Ssam strcat(line, " "); 58110294Ssam printf("(remote-file) "); 58210294Ssam gets(&line[strlen(line)]); 58310294Ssam makeargv(); 58410294Ssam argc = margc; 58510294Ssam argv = margv; 58610294Ssam } 58710294Ssam if (argc < 2) { 58810294Ssam printf("%s remote-file\n", argv[0]); 58910294Ssam return; 59010294Ssam } 59110294Ssam (void) command("DELE %s", argv[1]); 59210294Ssam } 59310294Ssam 59410294Ssam /* 59511650Ssam * Delete multiple files. 59611650Ssam */ 59711650Ssam mdelete(argc, argv) 59811650Ssam char *argv[]; 59911650Ssam { 60011650Ssam char *cp; 60111650Ssam 60211650Ssam if (argc < 2) { 60311650Ssam strcat(line, " "); 60411650Ssam printf("(remote-files) "); 60511650Ssam gets(&line[strlen(line)]); 60611650Ssam makeargv(); 60711650Ssam argc = margc; 60811650Ssam argv = margv; 60911650Ssam } 61011650Ssam if (argc < 2) { 61111650Ssam printf("%s remote-files\n", argv[0]); 61211650Ssam return; 61311650Ssam } 61411650Ssam while ((cp = remglob(argc, argv)) != NULL) 61511650Ssam if (confirm(argv[0], cp)) 61611650Ssam (void) command("DELE %s", cp); 61711650Ssam } 61811756Ssam 61911650Ssam /* 62010294Ssam * Rename a remote file. 62110294Ssam */ 62210294Ssam renamefile(argc, argv) 62310294Ssam char *argv[]; 62410294Ssam { 62510294Ssam 62610294Ssam if (argc < 2) { 62710294Ssam strcat(line, " "); 62810294Ssam printf("(from-name) "); 62910294Ssam gets(&line[strlen(line)]); 63010294Ssam makeargv(); 63110294Ssam argc = margc; 63210294Ssam argv = margv; 63310294Ssam } 63410294Ssam if (argc < 2) { 63510294Ssam usage: 63610294Ssam printf("%s from-name to-name\n", argv[0]); 63710294Ssam return; 63810294Ssam } 63910294Ssam if (argc < 3) { 64010294Ssam strcat(line, " "); 64110294Ssam printf("(to-name) "); 64210294Ssam gets(&line[strlen(line)]); 64310294Ssam makeargv(); 64410294Ssam argc = margc; 64510294Ssam argv = margv; 64610294Ssam } 64710294Ssam if (argc < 3) 64810294Ssam goto usage; 64910294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 65010294Ssam (void) command("RNTO %s", argv[2]); 65110294Ssam } 65210294Ssam 65310294Ssam /* 65410294Ssam * Get a directory listing 65510294Ssam * of remote files. 65610294Ssam */ 65710294Ssam ls(argc, argv) 65810294Ssam char *argv[]; 65910294Ssam { 66011756Ssam char *cmd; 66110294Ssam 66210294Ssam if (argc < 2) 66310294Ssam argc++, argv[1] = NULL; 66410294Ssam if (argc < 3) 66510294Ssam argc++, argv[2] = "-"; 66611756Ssam if (argc > 3) { 66711756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 66811756Ssam return; 66911756Ssam } 67010294Ssam cmd = argv[0][0] == 'l' ? "NLST" : "LIST"; 67111353Ssam if (strcmp(argv[2], "-") && !globulize(&argv[2])) 67211353Ssam return; 67311756Ssam recvrequest(cmd, argv[2], argv[1], "w"); 67410294Ssam } 67510294Ssam 67610294Ssam /* 67711756Ssam * Get a directory listing 67811756Ssam * of multiple remote files. 67911756Ssam */ 68011756Ssam mls(argc, argv) 68111756Ssam char *argv[]; 68211756Ssam { 68313212Ssam char *cmd, *mode, *cp, *dest; 68411756Ssam 68513212Ssam if (argc < 2) { 68613212Ssam strcat(line, " "); 68713212Ssam printf("(remote-files) "); 68813212Ssam gets(&line[strlen(line)]); 68913212Ssam makeargv(); 69013212Ssam argc = margc; 69113212Ssam argv = margv; 69213212Ssam } 69313212Ssam if (argc < 3) { 69413212Ssam strcat(line, " "); 69513212Ssam printf("(local-file) "); 69613212Ssam gets(&line[strlen(line)]); 69713212Ssam makeargv(); 69813212Ssam argc = margc; 69913212Ssam argv = margv; 70013212Ssam } 70113212Ssam if (argc < 3) { 70213212Ssam printf("%s remote-files local-file\n", argv[0]); 70313212Ssam return; 70413212Ssam } 70513212Ssam dest = argv[argc - 1]; 70613212Ssam argv[argc - 1] = NULL; 70713212Ssam if (strcmp(dest, "-")) 70816324Sralph if (!globulize(&dest) || !confirm("local-file", dest)) 70913212Ssam return; 71011756Ssam cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 71113212Ssam for (mode = "w"; cp = remglob(argc, argv); mode = "a") 71213212Ssam if (confirm(argv[0], cp)) 71313212Ssam recvrequest(cmd, dest, cp, mode); 71411756Ssam } 71511756Ssam 71611756Ssam /* 71710294Ssam * Do a shell escape 71810294Ssam */ 71910294Ssam shell(argc, argv) 72010294Ssam char *argv[]; 72110294Ssam { 72211756Ssam int pid, status, (*old1)(), (*old2)(); 72311756Ssam char shellnam[40], *shell, *namep; 72411756Ssam char **cpp, **gargs; 72510294Ssam 72611756Ssam old1 = signal (SIGINT, SIG_IGN); 72711756Ssam old2 = signal (SIGQUIT, SIG_IGN); 72811756Ssam if ((pid = fork()) == 0) { 72911756Ssam for (pid = 3; pid < 20; pid++) 73011756Ssam close(pid); 73111756Ssam signal(SIGINT, SIG_DFL); 73211756Ssam signal(SIGQUIT, SIG_DFL); 73311756Ssam if (argc <= 1) { 73411756Ssam shell = getenv("SHELL"); 73511756Ssam if (shell == NULL) 73611756Ssam shell = "/bin/sh"; 73711756Ssam namep = rindex(shell,'/'); 73811756Ssam if (namep == NULL) 73911756Ssam namep = shell; 74011756Ssam strcpy(shellnam,"-"); 74111756Ssam strcat(shellnam, ++namep); 74211756Ssam if (strcmp(namep, "sh") != 0) 74311756Ssam shellnam[0] = '+'; 74411756Ssam if (debug) { 74511756Ssam printf ("%s\n", shell); 74611756Ssam fflush (stdout); 74711756Ssam } 74811756Ssam execl(shell, shellnam, 0); 74911756Ssam perror(shell); 75011756Ssam exit(1); 75111756Ssam } 75211756Ssam cpp = &argv[1]; 75311756Ssam if (argc > 2) { 75411756Ssam if ((gargs = glob(cpp)) != NULL) 75511756Ssam cpp = gargs; 75611756Ssam if (globerr != NULL) { 75711756Ssam printf("%s\n", globerr); 75811756Ssam exit(1); 75911756Ssam } 76011756Ssam } 76111756Ssam if (debug) { 76211756Ssam register char **zip = cpp; 76311756Ssam 76411756Ssam printf("%s", *zip); 76511756Ssam while (*++zip != NULL) 76611756Ssam printf(" %s", *zip); 76711756Ssam printf("\n"); 76811756Ssam fflush(stdout); 76911756Ssam } 77011756Ssam execvp(argv[1], cpp); 77111756Ssam perror(argv[1]); 77211756Ssam exit(1); 77311756Ssam } 77411756Ssam if (pid > 0) 77511756Ssam while (wait(&status) != pid) 77611756Ssam ; 77711756Ssam signal(SIGINT, old1); 77811756Ssam signal(SIGQUIT, old2); 77911756Ssam if (pid == -1) 78011756Ssam perror("Try again later"); 78111756Ssam return (0); 78210294Ssam } 78310294Ssam 78410294Ssam /* 78510294Ssam * Send new user information (re-login) 78610294Ssam */ 78710294Ssam user(argc, argv) 78810294Ssam int argc; 78910294Ssam char **argv; 79010294Ssam { 79110294Ssam char acct[80], *getpass(); 79210294Ssam int n; 79310294Ssam 79410294Ssam if (argc < 2) { 79510294Ssam strcat(line, " "); 79610294Ssam printf("(username) "); 79710294Ssam gets(&line[strlen(line)]); 79810294Ssam makeargv(); 79910294Ssam argc = margc; 80010294Ssam argv = margv; 80110294Ssam } 80210294Ssam if (argc > 4) { 80310294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 80411756Ssam return (0); 80510294Ssam } 80610294Ssam n = command("USER %s", argv[1]); 80710294Ssam if (n == CONTINUE) { 80810294Ssam if (argc < 3 ) 80910294Ssam argv[2] = getpass("Password: "), argc++; 81010294Ssam n = command("PASS %s", argv[2]); 81110294Ssam } 81210294Ssam if (n == CONTINUE) { 81310294Ssam if (argc < 4) { 81410294Ssam printf("Account: "); (void) fflush(stdout); 81510294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 81610294Ssam acct[strlen(acct) - 1] = '\0'; 81710294Ssam argv[3] = acct; argc++; 81810294Ssam } 81910294Ssam n = command("ACCT %s", acct); 82010294Ssam } 82110294Ssam if (n != COMPLETE) { 82210294Ssam fprintf(stderr, "Login failed.\n"); 82310294Ssam return (0); 82410294Ssam } 82510294Ssam return (1); 82610294Ssam } 82710294Ssam 82810294Ssam /* 82910294Ssam * Print working directory. 83010294Ssam */ 83110294Ssam /*VARARGS*/ 83210294Ssam pwd() 83310294Ssam { 83411756Ssam 83510294Ssam (void) command("XPWD"); 83610294Ssam } 83710294Ssam 83810294Ssam /* 83910294Ssam * Make a directory. 84010294Ssam */ 84110294Ssam makedir(argc, argv) 84210294Ssam char *argv[]; 84310294Ssam { 84410294Ssam 84510294Ssam if (argc < 2) { 84610294Ssam strcat(line, " "); 84710294Ssam printf("(directory-name) "); 84810294Ssam gets(&line[strlen(line)]); 84910294Ssam makeargv(); 85010294Ssam argc = margc; 85110294Ssam argv = margv; 85210294Ssam } 85310294Ssam if (argc < 2) { 85410294Ssam printf("%s directory-name\n", argv[0]); 85510294Ssam return; 85610294Ssam } 85710294Ssam (void) command("XMKD %s", argv[1]); 85810294Ssam } 85910294Ssam 86010294Ssam /* 86110294Ssam * Remove a directory. 86210294Ssam */ 86310294Ssam removedir(argc, argv) 86410294Ssam char *argv[]; 86510294Ssam { 86610294Ssam 86710294Ssam if (argc < 2) { 86810294Ssam strcat(line, " "); 86910294Ssam printf("(directory-name) "); 87010294Ssam gets(&line[strlen(line)]); 87110294Ssam makeargv(); 87210294Ssam argc = margc; 87310294Ssam argv = margv; 87410294Ssam } 87510294Ssam if (argc < 2) { 87610294Ssam printf("%s directory-name\n", argv[0]); 87710294Ssam return; 87810294Ssam } 87910294Ssam (void) command("XRMD %s", argv[1]); 88010294Ssam } 88110294Ssam 88210294Ssam /* 88310294Ssam * Send a line, verbatim, to the remote machine. 88410294Ssam */ 88510294Ssam quote(argc, argv) 88610294Ssam char *argv[]; 88710294Ssam { 88810294Ssam int i; 88910294Ssam char buf[BUFSIZ]; 89010294Ssam 89110294Ssam if (argc < 2) { 89210294Ssam strcat(line, " "); 89310294Ssam printf("(command line to send) "); 89410294Ssam gets(&line[strlen(line)]); 89510294Ssam makeargv(); 89610294Ssam argc = margc; 89710294Ssam argv = margv; 89810294Ssam } 89910294Ssam if (argc < 2) { 90010294Ssam printf("usage: %s line-to-send\n", argv[0]); 90110294Ssam return; 90210294Ssam } 90310294Ssam strcpy(buf, argv[1]); 90410294Ssam for (i = 2; i < argc; i++) { 90510294Ssam strcat(buf, " "); 90610294Ssam strcat(buf, argv[i]); 90710294Ssam } 90810294Ssam (void) command(buf); 90910294Ssam } 91010294Ssam 91110294Ssam /* 91210294Ssam * Ask the other side for help. 91310294Ssam */ 91410294Ssam rmthelp(argc, argv) 91510294Ssam char *argv[]; 91610294Ssam { 91710294Ssam int oldverbose = verbose; 91810294Ssam 91910294Ssam verbose = 1; 92010294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 92110294Ssam verbose = oldverbose; 92210294Ssam } 92310294Ssam 92410294Ssam /* 92510294Ssam * Terminate session and exit. 92610294Ssam */ 92710294Ssam /*VARARGS*/ 92810294Ssam quit() 92910294Ssam { 93010294Ssam 931*18286Sralph if (connected) 932*18286Sralph disconnect(); 93310294Ssam exit(0); 93410294Ssam } 93510294Ssam 93610294Ssam /* 93710294Ssam * Terminate session, but don't exit. 93810294Ssam */ 93910294Ssam disconnect() 94010294Ssam { 94110294Ssam extern FILE *cout; 94210294Ssam extern int data; 94310294Ssam 94410294Ssam if (!connected) 94510294Ssam return; 94610294Ssam (void) command("QUIT"); 94710294Ssam (void) fclose(cout); 94810294Ssam cout = NULL; 94910294Ssam connected = 0; 95010294Ssam data = -1; 95110294Ssam } 95211353Ssam 95311650Ssam confirm(cmd, file) 95411353Ssam char *cmd, *file; 95511353Ssam { 95611353Ssam char line[BUFSIZ]; 95711353Ssam 95811353Ssam if (!interactive) 95911650Ssam return (1); 96011353Ssam printf("%s %s? ", cmd, file); 96111353Ssam fflush(stdout); 96211353Ssam gets(line); 96311650Ssam return (*line != 'n' && *line != 'N'); 96411353Ssam } 96511353Ssam 96611353Ssam fatal(msg) 96711353Ssam char *msg; 96811353Ssam { 96911353Ssam 97011353Ssam fprintf(stderr, "ftp: %s\n"); 97111353Ssam exit(1); 97211353Ssam } 97311353Ssam 97411353Ssam /* 97511353Ssam * Glob a local file name specification with 97611353Ssam * the expectation of a single return value. 97711353Ssam * Can't control multiple values being expanded 97811353Ssam * from the expression, we return only the first. 97911353Ssam */ 98011353Ssam globulize(cpp) 98111353Ssam char **cpp; 98211353Ssam { 98311353Ssam char **globbed; 98411353Ssam 98511353Ssam if (!doglob) 98611353Ssam return (1); 98711353Ssam globbed = glob(*cpp); 98811353Ssam if (globerr != NULL) { 98911353Ssam printf("%s: %s\n", *cpp, globerr); 99011353Ssam if (globbed) 99111353Ssam blkfree(globbed); 99211353Ssam return (0); 99311353Ssam } 99411353Ssam if (globbed) { 99511353Ssam *cpp = *globbed++; 99611353Ssam /* don't waste too much memory */ 99711353Ssam if (*globbed) 99811353Ssam blkfree(globbed); 99911353Ssam } 100011353Ssam return (1); 100111353Ssam } 1002