home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / ftp / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-22  |  30.7 KB  |  1,468 lines

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