⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:

#ifdef HAVE_SIGSETJMP
		sj = sigsetjmp(gCancelConnectJmp, 1);
#else
		sj = setjmp(gCancelConnectJmp);
#endif	/* HAVE_SIGSETJMP */

		if (sj != 0) {
			/* Interrupted by a signal. */
			(void) closesocket(sockfd);
			(void) signal(SIGINT, (FTPSigProc) osigint);
			if (vcip->connTimeout > 0) {
				(void) alarm(0);
				(void) signal(SIGALRM, (FTPSigProc) osigalrm);
			}
			if (gGotSig == SIGINT) {
				result = vcip->errNo = kErrConnectMiscErr;
				Error(vcip, kDontPerror, "Connection attempt canceled.\n");
				(void) kill(getpid(), SIGINT);
			} else if (gGotSig == SIGALRM) {
				result = vcip->errNo = kErrConnectRetryableErr;
				Error(vcip, kDontPerror, "Connection attempt timed-out.\n");
				(void) kill(getpid(), SIGALRM);
			} else {
				result = vcip->errNo = kErrConnectMiscErr;
				Error(vcip, kDontPerror, "Connection attempt failed due to an unexpected signal (%d).\n", gGotSig);
			}
			return (result);
		} else  {
			err = connect(sockfd, (struct sockaddr *) &cip->servCtlAddr,
				      (int) sizeof (cip->servCtlAddr));
			if (cip->connTimeout > 0) {
				(void) alarm(0);
				(void) signal(SIGALRM, (FTPSigProc) osigalrm);
			}
			(void) signal(SIGINT, (FTPSigProc) osigint);
		}

		if (err < 0) {
			oerrno = errno;
			(void) closesocket(sockfd);
			errno = oerrno;
			sockfd = -1;
		}
