date and time created 83/01/15 16:52:34 by sam
[unix-history] / usr / src / usr.bin / ftp / cmds.c
CommitLineData
59d0d309
SL
1#ifndef lint
2static 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
19int autologin = 1;
20
21/*
22 * Connect to peer server and
23 * auto-login, if possible.
24 */
25setpeer(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
66struct 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 */
82settype(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*/
121setbinary()
122{
123
124 call(settype, "type", "binary", 0);
125}
126
127/*
128 * Set ascii transfer type.
129 */
130/*VARARGS*/
131setascii()
132{
133
134 call(settype, "type", "ascii", 0);
135}
136
137/*
138 * Set tenex transfer type.
139 */
140/*VARARGS*/
141settenex()
142{
143
144 call(settype, "type", "tenex", 0);
145}
146
147/*
148 * Set ebcdic transfer type.
149 */
150/*VARARGS*/
151setebcdic()
152{
153
154 call(settype, "type", "ebcdic", 0);
155}
156
157/*
158 * Set file transfer mode.
159 */
160setmode(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 */
170setform(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 */
180setstruct(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 */
190put(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) {
212usage:
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 */
232get(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) {
255usage:
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
272char *
273onoff(bool)
274 int bool;
275{
276
277 return (bool ? "on" : "off");
278}
279
280/*
281 * Show status.
282 */
283status(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*/
301setbell()
302{
303
304 bell = !bell;
305 printf("Bell mode %s.\n", onoff(bell));
306}
307
308/*
309 * Turn on packet tracing.
310 */
311/*VARARGS*/
312settrace()
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*/
323setverbose()
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*/
335setprompt()
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*/
347setdebug(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 */
372cd(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 */
401lcd(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 */
429delete(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 */
451renamefile(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) {
464usage:
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 */
486ls(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 */
506shell(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 */
516user(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*/
561pwd()
562{
563 if (!connected) {
564 printf("Not connected.\n");
565 return;
566 }
567 (void) command("XPWD");
568}
569
570/*
571 * Make a directory.
572 */
573makedir(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 */
595removedir(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 */
617quote(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 */
646rmthelp(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*/
660quit()
661{
662
663 disconnect();
664 exit(0);
665}
666
667/*
668 * Terminate session, but don't exit.
669 */
670disconnect()
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}