Commit | Line | Data |
---|---|---|
59d0d309 SL |
1 | #ifndef lint |
2 | static char sccsid[] = "@(#)cmds.c 4.1 (Berkeley) %G%"; | |
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 | } |