#endif	/* NO_SIGNALS */
	} else {
		/* We can try each address in the list.  We'll quit when we
		 * run out of addresses to try or get a successful connection.
		 */
		for (curaddr = hp->h_addr_list; *curaddr != NULL; curaddr++) {
			if ((sockfd = socket(cip->servCtlAddr.sin_family, SOCK_STREAM, 0)) < 0) {
				Error(cip, kDoPerror, "Could not get a socket.\n");
				cip->errNo = kErrNewStreamSocket;
				return (kErrNewStreamSocket);
			}
			/* This could overwrite the address field in the structure,
			 * but this is okay because the structure has a junk field
			 * just for this purpose.
			 */
			(void) memcpy(&cip->servCtlAddr.sin_addr, *curaddr, (size_t) hp->h_length);

			/* This doesn't do anything if you left these
			 * at their defaults (zero).  Otherwise it
			 * tries to set the buffer size to the
			 * size specified.
			 */
			(void) SetSockBufSize(sockfd, cip->ctrlSocketRBufSize, cip->ctrlSocketSBufSize);

#ifdef NO_SIGNALS
			err = SConnect(sockfd, &cip->servCtlAddr, (int) cip->connTimeout);

			if (err == 0)
				break;
			oerrno = errno;
			(void) SClose(sockfd, 3);
			errno = oerrno;
			sockfd = -1;
#else	/* NO_SIGNALS */

			osigint = (volatile FTPSigProc) signal(SIGINT, CancelConnect);
			if (cip->connTimeout > 0) {
				osigalrm = (volatile FTPSigProc) signal(SIGALRM, CancelConnect);
				(void) alarm(cip->connTimeout);
			}

			vcip = cip;
#ifdef HAVE_SIGSETJMP
			sj = sigsetjmp(gCancelConnectJmp, 1);
#else
			sj = setjmp(gCancelConnectJmp);
#endif	/* HAVE_SIGSETJMP */

			if (sj != 0) {
				/* Interrupted by a signal. */
				(void) closesocket(sockfd);
				(void) signal(SIGINT, (FTPSigProc) osigint);
				if (vcip->connTimeout > 0) {
					(void) alarm(0);
					(void) signal(SIGALRM, (FTPSigProc) osigalrm);
				}
				if (gGotSig == SIGINT) {
					result = vcip->errNo = kErrConnectMiscErr;
					Error(vcip, kDontPerror, "Connection attempt canceled.\n");
					(void) kill(getpid(), SIGINT);
				} else if (gGotSig == SIGALRM) {
					result = vcip->errNo = kErrConnectRetryableErr;
					Error(vcip, kDontPerror, "Connection attempt timed-out.\n");
					(void) kill(getpid(), SIGALRM);
				} else {
					result = vcip->errNo = kErrConnectMiscErr;
					Error(vcip, kDontPerror, "Connection attempt failed due to an unexpected signal (%d).\n", gGotSig);
				}
				return (result);
			} else {
				err = connect(sockfd, (struct sockaddr *) &cip->servCtlAddr,
					      (int) sizeof (cip->servCtlAddr));
				if (cip->connTimeout > 0) {
					(void) alarm(0);
					(void) signal(SIGALRM, (FTPSigProc) osigalrm);
				}
				(void) signal(SIGINT, (FTPSigProc) osigint);
			}

			if (err == 0)
				break;
			oerrno = errno;
			(void) closesocket(sockfd);
			errno = oerrno;
			sockfd = -1;
#endif /* NO_SIGNALS */
		}
	}

	if (err < 0) {
		/* Could not connect.  Close up shop and go home. */

		/* If possible, tell the caller if they should bother
		 * calling back later.
		 */
		switch (errno) {
#ifdef ENETDOWN
			case ENETDOWN:
#elif defined(WSAENETDOWN)
			case WSAENETDOWN:
#endif
#ifdef ENETUNREACH
			case ENETUNREACH:
#elif defined(WSAENETUNREACH)
			case WSAENETUNREACH:
#endif
#ifdef ECONNABORTED
			case ECONNABORTED:
#elif defined(WSAECONNABORTED)
			case WSAECONNABORTED:
#endif
#ifdef ETIMEDOUT
			case ETIMEDOUT:
#elif defined(WSAETIMEDOUT)
			case WSAETIMEDOUT:
#endif
#ifdef EHOSTDOWN
			case EHOSTDOWN:
#elif defined(WSAEHOSTDOWN)
			case WSAEHOSTDOWN:
#endif
#ifdef ECONNRESET
			case ECONNRESET:
#elif defined(WSAECONNRESET)
			case WSAECONNRESET:
#endif
				Error(cip, kDoPerror, "Could not connect to %s -- try again later.\n", fhost);
				result = cip->errNo = kErrConnectRetryableErr;
				break;
#ifdef ECONNREFUSED
			case ECONNREFUSED:
#elif defined(WSAECONNREFUSED)
			case WSAECONNREFUSED:
#endif
				Error(cip, kDoPerror, "Could not connect to %s.\n", fhost);
				result = cip->errNo = kErrConnectRefused;
				break;
			default:
				Error(cip, kDoPerror, "Could not connect to %s.\n", fhost);
				result = cip->errNo = kErrConnectMiscErr;
		}
		goto fatal;
	}

	/* Get our end of the socket address for later use. */
	if ((result = GetSocketAddress(cip, sockfd, &cip->ourCtlAddr)) < 0)
		goto fatal;

#ifdef SO_OOBINLINE
	/* We want Out-of-band data to appear in the regular stream,
	 * since we can handle TELNET.
	 */
	(void) SetInlineOutOfBandData(cip, sockfd);
#endif
	(void) SetKeepAlive(cip, sockfd);
	(void) SetLinger(cip, sockfd, 0);	/* Don't need it for ctrl. */

#if defined(IP_TOS) && defined(IPTOS_LOWDELAY)
	/* Control connection is somewhat interactive, so quick response
	 * is desired.
	 */
	(void) SetTypeOfService(cip, sockfd, IPTOS_LOWDELAY);
#endif

#ifdef NO_SIGNALS
	cip->ctrlSocketR = sockfd;
	cip->ctrlSocketW = sockfd;
	cip->cout = NULL;
	cip->cin = NULL;
	sock2fd = kClosedFileDescriptor;

	if (InitSReadlineInfo(&cip->ctrlSrl, sockfd, cip->srlBuf, sizeof(cip->srlBuf), (int) cip->ctrlTimeout, 1) < 0) {
		result = kErrFdopenW;
		cip->errNo = kErrFdopenW;
		Error(cip, kDoPerror, "Could not fdopen.\n");
		goto fatal;
	}
