1 #ifndef lint 2 static char sccsid[] = "@(#)cmds.c 4.1 (Berkeley) 01/15/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[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 } 683