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