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