BSD 4_4 release
[unix-history] / usr / src / usr.bin / ftp / ftp.c
index 73dc1b7..77f07c8 100644 (file)
@@ -1,12 +1,38 @@
 /*
 /*
- * Copyright (c) 1985, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)ftp.c      5.37 (Berkeley) %G%";
+static char sccsid[] = "@(#)ftp.c      8.1 (Berkeley) 6/6/93";
 #endif /* not lint */
 
 #include <sys/param.h>
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -22,13 +48,16 @@ static char sccsid[] = "@(#)ftp.c   5.37 (Berkeley) %G%";
 #include <arpa/ftp.h>
 #include <arpa/telnet.h>
 
 #include <arpa/ftp.h>
 #include <arpa/telnet.h>
 
-#include <stdio.h>
 #include <signal.h>
 #include <signal.h>
-#include <errno.h>
 #include <netdb.h>
 #include <fcntl.h>
 #include <netdb.h>
 #include <fcntl.h>
+#include <errno.h>
 #include <pwd.h>
 #include <varargs.h>
 #include <pwd.h>
 #include <varargs.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 
 #include "ftp_var.h"
 
 
 #include "ftp_var.h"
 
@@ -38,10 +67,9 @@ int  data = -1;
 int    abrtflag = 0;
 int    ptflag = 0;
 struct sockaddr_in myctladdr;
 int    abrtflag = 0;
 int    ptflag = 0;
 struct sockaddr_in myctladdr;
-uid_t  getuid();
 sig_t  lostpeer();
 sig_t  lostpeer();
+off_t  restart_point = 0;
 
 
-extern char *strerror();
 extern int connected, errno;
 
 FILE   *cin, *cout;
 extern int connected, errno;
 
 FILE   *cin, *cout;
@@ -417,7 +445,7 @@ sendrequest(cmd, local, remote, printnames)
        register int c, d;
        FILE *fin, *dout = 0, *popen();
        int (*closefunc)(), pclose(), fclose();
        register int c, d;
        FILE *fin, *dout = 0, *popen();
        int (*closefunc)(), pclose(), fclose();
-       char buf[BUFSIZ], *bufp;
+       sig_t oldintr, oldintp;
        long bytes = 0, hashbytes = HASHBYTES;
        char *lmode, buf[BUFSIZ], *bufp;
        void abortsend();
        long bytes = 0, hashbytes = HASHBYTES;
        char *lmode, buf[BUFSIZ], *bufp;
        void abortsend();
@@ -498,6 +526,26 @@ sendrequest(cmd, local, remote, printnames)
        if (setjmp(sendabort))
                goto abort;
 
        if (setjmp(sendabort))
                goto abort;
 
