home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / inetutil.1 / inetutil / inetutils-1.1 / ftp / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-22  |  31.7 KB  |  1,556 lines

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