ftp.c

来自「一个类似windows」· C语言 代码 · 共 1,821 行 · 第 1/3 页

C
1,821
字号
		if (hash && bytes > 0) {
			if (bytes < HASHBYTES)
				(void) putchar('#');
			(void) putchar('\n');
			(void) fflush(stdout);
		}
		if (c < 0)
			perror(local);
		if (d <= 0) {
			if (d == 0)
				fprintf(stderr, "netout: write returned 0?\n");
			else if (errno != EPIPE)
				perror("netout");
			bytes = -1;
		}
		break;

	case TYPE_A:
		{
        char buf[1024];
		static int bufsize = 1024;
		int ipos=0;

		while ((c = getc(fin)) != EOF) {
                   if (c == '\n') {
                      while (hash && (bytes >= hashbytes)) {
                         (void) putchar('#');
                         (void) fflush(stdout);
                         hashbytes += HASHBYTES;
                      }
// Szurgot: The following code is unncessary on Win32.
//                      (void) fputcSocket(dout, '\r');
//                         bytes++;
                   }

				   if (ipos >= bufsize) {
						fputSocket(dout,buf,ipos);
						if(!hash) (void) putchar('.');
						ipos=0;
				   }
				   buf[ipos]=c; ++ipos;
				   bytes++;
		}
		if (ipos) {
			fputSocket(dout,buf,ipos);
			ipos=0;
		}
		if (hash) {
                   if (bytes < hashbytes)
                      (void) putchar('#');
                   (void) putchar('\n');
                   (void) fflush(stdout);
		}
		else {
			(void) putchar('.');
			(void) putchar('\n');
			(void) fflush(stdout);
		}
		if (ferror(fin))
                   perror(local);
//		if (ferror(dout)) {
//			if (errno != EPIPE)
//				perror("netout");
//			bytes = -1;
//		}
                break;
		}
	}
	(void) gettimeofday(&stop, (struct timezone *)0);
	if (closefunc != NULL)
		(*closefunc)(fin);
	if(closesocket(dout)) {
		int iret=WSAGetLastError ();
		fprintf(stdout,"Error closing socket(%d)\n",iret);
		(void) fflush(stdout);
	}
	(void) getreply(0);
null();//	(void) signal(SIGINT, oldintr);
	if (oldintp)
null();//		(void) signal(SIGPIPE, oldintp);
	if (bytes > 0)
		ptransfer("sent", bytes, &start, &stop);
	return;
abort:
	(void) gettimeofday(&stop, (struct timezone *)0);
null();//	(void) signal(SIGINT, oldintr);
	if (oldintp)
null();//		(void) signal(SIGPIPE, oldintp);
	if (!cpend) {
		code = -1;
		return;
	}
	if (data >= 0) {
		(void) close(data);
		data = -1;
	}
	if (dout)
		if(closesocket(dout)) {
			int iret=WSAGetLastError ();
			fprintf(stdout,"Error closing socket(%d)\n",iret);
			(void) fflush(stdout);
		}

	(void) getreply(0);
	code = -1;
	if (closefunc != NULL && fin != NULL)
		(*closefunc)(fin);
	if (bytes > 0)
		ptransfer("sent", bytes, &start, &stop);
}

jmp_buf	recvabort;

#if 0
void abortrecv()
{

	mflag = 0;
	abrtflag = 0;
	printf("\n");
	(void) fflush(stdout);
	longjmp(recvabort, 1);
}
#endif