+       if (restart_point &&
+           (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
+               if (fseek(fin, (long) restart_point, 0) < 0) {
+                       fprintf(stderr, "local: %s: %s\n", local,
+                               strerror(errno));
+                       restart_point = 0;
+                       if (closefunc != NULL)
+                               (*closefunc)(fin);
+                       return;
+               }
+               if (command("REST %ld", (long) restart_point)
+                       != CONTINUE) {
+                       restart_point = 0;
+                       if (closefunc != NULL)
+                               (*closefunc)(fin);
+                       return;
+               }
+               restart_point = 0;
+               lmode = "r+w";
+       }
        if (remote) {
                if (command("%s %s", cmd, remote) != PRELIM) {
                        (void) signal(SIGINT, oldintr);
        if (remote) {
                if (command("%s %s", cmd, remote) != PRELIM) {
                        (void) signal(SIGINT, oldintr);
@@ -528,9 +576,6 @@ sendrequest(cmd, local, remote, printnames)
                errno = d = 0;
                while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
                        bytes += c;
                errno = d = 0;
                while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
                        bytes += c;
-                       for (bufp = buf; c > 0; c -= d, bufp += d)
-                               if ((d = write(fileno(dout), bufp, c)) <= 0)
-                                       break;
                        for (bufp = buf; c > 0; c -= d, bufp += d)
                                if ((d = write(fileno(dout), bufp, c)) <= 0)
                                        break;
                        for (bufp = buf; c > 0; c -= d, bufp += d)
                                if ((d = write(fileno(dout), bufp, c)) <= 0)
                                        break;
@@ -551,10 +596,8 @@ sendrequest(cmd, local, remote, printnames)
                if (c < 0)
                        fprintf(stderr, "local: %s: %s\n", local,
                                strerror(errno));
                if (c < 0)
                        fprintf(stderr, "local: %s: %s\n", local,
                                strerror(errno));
-               if (d <= 0) {
-                       if (d == 0)
-                               fprintf(stderr, "netout: write returned 0?\n");
-                       else if (errno != EPIPE) 
+               if (d < 0) {
+                       if (errno != EPIPE) 
                                perror("netout");
                        bytes = -1;
                }
                                perror("netout");
                        bytes = -1;
                }
@@ -647,17 +690,17 @@ recvrequest(cmd, local, remote, lmode, printnames)
        char *cmd, *local, *remote, *lmode;
 {
        FILE *fout, *din = 0, *popen();
        char *cmd, *local, *remote, *lmode;
 {
        FILE *fout, *din = 0, *popen();
-       char *bufp, *gunique(), msg;
-       static char *buf;
+       int (*closefunc)(), pclose(), fclose();
+       sig_t oldintr, oldintp;
+       int is_retr, tcrflag, bare_lfs = 0;
+       char *gunique();
        static int bufsize;
        static char *buf;
        long bytes = 0, hashbytes = HASHBYTES;
        register int c, d;
        struct timeval start, stop;
        struct stat st;
        static int bufsize;
        static char *buf;
        long bytes = 0, hashbytes = HASHBYTES;
        register int c, d;
        struct timeval start, stop;
        struct stat st;
-       off_t lseek();
        void abortrecv();
        void abortrecv();
-       char *malloc();
 
        is_retr = strcmp(cmd, "RETR") == 0;
        if (is_retr && verbose && printnames) {
 
        is_retr = strcmp(cmd, "RETR") == 0;
        if (is_retr && verbose && printnames) {
@@ -790,7 +833,6 @@ recvrequest(cmd, local, remote, lmode, printnames)
                if (buf == NULL) {
                        perror("malloc");
                        bufsize = 0;
                if (buf == NULL) {
                        perror("malloc");
                        bufsize = 0;
-                       bufsize = 0;
                        goto abort;
                }
                bufsize = st.st_blksize;
                        goto abort;
                }
                bufsize = st.st_blksize;
@@ -800,6 +842,14 @@ recvrequest(cmd, local, remote, lmode, printnames)
 
        case TYPE_I:
        case TYPE_L:
 
        case TYPE_I:
        case TYPE_L:
+               if (restart_point &&
+                   lseek(fileno(fout), (off_t)restart_point, L_SET) < 0) {
+                       fprintf(stderr, "local: %s: %s\n", local,
+                               strerror(errno));
+                       if (closefunc != NULL)
+                               (*closefunc)(fout);
+                       return;
+               }
                errno = d = 0;
                while ((c = read(fileno(din), buf, bufsize)) > 0) {
                        if ((d = write(fileno(fout), buf, c)) != c)
                errno = d = 0;
                while ((c = read(fileno(din), buf, bufsize)) > 0) {
                        if ((d = write(fileno(fout), buf, c)) != c)
@@ -826,13 +876,35 @@ recvrequest(cmd, local, remote, lmode, printnames)
                }
                if (d < c) {
                        if (d < 0)
                }
                if (d < c) {
                        if (d < 0)
-                               perror(local);
+                               fprintf(stderr, "local: %s: %s\n", local,
+                                       strerror(errno));
                        else
                                fprintf(stderr, "%s: short write\n", local);
                }
                break;
 
        case TYPE_A:
                        else
                                fprintf(stderr, "%s: short write\n", local);
                }
                break;
 
        case TYPE_A:
+               if (restart_point) {
+                       register int i, n, ch;
+
+                       if (fseek(fout, 0L, L_SET) < 0)
+                               goto done;
+                       n = restart_point;
+                       for (i = 0; i++ < n;) {
+                               if ((ch = getc(fout)) == EOF)
+                                       goto done;
+                               if (ch == '\n')
+                                       i++;
+                       }
+                       if (fseek(fout, 0L, L_INCR) < 0) {
+done:
+                               fprintf(stderr, "local: %s: %s\n", local,
+                                       strerror(errno));
+                               if (closefunc != NULL)
+                                       (*closefunc)(fout);
+                               return;
+                       }
+               }
                while ((c = getc(din)) != EOF) {
                        if (c == '\n')
                                bare_lfs++;
                while ((c = getc(din)) != EOF) {
                        if (c == '\n')
                                bare_lfs++;
@@ -853,9 +925,6 @@ recvrequest(cmd, local, remote, lmode, printnames)
                                        }
                                        if (c == EOF)
                                                goto contin2;
                                        }
                                        if (c == EOF)
                                                goto contin2;
-                                       }
-                                       if (c == EOF)
-                                               goto contin2;
                                }
                        }
                        (void) putc(c, fout);
                                }
                        }
                        (void) putc(c, fout);