#else	/* NO_SIGNALS */
	if ((sock2fd = dup(sockfd)) < 0) {
		result = kErrDupSocket;
		cip->errNo = kErrDupSocket;
		Error(cip, kDoPerror, "Could not duplicate a file descriptor.\n");
		goto fatal;
	}

	/* Now setup the FILE pointers for use with the Std I/O library
	 * routines.
	 */
	if ((cip->cin = fdopen(sockfd, "r")) == NULL) {
		result = kErrFdopenR;
		cip->errNo = kErrFdopenR;
		Error(cip, kDoPerror, "Could not fdopen.\n");
		goto fatal;
	}

	if ((cip->cout = fdopen(sock2fd, "w")) == NULL) {
		result = kErrFdopenW;
		cip->errNo = kErrFdopenW;
		Error(cip, kDoPerror, "Could not fdopen.\n");
		CloseFile(&cip->cin);
		sockfd = kClosedFileDescriptor;
		goto fatal;
	}

	cip->ctrlSocketR = sockfd;
	cip->ctrlSocketW = sockfd;

	/* We'll be reading and writing lines, so use line buffering.  This
	 * is necessary since the stdio library will use full buffering
	 * for all streams not associated with the tty.
	 */
#ifdef HAVE_SETLINEBUF
	setlinebuf(cip->cin);
	setlinebuf(cip->cout);
#else
	(void) SETVBUF(cip->cin, NULL, _IOLBF, (size_t) BUFSIZ);
	(void) SETVBUF(cip->cout, NULL, _IOLBF, (size_t) BUFSIZ);
#endif
#endif	/* NO_SIGNALS */

#ifdef HAVE_INET_NTOP	/* Mostly to workaround bug in IRIX 6.5's inet_ntoa */
	(void) memset(cip->ip, 0, sizeof(cip->ip));
	(void) inet_ntop(AF_INET, &cip->servCtlAddr.sin_addr, cip->ip, sizeof(cip->ip) - 1);
#else
	(void) STRNCPY(cip->ip, inet_ntoa(cip->servCtlAddr.sin_addr));
#endif
	if ((hp == NULL) || (hp->h_name == NULL))
		(void) STRNCPY(cip->actualHost, fhost);
	else
		(void) STRNCPY(cip->actualHost, (char *) hp->h_name);

	/* Read the startup message from the server. */
	rp = InitResponse();
	if (rp == NULL) {
		Error(cip, kDontPerror, "Malloc failed.\n");
		cip->errNo = kErrMallocFailed;
		result = cip->errNo;
		goto fatal;
	}

	result = GetResponse(cip, rp);
	if ((result < 0) && (rp->msg.first == NULL)) {
		goto fatal;
	}
	if (rp->msg.first != NULL) {
		cip->serverType = kServerTypeUnknown;
		srvr = NULL;
		firstLine = rp->msg.first->line;
		secondLine = NULL;
		if (rp->msg.first->next != NULL)
			secondLine = rp->msg.first->next->line;

		if (strstr(firstLine, "Version wu-") != NULL) {
			cip->serverType = kServerTypeWuFTPd;
			srvr = "wu-ftpd";
		} else if (strstr(firstLine, "NcFTPd") != NULL) {
			cip->serverType = kServerTypeNcFTPd;
			srvr = "NcFTPd Server";
		} else if (STRNEQ("ProFTPD", firstLine, 7)) {
			cip->serverType = kServerTypeProFTPD;
			srvr = "ProFTPD";
		} else if (strstr(firstLine, "Microsoft FTP Service") != NULL) {
			cip->serverType = kServerTypeMicrosoftFTP;
			srvr = "Microsoft FTP Service";
		} else if (strstr(firstLine, "(NetWare ") != NULL) {
			cip->serverType = kServerTypeNetWareFTP;
			srvr = "NetWare FTP Service";
		} else if (STRNEQ("WFTPD", firstLine, 5)) {
			cip->serverType = kServerTypeWFTPD;
			srvr = "WFTPD";
		} else if (STRNEQ("Serv-U FTP", firstLine, 10)) {
			cip->serverType = kServerTypeServ_U;
			srvr = "Serv-U FTP-Server";
		} else if (strstr(firstLine, "VFTPD") != NULL) {
			cip->serverType = kServerTypeVFTPD;
			srvr = "VFTPD";
		} else if (STRNEQ("FTP-Max", firstLine, 7)) {
			cip->serverType = kServerTypeFTP_Max;
			srvr = "FTP-Max";
		} else if (strstr(firstLine, "Roxen") != NULL) {
			cip->serverType = kServerTypeRoxen;
			srvr = "Roxen";
		} else if (strstr(firstLine, "WS_FTP") != NULL) {
			cip->serverType = kServerTypeWS_FTP;
			srvr = "WS_FTP Server";
		} else if ((secondLine != NULL) && (strstr(secondLine, "WarFTP") != NULL)) {
			cip->serverType = kServerTypeWarFTPd;
			srvr = "WarFTPd";
		}

		if (srvr != NULL)
			PrintF(cip, "Remote server is running %s.\n", srvr);

		/* Do the application's connect message callback, if present. */
		if ((cip->onConnectMsgProc != 0) && (rp->codeType < 4))
			(*cip->onConnectMsgProc)(cip, rp);
	}

	if (rp->codeType >= 4) {
		/* They probably hung up on us right away.  That's too bad,
		 * but we can tell the caller that they can call back later
		 * and try again.
		 */
		DoneWithResponse(cip, rp);
		result = kErrConnectRetryableErr;
		Error(cip, kDontPerror, "Server hungup immediately after connect.\n");
		cip->errNo = kErrConnectRetryableErr;
		goto fatal;
	}
	if (result < 0)		/* Some other error occurred during connect message */
		goto fatal;
	cip->connected = 1;
	DoneWithResponse(cip, rp);
	return (kNoErr);

