xref: /csrg-svn/usr.bin/ftp/cmds.c (revision 11218)
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