121739Sdist /* 2*26048Sminshall * Copyright (c) 1985 Regents of the University of California. 321739Sdist * All rights reserved. The Berkeley software License Agreement 421739Sdist * specifies the terms and conditions for redistribution. 521739Sdist */ 621739Sdist 710296Ssam #ifndef lint 8*26048Sminshall static char sccsid[] = "@(#)ftp.c 5.6 (Berkeley) 02/03/86"; 921739Sdist #endif not lint 1010296Ssam 11*26048Sminshall #include "ftp_var.h" 12*26048Sminshall 1310296Ssam #include <sys/stat.h> 1410296Ssam #include <sys/ioctl.h> 1510296Ssam #include <sys/socket.h> 1613614Ssam #include <sys/time.h> 1710296Ssam 1810296Ssam #include <netinet/in.h> 1912397Ssam #include <arpa/ftp.h> 20*26048Sminshall #include <arpa/telnet.h> 2110296Ssam 2210296Ssam #include <stdio.h> 2310296Ssam #include <signal.h> 2410296Ssam #include <errno.h> 2510296Ssam #include <netdb.h> 26*26048Sminshall #include <fcntl.h> 27*26048Sminshall #include <pwd.h> 2810296Ssam 2910296Ssam struct sockaddr_in hisctladdr; 3010296Ssam struct sockaddr_in data_addr; 3110296Ssam int data = -1; 32*26048Sminshall int telflag = 0; 33*26048Sminshall int abrtflag = 0; 34*26048Sminshall int ptflag = 0; 3510296Ssam int connected; 3610296Ssam struct sockaddr_in myctladdr; 3710296Ssam 3810296Ssam FILE *cin, *cout; 3910296Ssam FILE *dataconn(); 4010296Ssam 4125904Skarels char * 4210296Ssam hookup(host, port) 4310296Ssam char *host; 4410296Ssam int port; 4510296Ssam { 4625904Skarels register struct hostent *hp = 0; 47*26048Sminshall int s,len,oldverbose; 4825904Skarels static char hostnamebuf[80]; 49*26048Sminshall char msg[2]; 5010296Ssam 5110296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 5225904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 5325904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 5425904Skarels hisctladdr.sin_family = AF_INET; 5525904Skarels (void) strcpy(hostnamebuf, host); 56*26048Sminshall } 57*26048Sminshall else { 5825100Sbloom hp = gethostbyname(host); 5925904Skarels if (hp == NULL) { 6025904Skarels printf("%s: unknown host\n", host); 61*26048Sminshall code = -1; 62*26048Sminshall return((char *) 0); 6325904Skarels } 6425904Skarels hisctladdr.sin_family = hp->h_addrtype; 6525904Skarels bcopy(hp->h_addr_list[0], 6625904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 6725904Skarels (void) strcpy(hostnamebuf, hp->h_name); 6810296Ssam } 6925904Skarels hostname = hostnamebuf; 7025904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 7110296Ssam if (s < 0) { 7210296Ssam perror("ftp: socket"); 73*26048Sminshall code = -1; 7410296Ssam return (0); 7510296Ssam } 7610296Ssam hisctladdr.sin_port = port; 7725904Skarels while (connect(s, (caddr_t)&hisctladdr, sizeof (hisctladdr)) < 0) { 7825904Skarels if (hp && hp->h_addr_list[1]) { 7925904Skarels int oerrno = errno; 8025904Skarels 8125904Skarels fprintf(stderr, "ftp: connect to address %s: ", 8225904Skarels inet_ntoa(hisctladdr.sin_addr)); 8325904Skarels errno = oerrno; 8425904Skarels perror(0); 8525904Skarels hp->h_addr_list++; 8625904Skarels bcopy(hp->h_addr_list[0], 87*26048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 8825904Skarels fprintf(stderr, "Trying %s...\n", 8925904Skarels inet_ntoa(hisctladdr.sin_addr)); 9025904Skarels continue; 9125904Skarels } 9210296Ssam perror("ftp: connect"); 93*26048Sminshall code = -1; 9410296Ssam goto bad; 9510296Ssam } 9611627Ssam len = sizeof (myctladdr); 9711627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 9811627Ssam perror("ftp: getsockname"); 99*26048Sminshall code = -1; 10010296Ssam goto bad; 10110296Ssam } 10210296Ssam cin = fdopen(s, "r"); 10310296Ssam cout = fdopen(s, "w"); 10411219Ssam if (cin == NULL || cout == NULL) { 10510296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 10610296Ssam if (cin) 10710296Ssam fclose(cin); 10810296Ssam if (cout) 10910296Ssam fclose(cout); 110*26048Sminshall code = -1; 11110296Ssam goto bad; 11210296Ssam } 11310296Ssam if (verbose) 114*26048Sminshall printf("Connected to %s.\n", hp->h_name); 115*26048Sminshall if (getreply(0) != 2) { /* read startup message from server */ 116*26048Sminshall if (cin) 117*26048Sminshall fclose(cin); 118*26048Sminshall if (cout) 119*26048Sminshall fclose(cout); 120*26048Sminshall code = -1; 121*26048Sminshall goto bad; 122*26048Sminshall } 123*26048Sminshall 124*26048Sminshall /* test to see if server command parser understands TELNET SYNC command */ 125*26048Sminshall 126*26048Sminshall fprintf(cout,"%c%c",IAC,NOP); 127*26048Sminshall (void) fflush(cout); 128*26048Sminshall *msg = IAC; 129*26048Sminshall *(msg+1) = DM; 130*26048Sminshall if (send(s,msg,2,MSG_OOB) != 2) { 131*26048Sminshall perror("sync"); 132*26048Sminshall } 133*26048Sminshall oldverbose = verbose; 134*26048Sminshall if (!debug) { 135*26048Sminshall verbose = -1; 136*26048Sminshall } 137*26048Sminshall if (command("NOOP") == COMPLETE) { 138*26048Sminshall telflag = 1; 139*26048Sminshall } 140*26048Sminshall else { 141*26048Sminshall telflag = 0; 142*26048Sminshall } 143*26048Sminshall verbose = oldverbose; 14425904Skarels return (hostname); 14510296Ssam bad: 14610296Ssam close(s); 14725904Skarels return ((char *)0); 14810296Ssam } 14910296Ssam 15025904Skarels login(host) 15125904Skarels char *host; 15210296Ssam { 153*26048Sminshall char tmp[80]; 154*26048Sminshall char *user, *pass, *acct, *getlogin(), *getpass(); 155*26048Sminshall int n, aflag = 0; 15610296Ssam 157*26048Sminshall user = pass = acct = 0; 158*26048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 159*26048Sminshall disconnect(); 160*26048Sminshall code = -1; 161*26048Sminshall return(0); 162*26048Sminshall } 163*26048Sminshall if (user == NULL) { 164*26048Sminshall char *myname = getlogin(); 165*26048Sminshall 166*26048Sminshall if (myname == NULL) { 167*26048Sminshall struct passwd *pp = getpwuid(getuid()); 168*26048Sminshall 169*26048Sminshall if (pp != NULL) { 170*26048Sminshall myname = pp->pw_name; 171*26048Sminshall } 172*26048Sminshall } 173*26048Sminshall printf("Name (%s:%s): ", host, myname); 174*26048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 175*26048Sminshall tmp[strlen(tmp) - 1] = '\0'; 176*26048Sminshall if (*tmp == '\0') { 177*26048Sminshall user = myname; 178*26048Sminshall } 179*26048Sminshall else { 180*26048Sminshall user = tmp; 181*26048Sminshall } 182*26048Sminshall } 18310296Ssam n = command("USER %s", user); 184*26048Sminshall if (n == CONTINUE) { 185*26048Sminshall if (pass == NULL) { 186*26048Sminshall pass = getpass("Password:"); 187*26048Sminshall } 18810296Ssam n = command("PASS %s", pass); 189*26048Sminshall } 19010296Ssam if (n == CONTINUE) { 191*26048Sminshall aflag++; 192*26048Sminshall acct = getpass("Account:"); 19310296Ssam n = command("ACCT %s", acct); 19410296Ssam } 19510296Ssam if (n != COMPLETE) { 19610296Ssam fprintf(stderr, "Login failed.\n"); 19710296Ssam return (0); 19810296Ssam } 199*26048Sminshall if (!aflag && acct != NULL) { 200*26048Sminshall (void) command("ACCT %s", acct); 201*26048Sminshall } 202*26048Sminshall if (proxy) { 203*26048Sminshall return(1); 204*26048Sminshall } 205*26048Sminshall for (n = 0; n < macnum; ++n) { 206*26048Sminshall if (!strcmp("init", macros[n].mac_name)) { 207*26048Sminshall strcpy(line, "$init"); 208*26048Sminshall makeargv(); 209*26048Sminshall domacro(margc, margv); 210*26048Sminshall break; 211*26048Sminshall } 212*26048Sminshall } 21310296Ssam return (1); 21410296Ssam } 21510296Ssam 216*26048Sminshall cmdabort() 217*26048Sminshall { 218*26048Sminshall extern jmp_buf ptabort; 219*26048Sminshall 220*26048Sminshall printf("\n"); 221*26048Sminshall (void) fflush(stdout); 222*26048Sminshall abrtflag++; 223*26048Sminshall if (ptflag) { 224*26048Sminshall longjmp(ptabort,1); 225*26048Sminshall } 226*26048Sminshall } 227*26048Sminshall 22810296Ssam /*VARARGS 1*/ 22910296Ssam command(fmt, args) 23010296Ssam char *fmt; 23110296Ssam { 232*26048Sminshall int r, (*oldintr)(), cmdabort(); 23310296Ssam 234*26048Sminshall abrtflag = 0; 23510296Ssam if (debug) { 23610296Ssam printf("---> "); 23710296Ssam _doprnt(fmt, &args, stdout); 23810296Ssam printf("\n"); 23910296Ssam (void) fflush(stdout); 24010296Ssam } 24111219Ssam if (cout == NULL) { 24211219Ssam perror ("No control connection for command"); 243*26048Sminshall code = -1; 24411219Ssam return (0); 24511219Ssam } 246*26048Sminshall oldintr = signal(SIGINT,cmdabort); 24710296Ssam _doprnt(fmt, &args, cout); 24810296Ssam fprintf(cout, "\r\n"); 24910296Ssam (void) fflush(cout); 250*26048Sminshall cpend = 1; 251*26048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 252*26048Sminshall if (abrtflag && oldintr != SIG_IGN) { 253*26048Sminshall (*oldintr)(); 254*26048Sminshall } 255*26048Sminshall (void) signal(SIGINT, oldintr); 256*26048Sminshall return(r); 25710296Ssam } 25810296Ssam 25910296Ssam #include <ctype.h> 26010296Ssam 26110296Ssam getreply(expecteof) 26210296Ssam int expecteof; 26310296Ssam { 26411219Ssam register int c, n; 265*26048Sminshall register int dig; 266*26048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 267*26048Sminshall int pflag = 0; 268*26048Sminshall char *pt = pasv; 26910296Ssam 270*26048Sminshall oldintr = signal(SIGINT,cmdabort); 27110296Ssam for (;;) { 27210296Ssam dig = n = code = 0; 27310296Ssam while ((c = getc(cin)) != '\n') { 27410296Ssam dig++; 27510296Ssam if (c == EOF) { 276*26048Sminshall if (expecteof) { 277*26048Sminshall (void) signal(SIGINT,oldintr); 278*26048Sminshall code = 221; 27910296Ssam return (0); 280*26048Sminshall } 28110296Ssam lostpeer(); 282*26048Sminshall if (verbose) { 283*26048Sminshall printf("421 Service not available, remote server has closed connection\n"); 284*26048Sminshall (void) fflush(stdout); 285*26048Sminshall code = 421; 286*26048Sminshall return(4); 287*26048Sminshall } 28810296Ssam } 289*26048Sminshall if (c != '\r' && (verbose > 0 || 290*26048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 291*26048Sminshall if ( proxflag && 292*26048Sminshall (dig == 1 || dig == 5 && verbose == 0)) { 293*26048Sminshall printf("%s:",hostname); 294*26048Sminshall } 29510296Ssam putchar(c); 296*26048Sminshall } 29710296Ssam if (dig < 4 && isdigit(c)) 29810296Ssam code = code * 10 + (c - '0'); 299*26048Sminshall if (!pflag && code == 227) { 300*26048Sminshall pflag = 1; 301*26048Sminshall } 302*26048Sminshall if (dig > 4 && pflag == 1 && isdigit(c)) { 303*26048Sminshall pflag = 2; 304*26048Sminshall } 305*26048Sminshall if (pflag == 2) { 306*26048Sminshall if (c != '\r' && c != ')') { 307*26048Sminshall *pt++ = c; 308*26048Sminshall } 309*26048Sminshall else { 310*26048Sminshall *pt = '\0'; 311*26048Sminshall pflag = 3; 312*26048Sminshall } 313*26048Sminshall } 314*26048Sminshall if (dig == 4 && c == '-') { 315*26048Sminshall if (continuation) { 316*26048Sminshall code = 0; 317*26048Sminshall } 31810296Ssam continuation++; 319*26048Sminshall } 32010296Ssam if (n == 0) 32110296Ssam n = c; 32210296Ssam } 323*26048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 32410296Ssam putchar(c); 32511346Ssam (void) fflush (stdout); 32611346Ssam } 32710296Ssam if (continuation && code != originalcode) { 32810296Ssam if (originalcode == 0) 32910296Ssam originalcode = code; 33010296Ssam continue; 33110296Ssam } 332*26048Sminshall if (n != '1') { 333*26048Sminshall cpend = 0; 334*26048Sminshall } 335*26048Sminshall (void) signal(SIGINT,oldintr); 336*26048Sminshall if (code == 421 || originalcode == 421) { 337*26048Sminshall lostpeer(); 338*26048Sminshall } 339*26048Sminshall if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) { 340*26048Sminshall (*oldintr)(); 341*26048Sminshall } 34225907Smckusick return (n - '0'); 34310296Ssam } 34410296Ssam } 34510296Ssam 346*26048Sminshall empty(mask, sec) 347*26048Sminshall long mask; 348*26048Sminshall int sec; 349*26048Sminshall { 350*26048Sminshall struct timeval t; 351*26048Sminshall 352*26048Sminshall t.tv_sec = (long) sec; 353*26048Sminshall t.tv_usec = 0; 354*26048Sminshall if (select(20, &mask, 0, 0, &t) < 0) { 355*26048Sminshall return(-1); 356*26048Sminshall } 357*26048Sminshall return (mask); 358*26048Sminshall } 359*26048Sminshall 36010296Ssam jmp_buf sendabort; 36110296Ssam 36210296Ssam abortsend() 36310296Ssam { 36410296Ssam 365*26048Sminshall mflag = 0; 366*26048Sminshall abrtflag = 0; 367*26048Sminshall printf("\nsend aborted\n"); 368*26048Sminshall (void) fflush(stdout); 36910296Ssam longjmp(sendabort, 1); 37010296Ssam } 37110296Ssam 37210296Ssam sendrequest(cmd, local, remote) 37310296Ssam char *cmd, *local, *remote; 37410296Ssam { 375*26048Sminshall FILE *fin, *dout = 0, *popen(); 376*26048Sminshall int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 377*26048Sminshall int abortsend(); 37811219Ssam char buf[BUFSIZ]; 37911651Ssam long bytes = 0, hashbytes = sizeof (buf); 38011346Ssam register int c, d; 38110296Ssam struct stat st; 38210296Ssam struct timeval start, stop; 38310296Ssam 384*26048Sminshall if (proxy) { 385*26048Sminshall proxtrans(cmd, local, remote); 386*26048Sminshall return; 387*26048Sminshall } 38810296Ssam closefunc = NULL; 389*26048Sminshall oldintr = NULL; 390*26048Sminshall oldintp = NULL; 391*26048Sminshall if (setjmp(sendabort)) { 392*26048Sminshall while (cpend) { 393*26048Sminshall (void) getreply(0); 394*26048Sminshall } 395*26048Sminshall if (data >= 0) { 396*26048Sminshall (void) close(data); 397*26048Sminshall data = -1; 398*26048Sminshall } 399*26048Sminshall if (oldintr) { 400*26048Sminshall (void) signal(SIGINT,oldintr); 401*26048Sminshall } 402*26048Sminshall if (oldintp) { 403*26048Sminshall (void) signal(SIGPIPE,oldintp); 404*26048Sminshall } 405*26048Sminshall code = -1; 406*26048Sminshall return; 407*26048Sminshall } 40810296Ssam oldintr = signal(SIGINT, abortsend); 40910296Ssam if (strcmp(local, "-") == 0) 41010296Ssam fin = stdin; 41110296Ssam else if (*local == '|') { 412*26048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 413*26048Sminshall fin = popen(local + 1, "r"); 41410296Ssam if (fin == NULL) { 415*26048Sminshall perror(local + 1); 416*26048Sminshall (void) signal(SIGINT, oldintr); 417*26048Sminshall (void) signal(SIGPIPE, oldintp); 418*26048Sminshall code = -1; 419*26048Sminshall return; 42010296Ssam } 42110296Ssam closefunc = pclose; 42210296Ssam } else { 42310296Ssam fin = fopen(local, "r"); 42410296Ssam if (fin == NULL) { 42510296Ssam perror(local); 426*26048Sminshall (void) signal(SIGINT, oldintr); 427*26048Sminshall code = -1; 428*26048Sminshall return; 42910296Ssam } 43010296Ssam closefunc = fclose; 43110296Ssam if (fstat(fileno(fin), &st) < 0 || 43210296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 43317949Sralph fprintf(stderr, "%s: not a plain file.\n", local); 434*26048Sminshall (void) signal(SIGINT, oldintr); 435*26048Sminshall code = -1; 436*26048Sminshall return; 43710296Ssam } 43810296Ssam } 439*26048Sminshall if (initconn()) { 440*26048Sminshall (void) signal(SIGINT, oldintr); 441*26048Sminshall if (oldintp) { 442*26048Sminshall (void) signal(SIGPIPE, oldintp); 443*26048Sminshall } 444*26048Sminshall code = -1; 445*26048Sminshall return; 446*26048Sminshall } 447*26048Sminshall if (setjmp(sendabort)) { 448*26048Sminshall goto abort; 449*26048Sminshall } 45010296Ssam if (remote) { 451*26048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 452*26048Sminshall (void) signal(SIGINT, oldintr); 453*26048Sminshall if (oldintp) { 454*26048Sminshall (void) signal(SIGPIPE, oldintp); 455*26048Sminshall } 456*26048Sminshall return; 457*26048Sminshall } 45810296Ssam } else 459*26048Sminshall if (command("%s", cmd) != PRELIM) { 460*26048Sminshall (void) signal(SIGINT, oldintr); 461*26048Sminshall if (oldintp) { 462*26048Sminshall (void) signal(SIGPIPE, oldintp); 463*26048Sminshall } 464*26048Sminshall return; 465*26048Sminshall } 46610296Ssam dout = dataconn("w"); 467*26048Sminshall if (dout == NULL) { 468*26048Sminshall goto abort; 469*26048Sminshall } 47010296Ssam gettimeofday(&start, (struct timezone *)0); 47111219Ssam switch (type) { 47211219Ssam 47311219Ssam case TYPE_I: 47411219Ssam case TYPE_L: 47511346Ssam errno = d = 0; 47611219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 47711346Ssam if ((d = write(fileno (dout), buf, c)) < 0) 47811219Ssam break; 47911219Ssam bytes += c; 48011651Ssam if (hash) { 48111651Ssam putchar('#'); 48211651Ssam fflush(stdout); 48311651Ssam } 48411219Ssam } 48513213Ssam if (hash && bytes > 0) { 48611651Ssam putchar('\n'); 48711651Ssam fflush(stdout); 48811651Ssam } 48911219Ssam if (c < 0) 49011219Ssam perror(local); 49111346Ssam if (d < 0) 49211219Ssam perror("netout"); 49311219Ssam break; 49411219Ssam 49511219Ssam case TYPE_A: 49611219Ssam while ((c = getc(fin)) != EOF) { 49711219Ssam if (c == '\n') { 49811651Ssam while (hash && (bytes >= hashbytes)) { 49911651Ssam putchar('#'); 50011651Ssam fflush(stdout); 50111651Ssam hashbytes += sizeof (buf); 50211651Ssam } 50311219Ssam if (ferror(dout)) 50411219Ssam break; 50511219Ssam putc('\r', dout); 50611219Ssam bytes++; 50711219Ssam } 50811219Ssam putc(c, dout); 50911219Ssam bytes++; 510*26048Sminshall /* if (c == '\r') { */ 511*26048Sminshall /* putc('\0', dout); /* this violates rfc */ 512*26048Sminshall /* bytes++; */ 513*26048Sminshall /* } */ 51411219Ssam } 51511651Ssam if (hash) { 51613213Ssam if (bytes < hashbytes) 51713213Ssam putchar('#'); 51811651Ssam putchar('\n'); 51911651Ssam fflush(stdout); 52011651Ssam } 52111219Ssam if (ferror(fin)) 52211219Ssam perror(local); 52311346Ssam if (ferror(dout)) 52411219Ssam perror("netout"); 52511219Ssam break; 52610296Ssam } 52710296Ssam gettimeofday(&stop, (struct timezone *)0); 52810296Ssam if (closefunc != NULL) 529*26048Sminshall (*closefunc)(fin); 53010296Ssam (void) fclose(dout); 531*26048Sminshall (void) getreply(0); 532*26048Sminshall (void) signal(SIGINT, oldintr); 53310296Ssam if (bytes > 0 && verbose) 534*26048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 53510296Ssam return; 536*26048Sminshall abort: 537*26048Sminshall gettimeofday(&stop, (struct timezone *)0); 538*26048Sminshall (void) signal(SIGINT, oldintr); 539*26048Sminshall if (oldintp) { 540*26048Sminshall (void) signal(SIGPIPE, oldintp); 541*26048Sminshall } 542*26048Sminshall if (!cpend) { 543*26048Sminshall code = -1; 544*26048Sminshall return; 545*26048Sminshall } 546*26048Sminshall if (data >= 0) { 547*26048Sminshall (void) close(data); 548*26048Sminshall data = -1; 549*26048Sminshall } 550*26048Sminshall if (dout) { 551*26048Sminshall (void) fclose(dout); 552*26048Sminshall } 553*26048Sminshall (void) getreply(0); 554*26048Sminshall code = -1; 55510296Ssam if (closefunc != NULL && fin != NULL) 556*26048Sminshall (*closefunc)(fin); 557*26048Sminshall if (bytes > 0 && verbose) 558*26048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 55910296Ssam } 56010296Ssam 56110296Ssam jmp_buf recvabort; 56210296Ssam 56310296Ssam abortrecv() 56410296Ssam { 56510296Ssam 566*26048Sminshall mflag = 0; 567*26048Sminshall abrtflag = 0; 568*26048Sminshall printf("\n"); 569*26048Sminshall (void) fflush(stdout); 57010296Ssam longjmp(recvabort, 1); 57110296Ssam } 57210296Ssam 57311651Ssam recvrequest(cmd, local, remote, mode) 57411651Ssam char *cmd, *local, *remote, *mode; 57510296Ssam { 576*26048Sminshall FILE *fout, *din = 0, *popen(); 577*26048Sminshall int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 578*26048Sminshall int abortrecv(), oldverbose, oldtype = 0, tcrflag; 579*26048Sminshall char buf[BUFSIZ], *gunique(); 580*26048Sminshall long bytes = 0, hashbytes = sizeof (buf), mask; 58111346Ssam register int c, d; 58210296Ssam struct timeval start, stop; 58310296Ssam 584*26048Sminshall if (proxy && strcmp(cmd,"RETR") == 0) { 585*26048Sminshall proxtrans(cmd, local, remote); 586*26048Sminshall return; 587*26048Sminshall } 58810296Ssam closefunc = NULL; 589*26048Sminshall oldintr = NULL; 590*26048Sminshall oldintp = NULL; 591*26048Sminshall tcrflag = !crflag && !strcmp(cmd, "RETR"); 592*26048Sminshall if (setjmp(recvabort)) { 593*26048Sminshall while (cpend) { 594*26048Sminshall (void) getreply(0); 595*26048Sminshall } 596*26048Sminshall if (data >= 0) { 597*26048Sminshall (void) close(data); 598*26048Sminshall data = -1; 599*26048Sminshall } 600*26048Sminshall if (oldintr) { 601*26048Sminshall (void) signal(SIGINT, oldintr); 602*26048Sminshall } 603*26048Sminshall code = -1; 604*26048Sminshall return; 605*26048Sminshall } 60610296Ssam oldintr = signal(SIGINT, abortrecv); 607*26048Sminshall if (strcmp(local, "-") && *local != '|') { 60810296Ssam if (access(local, 2) < 0) { 609*26048Sminshall char *dir = rindex(local, '/'); 61010296Ssam 611*26048Sminshall if (errno != ENOENT && errno != EACCES) { 61210296Ssam perror(local); 613*26048Sminshall (void) signal(SIGINT, oldintr); 614*26048Sminshall code = -1; 615*26048Sminshall return; 61610296Ssam } 617*26048Sminshall if (dir != NULL) 618*26048Sminshall *dir = 0; 619*26048Sminshall d = access(dir ? local : ".", 2); 620*26048Sminshall if (dir != NULL) 621*26048Sminshall *dir = '/'; 622*26048Sminshall if (d < 0) { 623*26048Sminshall perror(local); 624*26048Sminshall (void) signal(SIGINT, oldintr); 625*26048Sminshall code = -1; 626*26048Sminshall return; 627*26048Sminshall } 628*26048Sminshall if (!runique && errno == EACCES && 629*26048Sminshall chmod(local,0600) < 0) { 630*26048Sminshall perror(local); 631*26048Sminshall (void) signal(SIGINT, oldintr); 632*26048Sminshall code = -1; 633*26048Sminshall return; 634*26048Sminshall } 635*26048Sminshall if (runique && errno == EACCES && 636*26048Sminshall (local = gunique(local)) == NULL) { 637*26048Sminshall (void) signal(SIGINT, oldintr); 638*26048Sminshall code = -1; 639*26048Sminshall return; 640*26048Sminshall } 64110296Ssam } 642*26048Sminshall else if (runique && (local = gunique(local)) == NULL) { 643*26048Sminshall (void) signal(SIGINT, oldintr); 644*26048Sminshall code = -1; 645*26048Sminshall return; 646*26048Sminshall } 647*26048Sminshall } 648*26048Sminshall if (initconn()) { 649*26048Sminshall (void) signal(SIGINT, oldintr); 650*26048Sminshall code = -1; 651*26048Sminshall return; 652*26048Sminshall } 653*26048Sminshall if (setjmp(recvabort)) { 654*26048Sminshall goto abort; 655*26048Sminshall } 656*26048Sminshall if (strcmp(cmd, "RETR") && type != TYPE_A) { 657*26048Sminshall oldtype = type; 658*26048Sminshall oldverbose = verbose; 659*26048Sminshall if (!debug) { 660*26048Sminshall verbose = 0; 661*26048Sminshall } 662*26048Sminshall setascii(); 663*26048Sminshall verbose = oldverbose; 664*26048Sminshall } 66510296Ssam if (remote) { 666*26048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 667*26048Sminshall (void) signal(SIGINT, oldintr); 668*26048Sminshall if (oldtype) { 669*26048Sminshall if (!debug) { 670*26048Sminshall verbose = 0; 671*26048Sminshall } 672*26048Sminshall switch (oldtype) { 673*26048Sminshall case TYPE_I: 674*26048Sminshall setbinary(); 675*26048Sminshall break; 676*26048Sminshall case TYPE_E: 677*26048Sminshall setebcdic(); 678*26048Sminshall break; 679*26048Sminshall case TYPE_L: 680*26048Sminshall settenex(); 681*26048Sminshall break; 682*26048Sminshall } 683*26048Sminshall verbose = oldverbose; 684*26048Sminshall } 685*26048Sminshall return; 686*26048Sminshall } 687*26048Sminshall } else { 688*26048Sminshall if (command("%s", cmd) != PRELIM) { 689*26048Sminshall (void) signal(SIGINT, oldintr); 690*26048Sminshall if (oldtype) { 691*26048Sminshall if (!debug) { 692*26048Sminshall verbose = 0; 693*26048Sminshall } 694*26048Sminshall switch (oldtype) { 695*26048Sminshall case TYPE_I: 696*26048Sminshall setbinary(); 697*26048Sminshall break; 698*26048Sminshall case TYPE_E: 699*26048Sminshall setebcdic(); 700*26048Sminshall break; 701*26048Sminshall case TYPE_L: 702*26048Sminshall settenex(); 703*26048Sminshall break; 704*26048Sminshall } 705*26048Sminshall verbose = oldverbose; 706*26048Sminshall } 707*26048Sminshall return; 708*26048Sminshall } 709*26048Sminshall } 710*26048Sminshall din = dataconn("r"); 711*26048Sminshall if (din == NULL) 712*26048Sminshall goto abort; 713*26048Sminshall if (strcmp(local, "-") == 0) { 71410296Ssam fout = stdout; 715*26048Sminshall } 71610296Ssam else if (*local == '|') { 717*26048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 718*26048Sminshall fout = popen(local + 1, "w"); 719*26048Sminshall if (fout == NULL) { 720*26048Sminshall perror(local+1); 721*26048Sminshall goto abort; 722*26048Sminshall } 72310296Ssam closefunc = pclose; 724*26048Sminshall } 725*26048Sminshall else { 72611651Ssam fout = fopen(local, mode); 727*26048Sminshall if (fout == NULL) { 728*26048Sminshall perror(local); 729*26048Sminshall goto abort; 730*26048Sminshall } 73110296Ssam closefunc = fclose; 73210296Ssam } 73310296Ssam gettimeofday(&start, (struct timezone *)0); 73411219Ssam switch (type) { 73511219Ssam 73611219Ssam case TYPE_I: 73711219Ssam case TYPE_L: 73811346Ssam errno = d = 0; 73911219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 74011346Ssam if ((d = write(fileno(fout), buf, c)) < 0) 74111219Ssam break; 74211219Ssam bytes += c; 74311651Ssam if (hash) { 74411651Ssam putchar('#'); 74511651Ssam fflush(stdout); 74611651Ssam } 74711219Ssam } 74813213Ssam if (hash && bytes > 0) { 74911651Ssam putchar('\n'); 75011651Ssam fflush(stdout); 75111651Ssam } 75211219Ssam if (c < 0) 75311219Ssam perror("netin"); 75411346Ssam if (d < 0) 75510296Ssam perror(local); 75611219Ssam break; 75711219Ssam 75811219Ssam case TYPE_A: 75911219Ssam while ((c = getc(din)) != EOF) { 76011219Ssam if (c == '\r') { 76111651Ssam while (hash && (bytes >= hashbytes)) { 76211651Ssam putchar('#'); 76311651Ssam fflush(stdout); 76411651Ssam hashbytes += sizeof (buf); 76511651Ssam } 76610296Ssam bytes++; 767*26048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 76811219Ssam if (ferror (fout)) 76911219Ssam break; 77011219Ssam putc ('\r', fout); 77111219Ssam } 772*26048Sminshall /*if (c == '\0') { 77311219Ssam bytes++; 77411219Ssam continue; 775*26048Sminshall }*/ 77611219Ssam } 77711219Ssam putc (c, fout); 77811219Ssam bytes++; 77910296Ssam } 78011651Ssam if (hash) { 78113213Ssam if (bytes < hashbytes) 78213213Ssam putchar('#'); 78311651Ssam putchar('\n'); 78411651Ssam fflush(stdout); 78511651Ssam } 78611219Ssam if (ferror (din)) 78711219Ssam perror ("netin"); 78811219Ssam if (ferror (fout)) 78911219Ssam perror (local); 79011219Ssam break; 79110296Ssam } 792*26048Sminshall if (closefunc != NULL) { 793*26048Sminshall (*closefunc)(fout); 794*26048Sminshall } 795*26048Sminshall signal(SIGINT, oldintr); 796*26048Sminshall if (oldintp) { 797*26048Sminshall (void) signal(SIGPIPE, oldintp); 798*26048Sminshall } 79910296Ssam gettimeofday(&stop, (struct timezone *)0); 80010296Ssam (void) fclose(din); 801*26048Sminshall (void) getreply(0); 802*26048Sminshall if (bytes > 0 && verbose) 803*26048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 804*26048Sminshall if (oldtype) { 805*26048Sminshall if (!debug) { 806*26048Sminshall verbose = 0; 807*26048Sminshall } 808*26048Sminshall switch (oldtype) { 809*26048Sminshall case TYPE_I: 810*26048Sminshall setbinary(); 811*26048Sminshall break; 812*26048Sminshall case TYPE_E: 813*26048Sminshall setebcdic(); 814*26048Sminshall break; 815*26048Sminshall case TYPE_L: 816*26048Sminshall settenex(); 817*26048Sminshall break; 818*26048Sminshall } 819*26048Sminshall verbose = oldverbose; 820*26048Sminshall } 821*26048Sminshall return; 822*26048Sminshall abort: 823*26048Sminshall 824*26048Sminshall /* if server command parser understands TELNET commands, abort using */ 825*26048Sminshall /* recommended IP,SYNC sequence */ 826*26048Sminshall 827*26048Sminshall gettimeofday(&stop, (struct timezone *)0); 828*26048Sminshall if (oldintp) { 829*26048Sminshall (void) signal(SIGPIPE, oldintr); 830*26048Sminshall } 831*26048Sminshall (void) signal(SIGINT,SIG_IGN); 832*26048Sminshall if (oldtype) { 833*26048Sminshall if (!debug) { 834*26048Sminshall verbose = 0; 835*26048Sminshall } 836*26048Sminshall switch (oldtype) { 837*26048Sminshall case TYPE_I: 838*26048Sminshall setbinary(); 839*26048Sminshall break; 840*26048Sminshall case TYPE_E: 841*26048Sminshall setebcdic(); 842*26048Sminshall break; 843*26048Sminshall case TYPE_L: 844*26048Sminshall settenex(); 845*26048Sminshall break; 846*26048Sminshall } 847*26048Sminshall verbose = oldverbose; 848*26048Sminshall } 849*26048Sminshall if (!cpend) { 850*26048Sminshall code = -1; 851*26048Sminshall (void) signal(SIGINT,oldintr); 852*26048Sminshall return; 853*26048Sminshall } 854*26048Sminshall if (telflag) { 855*26048Sminshall char msg[2]; 856*26048Sminshall 857*26048Sminshall fprintf(cout,"%c%c",IAC,IP); 858*26048Sminshall (void) fflush(cout); 859*26048Sminshall *msg = IAC; 860*26048Sminshall *(msg+1) = DM; 861*26048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 862*26048Sminshall perror("abort"); 863*26048Sminshall } 864*26048Sminshall } 865*26048Sminshall fprintf(cout,"ABOR\r\n"); 866*26048Sminshall (void) fflush(cout); 867*26048Sminshall mask = (1 << fileno(cin)) | (din ? (1 << fileno(din)) : 0); 868*26048Sminshall if ((mask = empty(mask,10)) < 0) { 869*26048Sminshall perror("abort"); 870*26048Sminshall code = -1; 871*26048Sminshall lostpeer(); 872*26048Sminshall } 873*26048Sminshall if (din && mask & (1 << fileno(din))) { 874*26048Sminshall while ((c = read(fileno(din), buf, sizeof (buf))) > 0); 875*26048Sminshall } 876*26048Sminshall if ((c = getreply(0)) == ERROR) { /* needed for nic style abort */ 877*26048Sminshall if (data >= 0) { 878*26048Sminshall close(data); 879*26048Sminshall data = -1; 880*26048Sminshall } 88125907Smckusick (void) getreply(0); 88225907Smckusick } 883*26048Sminshall (void) getreply(0); 884*26048Sminshall code = -1; 885*26048Sminshall if (data >= 0) { 886*26048Sminshall (void) close(data); 887*26048Sminshall data = -1; 888*26048Sminshall } 889*26048Sminshall if (closefunc != NULL && fout != NULL) { 890*26048Sminshall (*closefunc)(fout); 891*26048Sminshall } 892*26048Sminshall if (din) { 893*26048Sminshall (void) fclose(din); 894*26048Sminshall } 89510296Ssam if (bytes > 0 && verbose) 896*26048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 897*26048Sminshall (void) signal(SIGINT,oldintr); 89810296Ssam } 89910296Ssam 90010296Ssam /* 90110296Ssam * Need to start a listen on the data channel 90210296Ssam * before we send the command, otherwise the 90310296Ssam * server's connect may fail. 90410296Ssam */ 90511651Ssam static int sendport = -1; 90611651Ssam 90710296Ssam initconn() 90810296Ssam { 90910296Ssam register char *p, *a; 910*26048Sminshall int result, len, tmpno = 0; 91117450Slepreau int on = 1; 91210296Ssam 91311651Ssam noport: 91410296Ssam data_addr = myctladdr; 91511651Ssam if (sendport) 91611651Ssam data_addr.sin_port = 0; /* let system pick one */ 91711651Ssam if (data != -1) 91811651Ssam (void) close (data); 91918287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 92010296Ssam if (data < 0) { 92110296Ssam perror("ftp: socket"); 922*26048Sminshall if (tmpno) { 923*26048Sminshall sendport = 1; 924*26048Sminshall } 92510296Ssam return (1); 92610296Ssam } 92712397Ssam if (!sendport) 92817450Slepreau if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { 929*26048Sminshall perror("ftp: setsockopt (resuse address)"); 93012397Ssam goto bad; 93112397Ssam } 93210296Ssam if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) { 93310296Ssam perror("ftp: bind"); 93410296Ssam goto bad; 93510296Ssam } 93610296Ssam if (options & SO_DEBUG && 93717450Slepreau setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) 93810296Ssam perror("ftp: setsockopt (ignored)"); 93911627Ssam len = sizeof (data_addr); 94011627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 94111627Ssam perror("ftp: getsockname"); 94210296Ssam goto bad; 94310296Ssam } 94410296Ssam if (listen(data, 1) < 0) { 94510296Ssam perror("ftp: listen"); 946*26048Sminshall 94710296Ssam } 94811651Ssam if (sendport) { 94911651Ssam a = (char *)&data_addr.sin_addr; 95011651Ssam p = (char *)&data_addr.sin_port; 95110296Ssam #define UC(b) (((int)b)&0xff) 95211651Ssam result = 95311651Ssam command("PORT %d,%d,%d,%d,%d,%d", 95411651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 95511651Ssam UC(p[0]), UC(p[1])); 95611651Ssam if (result == ERROR && sendport == -1) { 95711651Ssam sendport = 0; 958*26048Sminshall tmpno = 1; 95911651Ssam goto noport; 96011651Ssam } 96111651Ssam return (result != COMPLETE); 96211651Ssam } 963*26048Sminshall if (tmpno) { 964*26048Sminshall sendport = 1; 965*26048Sminshall } 96611651Ssam return (0); 96710296Ssam bad: 96810296Ssam (void) close(data), data = -1; 969*26048Sminshall if (tmpno) { 970*26048Sminshall sendport = 1; 971*26048Sminshall } 97210296Ssam return (1); 97310296Ssam } 97410296Ssam 97510296Ssam FILE * 97610296Ssam dataconn(mode) 97710296Ssam char *mode; 97810296Ssam { 97910296Ssam struct sockaddr_in from; 98010296Ssam int s, fromlen = sizeof (from); 98110296Ssam 98210296Ssam s = accept(data, &from, &fromlen, 0); 98310296Ssam if (s < 0) { 98410296Ssam perror("ftp: accept"); 98510296Ssam (void) close(data), data = -1; 98610296Ssam return (NULL); 98710296Ssam } 98810296Ssam (void) close(data); 98910296Ssam data = s; 99010296Ssam return (fdopen(data, mode)); 99110296Ssam } 99210296Ssam 993*26048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 994*26048Sminshall char *direction, *local, *remote; 99511651Ssam long bytes; 99610296Ssam struct timeval *t0, *t1; 99710296Ssam { 99810296Ssam struct timeval td; 99916437Sleres float s, bs; 100010296Ssam 100110296Ssam tvsub(&td, t1, t0); 100216437Sleres s = td.tv_sec + (td.tv_usec / 1000000.); 100310296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 100416437Sleres bs = bytes / nz(s); 1005*26048Sminshall if (local && *local != '-') { 1006*26048Sminshall printf("local: %s ", local); 1007*26048Sminshall } 1008*26048Sminshall if (remote) { 1009*26048Sminshall printf("remote: %s\n", remote); 1010*26048Sminshall } 101116437Sleres printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 101216437Sleres bytes, direction, s, bs / 1024.); 101310296Ssam } 101410296Ssam 101510296Ssam tvadd(tsum, t0) 101610296Ssam struct timeval *tsum, *t0; 101710296Ssam { 101810296Ssam 101910296Ssam tsum->tv_sec += t0->tv_sec; 102010296Ssam tsum->tv_usec += t0->tv_usec; 102110296Ssam if (tsum->tv_usec > 1000000) 102210296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 102310296Ssam } 102410296Ssam 102510296Ssam tvsub(tdiff, t1, t0) 102610296Ssam struct timeval *tdiff, *t1, *t0; 102710296Ssam { 102810296Ssam 102910296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 103010296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 103110296Ssam if (tdiff->tv_usec < 0) 103210296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 103310296Ssam } 1034*26048Sminshall 1035*26048Sminshall psabort() 1036*26048Sminshall { 1037*26048Sminshall extern int abrtflag; 1038*26048Sminshall 1039*26048Sminshall abrtflag++; 1040*26048Sminshall } 1041*26048Sminshall 1042*26048Sminshall pswitch(flag) 1043*26048Sminshall int flag; 1044*26048Sminshall { 1045*26048Sminshall extern int proxy, abrtflag; 1046*26048Sminshall int (*oldintr)(); 1047*26048Sminshall static struct comvars { 1048*26048Sminshall int connect; 1049*26048Sminshall char name[32]; 1050*26048Sminshall struct sockaddr_in mctl; 1051*26048Sminshall struct sockaddr_in hctl; 1052*26048Sminshall FILE *in; 1053*26048Sminshall FILE *out; 1054*26048Sminshall int tflag; 1055*26048Sminshall int tpe; 1056*26048Sminshall int cpnd; 1057*26048Sminshall int sunqe; 1058*26048Sminshall int runqe; 1059*26048Sminshall int mcse; 1060*26048Sminshall int ntflg; 1061*26048Sminshall char nti[17]; 1062*26048Sminshall char nto[17]; 1063*26048Sminshall int mapflg; 1064*26048Sminshall char mi[MAXPATHLEN]; 1065*26048Sminshall char mo[MAXPATHLEN]; 1066*26048Sminshall } proxstruct, tmpstruct; 1067*26048Sminshall struct comvars *ip, *op; 1068*26048Sminshall 1069*26048Sminshall abrtflag = 0; 1070*26048Sminshall oldintr = signal(SIGINT, psabort); 1071*26048Sminshall if (flag) { 1072*26048Sminshall if (proxy) { 1073*26048Sminshall return; 1074*26048Sminshall } 1075*26048Sminshall ip = &tmpstruct; 1076*26048Sminshall op = &proxstruct; 1077*26048Sminshall proxy++; 1078*26048Sminshall } 1079*26048Sminshall else { 1080*26048Sminshall if (!proxy) { 1081*26048Sminshall return; 1082*26048Sminshall } 1083*26048Sminshall ip = &proxstruct; 1084*26048Sminshall op = &tmpstruct; 1085*26048Sminshall proxy = 0; 1086*26048Sminshall } 1087*26048Sminshall ip->connect = connected; 1088*26048Sminshall connected = op->connect; 1089*26048Sminshall strncpy(ip->name, hostname, 31); 1090*26048Sminshall (ip->name)[strlen(ip->name)] = '\0'; 1091*26048Sminshall hostname = op->name; 1092*26048Sminshall ip->hctl = hisctladdr; 1093*26048Sminshall hisctladdr = op->hctl; 1094*26048Sminshall ip->mctl = myctladdr; 1095*26048Sminshall myctladdr = op->mctl; 1096*26048Sminshall ip->in = cin; 1097*26048Sminshall cin = op->in; 1098*26048Sminshall ip->out = cout; 1099*26048Sminshall cout = op->out; 1100*26048Sminshall ip->tflag = telflag; 1101*26048Sminshall telflag = op->tflag; 1102*26048Sminshall ip->tpe = type; 1103*26048Sminshall type = op->tpe; 1104*26048Sminshall if (!type) { 1105*26048Sminshall type = 1; 1106*26048Sminshall } 1107*26048Sminshall ip->cpnd = cpend; 1108*26048Sminshall cpend = op->cpnd; 1109*26048Sminshall ip->sunqe = sunique; 1110*26048Sminshall sunique = op->sunqe; 1111*26048Sminshall ip->runqe = runique; 1112*26048Sminshall runique = op->runqe; 1113*26048Sminshall ip->mcse = mcase; 1114*26048Sminshall mcase = op->mcse; 1115*26048Sminshall ip->ntflg = ntflag; 1116*26048Sminshall ntflag = op->ntflg; 1117*26048Sminshall strncpy(ip->nti, ntin, 16); 1118*26048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 1119*26048Sminshall strcpy(ntin, op->nti); 1120*26048Sminshall strncpy(ip->nto, ntout, 16); 1121*26048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 1122*26048Sminshall strcpy(ntout, op->nto); 1123*26048Sminshall ip->mapflg = mapflag; 1124*26048Sminshall mapflag = op->mapflg; 1125*26048Sminshall strncpy(ip->mi, mapin, MAXPATHLEN - 1); 1126*26048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 1127*26048Sminshall strcpy(mapin, op->mi); 1128*26048Sminshall strncpy(ip->mo, mapout, MAXPATHLEN - 1); 1129*26048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 1130*26048Sminshall strcpy(mapout, op->mo); 1131*26048Sminshall (void) signal(SIGINT, oldintr); 1132*26048Sminshall if (abrtflag) { 1133*26048Sminshall abrtflag = 0; 1134*26048Sminshall (*oldintr)(); 1135*26048Sminshall } 1136*26048Sminshall } 1137*26048Sminshall 1138*26048Sminshall jmp_buf ptabort; 1139*26048Sminshall int ptabflg; 1140*26048Sminshall 1141*26048Sminshall abortpt() 1142*26048Sminshall { 1143*26048Sminshall printf("\n"); 1144*26048Sminshall fflush(stdout); 1145*26048Sminshall ptabflg++; 1146*26048Sminshall mflag = 0; 1147*26048Sminshall abrtflag = 0; 1148*26048Sminshall longjmp(ptabort, 1); 1149*26048Sminshall } 1150*26048Sminshall 1151*26048Sminshall proxtrans(cmd, local, remote) 1152*26048Sminshall char *cmd, *local, *remote; 1153*26048Sminshall { 1154*26048Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0; 1155*26048Sminshall extern jmp_buf ptabort; 1156*26048Sminshall char *cmd2; 1157*26048Sminshall long mask; 1158*26048Sminshall 1159*26048Sminshall if (strcmp(cmd, "RETR")) { 1160*26048Sminshall cmd2 = "RETR"; 1161*26048Sminshall } 1162*26048Sminshall else { 1163*26048Sminshall cmd2 = runique ? "STOU" : "STOR"; 1164*26048Sminshall } 1165*26048Sminshall if (command("PASV") != COMPLETE) { 1166*26048Sminshall printf("proxy server does not support third part transfers.\n"); 1167*26048Sminshall return; 1168*26048Sminshall } 1169*26048Sminshall tmptype = type; 1170*26048Sminshall pswitch(0); 1171*26048Sminshall if (!connected) { 1172*26048Sminshall printf("No primary connection\n"); 1173*26048Sminshall pswitch(1); 1174*26048Sminshall code = -1; 1175*26048Sminshall return; 1176*26048Sminshall } 1177*26048Sminshall if (type != tmptype) { 1178*26048Sminshall oldtype = type; 1179*26048Sminshall switch (tmptype) { 1180*26048Sminshall case TYPE_A: 1181*26048Sminshall setascii(); 1182*26048Sminshall break; 1183*26048Sminshall case TYPE_I: 1184*26048Sminshall setbinary(); 1185*26048Sminshall break; 1186*26048Sminshall case TYPE_E: 1187*26048Sminshall setebcdic(); 1188*26048Sminshall break; 1189*26048Sminshall case TYPE_L: 1190*26048Sminshall settenex(); 1191*26048Sminshall break; 1192*26048Sminshall } 1193*26048Sminshall } 1194*26048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 1195*26048Sminshall switch (oldtype) { 1196*26048Sminshall case 0: 1197*26048Sminshall break; 1198*26048Sminshall case TYPE_A: 1199*26048Sminshall setascii(); 1200*26048Sminshall break; 1201*26048Sminshall case TYPE_I: 1202*26048Sminshall setbinary(); 1203*26048Sminshall break; 1204*26048Sminshall case TYPE_E: 1205*26048Sminshall setebcdic(); 1206*26048Sminshall break; 1207*26048Sminshall case TYPE_L: 1208*26048Sminshall settenex(); 1209*26048Sminshall break; 1210*26048Sminshall } 1211*26048Sminshall pswitch(1); 1212*26048Sminshall return; 1213*26048Sminshall } 1214*26048Sminshall if (setjmp(ptabort)) { 1215*26048Sminshall goto abort; 1216*26048Sminshall } 1217*26048Sminshall oldintr = signal(SIGINT, abortpt); 1218*26048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 1219*26048Sminshall (void) signal(SIGINT, oldintr); 1220*26048Sminshall switch (oldtype) { 1221*26048Sminshall case 0: 1222*26048Sminshall break; 1223*26048Sminshall case TYPE_A: 1224*26048Sminshall setascii(); 1225*26048Sminshall break; 1226*26048Sminshall case TYPE_I: 1227*26048Sminshall setbinary(); 1228*26048Sminshall break; 1229*26048Sminshall case TYPE_E: 1230*26048Sminshall setebcdic(); 1231*26048Sminshall break; 1232*26048Sminshall case TYPE_L: 1233*26048Sminshall settenex(); 1234*26048Sminshall break; 1235*26048Sminshall } 1236*26048Sminshall pswitch(1); 1237*26048Sminshall return; 1238*26048Sminshall } 1239*26048Sminshall sleep(2); 1240*26048Sminshall pswitch(1); 1241*26048Sminshall secndflag++; 1242*26048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 1243*26048Sminshall goto abort; 1244*26048Sminshall } 1245*26048Sminshall ptflag++; 1246*26048Sminshall (void) getreply(0); 1247*26048Sminshall pswitch(0); 1248*26048Sminshall (void) getreply(0); 1249*26048Sminshall (void) signal(SIGINT, oldintr); 1250*26048Sminshall switch (oldtype) { 1251*26048Sminshall case 0: 1252*26048Sminshall break; 1253*26048Sminshall case TYPE_A: 1254*26048Sminshall setascii(); 1255*26048Sminshall break; 1256*26048Sminshall case TYPE_I: 1257*26048Sminshall setbinary(); 1258*26048Sminshall break; 1259*26048Sminshall case TYPE_E: 1260*26048Sminshall setebcdic(); 1261*26048Sminshall break; 1262*26048Sminshall case TYPE_L: 1263*26048Sminshall settenex(); 1264*26048Sminshall break; 1265*26048Sminshall } 1266*26048Sminshall pswitch(1); 1267*26048Sminshall ptflag = 0; 1268*26048Sminshall printf("local: %s remote: %s\n", local, remote); 1269*26048Sminshall return; 1270*26048Sminshall abort: 1271*26048Sminshall (void) signal(SIGINT, SIG_IGN); 1272*26048Sminshall ptflag = 0; 1273*26048Sminshall if (strcmp(cmd, "RETR") && !proxy) { 1274*26048Sminshall pswitch(1); 1275*26048Sminshall } 1276*26048Sminshall else if (!strcmp(cmd, "RETR") && proxy) { 1277*26048Sminshall pswitch(0); 1278*26048Sminshall } 1279*26048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1280*26048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 1281*26048Sminshall pswitch(0); 1282*26048Sminshall switch (oldtype) { 1283*26048Sminshall case 0: 1284*26048Sminshall break; 1285*26048Sminshall case TYPE_A: 1286*26048Sminshall setascii(); 1287*26048Sminshall break; 1288*26048Sminshall case TYPE_I: 1289*26048Sminshall setbinary(); 1290*26048Sminshall break; 1291*26048Sminshall case TYPE_E: 1292*26048Sminshall setebcdic(); 1293*26048Sminshall break; 1294*26048Sminshall case TYPE_L: 1295*26048Sminshall settenex(); 1296*26048Sminshall break; 1297*26048Sminshall } 1298*26048Sminshall if (cpend && telflag) { 1299*26048Sminshall char msg[2]; 1300*26048Sminshall 1301*26048Sminshall fprintf(cout,"%c%c",IAC,IP); 1302*26048Sminshall (void) fflush(cout); 1303*26048Sminshall *msg = IAC; 1304*26048Sminshall *(msg+1) = DM; 1305*26048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 1306*26048Sminshall perror("abort"); 1307*26048Sminshall } 1308*26048Sminshall } 1309*26048Sminshall if (cpend) { 1310*26048Sminshall fprintf(cout,"ABOR\r\n"); 1311*26048Sminshall (void) fflush(cout); 1312*26048Sminshall mask = 1 << fileno(cin); 1313*26048Sminshall if ((mask = empty(mask,10)) < 0) { 1314*26048Sminshall perror("abort"); 1315*26048Sminshall if (ptabflg) { 1316*26048Sminshall code = -1; 1317*26048Sminshall } 1318*26048Sminshall lostpeer(); 1319*26048Sminshall } 1320*26048Sminshall (void) getreply(0); 1321*26048Sminshall (void) getreply(0); 1322*26048Sminshall } 1323*26048Sminshall } 1324*26048Sminshall pswitch(1); 1325*26048Sminshall if (ptabflg) { 1326*26048Sminshall code = -1; 1327*26048Sminshall } 1328*26048Sminshall (void) signal(SIGINT, oldintr); 1329*26048Sminshall return; 1330*26048Sminshall } 1331*26048Sminshall if (cpend && telflag) { 1332*26048Sminshall char msg[2]; 1333*26048Sminshall 1334*26048Sminshall fprintf(cout,"%c%c",IAC,IP); 1335*26048Sminshall (void) fflush(cout); 1336*26048Sminshall *msg = IAC; 1337*26048Sminshall *(msg+1) = DM; 1338*26048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 1339*26048Sminshall perror("abort"); 1340*26048Sminshall } 1341*26048Sminshall } 1342*26048Sminshall if (cpend) { 1343*26048Sminshall fprintf(cout,"ABOR\r\n"); 1344*26048Sminshall (void) fflush(cout); 1345*26048Sminshall mask = 1 << fileno(cin); 1346*26048Sminshall if ((mask = empty(mask,10)) < 0) { 1347*26048Sminshall perror("abort"); 1348*26048Sminshall if (ptabflg) { 1349*26048Sminshall code = -1; 1350*26048Sminshall } 1351*26048Sminshall lostpeer(); 1352*26048Sminshall } 1353*26048Sminshall (void) getreply(0); 1354*26048Sminshall (void) getreply(0); 1355*26048Sminshall } 1356*26048Sminshall pswitch(!proxy); 1357*26048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1358*26048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 1359*26048Sminshall pswitch(0); 1360*26048Sminshall switch (oldtype) { 1361*26048Sminshall case 0: 1362*26048Sminshall break; 1363*26048Sminshall case TYPE_A: 1364*26048Sminshall setascii(); 1365*26048Sminshall break; 1366*26048Sminshall case TYPE_I: 1367*26048Sminshall setbinary(); 1368*26048Sminshall break; 1369*26048Sminshall case TYPE_E: 1370*26048Sminshall setebcdic(); 1371*26048Sminshall break; 1372*26048Sminshall case TYPE_L: 1373*26048Sminshall settenex(); 1374*26048Sminshall break; 1375*26048Sminshall } 1376*26048Sminshall if (cpend && telflag) { 1377*26048Sminshall char msg[2]; 1378*26048Sminshall 1379*26048Sminshall fprintf(cout,"%c%c",IAC,IP); 1380*26048Sminshall (void) fflush(cout); 1381*26048Sminshall *msg = IAC; 1382*26048Sminshall *(msg+1) = DM; 1383*26048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 1384*26048Sminshall perror("abort"); 1385*26048Sminshall } 1386*26048Sminshall } 1387*26048Sminshall if (cpend) { 1388*26048Sminshall fprintf(cout,"ABOR\r\n"); 1389*26048Sminshall (void) fflush(cout); 1390*26048Sminshall mask = 1 << fileno(cin); 1391*26048Sminshall if ((mask = empty(mask,10)) < 0) { 1392*26048Sminshall perror("abort"); 1393*26048Sminshall if (ptabflg) { 1394*26048Sminshall code = -1; 1395*26048Sminshall } 1396*26048Sminshall lostpeer(); 1397*26048Sminshall } 1398*26048Sminshall (void) getreply(0); 1399*26048Sminshall (void) getreply(0); 1400*26048Sminshall } 1401*26048Sminshall pswitch(1); 1402*26048Sminshall if (ptabflg) { 1403*26048Sminshall code = -1; 1404*26048Sminshall } 1405*26048Sminshall (void) signal(SIGINT, oldintr); 1406*26048Sminshall return; 1407*26048Sminshall } 1408*26048Sminshall } 1409*26048Sminshall if (cpend && telflag) { 1410*26048Sminshall char msg[2]; 1411*26048Sminshall 1412*26048Sminshall fprintf(cout,"%c%c",IAC,IP); 1413*26048Sminshall (void) fflush(cout); 1414*26048Sminshall *msg = IAC; 1415*26048Sminshall *(msg+1) = DM; 1416*26048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 1417*26048Sminshall perror("abort"); 1418*26048Sminshall } 1419*26048Sminshall } 1420*26048Sminshall if (cpend) { 1421*26048Sminshall fprintf(cout,"ABOR\r\n"); 1422*26048Sminshall (void) fflush(cout); 1423*26048Sminshall mask = 1 << fileno(cin); 1424*26048Sminshall if ((mask = empty(mask,10)) < 0) { 1425*26048Sminshall perror("abort"); 1426*26048Sminshall if (ptabflg) { 1427*26048Sminshall code = -1; 1428*26048Sminshall } 1429*26048Sminshall lostpeer(); 1430*26048Sminshall } 1431*26048Sminshall (void) getreply(0); 1432*26048Sminshall (void) getreply(0); 1433*26048Sminshall } 1434*26048Sminshall pswitch(!proxy); 1435*26048Sminshall if (cpend) { 1436*26048Sminshall mask = 1 << fileno(cin); 1437*26048Sminshall if ((mask = empty(mask,10)) < 0) { 1438*26048Sminshall perror("abort"); 1439*26048Sminshall if (ptabflg) { 1440*26048Sminshall code = -1; 1441*26048Sminshall } 1442*26048Sminshall lostpeer(); 1443*26048Sminshall } 1444*26048Sminshall (void) getreply(0); 1445*26048Sminshall (void) getreply(0); 1446*26048Sminshall } 1447*26048Sminshall if (proxy) { 1448*26048Sminshall pswitch(0); 1449*26048Sminshall } 1450*26048Sminshall switch (oldtype) { 1451*26048Sminshall case 0: 1452*26048Sminshall break; 1453*26048Sminshall case TYPE_A: 1454*26048Sminshall setascii(); 1455*26048Sminshall break; 1456*26048Sminshall case TYPE_I: 1457*26048Sminshall setbinary(); 1458*26048Sminshall break; 1459*26048Sminshall case TYPE_E: 1460*26048Sminshall setebcdic(); 1461*26048Sminshall break; 1462*26048Sminshall case TYPE_L: 1463*26048Sminshall settenex(); 1464*26048Sminshall break; 1465*26048Sminshall } 1466*26048Sminshall pswitch(1); 1467*26048Sminshall if (ptabflg) { 1468*26048Sminshall code = -1; 1469*26048Sminshall } 1470*26048Sminshall (void) signal(SIGINT, oldintr); 1471*26048Sminshall } 1472*26048Sminshall 1473*26048Sminshall reset() 1474*26048Sminshall { 1475*26048Sminshall long mask; 1476*26048Sminshall 1477*26048Sminshall mask = 1 << fileno(cin); 1478*26048Sminshall while (mask > 0) { 1479*26048Sminshall if ((mask = empty(mask,0)) < 0) { 1480*26048Sminshall perror("reset"); 1481*26048Sminshall code = -1; 1482*26048Sminshall lostpeer(); 1483*26048Sminshall } 1484*26048Sminshall if (mask > 0) { 1485*26048Sminshall (void) getreply(0); 1486*26048Sminshall } 1487*26048Sminshall } 1488*26048Sminshall } 1489*26048Sminshall 1490*26048Sminshall char * 1491*26048Sminshall gunique(local) 1492*26048Sminshall char *local; 1493*26048Sminshall { 1494*26048Sminshall static char new[MAXPATHLEN]; 1495*26048Sminshall char *cp = rindex(local, '/'); 1496*26048Sminshall int d, count=0; 1497*26048Sminshall char ext = '1'; 1498*26048Sminshall 1499*26048Sminshall if (cp) { 1500*26048Sminshall *cp = '\0'; 1501*26048Sminshall } 1502*26048Sminshall d = access(cp ? local : ".", 2); 1503*26048Sminshall if (cp) { 1504*26048Sminshall *cp = '/'; 1505*26048Sminshall } 1506*26048Sminshall if (d < 0) { 1507*26048Sminshall perror(local); 1508*26048Sminshall return((char *) 0); 1509*26048Sminshall } 1510*26048Sminshall (void) strcpy(new, local); 1511*26048Sminshall cp = new + strlen(new); 1512*26048Sminshall *cp++ = '.'; 1513*26048Sminshall while (!d) { 1514*26048Sminshall if (++count == 100) { 1515*26048Sminshall printf("runique: can't find unique file name.\n"); 1516*26048Sminshall return((char *) 0); 1517*26048Sminshall } 1518*26048Sminshall *cp++ = ext; 1519*26048Sminshall *cp = '\0'; 1520*26048Sminshall if (ext == '9') { 1521*26048Sminshall ext = '0'; 1522*26048Sminshall } 1523*26048Sminshall else { 1524*26048Sminshall ext++; 1525*26048Sminshall } 1526*26048Sminshall if ((d = access(new, 0)) < 0) { 1527*26048Sminshall break; 1528*26048Sminshall } 1529*26048Sminshall if (ext != '0') { 1530*26048Sminshall cp--; 1531*26048Sminshall } 1532*26048Sminshall else if (*(cp - 2) == '.') { 1533*26048Sminshall *(cp - 1) = '1'; 1534*26048Sminshall } 1535*26048Sminshall else { 1536*26048Sminshall *(cp - 2) = *(cp - 2) + 1; 1537*26048Sminshall cp--; 1538*26048Sminshall } 1539*26048Sminshall } 1540*26048Sminshall return(new); 1541*26048Sminshall } 1542