fatal:
	if (sockfd > 0)
		(void) closesocket(sockfd);
	if (sock2fd > 0)
		(void) closesocket(sock2fd);
	CloseFile(&cip->cin);
	CloseFile(&cip->cout);
	cip->ctrlSocketR = kClosedFileDescriptor;
	cip->ctrlSocketW = kClosedFileDescriptor;
	return (result);
}	/* OpenControlConnection */




void
CloseDataConnection(const FTPCIPtr cip)
{
	if (cip->dataSocket != kClosedFileDescriptor) {
#ifdef NO_SIGNALS
		SClose(cip->dataSocket, 3);
#else	/* NO_SIGNALS */
		if (cip->xferTimeout > 0)
			(void) alarm(cip->xferTimeout);
		(void) closesocket(cip->dataSocket);
		if (cip->xferTimeout > 0)
			(void) alarm(0);
#endif	/* NO_SIGNALS */
		cip->dataSocket = kClosedFileDescriptor;
	}
	memset(&cip->ourDataAddr, 0, sizeof(cip->ourDataAddr));
	memset(&cip->servDataAddr, 0, sizeof(cip->servDataAddr));
}	/* CloseDataConnection */




int
SetStartOffset(const FTPCIPtr cip, longest_int restartPt)
{
	ResponsePtr rp;
	int result;

	if (restartPt != (longest_int) 0) {
		rp = InitResponse();
		if (rp == NULL) {
			Error(cip, kDontPerror, "Malloc failed.\n");
			cip->errNo = kErrMallocFailed;
			return (cip->errNo);
		}

		/* Force reset to offset zero. */
		if (restartPt == (longest_int) -1)
			restartPt = (longest_int) 0;
#ifdef PRINTF_LONG_LONG
		result = RCmd(cip, rp,
		"REST " PRINTF_LONG_LONG,
		restartPt);
#else
		result = RCmd(cip, rp, "REST %ld", (long) restartPt);
#endif

		if (result < 0) {
			return (result);
		} else if (result == 3) {
			cip->hasREST = kCommandAvailable;
			DoneWithResponse(cip, rp);
		} else if (UNIMPLEMENTED_CMD(rp->code)) {
			cip->hasREST = kCommandNotAvailable;
			DoneWithResponse(cip, rp);
			cip->errNo = kErrSetStartPoint;
			return (kErrSetStartPoint);
		} else {
			DoneWithResponse(cip, rp);
			cip->errNo = kErrSetStartPoint;
			return (kErrSetStartPoint);
		}
	}
	return (0);
}	/* SetStartOffset */



static int
SendPort(const FTPCIPtr cip, struct sockaddr_in *saddr)
{
	char *a, *p;
	int result;
	ResponsePtr rp;

	rp = InitResponse();
	if (rp == NULL) {
		Error(cip, kDontPerror, "Malloc failed.\n");
		cip->errNo = kErrMallocFailed;
		return (cip->errNo);
	}

⌨️ 快捷键说明

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