void recvrequest(const char *cmd, const char *local, const char *remote, const char *mode,
                int printnames)
{
	FILE *fout = stdout;
        int din = 0;
	int (*closefunc)(), _pclose(), fclose();
	void (*oldintr)(int), (*oldintp)(int);
	int oldverbose = 0, oldtype = 0, is_retr, tcrflag, nfnd, bare_lfs = 0;
	char msg;
//	static char *buf; // Szurgot: Shouldn't this go SOMEWHERE?
        char buf[1024];
	static int bufsize = 1024;
	long bytes = 0, hashbytes = HASHBYTES;
//	struct
		fd_set mask;
	register int c, d;
	struct timeval start, stop;
//	struct stat st;
	extern void *malloc();

	is_retr = strcmp(cmd, "RETR") == 0;
	if (is_retr && verbose && printnames) {
		if (local && *local != '-')
			printf("local: %s ", local);
		if (remote)
			printf("remote: %s\n", remote);
		(void) fflush(stdout);
	}
	if (proxy && is_retr) {
		proxtrans(cmd, local, remote);
		return;
	}
	closefunc = NULL;
	oldintr = NULL;
	oldintp = NULL;
	tcrflag = !crflag && is_retr;
	if (setjmp(recvabort)) {
		while (cpend) {
			(void) getreply(0);
		}
		if (data >= 0) {
			(void) close(data);
			data = -1;
		}
		if (oldintr)
null();//			(void) signal(SIGINT, oldintr);
		code = -1;
		return;
	}
null();//	oldintr = signal(SIGINT, abortrecv);
	if (strcmp(local, "-") && *local != '|') {
#ifndef __WIN32__
// This whole thing is a problem... access Won't work on non-existent files
           if (access(local, 2) < 0) {
              char *dir = rindex(local, '/');

              if (errno != ENOENT && errno != EACCES) {
                 perror(local);
                 (void) signal(SIGINT, oldintr);
                 code = -1;
                 return;
              }
              if (dir != NULL)
                 *dir = 0;
              d = access(dir ? local : ".", 2);
              if (dir != NULL)
                 *dir = '/';
              if (d < 0) {
                 perror(local);
                 (void) signal(SIGINT, oldintr);
                 code = -1;
                 return;
              }
              if (!runique && errno == EACCES &&
                  chmod(local, 0600) < 0) {
                 perror(local);
                 (void) signal(SIGINT, oldintr);
                 code = -1;
                 return;
              }
              if (runique && errno == EACCES &&
                  (local = gunique(local)) == NULL) {
                 (void) signal(SIGINT, oldintr);
                 code = -1;
                 return;
              }
           }
           else if (runique && (local = gunique(local)) == NULL) {
              (void) signal(SIGINT, oldintr);
              code = -1;
              return;
           }
#endif
	}
	if (initconn()) {
null();//		(void) signal(SIGINT, oldintr);
		code = -1;
		return;
	}
	if (setjmp(recvabort))
		goto abort;
	if (!is_retr) {
		if (type != TYPE_A && (allbinary == 0 || type != TYPE_I)) {
			oldtype = type;
			oldverbose = verbose;
			if (!debug)
				verbose = 0;
			setascii();
			verbose = oldverbose;
		}
	} else if (restart_point) {
		if (command("REST %ld", (long) restart_point) != CONTINUE)
			return;
	}
	if (remote) {
		if (command("%s %s", cmd, remote) != PRELIM) {
null();//			(void) signal(SIGINT, oldintr);
			if (oldtype) {
				if (!debug)
					verbose = 0;
				switch (oldtype) {
					case TYPE_I:
						setbinary();
						break;
					case TYPE_E:
						setebcdic();
						break;
					case TYPE_L:
						settenex();
						break;
				}
				verbose = oldverbose;
			}
			return;
		}
	} else {
		if (command("%s", cmd) != PRELIM) {
null();//			(void) signal(SIGINT, oldintr);
			if (oldtype) {
				if (!debug)
					verbose = 0;
				switch (oldtype) {
					case TYPE_I:
						setbinary();
						break;
					case TYPE_E:
						setebcdic();
						break;
					case TYPE_L:
						settenex();
						break;
				}
				verbose = oldverbose;
			}
			return;
		}
	}
	din = dataconn("r");
	if (din == (int)NULL)
		goto abort;
	if (strcmp(local, "-") == 0)
		fout = stdout;
	else if (*local == '|') {
null();//		oldintp = signal(SIGPIPE, SIG_IGN);
		fout = _popen(local + 1, "w");
		if (fout == NULL) {
			perror(local+1);
			goto abort;
		}
		closefunc = _pclose;
	} else {
		fout = fopen(local, mode);
		if (fout == NULL) {
			perror(local);
			goto abort;
		}
		closefunc = fclose;
	}
	(void) gettimeofday(&start, (struct timezone *)0);
	switch (type) {

	case TYPE_I:
	case TYPE_L:
		if (restart_point &&
		    lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
			perror(local);
			if (closefunc != NULL)
				(*closefunc)(fout);
			return;
		}
		errno = d = 0;
//		while ((c = recv(din, buf, bufsize, 1)) > 0) {
//			if ((d = write(fileno(fout), buf, c)) != c)
//			if ((d = write(fileno(fout), buf, c)) != c)
//				break;
		while ((c = recv(din, buf, bufsize, 0)) > 0) {
                   write(fileno(fout), buf, c);
                   bytes += c;
                   if (hash) {
                      while (bytes >= hashbytes) {
                         (void) putchar('#');
                         hashbytes += HASHBYTES;
                      }
                      (void) fflush(stdout);
                   }
		}
		if (hash && bytes > 0) {
			if (bytes < HASHBYTES)
				(void) putchar('#');
			(void) putchar('\n');
			(void) fflush(stdout);
		}
//		if (c < 0) {
//			if (errno != EPIPE)
//				perror("netin");
//			bytes = -1;
//		}
//		if (d < c) {
//			if (d < 0)
//				perror(local);
//			else
//				fprintf(stderr, "%s: short write\n", local);
//		}
		break;

	case TYPE_A:
		if (restart_point) {
			register int i, n, c;

			if (fseek(fout, 0L, L_SET) < 0)
				goto done;
			n = restart_point;
			i = 0;
			while (i++ < n) {
				if ((c=getc(fout)) == EOF)
					goto done;
				if (c == '\n')
					i++;
			}
			if (fseek(fout, 0L, L_INCR) < 0) {
done:
				perror(local);
				if (closefunc != NULL)
					(*closefunc)(fout);
				return;
			}
		}
		while ((c = fgetcSocket(din)) != EOF) {
			if (c == '\n')
				bare_lfs++;
			while (c == '\r') {
                           while (hash && (bytes >= hashbytes)) {
                              (void) putchar('#');
                              (void) fflush(stdout);
                              hashbytes += HASHBYTES;
                           }
                           bytes++;
                           if ((c = fgetcSocket(din)) != '\n' || tcrflag) {
                              if (ferror(fout))
                                 goto break2;
                              (void) putc('\r', fout);
                              if (c == '\0') {
                                 bytes++;
                                 goto contin2;
                              }
                              if (c == EOF)
                                 goto contin2;
                           }
			}
			(void) putc(c, fout);
			bytes++;
	contin2:	;
		}
break2:
		if (bare_lfs) {
			printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
			printf("File may not have transferred correctly.\n");
			(void) fflush(stdout);
		}
		if (hash) {
			if (bytes < hashbytes)
				(void) putchar('#');
			(void) putchar('\n');
			(void) fflush(stdout);
		}
//		if (ferror(din)) {
//			if (errno != EPIPE)
//				perror("netin");
//			bytes = -1;
//		}
		if (ferror(fout))
			perror(local);
		break;
	}
	if (closefunc != NULL)
		(*closefunc)(fout);
null();//	(void) signal(SIGINT, oldintr);
	if (oldintp)
null();//		(void) signal(SIGPIPE, oldintp);
	(void) gettimeofday(&stop, (struct timezone *)0);
	if(closesocket(din)) {
		int iret=WSAGetLastError ();
		fprintf(stdout,"Error closing socket(%d)\n",iret);
		(void) fflush(stdout);
	}

	(void) getreply(0);
	if (bytes > 0 && is_retr)
		ptransfer("received", bytes, &start, &stop);
	if (oldtype) {
		if (!debug)
			verbose = 0;
		switch (oldtype) {
			case TYPE_I:
				setbinary();
				break;
			case TYPE_E:
				setebcdic();
				break;
			case TYPE_L:
				settenex();
				break;
		}
		verbose = oldverbose;
	}
	return;
abort:

/* abort using RFC959 recommended IP,SYNC sequence  */

	(void) gettimeofday(&stop, (struct timezone *)0);
	if (oldintp)
null();//		(void) signal(SIGPIPE, oldintr);
null();//	(void) signal(SIGINT,SIG_IGN);
	if (oldtype) {
		if (!debug)
			verbose = 0;
		switch (oldtype) {
			case TYPE_I:
				setbinary();
				break;
			case TYPE_E:
				setebcdic();
				break;
			case TYPE_L:
				settenex();
				break;
		}
		verbose = oldverbose;
	}
	if (!cpend) {
		code = -1;
null();//		(void) signal(SIGINT,oldintr);
		return;
	}

	fprintfSocket(cout,"%c%c",IAC,IP);
	msg = (char)IAC;
/* send IAC in urgent mode instead of DM because UNIX places oob mark */
/* after urgent byte rather than before as now is protocol            */
	if (send(cout,&msg,1,MSG_OOB) != 1) {
		perror("abort");
	}
	fprintfSocket(cout,"%cABOR\r\n",DM);
	FD_ZERO(&mask);
	FD_SET(cin, &mask); // Need to correct this
	if (din) {
		FD_SET(din, &mask); // Need to correct this
	}
	if ((nfnd = empty(&mask,10)) <= 0) {
		if (nfnd < 0) {
			perror("abort");
		}
		code = -1;
		lostpeer();
	}
	if (din && FD_ISSET(din, &mask)) {
		while ((c = recv(din, buf, bufsize, 0)) > 0)
			;
	}
	if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
		if (data >= 0) {
			(void) close(data);
			data = -1;
		}
		(void) getreply(0);
	}
	(void) getreply(0);
	code = -1;
	if (data >= 0) {
		(void) close(data);
		data = -1;
	}
	if (closefunc != NULL && fout != NULL)
		(*closefunc)(fout);
	if (din)
		if(closesocket(din)) {
			int iret=WSAGetLastError ();
			fprintf(stdout,"Error closing socket(%d)\n",iret);
			(void) fflush(stdout);
		}

	if (bytes > 0)
		ptransfer("received", bytes, &start, &stop);
