1: /*
   2:  * Copyright (c) 1985, 1989 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms are permitted
   6:  * provided that the above copyright notice and this paragraph are
   7:  * duplicated in all such forms and that any documentation,
   8:  * advertising materials, and other materials related to such
   9:  * distribution and use acknowledge that the software was developed
  10:  * by the University of California, Berkeley.  The name of the
  11:  * University may not be used to endorse or promote products derived
  12:  * from this software without specific prior written permission.
  13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16:  */
  17: 
  18: #if !defined(lint) && defined(DOSCCS)
  19: static char sccsid[] = "@(#)ftp.c	5.28.1 (2.11BSD) 1997/10/2";
  20: #endif
  21: 
  22: #include <sys/param.h>
  23: #include <sys/stat.h>
  24: #include <sys/ioctl.h>
  25: #include <sys/socket.h>
  26: #include <sys/time.h>
  27: #include <sys/file.h>
  28: 
  29: #include <netinet/in.h>
  30: #include <arpa/ftp.h>
  31: #include <arpa/telnet.h>
  32: #include <arpa/inet.h>
  33: 
  34: #include <stdio.h>
  35: #include <signal.h>
  36: #include <errno.h>
  37: #include <netdb.h>
  38: #include <fcntl.h>
  39: #include <pwd.h>
  40: #include <unistd.h>
  41: #include <varargs.h>
  42: 
  43: #include "ftp_var.h"
  44: 
  45: #ifndef MAXHOSTNAMELEN
  46: #define MAXHOSTNAMELEN 64
  47: #endif
  48: 
  49: #ifdef sun
  50: /* FD_SET wasn't defined until 4.0. its a cheap test for uid_t  presence */
  51: #ifndef FD_SET
  52: #define NBBY    8       /* number of bits in a byte */
  53: /*
  54:  * Select uses bit masks of file descriptors in longs.
  55:  * These macros manipulate such bit fields (the filesystem macros use chars).
  56:  * FD_SETSIZE may be defined by the user, but the default here
  57:  * should be >= NOFILE (param.h).
  58:  */
  59: #ifndef FD_SETSIZE
  60: #define FD_SETSIZE  256
  61: #endif
  62: 
  63: typedef long    fd_mask;
  64: #define NFDBITS (sizeof(fd_mask) * NBBY)    /* bits per mask */
  65: #ifndef howmany
  66: #define howmany(x, y)   (((x)+((y)-1))/(y))
  67: #endif
  68: 
  69: #define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  70: #define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  71: #define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  72: #define FD_ZERO(p)  bzero((char *)(p), sizeof(*(p)))
  73: 
  74: typedef int uid_t;
  75: typedef int gid_t;
  76: #endif
  77: #endif
  78: 
  79: struct  sockaddr_in hisctladdr;
  80: struct  sockaddr_in data_addr;
  81: int data = -1;
  82: int abrtflag = 0;
  83: int ptflag = 0;
  84: int connected;
  85: int allbinary;
  86: struct  sockaddr_in myctladdr;
  87: uid_t   getuid();
  88: off_t   restart_point = 0;
  89: 
  90: FILE    *cin, *cout;
  91: FILE    *dataconn();
  92: 
  93: char *
  94: hookup(host, port)
  95:     char *host;
  96:     int port;
  97: {
  98:     register struct hostent *hp = 0;
  99:     int s,len;
 100:     static char hostnamebuf[80];
 101: 
 102:     bzero((char *)&hisctladdr, sizeof (hisctladdr));
 103:     hisctladdr.sin_addr.s_addr = inet_addr(host);
 104:     if (hisctladdr.sin_addr.s_addr != -1) {
 105:         hisctladdr.sin_family = AF_INET;
 106:         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
 107:     } else {
 108:         hp = gethostbyname(host);
 109:         if (hp == NULL) {
 110:             fprintf(stderr, "ftp: %s: ", host);
 111:             herror((char *)NULL);
 112:             code = -1;
 113:             return((char *) 0);
 114:         }
 115:         hisctladdr.sin_family = hp->h_addrtype;
 116:         bcopy(hp->h_addr_list[0],
 117:             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
 118:         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
 119:     }
 120:     hostname = hostnamebuf;
 121:     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
 122:     if (s < 0) {
 123:         perror("ftp: socket");
 124:         code = -1;
 125:         return (0);
 126:     }
 127:     hisctladdr.sin_port = port;
 128:     while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
 129:         if (hp && hp->h_addr_list[1]) {
 130:             int oerrno = errno;
 131: 
 132:             fprintf(stderr, "ftp: connect to address %s: ",
 133:                 inet_ntoa(hisctladdr.sin_addr));
 134:             errno = oerrno;
 135:             perror((char *) 0);
 136:             hp->h_addr_list++;
 137:             bcopy(hp->h_addr_list[0],
 138:                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
 139:             fprintf(stdout, "Trying %s...\n",
 140:                 inet_ntoa(hisctladdr.sin_addr));
 141:             (void) close(s);
 142:             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
 143:             if (s < 0) {
 144:                 perror("ftp: socket");
 145:                 code = -1;
 146:                 return (0);
 147:             }
 148:             continue;
 149:         }
 150:         perror("ftp: connect");
 151:         code = -1;
 152:         goto bad;
 153:     }
 154:     len = sizeof (myctladdr);
 155:     if (getsockname(s, (char *)&myctladdr, &len) < 0) {
 156:         perror("ftp: getsockname");
 157:         code = -1;
 158:         goto bad;
 159:     }
 160:     cin = fdopen(s, "r");
 161:     cout = fdopen(s, "w");
 162:     if (cin == NULL || cout == NULL) {
 163:         fprintf(stderr, "ftp: fdopen failed.\n");
 164:         if (cin)
 165:             (void) fclose(cin);
 166:         if (cout)
 167:             (void) fclose(cout);
 168:         code = -1;
 169:         goto bad;
 170:     }
 171:     if (verbose)
 172:         printf("Connected to %s.\n", hostname);
 173:     if (getreply(0) > 2) {  /* read startup message from server */
 174:         if (cin)
 175:             (void) fclose(cin);
 176:         if (cout)
 177:             (void) fclose(cout);
 178:         code = -1;
 179:         goto bad;
 180:     }
 181: #ifdef SO_OOBINLINE
 182:     {
 183:     int on = 1;
 184: 
 185:     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
 186:         < 0 && debug) {
 187:             perror("ftp: setsockopt");
 188:         }
 189:     }
 190: #endif SO_OOBINLINE
 191: 
 192:     return (hostname);
 193: bad:
 194:     (void) close(s);
 195:     return ((char *)0);
 196: }
 197: 
 198: login(host)
 199:     char *host;
 200: {
 201:     char tmp[80];
 202:     char *user, *pass, *acct;
 203:     int n, aflag = 0;
 204: 
 205:     user = pass = acct = 0;
 206:     if (ruserpass(host, &user, &pass, &acct) < 0) {
 207:         code = -1;
 208:         return(0);
 209:     }
 210:     while (user == NULL) {
 211:         char *myname = getlogin();
 212: 
 213:         if (myname == NULL) {
 214:             struct passwd *pp = getpwuid(getuid());
 215: 
 216:             if (pp != NULL)
 217:                 myname = pp->pw_name;
 218:         }
 219:         if (myname)
 220:             printf("Name (%s:%s): ", host, myname);
 221:         else
 222:             printf("Name (%s): ", host);
 223:         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
 224:         tmp[strlen(tmp) - 1] = '\0';
 225:         if (*tmp == '\0')
 226:             user = myname;
 227:         else
 228:             user = tmp;
 229:     }
 230:     n = command("USER %s", user);
 231:     if (n == CONTINUE) {
 232:         if (pass == NULL)
 233:             pass = getpass("Password:");
 234:         n = command("PASS %s", pass);
 235:     }
 236:     if (n == CONTINUE) {
 237:         aflag++;
 238:         acct = getpass("Account:");
 239:         n = command("ACCT %s", acct);
 240:     }
 241:     if (n != COMPLETE) {
 242:         fprintf(stderr, "Login failed.\n");
 243:         return (0);
 244:     }
 245:     if (!aflag && acct != NULL)
 246:         (void) command("ACCT %s", acct);
 247:     if (proxy)
 248:         return(1);
 249:     for (n = 0; n < macnum; ++n) {
 250:         if (!strcmp("init", macros[n].mac_name)) {
 251:             (void) strcpy(line, "$init");
 252:             makeargv();
 253:             domacro(margc, margv);
 254:             break;
 255:         }
 256:     }
 257:     return (1);
 258: }
 259: 
 260: cmdabort()
 261: {
 262:     extern jmp_buf ptabort;
 263: 
 264:     printf("\n");
 265:     (void) fflush(stdout);
 266:     abrtflag++;
 267:     if (ptflag)
 268:         longjmp(ptabort,1);
 269: }
 270: 
 271: /*VARARGS1*/
 272: #ifdef pyr
 273: command(fmt, va_alist)
 274:     char *fmt;
 275: va_dcl
 276: #else
 277: command(fmt, args)
 278:     char *fmt;
 279: #endif /* !pyr */
 280: {
 281: #ifdef pyr
 282:     va_list ap;
 283: #endif /* pyr */
 284:     int r, (*oldintr)(), cmdabort();
 285: 
 286:     abrtflag = 0;
 287:     if (debug) {
 288:         printf("---> ");
 289: #ifdef pyr
 290:         va_start(ap);
 291:         _doprnt(fmt, ap, stdout);
 292:         va_end(ap);
 293: #else
 294:         _doprnt(fmt, &args, stdout);
 295: #endif /* !pyr */
 296:         printf("\n");
 297:         (void) fflush(stdout);
 298:     }
 299:     if (cout == NULL) {
 300:         perror ("No control connection for command");
 301:         code = -1;
 302:         return (0);
 303:     }
 304:     oldintr = signal(SIGINT,cmdabort);
 305: #ifdef pyr
 306:     va_start(ap);
 307:     _doprnt(fmt, ap, cout);
 308:     va_end(ap);
 309: #else
 310:     _doprnt(fmt, &args, cout);
 311: #endif /* !pyr */
 312:     fprintf(cout, "\r\n");
 313:     (void) fflush(cout);
 314:     cpend = 1;
 315:     r = getreply(!strcmp(fmt, "QUIT"));
 316:     if (abrtflag && oldintr != SIG_IGN)
 317:         (*oldintr)();
 318:     (void) signal(SIGINT, oldintr);
 319:     return(r);
 320: }
 321: 
 322: char reply_string[BUFSIZ];      /* last line of previous reply */
 323: 
 324: #include <ctype.h>
 325: 
 326: getreply(expecteof)
 327:     int expecteof;
 328: {
 329:     register int c, n;
 330:     register int dig;
 331:     register char *cp;
 332:     int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
 333:     int pflag = 0;
 334:     char *pt = pasv;
 335: 
 336:     oldintr = signal(SIGINT,cmdabort);
 337:     for (;;) {
 338:         dig = n = code = 0;
 339:         cp = reply_string;
 340:         while ((c = getc(cin)) != '\n') {
 341:             if (c == IAC) {     /* handle telnet commands */
 342:                 switch (c = getc(cin)) {
 343:                 case WILL:
 344:                 case WONT:
 345:                     c = getc(cin);
 346:                     fprintf(cout, "%c%c%c",IAC,DONT,c);
 347:                     (void) fflush(cout);
 348:                     break;
 349:                 case DO:
 350:                 case DONT:
 351:                     c = getc(cin);
 352:                     fprintf(cout, "%c%c%c",IAC,WONT,c);
 353:                     (void) fflush(cout);
 354:                     break;
 355:                 default:
 356:                     break;
 357:                 }
 358:                 continue;
 359:             }
 360:             dig++;
 361:             if (c == EOF) {
 362:                 if (expecteof) {
 363:                     (void) signal(SIGINT,oldintr);
 364:                     code = 221;
 365:                     return (0);
 366:                 }
 367:                 lostpeer();
 368:                 if (verbose) {
 369:                     printf("421 Service not available, remote server has closed connection\n");
 370:                     (void) fflush(stdout);
 371:                 }
 372:                 code = 421;
 373:                 return(4);
 374:             }
 375:             if (c != '\r' && (verbose > 0 ||
 376:                 (verbose > -1 && n == '5' && dig > 4))) {
 377:                 if (proxflag &&
 378:                    (dig == 1 || dig == 5 && verbose == 0))
 379:                     printf("%s:",hostname);
 380:                 (void) putchar(c);
 381:             }
 382:             if (dig < 4 && isdigit(c))
 383:                 code = code * 10 + (c - '0');
 384:             if (!pflag && code == 227)
 385:                 pflag = 1;
 386:             if (dig > 4 && pflag == 1 && isdigit(c))
 387:                 pflag = 2;
 388:             if (pflag == 2) {
 389:                 if (c != '\r' && c != ')')
 390:                     *pt++ = c;
 391:                 else {
 392:                     *pt = '\0';
 393:                     pflag = 3;
 394:                 }
 395:             }
 396:             if (dig == 4 && c == '-') {
 397:                 if (continuation)
 398:                     code = 0;
 399:                 continuation++;
 400:             }
 401:             if (n == 0)
 402:                 n = c;
 403:             if (cp < &reply_string[sizeof(reply_string) - 1])
 404:                 *cp++ = c;
 405:         }
 406:         if (verbose > 0 || verbose > -1 && n == '5') {
 407:             (void) putchar(c);
 408:             (void) fflush (stdout);
 409:         }
 410:         if (continuation && code != originalcode) {
 411:             if (originalcode == 0)
 412:                 originalcode = code;
 413:             continue;
 414:         }
 415:         *cp = '\0';
 416:         if (n != '1')
 417:             cpend = 0;
 418:         (void) signal(SIGINT,oldintr);
 419:         if (code == 421 || originalcode == 421)
 420:             lostpeer();
 421:         if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
 422:             (*oldintr)();
 423:         return (n - '0');
 424:     }
 425: }
 426: 
 427: empty(mask, sec)
 428:     struct fd_set *mask;
 429:     int sec;
 430: {
 431:     struct timeval t;
 432: 
 433:     t.tv_sec = (long) sec;
 434:     t.tv_usec = 0;
 435:     return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
 436: }
 437: 
 438: jmp_buf sendabort;
 439: 
 440: abortsend()
 441: {
 442: 
 443:     mflag = 0;
 444:     abrtflag = 0;
 445:     printf("\nsend aborted\n");
 446:     (void) fflush(stdout);
 447:     longjmp(sendabort, 1);
 448: }
 449: 
 450: #define HASHBYTES 1024
 451: 
 452: sendrequest(cmd, local, remote, printnames)
 453:     char *cmd, *local, *remote;
 454:     int printnames;
 455: {
 456:     FILE *fin, *dout = 0, *popen();
 457:     int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
 458:     int abortsend();
 459:     char buf[BUFSIZ], *bufp;
 460:     long bytes = 0, hashbytes = HASHBYTES;
 461:     register int c, d;
 462:     struct stat st;
 463:     struct timeval start, stop;
 464:     char *mode;
 465: 
 466:     if (verbose && printnames) {
 467:         if (local && *local != '-')
 468:             printf("local: %s ", local);
 469:         if (remote)
 470:             printf("remote: %s\n", remote);
 471:     }
 472:     if (proxy) {
 473:         proxtrans(cmd, local, remote);
 474:         return;
 475:     }
 476:     closefunc = NULL;
 477:     oldintr = NULL;
 478:     oldintp = NULL;
 479:     mode = "w";
 480:     if (setjmp(sendabort)) {
 481:         while (cpend) {
 482:             (void) getreply(0);
 483:         }
 484:         if (data >= 0) {
 485:             (void) close(data);
 486:             data = -1;
 487:         }
 488:         if (oldintr)
 489:             (void) signal(SIGINT,oldintr);
 490:         if (oldintp)
 491:             (void) signal(SIGPIPE,oldintp);
 492:         code = -1;
 493:         return;
 494:     }
 495:     oldintr = signal(SIGINT, abortsend);
 496:     if (strcmp(local, "-") == 0)
 497:         fin = stdin;
 498:     else if (*local == '|') {
 499:         oldintp = signal(SIGPIPE,SIG_IGN);
 500:         fin = popen(local + 1, "r");
 501:         if (fin == NULL) {
 502:             perror(local + 1);
 503:             (void) signal(SIGINT, oldintr);
 504:             (void) signal(SIGPIPE, oldintp);
 505:             code = -1;
 506:             return;
 507:         }
 508:         closefunc = pclose;
 509:     } else {
 510:         fin = fopen(local, "r");
 511:         if (fin == NULL) {
 512:             perror(local);
 513:             (void) signal(SIGINT, oldintr);
 514:             code = -1;
 515:             return;
 516:         }
 517:         closefunc = fclose;
 518:         if (fstat(fileno(fin), &st) < 0 ||
 519:             (st.st_mode&S_IFMT) != S_IFREG) {
 520:             fprintf(stdout, "%s: not a plain file.\n", local);
 521:             (void) signal(SIGINT, oldintr);
 522:             fclose(fin);
 523:             code = -1;
 524:             return;
 525:         }
 526:     }
 527:     if (initconn()) {
 528:         (void) signal(SIGINT, oldintr);
 529:         if (oldintp)
 530:             (void) signal(SIGPIPE, oldintp);
 531:         code = -1;
 532:         if (closefunc != NULL)
 533:             (*closefunc)(fin);
 534:         return;
 535:     }
 536:     if (setjmp(sendabort))
 537:         goto abort;
 538: 
 539:     if (restart_point &&
 540:         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
 541:         if (fseek(fin, (long) restart_point, 0) < 0) {
 542:             perror(local);
 543:             restart_point = 0;
 544:             if (closefunc != NULL)
 545:                 (*closefunc)(fin);
 546:             return;
 547:         }
 548:         if (command("REST %ld", (long) restart_point)
 549:             != CONTINUE) {
 550:             restart_point = 0;
 551:             if (closefunc != NULL)
 552:                 (*closefunc)(fin);
 553:             return;
 554:         }
 555:         restart_point = 0;
 556:         mode = "r+w";
 557:     }
 558:     if (remote) {
 559:         if (command("%s %s", cmd, remote) != PRELIM) {
 560:             (void) signal(SIGINT, oldintr);
 561:             if (oldintp)
 562:                 (void) signal(SIGPIPE, oldintp);
 563:             if (closefunc != NULL)
 564:                 (*closefunc)(fin);
 565:             return;
 566:         }
 567:     } else
 568:         if (command("%s", cmd) != PRELIM) {
 569:             (void) signal(SIGINT, oldintr);
 570:             if (oldintp)
 571:                 (void) signal(SIGPIPE, oldintp);
 572:             if (closefunc != NULL)
 573:                 (*closefunc)(fin);
 574:             return;
 575:         }
 576:     dout = dataconn(mode);
 577:     if (dout == NULL)
 578:         goto abort;
 579:     (void) gettimeofday(&start, (struct timezone *)0);
 580:     oldintp = signal(SIGPIPE, SIG_IGN);
 581:     switch (type) {
 582: 
 583:     case TYPE_I:
 584:     case TYPE_L:
 585:         errno = d = 0;
 586:         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
 587:             bytes += c;
 588:             for (bufp = buf; c > 0; c -= d, bufp += d)
 589:                 if ((d = write(fileno(dout), bufp, c)) <= 0)
 590:                     break;
 591:             if (hash) {
 592:                 while (bytes >= hashbytes) {
 593:                     (void) putchar('#');
 594:                     hashbytes += HASHBYTES;
 595:                 }
 596:                 (void) fflush(stdout);
 597:             }
 598:         }
 599:         if (hash && bytes > 0) {
 600:             if (bytes < HASHBYTES)
 601:                 (void) putchar('#');
 602:             (void) putchar('\n');
 603:             (void) fflush(stdout);
 604:         }
 605:         if (c < 0)
 606:             perror(local);
 607:         if (d <= 0) {
 608:             if (d == 0)
 609:                 fprintf(stderr, "netout: write returned 0?\n");
 610:             else if (errno != EPIPE)
 611:                 perror("netout");
 612:             bytes = -1;
 613:         }
 614:         break;
 615: 
 616:     case TYPE_A:
 617:         while ((c = getc(fin)) != EOF) {
 618:             if (c == '\n') {
 619:                 while (hash && (bytes >= hashbytes)) {
 620:                     (void) putchar('#');
 621:                     (void) fflush(stdout);
 622:                     hashbytes += HASHBYTES;
 623:                 }
 624:                 if (ferror(dout))
 625:                     break;
 626:                 (void) putc('\r', dout);
 627:                 bytes++;
 628:             }
 629:             (void) putc(c, dout);
 630:             bytes++;
 631:     /*		if (c == '\r') {			  	*/
 632:     /*		(void)	putc('\0', dout);  /* this violates rfc */
 633:     /*			bytes++;				*/
 634:     /*		}                          			*/
 635:         }
 636:         if (hash) {
 637:             if (bytes < hashbytes)
 638:                 (void) putchar('#');
 639:             (void) putchar('\n');
 640:             (void) fflush(stdout);
 641:         }
 642:         if (ferror(fin))
 643:             perror(local);
 644:         if (ferror(dout)) {
 645:             if (errno != EPIPE)
 646:                 perror("netout");
 647:             bytes = -1;
 648:         }
 649:         break;
 650:     }
 651:     (void) gettimeofday(&stop, (struct timezone *)0);
 652:     if (closefunc != NULL)
 653:         (*closefunc)(fin);
 654:     (void) fclose(dout);
 655:     (void) getreply(0);
 656:     (void) signal(SIGINT, oldintr);
 657:     if (oldintp)
 658:         (void) signal(SIGPIPE, oldintp);
 659:     if (bytes > 0)
 660:         ptransfer("sent", bytes, &start, &stop);
 661:     return;
 662: abort:
 663:     (void) gettimeofday(&stop, (struct timezone *)0);
 664:     (void) signal(SIGINT, oldintr);
 665:     if (oldintp)
 666:         (void) signal(SIGPIPE, oldintp);
 667:     if (!cpend) {
 668:         code = -1;
 669:         return;
 670:     }
 671:     if (data >= 0) {
 672:         (void) close(data);
 673:         data = -1;
 674:     }
 675:     if (dout)
 676:         (void) fclose(dout);
 677:     (void) getreply(0);
 678:     code = -1;
 679:     if (closefunc != NULL && fin != NULL)
 680:         (*closefunc)(fin);
 681:     if (bytes > 0)
 682:         ptransfer("sent", bytes, &start, &stop);
 683: }
 684: 
 685: jmp_buf recvabort;
 686: 
 687: abortrecv()
 688: {
 689: 
 690:     mflag = 0;
 691:     abrtflag = 0;
 692:     printf("\n");
 693:     (void) fflush(stdout);
 694:     longjmp(recvabort, 1);
 695: }
 696: 
 697: recvrequest(cmd, local, remote, mode, printnames)
 698:     char *cmd, *local, *remote, *mode;
 699: {
 700:     FILE *fout, *din = 0, *popen();
 701:     int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
 702:     int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd;
 703:     char *bufp, *gunique(), msg;
 704:     static char *buf;
 705:     static long bufsize;
 706:     long bytes = 0, hashbytes = HASHBYTES;
 707:     struct fd_set mask;
 708:     register int c, d;
 709:     struct timeval start, stop;
 710:     struct stat st;
 711:     extern char *malloc();
 712: 
 713:     is_retr = strcmp(cmd, "RETR") == 0;
 714:     if (is_retr && verbose && printnames) {
 715:         if (local && *local != '-')
 716:             printf("local: %s ", local);
 717:         if (remote)
 718:             printf("remote: %s\n", remote);
 719:     }
 720:     if (proxy && is_retr) {
 721:         proxtrans(cmd, local, remote);
 722:         return;
 723:     }
 724:     closefunc = NULL;
 725:     oldintr = NULL;
 726:     oldintp = NULL;
 727:     tcrflag = !crflag && is_retr;
 728:     if (setjmp(recvabort)) {
 729:         while (cpend) {
 730:             (void) getreply(0);
 731:         }
 732:         if (data >= 0) {
 733:             (void) close(data);
 734:             data = -1;
 735:         }
 736:         if (oldintr)
 737:             (void) signal(SIGINT, oldintr);
 738:         code = -1;
 739:         return;
 740:     }
 741:     oldintr = signal(SIGINT, abortrecv);
 742:     if (strcmp(local, "-") && *local != '|') {
 743:         if (access(local, 2) < 0) {
 744:             char *dir = rindex(local, '/');
 745: 
 746:             if (errno != ENOENT && errno != EACCES) {
 747:                 perror(local);
 748:                 (void) signal(SIGINT, oldintr);
 749:                 code = -1;
 750:                 return;
 751:             }
 752:             if (dir != NULL)
 753:                 *dir = 0;
 754:             d = access(dir ? local : ".", 2);
 755:             if (dir != NULL)
 756:                 *dir = '/';
 757:             if (d < 0) {
 758:                 perror(local);
 759:                 (void) signal(SIGINT, oldintr);
 760:                 code = -1;
 761:                 return;
 762:             }
 763:             if (!runique && errno == EACCES &&
 764:                 chmod(local, 0600) < 0) {
 765:                 perror(local);
 766:                 (void) signal(SIGINT, oldintr);
 767:                 code = -1;
 768:                 return;
 769:             }
 770:             if (runique && errno == EACCES &&
 771:                (local = gunique(local)) == NULL) {
 772:                 (void) signal(SIGINT, oldintr);
 773:                 code = -1;
 774:                 return;
 775:             }
 776:         }
 777:         else if (runique && (local = gunique(local)) == NULL) {
 778:             (void) signal(SIGINT, oldintr);
 779:             code = -1;
 780:             return;
 781:         }
 782:     }
 783:     if (initconn()) {
 784:         (void) signal(SIGINT, oldintr);
 785:         code = -1;
 786:         return;
 787:     }
 788:     if (setjmp(recvabort))
 789:         goto abort;
 790:     if (!is_retr) {
 791:         if (type != TYPE_A && (allbinary == 0 || type != TYPE_I)) {
 792:             oldtype = type;
 793:             oldverbose = verbose;
 794:             if (!debug)
 795:                 verbose = 0;
 796:             setascii();
 797:             verbose = oldverbose;
 798:         }
 799:     } else if (restart_point) {
 800:         if (command("REST %ld", (long) restart_point) != CONTINUE)
 801:             return;
 802:     }
 803:     if (remote) {
 804:         if (command("%s %s", cmd, remote) != PRELIM) {
 805:             (void) signal(SIGINT, oldintr);
 806:             if (oldtype) {
 807:                 if (!debug)
 808:                     verbose = 0;
 809:                 switch (oldtype) {
 810:                     case TYPE_I:
 811:                         setbinary();
 812:                         break;
 813:                     case TYPE_E:
 814:                         setebcdic();
 815:                         break;
 816:                     case TYPE_L:
 817:                         settenex();
 818:                         break;
 819:                 }
 820:                 verbose = oldverbose;
 821:             }
 822:             return;
 823:         }
 824:     } else {
 825:         if (command("%s", cmd) != PRELIM) {
 826:             (void) signal(SIGINT, oldintr);
 827:             if (oldtype) {
 828:                 if (!debug)
 829:                     verbose = 0;
 830:                 switch (oldtype) {
 831:                     case TYPE_I:
 832:                         setbinary();
 833:                         break;
 834:                     case TYPE_E:
 835:                         setebcdic();
 836:                         break;
 837:                     case TYPE_L:
 838:                         settenex();
 839:                         break;
 840:                 }
 841:                 verbose = oldverbose;
 842:             }
 843:             return;
 844:         }
 845:     }
 846:     din = dataconn("r");
 847:     if (din == NULL)
 848:         goto abort;
 849:     if (strcmp(local, "-") == 0)
 850:         fout = stdout;
 851:     else if (*local == '|') {
 852:         oldintp = signal(SIGPIPE, SIG_IGN);
 853:         fout = popen(local + 1, "w");
 854:         if (fout == NULL) {
 855:             perror(local+1);
 856:             goto abort;
 857:         }
 858:         closefunc = pclose;
 859:     } else {
 860:         fout = fopen(local, mode);
 861:         if (fout == NULL) {
 862:             perror(local);
 863:             goto abort;
 864:         }
 865:         closefunc = fclose;
 866:     }
 867:     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
 868:         st.st_blksize = BUFSIZ;
 869:     if (st.st_blksize > bufsize) {
 870:         if (buf)
 871:             (void) free(buf);
 872:         buf = malloc((int)st.st_blksize);
 873:         if (buf == NULL) {
 874:             perror("malloc");
 875:             bufsize = 0;
 876:             goto abort;
 877:         }
 878:         bufsize = st.st_blksize;
 879:     }
 880:     (void) gettimeofday(&start, (struct timezone *)0);
 881:     switch (type) {
 882: 
 883:     case TYPE_I:
 884:     case TYPE_L:
 885:         if (restart_point &&
 886:             lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
 887:             perror(local);
 888:             if (closefunc != NULL)
 889:                 (*closefunc)(fout);
 890:             return;
 891:         }
 892:         errno = d = 0;
 893:         while ((c = read(fileno(din), buf, (int)bufsize)) > 0) {
 894:             if ((d = write(fileno(fout), buf, c)) != c)
 895:                 break;
 896:             bytes += c;
 897:             if (hash) {
 898:                 while (bytes >= hashbytes) {
 899:                     (void) putchar('#');
 900:                     hashbytes += HASHBYTES;
 901:                 }
 902:                 (void) fflush(stdout);
 903:             }
 904:         }
 905:         if (hash && bytes > 0) {
 906:             if (bytes < HASHBYTES)
 907:                 (void) putchar('#');
 908:             (void) putchar('\n');
 909:             (void) fflush(stdout);
 910:         }
 911:         if (c < 0) {
 912:             if (errno != EPIPE)
 913:                 perror("netin");
 914:             bytes = -1;
 915:         }
 916:         if (d < c) {
 917:             if (d < 0)
 918:                 perror(local);
 919:             else
 920:                 fprintf(stderr, "%s: short write\n", local);
 921:         }
 922:         break;
 923: 
 924:     case TYPE_A:
 925:         if (restart_point) {
 926:             register int i, n, c;
 927: 
 928:             if (fseek(fout, 0L, L_SET) < 0)
 929:                 goto done;
 930:             n = restart_point;
 931:             i = 0;
 932:             while (i++ < n) {
 933:                 if ((c=getc(fout)) == EOF)
 934:                     goto done;
 935:                 if (c == '\n')
 936:                     i++;
 937:             }
 938:             if (fseek(fout, 0L, L_INCR) < 0) {
 939: done:
 940:                 perror(local);
 941:                 if (closefunc != NULL)
 942:                     (*closefunc)(fout);
 943:                 return;
 944:             }
 945:         }
 946:         while ((c = getc(din)) != EOF) {
 947:             while (c == '\r') {
 948:                 while (hash && (bytes >= hashbytes)) {
 949:                     (void) putchar('#');
 950:                     (void) fflush(stdout);
 951:                     hashbytes += HASHBYTES;
 952:                 }
 953:                 bytes++;
 954:                 if ((c = getc(din)) != '\n' || tcrflag) {
 955:                     if (ferror(fout))
 956:                         goto break2;
 957:                     (void) putc('\r', fout);
 958:                     if (c == '\0') {
 959:                         bytes++;
 960:                         goto contin2;
 961:                     }
 962:                     if (c == EOF)
 963:                         goto contin2;
 964:                 }
 965:             }
 966:             (void) putc(c, fout);
 967:             bytes++;
 968:     contin2:    ;
 969:         }
 970: break2:
 971:         if (hash) {
 972:             if (bytes < hashbytes)
 973:                 (void) putchar('#');
 974:             (void) putchar('\n');
 975:             (void) fflush(stdout);
 976:         }
 977:         if (ferror(din)) {
 978:             if (errno != EPIPE)
 979:                 perror("netin");
 980:             bytes = -1;
 981:         }
 982:         if (ferror(fout))
 983:             perror(local);
 984:         break;
 985:     }
 986:     if (closefunc != NULL)
 987:         (*closefunc)(fout);
 988:     (void) signal(SIGINT, oldintr);
 989:     if (oldintp)
 990:         (void) signal(SIGPIPE, oldintp);
 991:     (void) gettimeofday(&stop, (struct timezone *)0);
 992:     (void) fclose(din);
 993:     (void) getreply(0);
 994:     if (bytes > 0 && is_retr)
 995:         ptransfer("received", bytes, &start, &stop);
 996:     if (oldtype) {
 997:         if (!debug)
 998:             verbose = 0;
 999:         switch (oldtype) {
1000:             case TYPE_I:
1001:                 setbinary();
1002:                 break;
1003:             case TYPE_E:
1004:                 setebcdic();
1005:                 break;
1006:             case TYPE_L:
1007:                 settenex();
1008:                 break;
1009:         }
1010:         verbose = oldverbose;
1011:     }
1012:     return;
1013: abort:
1014: 
1015: /* abort using RFC959 recommended IP,SYNC sequence  */
1016: 
1017:     (void) gettimeofday(&stop, (struct timezone *)0);
1018:     if (oldintp)
1019:         (void) signal(SIGPIPE, oldintr);
1020:     (void) signal(SIGINT,SIG_IGN);
1021:     if (oldtype) {
1022:         if (!debug)
1023:             verbose = 0;
1024:         switch (oldtype) {
1025:             case TYPE_I:
1026:                 setbinary();
1027:                 break;
1028:             case TYPE_E:
1029:                 setebcdic();
1030:                 break;
1031:             case TYPE_L:
1032:                 settenex();
1033:                 break;
1034:         }
1035:         verbose = oldverbose;
1036:     }
1037:     if (!cpend) {
1038:         code = -1;
1039:         (void) signal(SIGINT,oldintr);
1040:         return;
1041:     }
1042: 
1043:     fprintf(cout,"%c%c",IAC,IP);
1044:     (void) fflush(cout);
1045:     msg = IAC;
1046: /* send IAC in urgent mode instead of DM because UNIX places oob mark */
1047: /* after urgent byte rather than before as now is protocol            */
1048:     if (send(fileno(cout),&msg,1,MSG_OOB) != 1) {
1049:         perror("abort");
1050:     }
1051:     fprintf(cout,"%cABOR\r\n",DM);
1052:     (void) fflush(cout);
1053:     FD_ZERO(&mask);
1054:     FD_SET(fileno(cin), &mask);
1055:     if (din) {
1056:         FD_SET(fileno(din), &mask);
1057:     }
1058:     if ((nfnd = empty(&mask,10)) <= 0) {
1059:         if (nfnd < 0) {
1060:             perror("abort");
1061:         }
1062:         code = -1;
1063:         lostpeer();
1064:     }
1065:     if (din && FD_ISSET(fileno(din), &mask)) {
1066:         while ((c = read(fileno(din), buf, (int)bufsize)) > 0)
1067:             ;
1068:     }
1069:     if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
1070:         if (data >= 0) {
1071:             (void) close(data);
1072:             data = -1;
1073:         }
1074:         (void) getreply(0);
1075:     }
1076:     (void) getreply(0);
1077:     code = -1;
1078:     if (data >= 0) {
1079:         (void) close(data);
1080:         data = -1;
1081:     }
1082:     if (closefunc != NULL && fout != NULL)
1083:         (*closefunc)(fout);
1084:     if (din)
1085:         (void) fclose(din);
1086:     if (bytes > 0)
1087:         ptransfer("received", bytes, &start, &stop);
1088:     (void) signal(SIGINT,oldintr);
1089: }
1090: 
1091: /*
1092:  * Need to start a listen on the data channel
1093:  * before we send the command, otherwise the
1094:  * server's connect may fail.
1095:  */
1096: int sendport = -1;
1097: 
1098: initconn()
1099: {
1100:     register char *p, *a;
1101:     int result, len, tmpno = 0;
1102:     int on = 1;
1103: 
1104: noport:
1105:     data_addr = myctladdr;
1106:     if (sendport)
1107:         data_addr.sin_port = 0; /* let system pick one */
1108:     if (data != -1)
1109:         (void) close (data);
1110:     data = socket(AF_INET, SOCK_STREAM, 0);
1111:     if (data < 0) {
1112:         perror("ftp: socket");
1113:         if (tmpno)
1114:             sendport = 1;
1115:         return (1);
1116:     }
1117:     if (!sendport)
1118:         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
1119:             perror("ftp: setsockopt (reuse address)");
1120:             goto bad;
1121:         }
1122:     if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
1123:         perror("ftp: bind");
1124:         goto bad;
1125:     }
1126:     if (options & SO_DEBUG &&
1127:         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1128:         perror("ftp: setsockopt (ignored)");
1129:     len = sizeof (data_addr);
1130:     if (getsockname(data, (char *)&data_addr, &len) < 0) {
1131:         perror("ftp: getsockname");
1132:         goto bad;
1133:     }
1134:     if (listen(data, 1) < 0)
1135:         perror("ftp: listen");
1136:     if (sendport) {
1137:         a = (char *)&data_addr.sin_addr;
1138:         p = (char *)&data_addr.sin_port;
1139: #define UC(b)   (((int)b)&0xff)
1140:         result =
1141:             command("PORT %d,%d,%d,%d,%d,%d",
1142:               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1143:               UC(p[0]), UC(p[1]));
1144:         if (result == ERROR && sendport == -1) {
1145:             sendport = 0;
1146:             tmpno = 1;
1147:             goto noport;
1148:         }
1149:         return (result != COMPLETE);
1150:     }
1151:     if (tmpno)
1152:         sendport = 1;
1153:     return (0);
1154: bad:
1155:     (void) close(data), data = -1;
1156:     if (tmpno)
1157:         sendport = 1;
1158:     return (1);
1159: }
1160: 
1161: FILE *
1162: dataconn(mode)
1163:     char *mode;
1164: {
1165:     struct sockaddr_in from;
1166:     int s, fromlen = sizeof (from);
1167: 
1168:     s = accept(data, (struct sockaddr *) &from, &fromlen);
1169:     if (s < 0) {
1170:         perror("ftp: accept");
1171:         (void) close(data), data = -1;
1172:         return (NULL);
1173:     }
1174:     (void) close(data);
1175:     data = s;
1176:     return (fdopen(data, mode));
1177: }
1178: 
1179: ptransfer(direction, bytes, t0, t1)
1180:     char *direction;
1181:     long bytes;
1182:     struct timeval *t0, *t1;
1183: {
1184:     struct timeval td;
1185:     float s, bs;
1186: 
1187:     if (verbose) {
1188:         tvsub(&td, t1, t0);
1189:         s = td.tv_sec + (td.tv_usec / 1000000.);
1190: #define nz(x)   ((x) == 0 ? 1 : (x))
1191:         bs = bytes / nz(s);
1192:         printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
1193:             bytes, direction, s, bs / 1024.);
1194:     }
1195: }
1196: 
1197: /*tvadd(tsum, t0)
1198: 	struct timeval *tsum, *t0;
1199: {
1200: 
1201: 	tsum->tv_sec += t0->tv_sec;
1202: 	tsum->tv_usec += t0->tv_usec;
1203: 	if (tsum->tv_usec > 1000000)
1204: 		tsum->tv_sec++, tsum->tv_usec -= 1000000;
1205: } */
1206: 
1207: tvsub(tdiff, t1, t0)
1208:     struct timeval *tdiff, *t1, *t0;
1209: {
1210: 
1211:     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1212:     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1213:     if (tdiff->tv_usec < 0)
1214:         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1215: }
1216: 
1217: psabort()
1218: {
1219:     extern int abrtflag;
1220: 
1221:     abrtflag++;
1222: }
1223: 
1224: pswitch(flag)
1225:     int flag;
1226: {
1227:     extern int proxy, abrtflag;
1228:     int (*oldintr)();
1229:     static struct comvars {
1230:         int connect;
1231:         char name[MAXHOSTNAMELEN];
1232:         struct sockaddr_in mctl;
1233:         struct sockaddr_in hctl;
1234:         FILE *in;
1235:         FILE *out;
1236:         int tpe;
1237:         int cpnd;
1238:         int sunqe;
1239:         int runqe;
1240:         int mcse;
1241:         int ntflg;
1242:         char nti[17];
1243:         char nto[17];
1244:         int mapflg;
1245:         char mi[MAXPATHLEN];
1246:         char mo[MAXPATHLEN];
1247:         } proxstruct, tmpstruct;
1248:     struct comvars *ip, *op;
1249: 
1250:     abrtflag = 0;
1251:     oldintr = signal(SIGINT, psabort);
1252:     if (flag) {
1253:         if (proxy)
1254:             return;
1255:         ip = &tmpstruct;
1256:         op = &proxstruct;
1257:         proxy++;
1258:     }
1259:     else {
1260:         if (!proxy)
1261:             return;
1262:         ip = &proxstruct;
1263:         op = &tmpstruct;
1264:         proxy = 0;
1265:     }
1266:     ip->connect = connected;
1267:     connected = op->connect;
1268:     if (hostname) {
1269:         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1270:         ip->name[strlen(ip->name)] = '\0';
1271:     } else
1272:         ip->name[0] = 0;
1273:     hostname = op->name;
1274:     ip->hctl = hisctladdr;
1275:     hisctladdr = op->hctl;
1276:     ip->mctl = myctladdr;
1277:     myctladdr = op->mctl;
1278:     ip->in = cin;
1279:     cin = op->in;
1280:     ip->out = cout;
1281:     cout = op->out;
1282:     ip->tpe = type;
1283:     type = op->tpe;
1284:     if (!type)
1285:         type = 1;
1286:     ip->cpnd = cpend;
1287:     cpend = op->cpnd;
1288:     ip->sunqe = sunique;
1289:     sunique = op->sunqe;
1290:     ip->runqe = runique;
1291:     runique = op->runqe;
1292:     ip->mcse = mcase;
1293:     mcase = op->mcse;
1294:     ip->ntflg = ntflag;
1295:     ntflag = op->ntflg;
1296:     (void) strncpy(ip->nti, ntin, 16);
1297:     (ip->nti)[strlen(ip->nti)] = '\0';
1298:     (void) strcpy(ntin, op->nti);
1299:     (void) strncpy(ip->nto, ntout, 16);
1300:     (ip->nto)[strlen(ip->nto)] = '\0';
1301:     (void) strcpy(ntout, op->nto);
1302:     ip->mapflg = mapflag;
1303:     mapflag = op->mapflg;
1304:     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
1305:     (ip->mi)[strlen(ip->mi)] = '\0';
1306:     (void) strcpy(mapin, op->mi);
1307:     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
1308:     (ip->mo)[strlen(ip->mo)] = '\0';
1309:     (void) strcpy(mapout, op->mo);
1310:     (void) signal(SIGINT, oldintr);
1311:     if (abrtflag) {
1312:         abrtflag = 0;
1313:         (*oldintr)();
1314:     }
1315: }
1316: 
1317: jmp_buf ptabort;
1318: int ptabflg;
1319: 
1320: abortpt()
1321: {
1322:     printf("\n");
1323:     (void) fflush(stdout);
1324:     ptabflg++;
1325:     mflag = 0;
1326:     abrtflag = 0;
1327:     longjmp(ptabort, 1);
1328: }
1329: 
1330: proxtrans(cmd, local, remote)
1331:     char *cmd, *local, *remote;
1332: {
1333:     int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
1334:     extern jmp_buf ptabort;
1335:     char *cmd2;
1336:     struct fd_set mask;
1337: 
1338:     if (strcmp(cmd, "RETR"))
1339:         cmd2 = "RETR";
1340:     else
1341:         cmd2 = runique ? "STOU" : "STOR";
1342:     if (command("PASV") != COMPLETE) {
1343:         printf("proxy server does not support third part transfers.\n");
1344:         return;
1345:     }
1346:     tmptype = type;
1347:     pswitch(0);
1348:     if (!connected) {
1349:         printf("No primary connection\n");
1350:         pswitch(1);
1351:         code = -1;
1352:         return;
1353:     }
1354:     if (type != tmptype) {
1355:         oldtype = type;
1356:         switch (tmptype) {
1357:             case TYPE_A:
1358:                 setascii();
1359:                 break;
1360:             case TYPE_I:
1361:                 setbinary();
1362:                 break;
1363:             case TYPE_E:
1364:                 setebcdic();
1365:                 break;
1366:             case TYPE_L:
1367:                 settenex();
1368:                 break;
1369:         }
1370:     }
1371:     if (command("PORT %s", pasv) != COMPLETE) {
1372:         switch (oldtype) {
1373:             case 0:
1374:                 break;
1375:             case TYPE_A:
1376:                 setascii();
1377:                 break;
1378:             case TYPE_I:
1379:                 setbinary();
1380:                 break;
1381:             case TYPE_E:
1382:                 setebcdic();
1383:                 break;
1384:             case TYPE_L:
1385:                 settenex();
1386:                 break;
1387:         }
1388:         pswitch(1);
1389:         return;
1390:     }
1391:     if (setjmp(ptabort))
1392:         goto abort;
1393:     oldintr = signal(SIGINT, abortpt);
1394:     if (command("%s %s", cmd, remote) != PRELIM) {
1395:         (void) signal(SIGINT, oldintr);
1396:         switch (oldtype) {
1397:             case 0:
1398:                 break;
1399:             case TYPE_A:
1400:                 setascii();
1401:                 break;
1402:             case TYPE_I:
1403:                 setbinary();
1404:                 break;
1405:             case TYPE_E:
1406:                 setebcdic();
1407:                 break;
1408:             case TYPE_L:
1409:                 settenex();
1410:                 break;
1411:         }
1412:         pswitch(1);
1413:         return;
1414:     }
1415:     sleep(2);
1416:     pswitch(1);
1417:     secndflag++;
1418:     if (command("%s %s", cmd2, local) != PRELIM)
1419:         goto abort;
1420:     ptflag++;
1421:     (void) getreply(0);
1422:     pswitch(0);
1423:     (void) getreply(0);
1424:     (void) signal(SIGINT, oldintr);
1425:     switch (oldtype) {
1426:         case 0:
1427:             break;
1428:         case TYPE_A:
1429:             setascii();
1430:             break;
1431:         case TYPE_I:
1432:             setbinary();
1433:             break;
1434:         case TYPE_E:
1435:             setebcdic();
1436:             break;
1437:         case TYPE_L:
1438:             settenex();
1439:             break;
1440:     }
1441:     pswitch(1);
1442:     ptflag = 0;
1443:     printf("local: %s remote: %s\n", local, remote);
1444:     return;
1445: abort:
1446:     (void) signal(SIGINT, SIG_IGN);
1447:     ptflag = 0;
1448:     if (strcmp(cmd, "RETR") && !proxy)
1449:         pswitch(1);
1450:     else if (!strcmp(cmd, "RETR") && proxy)
1451:         pswitch(0);
1452:     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
1453:         if (command("%s %s", cmd2, local) != PRELIM) {
1454:             pswitch(0);
1455:             switch (oldtype) {
1456:                 case 0:
1457:                     break;
1458:                 case TYPE_A:
1459:                     setascii();
1460:                     break;
1461:                 case TYPE_I:
1462:                     setbinary();
1463:                     break;
1464:                 case TYPE_E:
1465:                     setebcdic();
1466:                     break;
1467:                 case TYPE_L:
1468:                     settenex();
1469:                     break;
1470:             }
1471:             if (cpend) {
1472:                 char msg[2];
1473: 
1474:                 fprintf(cout,"%c%c",IAC,IP);
1475:                 (void) fflush(cout);
1476:                 *msg = IAC;
1477:                 *(msg+1) = DM;
1478:                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1479:                     perror("abort");
1480:                 fprintf(cout,"ABOR\r\n");
1481:                 (void) fflush(cout);
1482:                 FD_ZERO(&mask);
1483:                 FD_SET(fileno(cin), &mask);
1484:                 if ((nfnd = empty(&mask,10)) <= 0) {
1485:                     if (nfnd < 0) {
1486:                         perror("abort");
1487:                     }
1488:                     if (ptabflg)
1489:                         code = -1;
1490:                     lostpeer();
1491:                 }
1492:                 (void) getreply(0);
1493:                 (void) getreply(0);
1494:             }
1495:         }
1496:         pswitch(1);
1497:         if (ptabflg)
1498:             code = -1;
1499:         (void) signal(SIGINT, oldintr);
1500:         return;
1501:     }
1502:     if (cpend) {
1503:         char msg[2];
1504: 
1505:         fprintf(cout,"%c%c",IAC,IP);
1506:         (void) fflush(cout);
1507:         *msg = IAC;
1508:         *(msg+1) = DM;
1509:         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1510:             perror("abort");
1511:         fprintf(cout,"ABOR\r\n");
1512:         (void) fflush(cout);
1513:         FD_ZERO(&mask);
1514:         FD_SET(fileno(cin), &mask);
1515:         if ((nfnd = empty(&mask,10)) <= 0) {
1516:             if (nfnd < 0) {
1517:                 perror("abort");
1518:             }
1519:             if (ptabflg)
1520:                 code = -1;
1521:             lostpeer();
1522:         }
1523:         (void) getreply(0);
1524:         (void) getreply(0);
1525:     }
1526:     pswitch(!proxy);
1527:     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
1528:         if (command("%s %s", cmd2, local) != PRELIM) {
1529:             pswitch(0);
1530:             switch (oldtype) {
1531:                 case 0:
1532:                     break;
1533:                 case TYPE_A:
1534:                     setascii();
1535:                     break;
1536:                 case TYPE_I:
1537:                     setbinary();
1538:                     break;
1539:                 case TYPE_E:
1540:                     setebcdic();
1541:                     break;
1542:                 case TYPE_L:
1543:                     settenex();
1544:                     break;
1545:             }
1546:             if (cpend) {
1547:                 char msg[2];
1548: 
1549:                 fprintf(cout,"%c%c",IAC,IP);
1550:                 (void) fflush(cout);
1551:                 *msg = IAC;
1552:                 *(msg+1) = DM;
1553:                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1554:                     perror("abort");
1555:                 fprintf(cout,"ABOR\r\n");
1556:                 (void) fflush(cout);
1557:                 FD_ZERO(&mask);
1558:                 FD_SET(fileno(cin), &mask);
1559:                 if ((nfnd = empty(&mask,10)) <= 0) {
1560:                     if (nfnd < 0) {
1561:                         perror("abort");
1562:                     }
1563:                     if (ptabflg)
1564:                         code = -1;
1565:                     lostpeer();
1566:                 }
1567:                 (void) getreply(0);
1568:                 (void) getreply(0);
1569:             }
1570:             pswitch(1);
1571:             if (ptabflg)
1572:                 code = -1;
1573:             (void) signal(SIGINT, oldintr);
1574:             return;
1575:         }
1576:     }
1577:     if (cpend) {
1578:         char msg[2];
1579: 
1580:         fprintf(cout,"%c%c",IAC,IP);
1581:         (void) fflush(cout);
1582:         *msg = IAC;
1583:         *(msg+1) = DM;
1584:         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1585:             perror("abort");
1586:         fprintf(cout,"ABOR\r\n");
1587:         (void) fflush(cout);
1588:         FD_ZERO(&mask);
1589:         FD_SET(fileno(cin), &mask);
1590:         if ((nfnd = empty(&mask,10)) <= 0) {
1591:             if (nfnd < 0) {
1592:                 perror("abort");
1593:             }
1594:             if (ptabflg)
1595:                 code = -1;
1596:             lostpeer();
1597:         }
1598:         (void) getreply(0);
1599:         (void) getreply(0);
1600:     }
1601:     pswitch(!proxy);
1602:     if (cpend) {
1603:         FD_ZERO(&mask);
1604:         FD_SET(fileno(cin), &mask);
1605:         if ((nfnd = empty(&mask,10)) <= 0) {
1606:             if (nfnd < 0) {
1607:                 perror("abort");
1608:             }
1609:             if (ptabflg)
1610:                 code = -1;
1611:             lostpeer();
1612:         }
1613:         (void) getreply(0);
1614:         (void) getreply(0);
1615:     }
1616:     if (proxy)
1617:         pswitch(0);
1618:     switch (oldtype) {
1619:         case 0:
1620:             break;
1621:         case TYPE_A:
1622:             setascii();
1623:             break;
1624:         case TYPE_I:
1625:             setbinary();
1626:             break;
1627:         case TYPE_E:
1628:             setebcdic();
1629:             break;
1630:         case TYPE_L:
1631:             settenex();
1632:             break;
1633:     }
1634:     pswitch(1);
1635:     if (ptabflg)
1636:         code = -1;
1637:     (void) signal(SIGINT, oldintr);
1638: }
1639: 
1640: reset()
1641: {
1642:     struct fd_set mask;
1643:     int nfnd = 1;
1644: 
1645:     FD_ZERO(&mask);
1646:     while (nfnd > 0) {
1647:         FD_SET(fileno(cin), &mask);
1648:         if ((nfnd = empty(&mask,0)) < 0) {
1649:             perror("reset");
1650:             code = -1;
1651:             lostpeer();
1652:         }
1653:         else if (nfnd) {
1654:             (void) getreply(0);
1655:         }
1656:     }
1657: }
1658: 
1659: char *
1660: gunique(local)
1661:     char *local;
1662: {
1663:     static char new[MAXPATHLEN];
1664:     char *cp = rindex(local, '/');
1665:     int d, count=0;
1666:     char ext = '1';
1667: 
1668:     if (cp)
1669:         *cp = '\0';
1670:     d = access(cp ? local : ".", 2);
1671:     if (cp)
1672:         *cp = '/';
1673:     if (d < 0) {
1674:         perror(local);
1675:         return((char *) 0);
1676:     }
1677:     (void) strcpy(new, local);
1678:     cp = new + strlen(new);
1679:     *cp++ = '.';
1680:     while (!d) {
1681:         if (++count == 100) {
1682:             printf("runique: can't find unique file name.\n");
1683:             return((char *) 0);
1684:         }
1685:         *cp++ = ext;
1686:         *cp = '\0';
1687:         if (ext == '9')
1688:             ext = '0';
1689:         else
1690:             ext++;
1691:         if ((d = access(new, 0)) < 0)
1692:             break;
1693:         if (ext != '0')
1694:             cp--;
1695:         else if (*(cp - 2) == '.')
1696:             *(cp - 1) = '1';
1697:         else {
1698:             *(cp - 2) = *(cp - 2) + 1;
1699:             cp--;
1700:         }
1701:     }
1702:     return(new);
1703: }

