121737Sdist /* 2*26049Sminshall * Copyright (c) 1985 Regents of the University of California. 321737Sdist * All rights reserved. The Berkeley software License Agreement 421737Sdist * specifies the terms and conditions for redistribution. 521737Sdist */ 621737Sdist 710294Ssam #ifndef lint 8*26049Sminshall static char sccsid[] = "@(#)cmds.c 5.4 (Berkeley) 02/03/86"; 921737Sdist #endif not lint 1010294Ssam 1110294Ssam /* 1210294Ssam * FTP User Program -- Command Routines. 1310294Ssam */ 14*26049Sminshall #include "ftp_var.h" 1510294Ssam #include <sys/socket.h> 1610294Ssam 1712396Ssam #include <arpa/ftp.h> 1812396Ssam 1910294Ssam #include <signal.h> 2010294Ssam #include <stdio.h> 2110294Ssam #include <errno.h> 2210294Ssam #include <netdb.h> 23*26049Sminshall #include <ctype.h> 2410294Ssam 2510294Ssam 2611353Ssam extern char *globerr; 2711353Ssam extern char **glob(); 2811756Ssam extern char *home; 2911353Ssam extern short gflag; 3011756Ssam extern char *remglob(); 3111756Ssam extern char *getenv(); 3211756Ssam extern char *index(); 3311756Ssam extern char *rindex(); 34*26049Sminshall char *mname; 35*26049Sminshall jmp_buf jabort; 36*26049Sminshall char *dotrans(), *domap(); 3710294Ssam 3810294Ssam /* 3910294Ssam * Connect to peer server and 4010294Ssam * auto-login, if possible. 4110294Ssam */ 4210294Ssam setpeer(argc, argv) 4310294Ssam int argc; 4410294Ssam char *argv[]; 4510294Ssam { 4625903Skarels char *host, *hookup(); 4710294Ssam int port; 4810294Ssam 4910294Ssam if (connected) { 50*26049Sminshall printf("Already connected to %s, use close first.\n", 5110294Ssam hostname); 52*26049Sminshall code = -1; 5310294Ssam return; 5410294Ssam } 5510294Ssam if (argc < 2) { 5610294Ssam strcat(line, " "); 5710294Ssam printf("(to) "); 5810294Ssam gets(&line[strlen(line)]); 5910294Ssam makeargv(); 6010294Ssam argc = margc; 6110294Ssam argv = margv; 6210294Ssam } 6310294Ssam if (argc > 3) { 6410294Ssam printf("usage: %s host-name [port]\n", argv[0]); 65*26049Sminshall code = -1; 6610294Ssam return; 6710294Ssam } 6810294Ssam port = sp->s_port; 6910294Ssam if (argc > 2) { 7011218Ssam port = atoi(argv[2]); 7110294Ssam if (port <= 0) { 7211218Ssam printf("%s: bad port number-- %s\n", argv[1], argv[2]); 7311218Ssam printf ("usage: %s host-name [port]\n", argv[0]); 74*26049Sminshall code = -1; 7510294Ssam return; 7610294Ssam } 7710294Ssam port = htons(port); 7810294Ssam } 7910294Ssam host = hookup(argv[1], port); 8010294Ssam if (host) { 8110294Ssam connected = 1; 8210294Ssam if (autologin) 83*26049Sminshall login(argv[1]); 8410294Ssam } 8510294Ssam } 8610294Ssam 8710294Ssam struct types { 8810294Ssam char *t_name; 8910294Ssam char *t_mode; 9010294Ssam int t_type; 9111218Ssam char *t_arg; 9210294Ssam } types[] = { 9311218Ssam { "ascii", "A", TYPE_A, 0 }, 9411218Ssam { "binary", "I", TYPE_I, 0 }, 9511218Ssam { "image", "I", TYPE_I, 0 }, 9611218Ssam { "ebcdic", "E", TYPE_E, 0 }, 9711218Ssam { "tenex", "L", TYPE_L, bytename }, 9810294Ssam 0 9910294Ssam }; 10010294Ssam 10110294Ssam /* 10210294Ssam * Set transfer type. 10310294Ssam */ 10410294Ssam settype(argc, argv) 10510294Ssam char *argv[]; 10610294Ssam { 10710294Ssam register struct types *p; 10811218Ssam int comret; 10910294Ssam 11010294Ssam if (argc > 2) { 11110294Ssam char *sep; 11210294Ssam 11310294Ssam printf("usage: %s [", argv[0]); 11410294Ssam sep = " "; 11510294Ssam for (p = types; p->t_name; p++) { 11610294Ssam printf("%s%s", sep, p->t_name); 11710294Ssam if (*sep == ' ') 11810294Ssam sep = " | "; 11910294Ssam } 12010294Ssam printf(" ]\n"); 121*26049Sminshall code = -1; 12210294Ssam return; 12310294Ssam } 12410294Ssam if (argc < 2) { 12510294Ssam printf("Using %s mode to transfer files.\n", typename); 126*26049Sminshall code = 0; 12710294Ssam return; 12810294Ssam } 12910294Ssam for (p = types; p->t_name; p++) 13010294Ssam if (strcmp(argv[1], p->t_name) == 0) 13110294Ssam break; 13210294Ssam if (p->t_name == 0) { 13310294Ssam printf("%s: unknown mode\n", argv[1]); 134*26049Sminshall code = -1; 13510294Ssam return; 13610294Ssam } 13711218Ssam if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) 13811218Ssam comret = command ("TYPE %s %s", p->t_mode, p->t_arg); 13911218Ssam else 14011218Ssam comret = command("TYPE %s", p->t_mode); 14111218Ssam if (comret == COMPLETE) { 14210294Ssam strcpy(typename, p->t_name); 14310294Ssam type = p->t_type; 14410294Ssam } 14510294Ssam } 14610294Ssam 14710294Ssam /* 14810294Ssam * Set binary transfer type. 14910294Ssam */ 15010294Ssam /*VARARGS*/ 15110294Ssam setbinary() 15210294Ssam { 15310294Ssam 15410294Ssam call(settype, "type", "binary", 0); 15510294Ssam } 15610294Ssam 15710294Ssam /* 15810294Ssam * Set ascii transfer type. 15910294Ssam */ 16010294Ssam /*VARARGS*/ 16110294Ssam setascii() 16210294Ssam { 16310294Ssam 16410294Ssam call(settype, "type", "ascii", 0); 16510294Ssam } 16610294Ssam 16710294Ssam /* 16810294Ssam * Set tenex transfer type. 16910294Ssam */ 17010294Ssam /*VARARGS*/ 17110294Ssam settenex() 17210294Ssam { 17310294Ssam 17410294Ssam call(settype, "type", "tenex", 0); 17510294Ssam } 17610294Ssam 17710294Ssam /* 17810294Ssam * Set ebcdic transfer type. 17910294Ssam */ 18010294Ssam /*VARARGS*/ 18110294Ssam setebcdic() 18210294Ssam { 18310294Ssam 18410294Ssam call(settype, "type", "ebcdic", 0); 18510294Ssam } 18610294Ssam 18710294Ssam /* 18810294Ssam * Set file transfer mode. 18910294Ssam */ 19010294Ssam setmode(argc, argv) 19110294Ssam char *argv[]; 19210294Ssam { 19310294Ssam 19410294Ssam printf("We only support %s mode, sorry.\n", modename); 195*26049Sminshall code = -1; 19610294Ssam } 19710294Ssam 19810294Ssam /* 19910294Ssam * Set file transfer format. 20010294Ssam */ 20110294Ssam setform(argc, argv) 20210294Ssam char *argv[]; 20310294Ssam { 20410294Ssam 20510294Ssam printf("We only support %s format, sorry.\n", formname); 206*26049Sminshall code = -1; 20710294Ssam } 20810294Ssam 20910294Ssam /* 21010294Ssam * Set file transfer structure. 21110294Ssam */ 21210294Ssam setstruct(argc, argv) 21310294Ssam char *argv[]; 21410294Ssam { 21510294Ssam 21610294Ssam printf("We only support %s structure, sorry.\n", structname); 217*26049Sminshall code = -1; 21810294Ssam } 21910294Ssam 22018286Sralph /* 22118286Sralph * Send a single file. 22218286Sralph */ 22310294Ssam put(argc, argv) 22411756Ssam int argc; 22510294Ssam char *argv[]; 22610294Ssam { 22711650Ssam char *cmd; 228*26049Sminshall int loc = 0; 22925908Smckusick char *oldargv1; 23011650Ssam 231*26049Sminshall if (argc == 2) { 232*26049Sminshall argc++; 233*26049Sminshall argv[2] = argv[1]; 234*26049Sminshall loc++; 235*26049Sminshall } 23610294Ssam if (argc < 2) { 23710294Ssam strcat(line, " "); 23810294Ssam printf("(local-file) "); 23910294Ssam gets(&line[strlen(line)]); 24010294Ssam makeargv(); 24110294Ssam argc = margc; 24210294Ssam argv = margv; 24310294Ssam } 24410294Ssam if (argc < 2) { 24510294Ssam usage: 246*26049Sminshall printf("usage:%s local-file remote-file\n", argv[0]); 247*26049Sminshall code = -1; 24810294Ssam return; 24910294Ssam } 25010294Ssam if (argc < 3) { 25110294Ssam strcat(line, " "); 25210294Ssam printf("(remote-file) "); 25310294Ssam gets(&line[strlen(line)]); 25410294Ssam makeargv(); 25510294Ssam argc = margc; 25610294Ssam argv = margv; 25710294Ssam } 25810294Ssam if (argc < 3) 25910294Ssam goto usage; 26025908Smckusick oldargv1 = argv[1]; 261*26049Sminshall if (!globulize(&argv[1])) { 262*26049Sminshall code = -1; 26311353Ssam return; 264*26049Sminshall } 26525908Smckusick /* 26625908Smckusick * If "globulize" modifies argv[1], and argv[2] is a copy of 26725908Smckusick * the old argv[1], make it a copy of the new argv[1]. 26825908Smckusick */ 269*26049Sminshall if (argv[1] != oldargv1 && argv[2] == oldargv1) { 27025908Smckusick argv[2] = argv[1]; 271*26049Sminshall } 272*26049Sminshall cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); 273*26049Sminshall if (loc && ntflag) { 274*26049Sminshall argv[2] = dotrans(argv[2]); 275*26049Sminshall } 276*26049Sminshall if (loc && mapflag) { 277*26049Sminshall argv[2] = domap(argv[2]); 278*26049Sminshall } 27911650Ssam sendrequest(cmd, argv[1], argv[2]); 28010294Ssam } 28110294Ssam 28210294Ssam /* 28311756Ssam * Send multiple files. 28410294Ssam */ 28511353Ssam mput(argc, argv) 28611353Ssam char *argv[]; 28711353Ssam { 28813212Ssam register int i; 289*26049Sminshall int ointer, (*oldintr)(), mabort(); 290*26049Sminshall extern jmp_buf jabort; 291*26049Sminshall char *tp; 29211353Ssam 29311650Ssam if (argc < 2) { 29411650Ssam strcat(line, " "); 29511650Ssam printf("(local-files) "); 29611650Ssam gets(&line[strlen(line)]); 29711650Ssam makeargv(); 29811650Ssam argc = margc; 29911650Ssam argv = margv; 30011353Ssam } 30111353Ssam if (argc < 2) { 302*26049Sminshall printf("usage:%s local-files\n", argv[0]); 303*26049Sminshall code = -1; 30411353Ssam return; 30511353Ssam } 306*26049Sminshall mname = argv[0]; 307*26049Sminshall mflag = 1; 308*26049Sminshall oldintr = signal(SIGINT, mabort); 309*26049Sminshall (void) setjmp(jabort); 310*26049Sminshall if (proxy) { 311*26049Sminshall char *cp, *tp2, tmpbuf[MAXPATHLEN]; 312*26049Sminshall 313*26049Sminshall while ((cp = remglob(argc, argv, 0)) != NULL) { 314*26049Sminshall if (*cp == 0) { 315*26049Sminshall mflag = 0; 316*26049Sminshall continue; 317*26049Sminshall } 318*26049Sminshall if (mflag && confirm(argv[0], cp)) { 319*26049Sminshall tp = cp; 320*26049Sminshall if (mcase) { 321*26049Sminshall while (*tp && !islower(*tp)) { 322*26049Sminshall tp++; 323*26049Sminshall } 324*26049Sminshall if (!*tp) { 325*26049Sminshall tp = cp; 326*26049Sminshall tp2 = tmpbuf; 327*26049Sminshall while ((*tp2 = *tp) != NULL) { 328*26049Sminshall if (isupper(*tp2)) { 329*26049Sminshall *tp2 = 'a' + *tp2 - 'A'; 330*26049Sminshall } 331*26049Sminshall tp++; 332*26049Sminshall tp2++; 333*26049Sminshall } 334*26049Sminshall } 335*26049Sminshall tp = tmpbuf; 336*26049Sminshall } 337*26049Sminshall if (ntflag) { 338*26049Sminshall tp = dotrans(tp); 339*26049Sminshall } 340*26049Sminshall if (mapflag) { 341*26049Sminshall tp = domap(tp); 342*26049Sminshall } 343*26049Sminshall sendrequest((sunique) ? "STOU" : "STOR", cp,tp); 344*26049Sminshall if (!mflag && fromatty) { 345*26049Sminshall ointer = interactive; 346*26049Sminshall interactive = 1; 347*26049Sminshall if (confirm("Continue with","mput")) { 348*26049Sminshall mflag++; 349*26049Sminshall } 350*26049Sminshall interactive = ointer; 351*26049Sminshall } 352*26049Sminshall } 353*26049Sminshall } 354*26049Sminshall (void) signal(SIGINT, oldintr); 355*26049Sminshall mflag = 0; 356*26049Sminshall return; 357*26049Sminshall } 35813212Ssam for (i = 1; i < argc; i++) { 35913212Ssam register char **cpp, **gargs; 36013212Ssam 36113212Ssam if (!doglob) { 362*26049Sminshall if (mflag && confirm(argv[0], argv[i])) { 363*26049Sminshall tp = (ntflag) ? dotrans(argv[i]) : argv[i]; 364*26049Sminshall tp = (mapflag) ? domap(tp) : tp; 365*26049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 366*26049Sminshall argv[i], tp); 367*26049Sminshall if (!mflag && fromatty) { 368*26049Sminshall ointer = interactive; 369*26049Sminshall interactive = 1; 370*26049Sminshall if (confirm("Continue with","mput")) { 371*26049Sminshall mflag++; 372*26049Sminshall } 373*26049Sminshall interactive = ointer; 374*26049Sminshall } 375*26049Sminshall } 37613212Ssam continue; 37713212Ssam } 37813212Ssam gargs = glob(argv[i]); 37911650Ssam if (globerr != NULL) { 38011650Ssam printf("%s\n", globerr); 38111650Ssam if (gargs) 38211650Ssam blkfree(gargs); 38313212Ssam continue; 38411353Ssam } 385*26049Sminshall for (cpp = gargs; cpp && *cpp != NULL; cpp++) { 386*26049Sminshall if (mflag && confirm(argv[0], *cpp)) { 387*26049Sminshall tp = (ntflag) ? dotrans(*cpp) : *cpp; 388*26049Sminshall tp = (mapflag) ? domap(tp) : tp; 389*26049Sminshall sendrequest((sunique) ? "STOU" : "STOR", 390*26049Sminshall *cpp, tp); 391*26049Sminshall if (!mflag && fromatty) { 392*26049Sminshall ointer = interactive; 393*26049Sminshall interactive = 1; 394*26049Sminshall if (confirm("Continue with","mput")) { 395*26049Sminshall mflag++; 396*26049Sminshall } 397*26049Sminshall interactive = ointer; 398*26049Sminshall } 399*26049Sminshall } 400*26049Sminshall } 40113212Ssam if (gargs != NULL) 40213212Ssam blkfree(gargs); 40311353Ssam } 404*26049Sminshall (void) signal(SIGINT, oldintr); 405*26049Sminshall mflag = 0; 40611353Ssam } 40711353Ssam 40811353Ssam /* 40911353Ssam * Receive one file. 41011353Ssam */ 41110294Ssam get(argc, argv) 41210294Ssam char *argv[]; 41310294Ssam { 414*26049Sminshall int loc = 0; 41510294Ssam 416*26049Sminshall if (argc == 2) { 417*26049Sminshall argc++; 418*26049Sminshall argv[2] = argv[1]; 419*26049Sminshall loc++; 420*26049Sminshall } 42110294Ssam if (argc < 2) { 42210294Ssam strcat(line, " "); 42310294Ssam printf("(remote-file) "); 42410294Ssam gets(&line[strlen(line)]); 42510294Ssam makeargv(); 42610294Ssam argc = margc; 42710294Ssam argv = margv; 42810294Ssam } 42910294Ssam if (argc < 2) { 43010294Ssam usage: 431*26049Sminshall printf("usage: %s remote-file [ local-file ]\n", argv[0]); 432*26049Sminshall code = -1; 43310294Ssam return; 43410294Ssam } 43510294Ssam if (argc < 3) { 43610294Ssam strcat(line, " "); 43710294Ssam printf("(local-file) "); 43810294Ssam gets(&line[strlen(line)]); 43910294Ssam makeargv(); 44010294Ssam argc = margc; 44110294Ssam argv = margv; 44210294Ssam } 44310294Ssam if (argc < 3) 44410294Ssam goto usage; 445*26049Sminshall if (!globulize(&argv[2])) { 446*26049Sminshall code = -1; 44711353Ssam return; 448*26049Sminshall } 449*26049Sminshall if (loc && mcase) { 450*26049Sminshall char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; 451*26049Sminshall 452*26049Sminshall while (*tp && !islower(*tp)) { 453*26049Sminshall tp++; 454*26049Sminshall } 455*26049Sminshall if (!*tp) { 456*26049Sminshall tp = argv[2]; 457*26049Sminshall tp2 = tmpbuf; 458*26049Sminshall while ((*tp2 = *tp) != NULL) { 459*26049Sminshall if (isupper(*tp2)) { 460*26049Sminshall *tp2 = 'a' + *tp2 - 'A'; 461*26049Sminshall } 462*26049Sminshall tp++; 463*26049Sminshall tp2++; 464*26049Sminshall } 465*26049Sminshall argv[2] = tmpbuf; 466*26049Sminshall } 467*26049Sminshall } 468*26049Sminshall if (loc && ntflag) { 469*26049Sminshall argv[2] = dotrans(argv[2]); 470*26049Sminshall } 471*26049Sminshall if (loc && mapflag) { 472*26049Sminshall argv[2] = domap(argv[2]); 473*26049Sminshall } 47411650Ssam recvrequest("RETR", argv[2], argv[1], "w"); 47510294Ssam } 47610294Ssam 477*26049Sminshall mabort() 478*26049Sminshall { 479*26049Sminshall int ointer; 480*26049Sminshall extern jmp_buf jabort; 481*26049Sminshall 482*26049Sminshall printf("\n"); 483*26049Sminshall (void) fflush(stdout); 484*26049Sminshall if (mflag && fromatty) { 485*26049Sminshall ointer = interactive; 486*26049Sminshall interactive = 1; 487*26049Sminshall if (confirm("Continue with", mname)) { 488*26049Sminshall interactive = ointer; 489*26049Sminshall longjmp(jabort,0); 490*26049Sminshall } 491*26049Sminshall interactive = ointer; 492*26049Sminshall } 493*26049Sminshall mflag = 0; 494*26049Sminshall longjmp(jabort,0); 495*26049Sminshall } 496*26049Sminshall 49711353Ssam /* 49811353Ssam * Get multiple files. 49911353Ssam */ 50011353Ssam mget(argc, argv) 50111353Ssam char *argv[]; 50211353Ssam { 503*26049Sminshall char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; 504*26049Sminshall int ointer, (*oldintr)(), mabort(); 505*26049Sminshall extern jmp_buf jabort; 50611353Ssam 50711353Ssam if (argc < 2) { 50811353Ssam strcat(line, " "); 50911756Ssam printf("(remote-files) "); 51011353Ssam gets(&line[strlen(line)]); 51111353Ssam makeargv(); 51211353Ssam argc = margc; 51311353Ssam argv = margv; 51411353Ssam } 51511353Ssam if (argc < 2) { 516*26049Sminshall printf("usage:%s remote-files\n", argv[0]); 517*26049Sminshall code = -1; 51811353Ssam return; 51911353Ssam } 520*26049Sminshall mname = argv[0]; 521*26049Sminshall mflag = 1; 522*26049Sminshall oldintr = signal(SIGINT,mabort); 523*26049Sminshall (void) setjmp(jabort); 524*26049Sminshall while ((cp = remglob(argc, argv, proxy)) != NULL) { 525*26049Sminshall if (*cp == '\0') { 526*26049Sminshall mflag = 0; 527*26049Sminshall continue; 528*26049Sminshall } 529*26049Sminshall if (mflag && confirm(argv[0], cp)) { 530*26049Sminshall tp = cp; 531*26049Sminshall if (mcase) { 532*26049Sminshall while (*tp && !islower(*tp)) { 533*26049Sminshall tp++; 534*26049Sminshall } 535*26049Sminshall if (!*tp) { 536*26049Sminshall tp = cp; 537*26049Sminshall tp2 = tmpbuf; 538*26049Sminshall while ((*tp2 = *tp) != NULL) { 539*26049Sminshall if (isupper(*tp2)) { 540*26049Sminshall *tp2 = 'a' + *tp2 - 'A'; 541*26049Sminshall } 542*26049Sminshall tp++; 543*26049Sminshall tp2++; 544*26049Sminshall } 545*26049Sminshall } 546*26049Sminshall tp = tmpbuf; 547*26049Sminshall } 548*26049Sminshall if (ntflag) { 549*26049Sminshall tp = dotrans(tp); 550*26049Sminshall } 551*26049Sminshall if (mapflag) { 552*26049Sminshall tp = domap(tp); 553*26049Sminshall } 554*26049Sminshall recvrequest("RETR", tp, cp, "w"); 555*26049Sminshall if (!mflag && fromatty) { 556*26049Sminshall ointer = interactive; 557*26049Sminshall interactive = 1; 558*26049Sminshall if (confirm("Continue with","mget")) { 559*26049Sminshall mflag++; 560*26049Sminshall } 561*26049Sminshall interactive = ointer; 562*26049Sminshall } 563*26049Sminshall } 564*26049Sminshall } 565*26049Sminshall (void) signal(SIGINT,oldintr); 566*26049Sminshall mflag = 0; 56711650Ssam } 56811650Ssam 56911650Ssam char * 570*26049Sminshall remglob(argc, argv, doswitch) 571*26049Sminshall int argc, doswitch; 57211650Ssam char *argv[]; 57311650Ssam { 57411756Ssam char temp[16]; 57511650Ssam static char buf[MAXPATHLEN]; 57611650Ssam static FILE *ftemp = NULL; 57711650Ssam static char **args; 57813212Ssam int oldverbose, oldhash; 57911756Ssam char *cp, *mode; 58011650Ssam 581*26049Sminshall if (!mflag) { 582*26049Sminshall if (!doglob) { 583*26049Sminshall args = NULL; 584*26049Sminshall } 585*26049Sminshall else { 586*26049Sminshall if (ftemp) { 587*26049Sminshall fclose(ftemp); 588*26049Sminshall ftemp = NULL; 589*26049Sminshall } 590*26049Sminshall } 591*26049Sminshall return(NULL); 592*26049Sminshall } 59311650Ssam if (!doglob) { 59411756Ssam if (args == NULL) 59511650Ssam args = argv; 59611650Ssam if ((cp = *++args) == NULL) 59711650Ssam args = NULL; 59811650Ssam return (cp); 59911353Ssam } 60011650Ssam if (ftemp == NULL) { 60111650Ssam strcpy(temp, "/tmp/ftpXXXXXX"); 60211650Ssam mktemp(temp); 60311650Ssam oldverbose = verbose, verbose = 0; 60413212Ssam oldhash = hash, hash = 0; 605*26049Sminshall if (doswitch) { 606*26049Sminshall pswitch(!proxy); 607*26049Sminshall } 60811756Ssam for (mode = "w"; *++argv != NULL; mode = "a") 60911756Ssam recvrequest ("NLST", temp, *argv, mode); 610*26049Sminshall if (doswitch) { 611*26049Sminshall pswitch(!proxy); 612*26049Sminshall } 61313212Ssam verbose = oldverbose; hash = oldhash; 61411650Ssam ftemp = fopen(temp, "r"); 61511650Ssam unlink(temp); 61611650Ssam if (ftemp == NULL) { 61711650Ssam printf("can't find list of remote files, oops\n"); 61811756Ssam return (NULL); 61911353Ssam } 62011353Ssam } 62111650Ssam if (fgets(buf, sizeof (buf), ftemp) == NULL) { 62211650Ssam fclose(ftemp), ftemp = NULL; 62311650Ssam return (NULL); 62411353Ssam } 62511650Ssam if ((cp = index(buf, '\n')) != NULL) 62611650Ssam *cp = '\0'; 62711650Ssam return (buf); 62811353Ssam } 62911353Ssam 63010294Ssam char * 63110294Ssam onoff(bool) 63210294Ssam int bool; 63310294Ssam { 63410294Ssam 63510294Ssam return (bool ? "on" : "off"); 63610294Ssam } 63710294Ssam 63810294Ssam /* 63910294Ssam * Show status. 64010294Ssam */ 64110294Ssam status(argc, argv) 64210294Ssam char *argv[]; 64310294Ssam { 644*26049Sminshall int i; 64510294Ssam 64610294Ssam if (connected) 64710294Ssam printf("Connected to %s.\n", hostname); 64810294Ssam else 64910294Ssam printf("Not connected.\n"); 650*26049Sminshall if (!proxy) { 651*26049Sminshall pswitch(1); 652*26049Sminshall if (connected) { 653*26049Sminshall printf("Connected for proxy commands to %s.\n", hostname); 654*26049Sminshall } 655*26049Sminshall else { 656*26049Sminshall printf("No proxy connection.\n"); 657*26049Sminshall } 658*26049Sminshall pswitch(0); 659*26049Sminshall } 66010294Ssam printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", 66110294Ssam modename, typename, formname, structname); 66211353Ssam printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", 66311353Ssam onoff(verbose), onoff(bell), onoff(interactive), 66411353Ssam onoff(doglob)); 665*26049Sminshall printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), 666*26049Sminshall onoff(runique)); 667*26049Sminshall printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); 668*26049Sminshall if (ntflag) { 669*26049Sminshall printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); 670*26049Sminshall } 671*26049Sminshall else { 672*26049Sminshall printf("Ntrans: off\n"); 673*26049Sminshall } 674*26049Sminshall if (mapflag) { 675*26049Sminshall printf("Nmap: (in) %s (out) %s\n", mapin, mapout); 676*26049Sminshall } 677*26049Sminshall else { 678*26049Sminshall printf("Nmap: off\n"); 679*26049Sminshall } 68014143Ssam printf("Hash mark printing: %s; Use of PORT cmds: %s\n", 68114143Ssam onoff(hash), onoff(sendport)); 682*26049Sminshall if (macnum > 0) { 683*26049Sminshall printf("Macros:\n"); 684*26049Sminshall for (i=0; i<macnum; i++) { 685*26049Sminshall printf("\t%s\n",macros[i].mac_name); 686*26049Sminshall } 687*26049Sminshall } 688*26049Sminshall code = 0; 68910294Ssam } 69010294Ssam 69110294Ssam /* 69210294Ssam * Set beep on cmd completed mode. 69310294Ssam */ 69410294Ssam /*VARARGS*/ 69510294Ssam setbell() 69610294Ssam { 69710294Ssam 69810294Ssam bell = !bell; 69910294Ssam printf("Bell mode %s.\n", onoff(bell)); 700*26049Sminshall code = bell; 70110294Ssam } 70210294Ssam 70310294Ssam /* 70410294Ssam * Turn on packet tracing. 70510294Ssam */ 70610294Ssam /*VARARGS*/ 70710294Ssam settrace() 70810294Ssam { 70910294Ssam 71010294Ssam trace = !trace; 71110294Ssam printf("Packet tracing %s.\n", onoff(trace)); 712*26049Sminshall code = trace; 71310294Ssam } 71410294Ssam 71510294Ssam /* 71611650Ssam * Toggle hash mark printing during transfers. 71711650Ssam */ 71811650Ssam /*VARARGS*/ 71911650Ssam sethash() 72011650Ssam { 72111650Ssam 72211650Ssam hash = !hash; 72311650Ssam printf("Hash mark printing %s", onoff(hash)); 724*26049Sminshall code = hash; 72511650Ssam if (hash) 72611650Ssam printf(" (%d bytes/hash mark)", BUFSIZ); 72711650Ssam printf(".\n"); 72811650Ssam } 72911650Ssam 73011650Ssam /* 73110294Ssam * Turn on printing of server echo's. 73210294Ssam */ 73310294Ssam /*VARARGS*/ 73410294Ssam setverbose() 73510294Ssam { 73610294Ssam 73710294Ssam verbose = !verbose; 73810294Ssam printf("Verbose mode %s.\n", onoff(verbose)); 739*26049Sminshall code = verbose; 74010294Ssam } 74110294Ssam 74210294Ssam /* 74311650Ssam * Toggle PORT cmd use before each data connection. 74411650Ssam */ 74511650Ssam /*VARARGS*/ 74611650Ssam setport() 74711650Ssam { 74811650Ssam 74911650Ssam sendport = !sendport; 75011650Ssam printf("Use of PORT cmds %s.\n", onoff(sendport)); 751*26049Sminshall code = sendport; 75211650Ssam } 75311650Ssam 75411650Ssam /* 75510294Ssam * Turn on interactive prompting 75610294Ssam * during mget, mput, and mdelete. 75710294Ssam */ 75810294Ssam /*VARARGS*/ 75910294Ssam setprompt() 76010294Ssam { 76110294Ssam 76210294Ssam interactive = !interactive; 76310294Ssam printf("Interactive mode %s.\n", onoff(interactive)); 764*26049Sminshall code = interactive; 76510294Ssam } 76610294Ssam 76710294Ssam /* 76811353Ssam * Toggle metacharacter interpretation 76911353Ssam * on local file names. 77011353Ssam */ 77111353Ssam /*VARARGS*/ 77211353Ssam setglob() 77311353Ssam { 77411353Ssam 77511353Ssam doglob = !doglob; 77611353Ssam printf("Globbing %s.\n", onoff(doglob)); 777*26049Sminshall code = doglob; 77811353Ssam } 77911353Ssam 78011353Ssam /* 78110294Ssam * Set debugging mode on/off and/or 78210294Ssam * set level of debugging. 78310294Ssam */ 78411756Ssam /*VARARGS*/ 78510294Ssam setdebug(argc, argv) 78610294Ssam char *argv[]; 78710294Ssam { 78810294Ssam int val; 78910294Ssam 79010294Ssam if (argc > 1) { 79110294Ssam val = atoi(argv[1]); 79210294Ssam if (val < 0) { 79310294Ssam printf("%s: bad debugging value.\n", argv[1]); 794*26049Sminshall code = -1; 79510294Ssam return; 79610294Ssam } 79710294Ssam } else 79810294Ssam val = !debug; 79910294Ssam debug = val; 80010294Ssam if (debug) 80110294Ssam options |= SO_DEBUG; 80210294Ssam else 80310294Ssam options &= ~SO_DEBUG; 80410294Ssam printf("Debugging %s (debug=%d).\n", onoff(debug), debug); 805*26049Sminshall code = debug > 0; 80610294Ssam } 80710294Ssam 80810294Ssam /* 80910294Ssam * Set current working directory 81010294Ssam * on remote machine. 81110294Ssam */ 81210294Ssam cd(argc, argv) 81310294Ssam char *argv[]; 81410294Ssam { 81510294Ssam 81610294Ssam if (argc < 2) { 81710294Ssam strcat(line, " "); 81810294Ssam printf("(remote-directory) "); 81910294Ssam gets(&line[strlen(line)]); 82010294Ssam makeargv(); 82110294Ssam argc = margc; 82210294Ssam argv = margv; 82310294Ssam } 82410294Ssam if (argc < 2) { 825*26049Sminshall printf("usage:%s remote-directory\n", argv[0]); 826*26049Sminshall code = -1; 82710294Ssam return; 82810294Ssam } 82910294Ssam (void) command("CWD %s", argv[1]); 83010294Ssam } 83110294Ssam 83210294Ssam /* 83310294Ssam * Set current working directory 83410294Ssam * on local machine. 83510294Ssam */ 83610294Ssam lcd(argc, argv) 83710294Ssam char *argv[]; 83810294Ssam { 83911353Ssam char buf[MAXPATHLEN]; 84010294Ssam 84111353Ssam if (argc < 2) 84211353Ssam argc++, argv[1] = home; 84310294Ssam if (argc != 2) { 844*26049Sminshall printf("usage:%s local-directory\n", argv[0]); 845*26049Sminshall code = -1; 84610294Ssam return; 84710294Ssam } 848*26049Sminshall if (!globulize(&argv[1])) { 849*26049Sminshall code = -1; 85011353Ssam return; 851*26049Sminshall } 85211353Ssam if (chdir(argv[1]) < 0) { 85310294Ssam perror(argv[1]); 854*26049Sminshall code = -1; 85511353Ssam return; 85611353Ssam } 85711353Ssam printf("Local directory now %s\n", getwd(buf)); 858*26049Sminshall code = 0; 85910294Ssam } 86010294Ssam 86110294Ssam /* 86210294Ssam * Delete a single file. 86310294Ssam */ 86410294Ssam delete(argc, argv) 86510294Ssam char *argv[]; 86610294Ssam { 86710294Ssam 86810294Ssam if (argc < 2) { 86910294Ssam strcat(line, " "); 87010294Ssam printf("(remote-file) "); 87110294Ssam gets(&line[strlen(line)]); 87210294Ssam makeargv(); 87310294Ssam argc = margc; 87410294Ssam argv = margv; 87510294Ssam } 87610294Ssam if (argc < 2) { 877*26049Sminshall printf("usage:%s remote-file\n", argv[0]); 878*26049Sminshall code = -1; 87910294Ssam return; 88010294Ssam } 88110294Ssam (void) command("DELE %s", argv[1]); 88210294Ssam } 88310294Ssam 88410294Ssam /* 88511650Ssam * Delete multiple files. 88611650Ssam */ 88711650Ssam mdelete(argc, argv) 88811650Ssam char *argv[]; 88911650Ssam { 89011650Ssam char *cp; 891*26049Sminshall int ointer, (*oldintr)(), mabort(); 892*26049Sminshall extern jmp_buf jabort; 89311650Ssam 89411650Ssam if (argc < 2) { 89511650Ssam strcat(line, " "); 89611650Ssam printf("(remote-files) "); 89711650Ssam gets(&line[strlen(line)]); 89811650Ssam makeargv(); 89911650Ssam argc = margc; 90011650Ssam argv = margv; 90111650Ssam } 90211650Ssam if (argc < 2) { 903*26049Sminshall printf("usage:%s remote-files\n", argv[0]); 904*26049Sminshall code = -1; 90511650Ssam return; 90611650Ssam } 907*26049Sminshall mname = argv[0]; 908*26049Sminshall mflag = 1; 909*26049Sminshall oldintr = signal(SIGINT, mabort); 910*26049Sminshall (void) setjmp(jabort); 911*26049Sminshall while ((cp = remglob(argc, argv, 0)) != NULL) { 912*26049Sminshall if (*cp == '\0') { 913*26049Sminshall mflag = 0; 914*26049Sminshall continue; 915*26049Sminshall } 916*26049Sminshall if (mflag && confirm(argv[0], cp)) { 91711650Ssam (void) command("DELE %s", cp); 918*26049Sminshall if (!mflag && fromatty) { 919*26049Sminshall ointer = interactive; 920*26049Sminshall interactive = 1; 921*26049Sminshall if (confirm("Continue with", "mdelete")) { 922*26049Sminshall mflag++; 923*26049Sminshall } 924*26049Sminshall interactive = ointer; 925*26049Sminshall } 926*26049Sminshall } 927*26049Sminshall } 928*26049Sminshall (void) signal(SIGINT, oldintr); 929*26049Sminshall mflag = 0; 93011650Ssam } 93111756Ssam 93211650Ssam /* 93310294Ssam * Rename a remote file. 93410294Ssam */ 93510294Ssam renamefile(argc, argv) 93610294Ssam char *argv[]; 93710294Ssam { 93810294Ssam 93910294Ssam if (argc < 2) { 94010294Ssam strcat(line, " "); 94110294Ssam printf("(from-name) "); 94210294Ssam gets(&line[strlen(line)]); 94310294Ssam makeargv(); 94410294Ssam argc = margc; 94510294Ssam argv = margv; 94610294Ssam } 94710294Ssam if (argc < 2) { 94810294Ssam usage: 94910294Ssam printf("%s from-name to-name\n", argv[0]); 950*26049Sminshall code = -1; 95110294Ssam return; 95210294Ssam } 95310294Ssam if (argc < 3) { 95410294Ssam strcat(line, " "); 95510294Ssam printf("(to-name) "); 95610294Ssam gets(&line[strlen(line)]); 95710294Ssam makeargv(); 95810294Ssam argc = margc; 95910294Ssam argv = margv; 96010294Ssam } 96110294Ssam if (argc < 3) 96210294Ssam goto usage; 96310294Ssam if (command("RNFR %s", argv[1]) == CONTINUE) 96410294Ssam (void) command("RNTO %s", argv[2]); 96510294Ssam } 96610294Ssam 96710294Ssam /* 96810294Ssam * Get a directory listing 96910294Ssam * of remote files. 97010294Ssam */ 97110294Ssam ls(argc, argv) 97210294Ssam char *argv[]; 97310294Ssam { 97411756Ssam char *cmd; 97510294Ssam 97610294Ssam if (argc < 2) 97710294Ssam argc++, argv[1] = NULL; 97810294Ssam if (argc < 3) 97910294Ssam argc++, argv[2] = "-"; 98011756Ssam if (argc > 3) { 98111756Ssam printf("usage: %s remote-directory local-file\n", argv[0]); 982*26049Sminshall code = -1; 98311756Ssam return; 98411756Ssam } 98510294Ssam cmd = argv[0][0] == 'l' ? "NLST" : "LIST"; 986*26049Sminshall if (strcmp(argv[2], "-") && !globulize(&argv[2])) { 987*26049Sminshall code = -1; 98811353Ssam return; 989*26049Sminshall } 99011756Ssam recvrequest(cmd, argv[2], argv[1], "w"); 99110294Ssam } 99210294Ssam 99310294Ssam /* 99411756Ssam * Get a directory listing 99511756Ssam * of multiple remote files. 99611756Ssam */ 99711756Ssam mls(argc, argv) 99811756Ssam char *argv[]; 99911756Ssam { 1000*26049Sminshall char *cmd, mode[1], *dest; 1001*26049Sminshall int ointer, i, (*oldintr)(), mabort(); 1002*26049Sminshall extern jmp_buf jabort; 100311756Ssam 100413212Ssam if (argc < 2) { 100513212Ssam strcat(line, " "); 100613212Ssam printf("(remote-files) "); 100713212Ssam gets(&line[strlen(line)]); 100813212Ssam makeargv(); 100913212Ssam argc = margc; 101013212Ssam argv = margv; 101113212Ssam } 101213212Ssam if (argc < 3) { 101313212Ssam strcat(line, " "); 101413212Ssam printf("(local-file) "); 101513212Ssam gets(&line[strlen(line)]); 101613212Ssam makeargv(); 101713212Ssam argc = margc; 101813212Ssam argv = margv; 101913212Ssam } 102013212Ssam if (argc < 3) { 1021*26049Sminshall printf("usage:%s remote-files local-file\n", argv[0]); 1022*26049Sminshall code = -1; 102313212Ssam return; 102413212Ssam } 102513212Ssam dest = argv[argc - 1]; 102613212Ssam argv[argc - 1] = NULL; 1027*26049Sminshall if (strcmp(dest, "-") && *dest != '|') 1028*26049Sminshall if (!globulize(&dest) || !confirm("output to local-file:", dest)) { 1029*26049Sminshall code = -1; 103013212Ssam return; 1031*26049Sminshall } 103211756Ssam cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; 1033*26049Sminshall mname = argv[0]; 1034*26049Sminshall mflag = 1; 1035*26049Sminshall oldintr = signal(SIGINT, mabort); 1036*26049Sminshall (void) setjmp(jabort); 1037*26049Sminshall for (i = 1; mflag && i < argc-1; ++i) { 1038*26049Sminshall *mode = (i == 1) ? 'w' : 'a'; 1039*26049Sminshall recvrequest(cmd, dest, argv[i], mode); 1040*26049Sminshall if (!mflag && fromatty) { 1041*26049Sminshall ointer = interactive; 1042*26049Sminshall interactive = 1; 1043*26049Sminshall if (confirm("Continue with", argv[0])) { 1044*26049Sminshall mflag ++; 1045*26049Sminshall } 1046*26049Sminshall interactive = ointer; 1047*26049Sminshall } 1048*26049Sminshall } 1049*26049Sminshall (void) signal(SIGINT, oldintr); 1050*26049Sminshall mflag = 0; 105111756Ssam } 105211756Ssam 105311756Ssam /* 105410294Ssam * Do a shell escape 105510294Ssam */ 105610294Ssam shell(argc, argv) 105710294Ssam char *argv[]; 105810294Ssam { 1059*26049Sminshall int i, pid, status, (*old1)(), (*old2)(); 1060*26049Sminshall char shellnam[40], *shell, *namep; 106110294Ssam 106211756Ssam old1 = signal (SIGINT, SIG_IGN); 106311756Ssam old2 = signal (SIGQUIT, SIG_IGN); 106411756Ssam if ((pid = fork()) == 0) { 106511756Ssam for (pid = 3; pid < 20; pid++) 106611756Ssam close(pid); 106711756Ssam signal(SIGINT, SIG_DFL); 106811756Ssam signal(SIGQUIT, SIG_DFL); 106925908Smckusick shell = getenv("SHELL"); 107025908Smckusick if (shell == NULL) 107125908Smckusick shell = "/bin/sh"; 107225908Smckusick namep = rindex(shell,'/'); 107325908Smckusick if (namep == NULL) 107425908Smckusick namep = shell; 1075*26049Sminshall strcpy(shellnam,"-"); 1076*26049Sminshall strcat(shellnam, ++namep); 1077*26049Sminshall if (strcmp(namep, "sh") != 0) 1078*26049Sminshall shellnam[0] = '+'; 1079*26049Sminshall if (debug) { 1080*26049Sminshall printf ("%s\n", shell); 1081*26049Sminshall fflush (stdout); 108211756Ssam } 1083*26049Sminshall if (argc > 1) { 1084*26049Sminshall execl(shell,shellnam,"-c",altarg,(char *)0); 1085*26049Sminshall } 1086*26049Sminshall else { 1087*26049Sminshall execl(shell,shellnam,(char *)0); 1088*26049Sminshall } 108925908Smckusick perror(shell); 1090*26049Sminshall code = -1; 109111756Ssam exit(1); 1092*26049Sminshall } 109311756Ssam if (pid > 0) 109411756Ssam while (wait(&status) != pid) 109511756Ssam ; 109611756Ssam signal(SIGINT, old1); 109711756Ssam signal(SIGQUIT, old2); 1098*26049Sminshall if (pid == -1) { 109911756Ssam perror("Try again later"); 1100*26049Sminshall code = -1; 1101*26049Sminshall } 1102*26049Sminshall else { 1103*26049Sminshall code = 0; 1104*26049Sminshall } 110511756Ssam return (0); 110610294Ssam } 110710294Ssam 110810294Ssam /* 110910294Ssam * Send new user information (re-login) 111010294Ssam */ 111110294Ssam user(argc, argv) 111210294Ssam int argc; 111310294Ssam char **argv; 111410294Ssam { 111510294Ssam char acct[80], *getpass(); 1116*26049Sminshall int n, aflag = 0; 111710294Ssam 111810294Ssam if (argc < 2) { 111910294Ssam strcat(line, " "); 112010294Ssam printf("(username) "); 112110294Ssam gets(&line[strlen(line)]); 112210294Ssam makeargv(); 112310294Ssam argc = margc; 112410294Ssam argv = margv; 112510294Ssam } 112610294Ssam if (argc > 4) { 112710294Ssam printf("usage: %s username [password] [account]\n", argv[0]); 1128*26049Sminshall code = -1; 112911756Ssam return (0); 113010294Ssam } 113110294Ssam n = command("USER %s", argv[1]); 113210294Ssam if (n == CONTINUE) { 113310294Ssam if (argc < 3 ) 113410294Ssam argv[2] = getpass("Password: "), argc++; 113510294Ssam n = command("PASS %s", argv[2]); 113610294Ssam } 113710294Ssam if (n == CONTINUE) { 113810294Ssam if (argc < 4) { 113910294Ssam printf("Account: "); (void) fflush(stdout); 114010294Ssam (void) fgets(acct, sizeof(acct) - 1, stdin); 114110294Ssam acct[strlen(acct) - 1] = '\0'; 114210294Ssam argv[3] = acct; argc++; 114310294Ssam } 1144*26049Sminshall n = command("ACCT %s", argv[3]); 1145*26049Sminshall aflag++; 114610294Ssam } 114710294Ssam if (n != COMPLETE) { 114810294Ssam fprintf(stderr, "Login failed.\n"); 114910294Ssam return (0); 115010294Ssam } 1151*26049Sminshall if (!aflag && argc == 4) { 1152*26049Sminshall (void) command("ACCT %s", argv[3]); 1153*26049Sminshall } 115410294Ssam return (1); 115510294Ssam } 115610294Ssam 115710294Ssam /* 115810294Ssam * Print working directory. 115910294Ssam */ 116010294Ssam /*VARARGS*/ 116110294Ssam pwd() 116210294Ssam { 116311756Ssam 1164*26049Sminshall (void) command("PWD"); 116510294Ssam } 116610294Ssam 116710294Ssam /* 116810294Ssam * Make a directory. 116910294Ssam */ 117010294Ssam makedir(argc, argv) 117110294Ssam char *argv[]; 117210294Ssam { 117310294Ssam 117410294Ssam if (argc < 2) { 117510294Ssam strcat(line, " "); 117610294Ssam printf("(directory-name) "); 117710294Ssam gets(&line[strlen(line)]); 117810294Ssam makeargv(); 117910294Ssam argc = margc; 118010294Ssam argv = margv; 118110294Ssam } 118210294Ssam if (argc < 2) { 1183*26049Sminshall printf("usage: %s directory-name\n", argv[0]); 1184*26049Sminshall code = -1; 118510294Ssam return; 118610294Ssam } 1187*26049Sminshall (void) command("MKD %s", argv[1]); 118810294Ssam } 118910294Ssam 119010294Ssam /* 119110294Ssam * Remove a directory. 119210294Ssam */ 119310294Ssam removedir(argc, argv) 119410294Ssam char *argv[]; 119510294Ssam { 119610294Ssam 119710294Ssam if (argc < 2) { 119810294Ssam strcat(line, " "); 119910294Ssam printf("(directory-name) "); 120010294Ssam gets(&line[strlen(line)]); 120110294Ssam makeargv(); 120210294Ssam argc = margc; 120310294Ssam argv = margv; 120410294Ssam } 120510294Ssam if (argc < 2) { 1206*26049Sminshall printf("usage: %s directory-name\n", argv[0]); 1207*26049Sminshall code = -1; 120810294Ssam return; 120910294Ssam } 1210*26049Sminshall (void) command("RMD %s", argv[1]); 121110294Ssam } 121210294Ssam 121310294Ssam /* 121410294Ssam * Send a line, verbatim, to the remote machine. 121510294Ssam */ 121610294Ssam quote(argc, argv) 121710294Ssam char *argv[]; 121810294Ssam { 121910294Ssam int i; 122010294Ssam char buf[BUFSIZ]; 122110294Ssam 122210294Ssam if (argc < 2) { 122310294Ssam strcat(line, " "); 122410294Ssam printf("(command line to send) "); 122510294Ssam gets(&line[strlen(line)]); 122610294Ssam makeargv(); 122710294Ssam argc = margc; 122810294Ssam argv = margv; 122910294Ssam } 123010294Ssam if (argc < 2) { 123110294Ssam printf("usage: %s line-to-send\n", argv[0]); 1232*26049Sminshall code = -1; 123310294Ssam return; 123410294Ssam } 123510294Ssam strcpy(buf, argv[1]); 123610294Ssam for (i = 2; i < argc; i++) { 123710294Ssam strcat(buf, " "); 123810294Ssam strcat(buf, argv[i]); 123910294Ssam } 1240*26049Sminshall if (command(buf) == PRELIM) { 1241*26049Sminshall while (getreply(0) == PRELIM); 1242*26049Sminshall } 124310294Ssam } 124410294Ssam 124510294Ssam /* 124610294Ssam * Ask the other side for help. 124710294Ssam */ 124810294Ssam rmthelp(argc, argv) 124910294Ssam char *argv[]; 125010294Ssam { 125110294Ssam int oldverbose = verbose; 125210294Ssam 125310294Ssam verbose = 1; 125410294Ssam (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); 125510294Ssam verbose = oldverbose; 125610294Ssam } 125710294Ssam 125810294Ssam /* 125910294Ssam * Terminate session and exit. 126010294Ssam */ 126110294Ssam /*VARARGS*/ 126210294Ssam quit() 126310294Ssam { 126410294Ssam 126518286Sralph if (connected) 126618286Sralph disconnect(); 1267*26049Sminshall pswitch(1); 1268*26049Sminshall if (connected) { 1269*26049Sminshall disconnect(); 1270*26049Sminshall } 127110294Ssam exit(0); 127210294Ssam } 127310294Ssam 127410294Ssam /* 127510294Ssam * Terminate session, but don't exit. 127610294Ssam */ 127710294Ssam disconnect() 127810294Ssam { 127910294Ssam extern FILE *cout; 128010294Ssam extern int data; 128110294Ssam 128210294Ssam if (!connected) 128310294Ssam return; 128410294Ssam (void) command("QUIT"); 1285*26049Sminshall if (cout) { 1286*26049Sminshall (void) fclose(cout); 1287*26049Sminshall } 128810294Ssam cout = NULL; 128910294Ssam connected = 0; 129010294Ssam data = -1; 1291*26049Sminshall if (!proxy) { 1292*26049Sminshall macnum = 0; 1293*26049Sminshall } 129410294Ssam } 129511353Ssam 129611650Ssam confirm(cmd, file) 129711353Ssam char *cmd, *file; 129811353Ssam { 129911353Ssam char line[BUFSIZ]; 130011353Ssam 130111353Ssam if (!interactive) 130211650Ssam return (1); 130311353Ssam printf("%s %s? ", cmd, file); 130411353Ssam fflush(stdout); 130511353Ssam gets(line); 130611650Ssam return (*line != 'n' && *line != 'N'); 130711353Ssam } 130811353Ssam 130911353Ssam fatal(msg) 131011353Ssam char *msg; 131111353Ssam { 131211353Ssam 131311353Ssam fprintf(stderr, "ftp: %s\n"); 131411353Ssam exit(1); 131511353Ssam } 131611353Ssam 131711353Ssam /* 131811353Ssam * Glob a local file name specification with 131911353Ssam * the expectation of a single return value. 132011353Ssam * Can't control multiple values being expanded 132111353Ssam * from the expression, we return only the first. 132211353Ssam */ 132311353Ssam globulize(cpp) 132411353Ssam char **cpp; 132511353Ssam { 132611353Ssam char **globbed; 132711353Ssam 132811353Ssam if (!doglob) 132911353Ssam return (1); 133011353Ssam globbed = glob(*cpp); 133111353Ssam if (globerr != NULL) { 133211353Ssam printf("%s: %s\n", *cpp, globerr); 133311353Ssam if (globbed) 133411353Ssam blkfree(globbed); 133511353Ssam return (0); 133611353Ssam } 133711353Ssam if (globbed) { 133811353Ssam *cpp = *globbed++; 133911353Ssam /* don't waste too much memory */ 134011353Ssam if (*globbed) 134111353Ssam blkfree(globbed); 134211353Ssam } 134311353Ssam return (1); 134411353Ssam } 1345*26049Sminshall 1346*26049Sminshall account(argc,argv) 1347*26049Sminshall 1348*26049Sminshall int argc; 1349*26049Sminshall char **argv; 1350*26049Sminshall { 1351*26049Sminshall char acct[50], *getpass(), *ap; 1352*26049Sminshall 1353*26049Sminshall if (argc > 1) { 1354*26049Sminshall ++argv; 1355*26049Sminshall --argc; 1356*26049Sminshall (void) strncpy(acct,*argv,49); 1357*26049Sminshall acct[50] = '\0'; 1358*26049Sminshall while (argc > 1) { 1359*26049Sminshall --argc; 1360*26049Sminshall ++argv; 1361*26049Sminshall (void) strncat(acct,*argv, 49-strlen(acct)); 1362*26049Sminshall } 1363*26049Sminshall ap = acct; 1364*26049Sminshall } 1365*26049Sminshall else { 1366*26049Sminshall ap = getpass("Account:"); 1367*26049Sminshall } 1368*26049Sminshall (void) command("ACCT %s", ap); 1369*26049Sminshall } 1370*26049Sminshall 1371*26049Sminshall jmp_buf abortprox; 1372*26049Sminshall 1373*26049Sminshall proxabort() 1374*26049Sminshall { 1375*26049Sminshall extern int proxy; 1376*26049Sminshall 1377*26049Sminshall if (!proxy) { 1378*26049Sminshall pswitch(1); 1379*26049Sminshall } 1380*26049Sminshall if (connected) { 1381*26049Sminshall proxflag = 1; 1382*26049Sminshall } 1383*26049Sminshall else { 1384*26049Sminshall proxflag = 0; 1385*26049Sminshall } 1386*26049Sminshall pswitch(0); 1387*26049Sminshall longjmp(abortprox,1); 1388*26049Sminshall } 1389*26049Sminshall 1390*26049Sminshall doproxy(argc,argv) 1391*26049Sminshall int argc; 1392*26049Sminshall char *argv[]; 1393*26049Sminshall { 1394*26049Sminshall int (*oldintr)(), proxabort(); 1395*26049Sminshall register struct cmd *c; 1396*26049Sminshall struct cmd *getcmd(); 1397*26049Sminshall extern struct cmd cmdtab[]; 1398*26049Sminshall extern jmp_buf abortprox; 1399*26049Sminshall 1400*26049Sminshall if (argc < 2) { 1401*26049Sminshall strcat(line, " "); 1402*26049Sminshall printf("(command) "); 1403*26049Sminshall gets(&line[strlen(line)]); 1404*26049Sminshall makeargv(); 1405*26049Sminshall argc = margc; 1406*26049Sminshall argv = margv; 1407*26049Sminshall } 1408*26049Sminshall if (argc < 2) { 1409*26049Sminshall printf("usage:%s command\n", argv[0]); 1410*26049Sminshall code = -1; 1411*26049Sminshall return; 1412*26049Sminshall } 1413*26049Sminshall c = getcmd(argv[1]); 1414*26049Sminshall if (c == (struct cmd *) -1) { 1415*26049Sminshall printf("?Ambiguous command\n"); 1416*26049Sminshall fflush(stdout); 1417*26049Sminshall code = -1; 1418*26049Sminshall return; 1419*26049Sminshall } 1420*26049Sminshall if (c == 0) { 1421*26049Sminshall printf("?Invalid command\n"); 1422*26049Sminshall fflush(stdout); 1423*26049Sminshall code = -1; 1424*26049Sminshall return; 1425*26049Sminshall } 1426*26049Sminshall if (!c->c_proxy) { 1427*26049Sminshall printf("?Invalid proxy command\n"); 1428*26049Sminshall fflush(stdout); 1429*26049Sminshall code = -1; 1430*26049Sminshall return; 1431*26049Sminshall } 1432*26049Sminshall if (setjmp(abortprox)) { 1433*26049Sminshall code = -1; 1434*26049Sminshall return; 1435*26049Sminshall } 1436*26049Sminshall oldintr = signal(SIGINT, proxabort); 1437*26049Sminshall pswitch(1); 1438*26049Sminshall if (c->c_conn && !connected) { 1439*26049Sminshall printf("Not connected\n"); 1440*26049Sminshall fflush(stdout); 1441*26049Sminshall pswitch(0); 1442*26049Sminshall (void) signal(SIGINT, oldintr); 1443*26049Sminshall code = -1; 1444*26049Sminshall return; 1445*26049Sminshall } 1446*26049Sminshall (*c->c_handler)(argc-1, argv+1); 1447*26049Sminshall if (connected) { 1448*26049Sminshall proxflag = 1; 1449*26049Sminshall } 1450*26049Sminshall else { 1451*26049Sminshall proxflag = 0; 1452*26049Sminshall } 1453*26049Sminshall pswitch(0); 1454*26049Sminshall (void) signal(SIGINT, oldintr); 1455*26049Sminshall } 1456*26049Sminshall 1457*26049Sminshall setcase() 1458*26049Sminshall { 1459*26049Sminshall mcase = !mcase; 1460*26049Sminshall printf("Case mapping %s.\n", onoff(mcase)); 1461*26049Sminshall code = mcase; 1462*26049Sminshall } 1463*26049Sminshall 1464*26049Sminshall setcr() 1465*26049Sminshall { 1466*26049Sminshall crflag = !crflag; 1467*26049Sminshall printf("Carriage Return stripping %s.\n", onoff(crflag)); 1468*26049Sminshall code = crflag; 1469*26049Sminshall } 1470*26049Sminshall 1471*26049Sminshall setntrans(argc,argv) 1472*26049Sminshall int argc; 1473*26049Sminshall char *argv[]; 1474*26049Sminshall { 1475*26049Sminshall if (argc == 1) { 1476*26049Sminshall ntflag = 0; 1477*26049Sminshall printf("Ntrans off.\n"); 1478*26049Sminshall code = ntflag; 1479*26049Sminshall return; 1480*26049Sminshall } 1481*26049Sminshall ntflag++; 1482*26049Sminshall code = ntflag; 1483*26049Sminshall (void) strncpy(ntin, argv[1], 16); 1484*26049Sminshall ntin[16] = '\0'; 1485*26049Sminshall if (argc == 2) { 1486*26049Sminshall ntout[0] = '\0'; 1487*26049Sminshall return; 1488*26049Sminshall } 1489*26049Sminshall (void) strncpy(ntout, argv[2], 16); 1490*26049Sminshall ntout[16] = '\0'; 1491*26049Sminshall } 1492*26049Sminshall 1493*26049Sminshall char * 1494*26049Sminshall dotrans(name) 1495*26049Sminshall char *name; 1496*26049Sminshall { 1497*26049Sminshall static char new[MAXPATHLEN]; 1498*26049Sminshall char *cp1, *cp2 = new; 1499*26049Sminshall register int i, ostop, found; 1500*26049Sminshall 1501*26049Sminshall for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++); 1502*26049Sminshall for (cp1 = name; *cp1; cp1++) { 1503*26049Sminshall found = 0; 1504*26049Sminshall for (i = 0; *(ntin + i) && i < 16; i++) { 1505*26049Sminshall if (*cp1 == *(ntin + i)) { 1506*26049Sminshall found++; 1507*26049Sminshall if (i < ostop) { 1508*26049Sminshall *cp2++ = *(ntout + i); 1509*26049Sminshall } 1510*26049Sminshall break; 1511*26049Sminshall } 1512*26049Sminshall } 1513*26049Sminshall if (!found) { 1514*26049Sminshall *cp2++ = *cp1; 1515*26049Sminshall } 1516*26049Sminshall } 1517*26049Sminshall *cp2 = '\0'; 1518*26049Sminshall return(new); 1519*26049Sminshall } 1520*26049Sminshall 1521*26049Sminshall setnmap(argc, argv) 1522*26049Sminshall int argc; 1523*26049Sminshall char *argv[]; 1524*26049Sminshall { 1525*26049Sminshall char *cp; 1526*26049Sminshall 1527*26049Sminshall if (argc == 1) { 1528*26049Sminshall mapflag = 0; 1529*26049Sminshall printf("Nmap off.\n"); 1530*26049Sminshall code = mapflag; 1531*26049Sminshall return; 1532*26049Sminshall } 1533*26049Sminshall if (argc < 3) { 1534*26049Sminshall strcat(line, " "); 1535*26049Sminshall printf("(mapout) "); 1536*26049Sminshall gets(&line[strlen(line)]); 1537*26049Sminshall makeargv(); 1538*26049Sminshall argc = margc; 1539*26049Sminshall argv = margv; 1540*26049Sminshall } 1541*26049Sminshall if (argc < 3) { 1542*26049Sminshall printf("Usage: %s [mapin mapout]\n",argv[0]); 1543*26049Sminshall code = -1; 1544*26049Sminshall return; 1545*26049Sminshall } 1546*26049Sminshall mapflag = 1; 1547*26049Sminshall code = 1; 1548*26049Sminshall cp = index(altarg, ' '); 1549*26049Sminshall if (proxy) { 1550*26049Sminshall while(*++cp == ' '); 1551*26049Sminshall altarg = cp; 1552*26049Sminshall cp = index(altarg, ' '); 1553*26049Sminshall } 1554*26049Sminshall *cp = '\0'; 1555*26049Sminshall (void) strncpy(mapin, altarg, MAXPATHLEN - 1); 1556*26049Sminshall while (*++cp == ' '); 1557*26049Sminshall (void) strncpy(mapout, cp, MAXPATHLEN - 1); 1558*26049Sminshall } 1559*26049Sminshall 1560*26049Sminshall char * 1561*26049Sminshall domap(name) 1562*26049Sminshall char *name; 1563*26049Sminshall { 1564*26049Sminshall static char new[MAXPATHLEN]; 1565*26049Sminshall register char *cp1 = name, *cp2 = mapin; 1566*26049Sminshall char *tp[9], *te[9]; 1567*26049Sminshall int i, toks[9], toknum, match = 1; 1568*26049Sminshall 1569*26049Sminshall for (i=0; i < 9; ++i) { 1570*26049Sminshall toks[i] = 0; 1571*26049Sminshall } 1572*26049Sminshall while (match && *cp1 && *cp2) { 1573*26049Sminshall switch (*cp2) { 1574*26049Sminshall case '\\': 1575*26049Sminshall if (*++cp2 != *cp1) { 1576*26049Sminshall match = 0; 1577*26049Sminshall } 1578*26049Sminshall break; 1579*26049Sminshall case '$': 1580*26049Sminshall if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { 1581*26049Sminshall if (*cp1 != *(++cp2+1)) { 1582*26049Sminshall toks[toknum = *cp2 - '1']++; 1583*26049Sminshall tp[toknum] = cp1; 1584*26049Sminshall while (*++cp1 && *(cp2+1) 1585*26049Sminshall != *cp1); 1586*26049Sminshall te[toknum] = cp1; 1587*26049Sminshall } 1588*26049Sminshall cp2++; 1589*26049Sminshall break; 1590*26049Sminshall } 1591*26049Sminshall /* intentional drop through */ 1592*26049Sminshall default: 1593*26049Sminshall if (*cp2 != *cp1) { 1594*26049Sminshall match = 0; 1595*26049Sminshall } 1596*26049Sminshall break; 1597*26049Sminshall } 1598*26049Sminshall if (*cp1) { 1599*26049Sminshall cp1++; 1600*26049Sminshall } 1601*26049Sminshall if (*cp2) { 1602*26049Sminshall cp2++; 1603*26049Sminshall } 1604*26049Sminshall } 1605*26049Sminshall cp1 = new; 1606*26049Sminshall *cp1 = '\0'; 1607*26049Sminshall cp2 = mapout; 1608*26049Sminshall while (*cp2) { 1609*26049Sminshall match = 0; 1610*26049Sminshall switch (*cp2) { 1611*26049Sminshall case '\\': 1612*26049Sminshall if (*(cp2 + 1)) { 1613*26049Sminshall *cp1++ = *++cp2; 1614*26049Sminshall } 1615*26049Sminshall break; 1616*26049Sminshall case '[': 1617*26049Sminshall LOOP: 1618*26049Sminshall if (*++cp2 == '$' && isdigit(*(cp2+1))) { 1619*26049Sminshall if (*++cp2 == '0') { 1620*26049Sminshall char *cp3 = name; 1621*26049Sminshall 1622*26049Sminshall while (*cp3) { 1623*26049Sminshall *cp1++ = *cp3++; 1624*26049Sminshall } 1625*26049Sminshall match = 1; 1626*26049Sminshall } 1627*26049Sminshall else if (toks[toknum = *cp2 - '1']) { 1628*26049Sminshall char *cp3 = tp[toknum]; 1629*26049Sminshall 1630*26049Sminshall while (cp3 != te[toknum]) { 1631*26049Sminshall *cp1++ = *cp3++; 1632*26049Sminshall } 1633*26049Sminshall match = 1; 1634*26049Sminshall } 1635*26049Sminshall } 1636*26049Sminshall else { 1637*26049Sminshall while (*cp2 && *cp2 != ',' && 1638*26049Sminshall *cp2 != ']') { 1639*26049Sminshall if (*cp2 == '\\') { 1640*26049Sminshall cp2++; 1641*26049Sminshall } 1642*26049Sminshall else if (*cp2 == '$' && 1643*26049Sminshall isdigit(*(cp2+1))) { 1644*26049Sminshall if (*++cp2 == '0') { 1645*26049Sminshall char *cp3 = name; 1646*26049Sminshall 1647*26049Sminshall while (*cp3) { 1648*26049Sminshall *cp1++ = *cp3++; 1649*26049Sminshall } 1650*26049Sminshall } 1651*26049Sminshall else if (toks[toknum = 1652*26049Sminshall *cp2 - '1']) { 1653*26049Sminshall char *cp3=tp[toknum]; 1654*26049Sminshall 1655*26049Sminshall while (cp3 != 1656*26049Sminshall te[toknum]) { 1657*26049Sminshall *cp1++ = *cp3++; 1658*26049Sminshall } 1659*26049Sminshall } 1660*26049Sminshall } 1661*26049Sminshall else if (*cp2) { 1662*26049Sminshall *cp1++ = *cp2++; 1663*26049Sminshall } 1664*26049Sminshall } 1665*26049Sminshall if (!*cp2) { 1666*26049Sminshall printf("nmap: unbalanced brackets\n"); 1667*26049Sminshall return(name); 1668*26049Sminshall } 1669*26049Sminshall match = 1; 1670*26049Sminshall cp2--; 1671*26049Sminshall } 1672*26049Sminshall if (match) { 1673*26049Sminshall while (*++cp2 && *cp2 != ']') { 1674*26049Sminshall if (*cp2 == '\\' && *(cp2 + 1)) { 1675*26049Sminshall cp2++; 1676*26049Sminshall } 1677*26049Sminshall } 1678*26049Sminshall if (!*cp2) { 1679*26049Sminshall printf("nmap: unbalanced brackets\n"); 1680*26049Sminshall return(name); 1681*26049Sminshall } 1682*26049Sminshall break; 1683*26049Sminshall } 1684*26049Sminshall switch (*++cp2) { 1685*26049Sminshall case ',': 1686*26049Sminshall goto LOOP; 1687*26049Sminshall case ']': 1688*26049Sminshall break; 1689*26049Sminshall default: 1690*26049Sminshall cp2--; 1691*26049Sminshall goto LOOP; 1692*26049Sminshall } 1693*26049Sminshall break; 1694*26049Sminshall case '$': 1695*26049Sminshall if (isdigit(*(cp2 + 1))) { 1696*26049Sminshall if (*++cp2 == '0') { 1697*26049Sminshall char *cp3 = name; 1698*26049Sminshall 1699*26049Sminshall while (*cp3) { 1700*26049Sminshall *cp1++ = *cp3++; 1701*26049Sminshall } 1702*26049Sminshall } 1703*26049Sminshall else if (toks[toknum = *cp2 - '1']) { 1704*26049Sminshall char *cp3 = tp[toknum]; 1705*26049Sminshall 1706*26049Sminshall while (cp3 != te[toknum]) { 1707*26049Sminshall *cp1++ = *cp3++; 1708*26049Sminshall } 1709*26049Sminshall } 1710*26049Sminshall break; 1711*26049Sminshall } 1712*26049Sminshall /* intentional drop through */ 1713*26049Sminshall default: 1714*26049Sminshall *cp1++ = *cp2; 1715*26049Sminshall break; 1716*26049Sminshall } 1717*26049Sminshall cp2++; 1718*26049Sminshall } 1719*26049Sminshall *cp1 = '\0'; 1720*26049Sminshall if (!*new) { 1721*26049Sminshall return(name); 1722*26049Sminshall } 1723*26049Sminshall return(new); 1724*26049Sminshall } 1725*26049Sminshall 1726*26049Sminshall setsunique() 1727*26049Sminshall { 1728*26049Sminshall sunique = !sunique; 1729*26049Sminshall printf("Store unique %s.\n", onoff(sunique)); 1730*26049Sminshall code = sunique; 1731*26049Sminshall } 1732*26049Sminshall 1733*26049Sminshall setrunique() 1734*26049Sminshall { 1735*26049Sminshall runique = !runique; 1736*26049Sminshall printf("Receive unique %s.\n", onoff(runique)); 1737*26049Sminshall code = runique; 1738*26049Sminshall } 1739*26049Sminshall 1740*26049Sminshall /* change directory to perent directory */ 1741*26049Sminshall cdup() 1742*26049Sminshall { 1743*26049Sminshall (void) command("CDUP"); 1744*26049Sminshall } 1745*26049Sminshall 1746*26049Sminshall macdef(argc, argv) 1747*26049Sminshall int argc; 1748*26049Sminshall char *argv[]; 1749*26049Sminshall { 1750*26049Sminshall char *tmp; 1751*26049Sminshall int c; 1752*26049Sminshall 1753*26049Sminshall if (macnum == 16) { 1754*26049Sminshall printf("Limit of 16 macros have already been defined\n"); 1755*26049Sminshall code = -1; 1756*26049Sminshall return; 1757*26049Sminshall } 1758*26049Sminshall if (argc < 2) { 1759*26049Sminshall strcat(line, " "); 1760*26049Sminshall printf("(macro name) "); 1761*26049Sminshall gets(&line[strlen(line)]); 1762*26049Sminshall makeargv(); 1763*26049Sminshall argc = margc; 1764*26049Sminshall argv = margv; 1765*26049Sminshall } 1766*26049Sminshall if (argc != 2) { 1767*26049Sminshall printf("Usage: %s macro_name\n",argv[0]); 1768*26049Sminshall code = -1; 1769*26049Sminshall return; 1770*26049Sminshall } 1771*26049Sminshall if (interactive) { 1772*26049Sminshall printf("Enter macro line by line, terminating it with a null line\n"); 1773*26049Sminshall } 1774*26049Sminshall strncpy(macros[macnum].mac_name, argv[1], 8); 1775*26049Sminshall if (macnum == 0) { 1776*26049Sminshall macros[macnum].mac_start = macbuf; 1777*26049Sminshall } 1778*26049Sminshall else { 1779*26049Sminshall macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; 1780*26049Sminshall } 1781*26049Sminshall tmp = macros[macnum].mac_start; 1782*26049Sminshall while (tmp != macbuf+4096) { 1783*26049Sminshall if ((c = getchar()) == EOF) { 1784*26049Sminshall printf("macdef:end of file encountered\n"); 1785*26049Sminshall code = -1; 1786*26049Sminshall return; 1787*26049Sminshall } 1788*26049Sminshall if ((*tmp = c) == '\n') { 1789*26049Sminshall if (tmp == macros[macnum].mac_start) { 1790*26049Sminshall macros[macnum++].mac_end = tmp; 1791*26049Sminshall code = 0; 1792*26049Sminshall return; 1793*26049Sminshall } 1794*26049Sminshall if (*(tmp-1) == '\0') { 1795*26049Sminshall macros[macnum++].mac_end = tmp - 1; 1796*26049Sminshall code = 0; 1797*26049Sminshall return; 1798*26049Sminshall } 1799*26049Sminshall *tmp = '\0'; 1800*26049Sminshall } 1801*26049Sminshall tmp++; 1802*26049Sminshall } 1803*26049Sminshall while (1) { 1804*26049Sminshall while ((c = getchar()) != '\n' && c != EOF); 1805*26049Sminshall if (c == EOF || getchar() == '\n') { 1806*26049Sminshall printf("Macro not defined - 4k buffer exceeded\n"); 1807*26049Sminshall code = -1; 1808*26049Sminshall return; 1809*26049Sminshall } 1810*26049Sminshall } 1811*26049Sminshall } 1812