xref: /csrg-svn/usr.bin/ftp/cmds.c (revision 10294)
1 #ifndef lint
2 static char sccsid[] = "@(#)cmds.c	4.1 (Berkeley) 01/15/83";
3 #endif
4 
5 /*
6  * FTP User Program -- Command Routines.
7  */
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 
11 #include <signal.h>
12 #include <stdio.h>
13 #include <errno.h>
14 #include <netdb.h>
15 
16 #include "ftp.h"
17 #include "ftp_var.h"
18 
19 int	autologin = 1;
20 
21 /*
22  * Connect to peer server and
23  * auto-login, if possible.
24  */
25 setpeer(argc, argv)
26 	int argc;
27 	char *argv[];
28 {
29 	struct hostent *host, *hookup();
30 	int port;
31 
32 	if (connected) {
33 		printf("Already connected to %s, use disconnect first.\n",
34 			hostname);
35 		return;
36 	}
37 	if (argc < 2) {
38 		strcat(line, " ");
39 		printf("(to) ");
40 		gets(&line[strlen(line)]);
41 		makeargv();
42 		argc = margc;
43 		argv = margv;
44 	}
45 	if (argc > 3) {
46 		printf("usage: %s host-name [port]\n", argv[0]);
47 		return;
48 	}
49 	port = sp->s_port;
50 	if (argc > 2) {
51 		port = atoi(argv[1]);
52 		if (port <= 0) {
53 			printf("%s: bad port number.\n", argv[1]);
54 			return;
55 		}
56 		port = htons(port);
57 	}
58 	host = hookup(argv[1], port);
59 	if (host) {
60 		connected = 1;
61 		if (autologin)
62 			login(host);
63 	}
64 }
65 
66 struct	types {
67 	char	*t_name;
68 	char	*t_mode;
69 	int	t_type;
70 } types[] = {
71 	{ "ascii",	"A",	TYPE_A },
72 	{ "binary",	"I",	TYPE_I },
73 	{ "image",	"I",	TYPE_I },
74 	{ "ebcdic",	"E",	TYPE_E },
75 	{ "tenex",	"L",	TYPE_L },
76 	0
77 };
78 
79 /*
80  * Set transfer type.
81  */
82 settype(argc, argv)
83 	char *argv[];
84 {
85 	register struct types *p;
86 
87 	if (argc > 2) {
88 		char *sep;
89 
90 		printf("usage: %s [", argv[0]);
91 		sep = " ";
92 		for (p = types; p->t_name; p++) {
93 			printf("%s%s", sep, p->t_name);
94 			if (*sep == ' ')
95 				sep = " | ";
96 		}
97 		printf(" ]\n");
98 		return;
99 	}
100 	if (argc < 2) {
101 		printf("Using %s mode to transfer files.\n", typename);
102 		return;
103 	}
104 	for (p = types; p->t_name; p++)
105 		if (strcmp(argv[1], p->t_name) == 0)
106 			break;
107 	if (p->t_name == 0) {
108 		printf("%s: unknown mode\n", argv[1]);
109 		return;
110 	}
111 	if (command("TYPE %s", p->t_mode) == COMPLETE) {
112 		strcpy(typename, p->t_name);
113 		type = p->t_type;
114 	}
115 }
116 
117 /*
118  * Set binary transfer type.
119  */
120 /*VARARGS*/
121 setbinary()
122 {
123 
124 	call(settype, "type", "binary", 0);
125 }
126 
127 /*
128  * Set ascii transfer type.
129  */
130 /*VARARGS*/
131 setascii()
132 {
133 
134 	call(settype, "type", "ascii", 0);
135 }
136 
137 /*
138  * Set tenex transfer type.
139  */
140 /*VARARGS*/
141 settenex()
142 {
143 
144 	call(settype, "type", "tenex", 0);
145 }
146 
147 /*
148  * Set ebcdic transfer type.
149  */
150 /*VARARGS*/
151 setebcdic()
152 {
153 
154 	call(settype, "type", "ebcdic", 0);
155 }
156 
157 /*
158  * Set file transfer mode.
159  */
160 setmode(argc, argv)
161 	char *argv[];
162 {
163 
164 	printf("We only support %s mode, sorry.\n", modename);
165 }
166 
167 /*
168  * Set file transfer format.
169  */
170 setform(argc, argv)
171 	char *argv[];
172 {
173 
174 	printf("We only support %s format, sorry.\n", formname);
175 }
176 
177 /*
178  * Set file transfer structure.
179  */
180 setstruct(argc, argv)
181 	char *argv[];
182 {
183 
184 	printf("We only support %s structure, sorry.\n", structname);
185 }
186 
187 /*
188  * Send a single file.
189  */
190 put(argc, argv)
191 	char *argv[];
192 {
193 	int fd;
194 	register int n, addr;
195 	register char *cp, *targ;
196 
197 	if (!connected) {
198 		printf("Not connected.\n");
199 		return;
200 	}
201 	if (argc == 2)
202 		argc++, argv[2] = argv[1];
203 	if (argc < 2) {
204 		strcat(line, " ");
205 		printf("(local-file) ");
206 		gets(&line[strlen(line)]);
207 		makeargv();
208 		argc = margc;
209 		argv = margv;
210 	}
211 	if (argc < 2) {
212 usage:
213 		printf("%s local-file remote-file\n", argv[0]);
214 		return;
215 	}
216 	if (argc < 3) {
217 		strcat(line, " ");
218 		printf("(remote-file) ");
219 		gets(&line[strlen(line)]);
220 		makeargv();
221 		argc = margc;
222 		argv = margv;
223 	}
224 	if (argc < 3)
225 		goto usage;
226 	sendrequest("STOR", argv[1], argv[2]);
227 }
228 
229 /*
230  * Receive a single file.
231  */
232 get(argc, argv)
233 	char *argv[];
234 {
235 	int fd;
236 	register int n, addr;
237 	register char *cp;
238 	char *src;
239 
240 	if (!connected) {
241 		printf("Not connected.\n");
242 		return;
243 	}
244 	if (argc == 2)
245 		argc++, argv[2] = argv[1];
246 	if (argc < 2) {
247 		strcat(line, " ");
248 		printf("(remote-file) ");
249 		gets(&line[strlen(line)]);
250 		makeargv();
251 		argc = margc;
252 		argv = margv;
253 	}
254 	if (argc < 2) {
255 usage:
256 		printf("%s remote-file local-file\n", argv[0]);
257 		return;
258 	}
259 	if (argc < 3) {
260 		strcat(line, " ");
261 		printf("(local-file) ");
262 		gets(&line[strlen(line)]);
263 		makeargv();
264 		argc = margc;
265 		argv = margv;
266 	}
267 	if (argc < 3)
268 		goto usage;
269 	recvrequest("RETR", argv[2], argv[1]);
270 }
271 
272 char *
273 onoff(bool)
274 	int bool;
275 {
276 
277 	return (bool ? "on" : "off");
278 }
279 
280 /*
281  * Show status.
282  */
283 status(argc, argv)
284 	char *argv[];
285 {
286 
287 	if (connected)
288 		printf("Connected to %s.\n", hostname);
289 	else
290 		printf("Not connected.\n");
291 	printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
292 		modename, typename, formname, structname);
293 	printf("Verbose: %s; Bell: %s; Prompting: %s\n",
294 		onoff(verbose), onoff(bell), onoff(interactive));
295 }
296 
297 /*
298  * Set beep on cmd completed mode.
299  */
300 /*VARARGS*/
301 setbell()
302 {
303 
304 	bell = !bell;
305 	printf("Bell mode %s.\n", onoff(bell));
306 }
307 
308 /*
309  * Turn on packet tracing.
310  */
311 /*VARARGS*/
312 settrace()
313 {
314 
315 	trace = !trace;
316 	printf("Packet tracing %s.\n", onoff(trace));
317 }
318 
319 /*
320  * Turn on printing of server echo's.
321  */
322 /*VARARGS*/
323 setverbose()
324 {
325 
326 	verbose = !verbose;
327 	printf("Verbose mode %s.\n", onoff(verbose));
328 }
329 
330 /*
331  * Turn on interactive prompting
332  * during mget, mput, and mdelete.
333  */
334 /*VARARGS*/
335 setprompt()
336 {
337 
338 	interactive = !interactive;
339 	printf("Interactive mode %s.\n", onoff(interactive));
340 }
341 
342 /*
343  * Set debugging mode on/off and/or
344  * set level of debugging.
345  */
346 /*VARARGS*/
347 setdebug(argc, argv)
348 	char *argv[];
349 {
350 	int val;
351 
352 	if (argc > 1) {
353 		val = atoi(argv[1]);
354 		if (val < 0) {
355 			printf("%s: bad debugging value.\n", argv[1]);
356 			return;
357 		}
358 	} else
359 		val = !debug;
360 	debug = val;
361 	if (debug)
362 		options |= SO_DEBUG;
363 	else
364 		options &= ~SO_DEBUG;
365 	printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
366 }
367 
368 /*
369  * Set current working directory
370  * on remote machine.
371  */
372 cd(argc, argv)
373 	char *argv[];
374 {
375 
376 	if (!connected) {
377 		printf("Not connected.\n");
378 		return;
379 	}
380 	if (argc < 2) {
381 		strcat(line, " ");
382 		printf("(remote-directory) ");
383 		gets(&line[strlen(line)]);
384 		makeargv();
385 		argc = margc;
386 		argv = margv;
387 	}
388 	if (argc < 2) {
389 		printf("%s remote-directory\n", argv[0]);
390 		return;
391 	}
392 	(void) command("CWD %s", argv[1]);
393 }
394 
395 #include <pwd.h>
396 
397 /*
398  * Set current working directory
399  * on local machine.
400  */
401 lcd(argc, argv)
402 	char *argv[];
403 {
404 	static struct passwd *pw = NULL;
405 
406 	if (argc < 2) {
407 		if (pw == NULL) {
408 			pw = getpwnam(getlogin());
409 			if (pw == NULL)
410 				pw = getpwuid(getuid());
411 		}
412 		if (pw == NULL) {
413 			printf("ftp: can't find home directory.\n");
414 			return;
415 		}
416 		argc++, argv[1] = pw->pw_dir;
417 	}
418 	if (argc != 2) {
419 		printf("%s local-directory\n", argv[0]);
420 		return;
421 	}
422 	if (chdir(argv[1]) < 0)
423 		perror(argv[1]);
424 }
425 
426 /*
427  * Delete a single file.
428  */
429 delete(argc, argv)
430 	char *argv[];
431 {
432 
433 	if (argc < 2) {
434 		strcat(line, " ");
435 		printf("(remote-file) ");
436 		gets(&line[strlen(line)]);
437 		makeargv();
438 		argc = margc;
439 		argv = margv;
440 	}
441 	if (argc < 2) {
442 		printf("%s remote-file\n", argv[0]);
443 		return;
444 	}
445 	(void) command("DELE %s", argv[1]);
446 }
447 
448 /*
449  * Rename a remote file.
450  */
451 renamefile(argc, argv)
452 	char *argv[];
453 {
454 
455 	if (argc < 2) {
456 		strcat(line, " ");
457 		printf("(from-name) ");
458 		gets(&line[strlen(line)]);
459 		makeargv();
460 		argc = margc;
461 		argv = margv;
462 	}
463 	if (argc < 2) {
464 usage:
465 		printf("%s from-name to-name\n", argv[0]);
466 		return;
467 	}
468 	if (argc < 3) {
469 		strcat(line, " ");
470 		printf("(to-name) ");
471 		gets(&line[strlen(line)]);
472 		makeargv();
473 		argc = margc;
474 		argv = margv;
475 	}
476 	if (argc < 3)
477 		goto usage;
478 	if (command("RNFR %s", argv[1]) == CONTINUE)
479 		(void) command("RNTO %s", argv[2]);
480 }
481 
482 /*
483  * Get a directory listing
484  * of remote files.
485  */
486 ls(argc, argv)
487 	char *argv[];
488 {
489 	char *cmd;
490 
491 	if (argc < 2)
492 		argc++, argv[1] = NULL;
493 	if (argc < 3)
494 		argc++, argv[2] = "-";
495 	if (argc > 3) {
496 		printf("usage: %s remote-directory local-file\n", argv[0]);
497 		return;
498 	}
499 	cmd = argv[0][0] == 'l' ? "NLST" : "LIST";
500 	recvrequest(cmd, argv[2], argv[1]);
501 }
502 
503 /*
504  * Do a shell escape
505  */
506 shell(argc, argv)
507 	char *argv[];
508 {
509 
510 	printf("Sorry, this function is unimplemented.\n");
511 }
512 
513 /*
514  * Send new user information (re-login)
515  */
516 user(argc, argv)
517 	int argc;
518 	char **argv;
519 {
520 	char acct[80], *getpass();
521 	int n;
522 
523 	if (argc < 2) {
524 		strcat(line, " ");
525 		printf("(username) ");
526 		gets(&line[strlen(line)]);
527 		makeargv();
528 		argc = margc;
529 		argv = margv;
530 	}
531 	if (argc > 4) {
532 		printf("usage: %s username [password] [account]\n", argv[0]);
533 		return;
534 	}
535 	n = command("USER %s", argv[1]);
536 	if (n == CONTINUE) {
537 		if (argc < 3 )
538 			argv[2] = getpass("Password: "), argc++;
539 		n = command("PASS %s", argv[2]);
540 	}
541 	if (n == CONTINUE) {
542 		if (argc < 4) {
543 			printf("Account: "); (void) fflush(stdout);
544 			(void) fgets(acct, sizeof(acct) - 1, stdin);
545 			acct[strlen(acct) - 1] = '\0';
546 			argv[3] = acct; argc++;
547 		}
548 		n = command("ACCT %s", acct);
549 	}
550 	if (n != COMPLETE) {
551 		fprintf(stderr, "Login failed.\n");
552 		return (0);
553 	}
554 	return (1);
555 }
556 
557 /*
558  * Print working directory.
559  */
560 /*VARARGS*/
561 pwd()
562 {
563 	if (!connected) {
564 		printf("Not connected.\n");
565 		return;
566 	}
567 	(void) command("XPWD");
568 }
569 
570 /*
571  * Make a directory.
572  */
573 makedir(argc, argv)
574 	char *argv[];
575 {
576 
577 	if (argc < 2) {
578 		strcat(line, " ");
579 		printf("(directory-name) ");
580 		gets(&line[strlen(line)]);
581 		makeargv();
582 		argc = margc;
583 		argv = margv;
584 	}
585 	if (argc < 2) {
586 		printf("%s directory-name\n", argv[0]);
587 		return;
588 	}
589 	(void) command("XMKD %s", argv[1]);
590 }
591 
592 /*
593  * Remove a directory.
594  */
595 removedir(argc, argv)
596 	char *argv[];
597 {
598 
599 	if (argc < 2) {
600 		strcat(line, " ");
601 		printf("(directory-name) ");
602 		gets(&line[strlen(line)]);
603 		makeargv();
604 		argc = margc;
605 		argv = margv;
606 	}
607 	if (argc < 2) {
608 		printf("%s directory-name\n", argv[0]);
609 		return;
610 	}
611 	(void) command("XRMD %s", argv[1]);
612 }
613 
614 /*
615  * Send a line, verbatim, to the remote machine.
616  */
617 quote(argc, argv)
618 	char *argv[];
619 {
620 	int i;
621 	char buf[BUFSIZ];
622 
623 	if (argc < 2) {
624 		strcat(line, " ");
625 		printf("(command line to send) ");
626 		gets(&line[strlen(line)]);
627 		makeargv();
628 		argc = margc;
629 		argv = margv;
630 	}
631 	if (argc < 2) {
632 		printf("usage: %s line-to-send\n", argv[0]);
633 		return;
634 	}
635 	strcpy(buf, argv[1]);
636 	for (i = 2; i < argc; i++) {
637 		strcat(buf, " ");
638 		strcat(buf, argv[i]);
639 	}
640 	(void) command(buf);
641 }
642 
643 /*
644  * Ask the other side for help.
645  */
646 rmthelp(argc, argv)
647 	char *argv[];
648 {
649 	int oldverbose = verbose;
650 
651 	verbose = 1;
652 	(void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
653 	verbose = oldverbose;
654 }
655 
656 /*
657  * Terminate session and exit.
658  */
659 /*VARARGS*/
660 quit()
661 {
662 
663 	disconnect();
664 	exit(0);
665 }
666 
667 /*
668  * Terminate session, but don't exit.
669  */
670 disconnect()
671 {
672 	extern FILE *cout;
673 	extern int data;
674 
675 	if (!connected)
676 		return;
677 	(void) command("QUIT");
678 	(void) fclose(cout);
679 	cout = NULL;
680 	connected = 0;
681 	data = -1;
682 }
683