Defined functions

abortpt defined in line 1320; used 2 times
abortrecv defined in line 687; used 2 times
abortsend defined in line 440; used 2 times
cmdabort defined in line 260; used 5 times
command defined in line 275; used 51 times
dataconn defined in line 1161; used 3 times
empty defined in line 427; used 7 times
getreply defined in line 326; used 25 times
gunique defined in line 1659; used 3 times
hookup defined in line 93; used 2 times
initconn defined in line 1098; used 2 times
login defined in line 198; used 1 times
proxtrans defined in line 1330; used 2 times
psabort defined in line 1217; used 1 times
pswitch defined in line 1224; used 29 times
ptransfer defined in line 1179; used 4 times
recvrequest defined in line 697; used 5 times
reset defined in line 1640; used 2 times
sendrequest defined in line 452; used 4 times
tvsub defined in line 1207; used 1 times

Defined variables

abrtflag defined in line 82; used 13 times
allbinary defined in line 85; used 2 times
connected defined in line 84; used 3 times
data defined in line 81; used 32 times
data_addr defined in line 80; used 8 times
hisctladdr defined in line 79; used 17 times
myctladdr defined in line 86; used 5 times
ptabflg defined in line 1318; used 9 times
ptabort defined in line 1317; used 5 times
ptflag defined in line 83; used 4 times
recvabort defined in line 685; used 3 times
reply_string defined in line 322; used 12 times
restart_point defined in line 88; used 17 times
sccsid defined in line 19; never used
sendabort defined in line 438; used 3 times
sendport defined in line 1096; used 8 times

Defined struct's

comvars defined in line 1229; used 2 times

Defined macros

FD_CLR defined in line 70; never used
FD_ISSET defined in line 71; used 1 times
FD_SET defined in line 69; used 9 times
FD_SETSIZE defined in line 60; used 1 times
  • in line 59
FD_ZERO defined in line 72; used 7 times
HASHBYTES defined in line 450; used 8 times
MAXHOSTNAMELEN defined in line 46; used 2 times
NBBY defined in line 52; used 1 times
  • in line 64
NFDBITS defined in line 64; used 6 times
UC defined in line 1139; used 6 times
howmany defined in line 66; used 1 times
  • in line 65
nz defined in line 1190; used 1 times
Last modified: 1997-10-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 12778
Valid CSS Valid XHTML 1.0 Strict