setup home directory for globbing
[unix-history] / usr / src / usr.bin / ftp / cmds.c
CommitLineData
59d0d309 1#ifndef lint
d33c618b 2static char sccsid[] = "@(#)cmds.c 4.2 (Berkeley) %G%";
59d0d309
SL
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) {
d33c618b 51 port = atoi(argv[2]);
59d0d309 52 if (port <= 0) {
d33c618b
SL
53 printf("%s: bad port number-- %s\n", argv[1], argv[2]);
54 printf ("usage: %s host-name [port]\n", argv[0]);
59d0d309
SL
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
67struct types {
68 char *t_name;
69 char *t_mode;
70 int t_type;
d33c618b 71 char *t_arg;
59d0d309 72} types[] = {
d33c618b
SL
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 },
59d0d309
SL
78 0
79};
80
81/*
82 * Set transfer type.
83 */
84settype(argc, argv)
85 char *argv[];
86{
87 register struct types *p;
d33c618b 88 int comret;
59d0d309
SL
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 }
d33c618b
SL
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) {
59d0d309
SL
119 strcpy(typename, p->t_name);
120 type = p->t_type;
121 }
122}
123
124/*
125 * Set binary transfer type.
126 */
127/*VARARGS*/
128setbinary()
129{
130
131 call(settype, "type", "binary", 0);
132}
133
134/*
135 * Set ascii transfer type.
136 */
137/*VARARGS*/
138setascii()
139{
140
141 call(settype, "type", "ascii", 0);
142}
143
144/*
145 * Set tenex transfer type.
146 */
147/*VARARGS*/
148settenex()
149{
150
151 call(settype, "type", "tenex", 0);
152}
153
154/*
155 * Set ebcdic transfer type.
156 */
157/*VARARGS*/
158setebcdic()
159{
160
161 call(settype, "type", "ebcdic", 0);
162}
163
164/*
165 * Set file transfer mode.
166 */
167setmode(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 */
177setform(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 */
187setstruct(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 */
197put(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) {
219usage:
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 */
239get(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) {
262usage:
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
279char *
280onoff(bool)
281 int bool;
282{
283
284 return (bool ? "on" : "off");
285}
286
287/*
288 * Show status.
289 */
290status(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*/
308setbell()
309{
310
311 bell = !bell;
312 printf("Bell mode %s.\n", onoff(bell));
313}
314
315/*
316 * Turn on packet tracing.
317 */
318/*VARARGS*/
319settrace()
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*/
330setverbose()
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*/
342setprompt()
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*/
354setdebug(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 */
379cd(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 */
408lcd(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 */
436delete(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 */
458renamefile(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) {
471usage:
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 */
493ls(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 */
513shell(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 */
523user(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*/
568pwd()
569{
570 if (!connected) {
571 printf("Not connected.\n");
572 return;
573 }
574 (void) command("XPWD");
575}
576
577/*
578 * Make a directory.
579 */
580makedir(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 */
602removedir(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 */
624quote(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 */
653rmthelp(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*/
667quit()
668{
669
670 disconnect();
671 exit(0);
672}
673
674/*
675 * Terminate session, but don't exit.
676 */
677disconnect()
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}