null();//	(void) signal(SIGINT,oldintr);
}

/*
 * Need to start a listen on the data channel
 * before we send the command, otherwise the
 * server's connect may fail.
 */
int sendport = -1;

int
initconn()
{
	register char *p, *a;
	int result, len, tmpno = 0;
	int on = 1;
	int a0, a1, a2, a3, p0, p1;


	if (passivemode) {
      data = socket(AF_INET, SOCK_STREAM, 0);
      if (data < 0) {
        perror("ftp: socket");
        return(1);
      }
      if ((options & SO_DEBUG) &&
          setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
                     sizeof (on)) < 0)
        perror("ftp: setsockopt (ignored)");
      if (command("PASV") != COMPLETE) {
        printf("Passive mode refused.\n");
        goto bad;
      }

      /*
       * What we've got at this point is a string of comma
       * separated one-byte unsigned integer values.
       * The first four are the an IP address. The fifth is
       * the MSB of the port number, the sixth is the LSB.
       * From that we'll prepare a sockaddr_in.
       */

      if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",
                 &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
        printf("Passive mode address scan failure. Shouldn't happen!\n");
        goto bad;
      }

      bzero(&data_addr, sizeof(data_addr));
      data_addr.sin_family = AF_INET;
      a = (char *)&data_addr.sin_addr.s_addr;
      a[0] = a0 & 0xff;
      a[1] = a1 & 0xff;
      a[2] = a2 & 0xff;
      a[3] = a3 & 0xff;
      p = (char *)&data_addr.sin_port;
      p[0] = p0 & 0xff;
      p[1] = p1 & 0xff;

      if (connect(data, (struct sockaddr *)&data_addr,
                  sizeof(data_addr)) < 0) {
        perror("ftp: connect");
        goto bad;
      }
      return(0);
	}


noport:
	data_addr = myctladdr;
	if (sendport)
		data_addr.sin_port = 0;	/* let system pick one */
	if (data != -1)
		(void) close (data);
	data = socket(AF_INET, SOCK_STREAM, 0);
	if (data < 0) {
		perror("ftp: socket");
		if (tmpno)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?