home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / ftp / ftp.c,v < prev    next >
Encoding:
Text File  |  1994-05-23  |  31.0 KB  |  1,495 lines

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