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

📄 rcmd.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
			return (cip->errNo);
		}
		return (kNoErr);
	}
	return (kErrNotConnected);
}	/* SendCommand */

#else	/* NO_SIGNALS */

static int
SendCommand(const FTPCIPtr cip, const char *cmdspec, va_list ap)
{
	longstring command;
	int result;
	volatile FTPCIPtr vcip;
	volatile FTPSigProc osigpipe;
	int sj;

	if (cip->cout != NULL) {
#ifdef HAVE_VSNPRINTF
		(void) vsnprintf(command, sizeof(command) - 1, cmdspec, ap);
		command[sizeof(command) - 1] = '\0';
#else
		(void) vsprintf(command, cmdspec, ap);
#endif
		if ((strncmp(command, "PASS", SZ(4)) != 0) || ((strcmp(cip->user, "anonymous") == 0) && (cip->firewallType == kFirewallNotInUse)))
			PrintF(cip, "Cmd: %s\n", command);
		else
			PrintF(cip, "Cmd: %s\n", "PASS xxxxxxxx");
		(void) STRNCAT(command, "\r\n");	/* Use TELNET end-of-line. */
		cip->lastFTPCmdResultStr[0] = '\0';
		cip->lastFTPCmdResultNum = -1;

		osigpipe = (volatile FTPSigProc) signal(SIGPIPE, BrokenCtrl);
		vcip = cip;

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

		if (sj != 0) {
			(void) signal(SIGPIPE, (FTPSigProc) osigpipe);
			FTPShutdownHost(vcip);
			if (vcip->eofOkay == 0) {
				Error(cip, kDontPerror, "Remote host has closed the connection.\n");
				vcip->errNo = kErrRemoteHostClosedConnection;
				return(vcip->errNo);
			}
			return (kNoErr);
		}

		result = fputs(command, cip->cout);
		if (result < 0) {
			(void) signal(SIGPIPE, osigpipe);
			cip->errNo = kErrSocketWriteFailed;
			Error(cip, kDoPerror, "Could not write to control stream.\n");
			return (cip->errNo);
		}
		result = fflush(cip->cout);
		if (result < 0) {
			(void) signal(SIGPIPE, osigpipe);
			cip->errNo = kErrSocketWriteFailed;
			Error(cip, kDoPerror, "Could not write to control stream.\n");
			return (cip->errNo);
		}
		(void) signal(SIGPIPE, osigpipe);
		return (kNoErr);
	}
	return (kErrNotConnected);
}	/* SendCommand */
#endif	/* NO_SIGNALS */



/* For "simple" (i.e. not data transfer) commands, this routine is used
 * to send the command and receive one response.  It returns the codeType
 * field of the 'Response' as the result, or a negative number upon error.
 */
/*VARARGS*/
int
FTPCmd(const FTPCIPtr cip, const char *const cmdspec, ...)
{
	va_list ap;
	int result;
	ResponsePtr rp;

	if (cip == NULL)
		return (kErrBadParameter);
	if (strcmp(cip->magic, kLibraryMagic))
		return (kErrBadMagic);

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

	va_start(ap, cmdspec);
#ifndef NO_SIGNALS
	if (cip->ctrlTimeout > 0)
		(void) alarm(cip->ctrlTimeout);
#endif	/* NO_SIGNALS */
	result = SendCommand(cip, cmdspec, ap);
	va_end(ap);
	if (result < 0) {
#ifndef NO_SIGNALS
		if (cip->ctrlTimeout > 0)
			(void) alarm(0);
#endif	/* NO_SIGNALS */
		return (result);
	}

	/* Get the response to the command we sent. */
	result = GetResponse(cip, rp);
#ifndef NO_SIGNALS
	if (cip->ctrlTimeout > 0)
		(void) alarm(0);
#endif	/* NO_SIGNALS */

	if (result == kNoErr)
		result = rp->codeType;
	DoneWithResponse(cip, rp);
	return (result);
}	/* FTPCmd */




/* This is for debugging the library -- don't use. */
/*VARARGS*/
int
FTPCmdNoResponse(const FTPCIPtr cip, const char *const cmdspec, ...)
{
	va_list ap;

	if (cip == NULL)
		return (kErrBadParameter);
	if (strcmp(cip->magic, kLibraryMagic))
		return (kErrBadMagic);

	va_start(ap, cmdspec);
#ifndef NO_SIGNALS
	if (cip->ctrlTimeout > 0)
		(void) alarm(cip->ctrlTimeout);
#endif	/* NO_SIGNALS */
	(void) SendCommand(cip, cmdspec, ap);
#ifndef NO_SIGNALS
	if (cip->ctrlTimeout > 0)
		(void) alarm(0);
#endif	/* NO_SIGNALS */
	va_end(ap);

	return (kNoErr);
}	/* FTPCmdNoResponse */




int
WaitResponse(const FTPCIPtr cip, unsigned int sec)
{
	int result;
	fd_set ss;
	struct timeval tv;
	int fd;

#ifdef NO_SIGNALS
	fd = cip->ctrlSocketR;
#else	/* NO_SIGNALS */
	if (cip->cin == NULL)
		return (-1);
	fd = fileno(cip->cin);
#endif	/* NO_SIGNALS */
	if (fd < 0)
		return (-1);
	FD_ZERO(&ss);
	FD_SET(fd, &ss);
	tv.tv_sec = (unsigned long) sec;
	tv.tv_usec = 0;
	result = select(fd + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, &tv);
	return (result);
}	/* WaitResponse */




/* For "simple" (i.e. not data transfer) commands, this routine is used
 * to send the command and receive one response.  It returns the codeType
 * field of the 'Response' as the result, or a negative number upon error.
 */

/*VARARGS*/
int
RCmd(const FTPCIPtr cip, ResponsePtr rp, const char *cmdspec, ...)
{
	va_list ap;
	int result;

	if (cip == NULL)
		return (kErrBadParameter);
	if (strcmp(cip->magic, kLibraryMagic))
		return (kErrBadMagic);

	va_start(ap, cmdspec);
#ifndef NO_SIGNALS
	if (cip->ctrlTimeout > 0)
		(void) alarm(cip->ctrlTimeout);
#endif	/* NO_SIGNALS */
	result = SendCommand(cip, cmdspec, ap);
	va_end(ap);
	if (result < 0) {
#ifndef NO_SIGNALS
		if (cip->ctrlTimeout > 0)
			(void) alarm(0);
#endif	/* NO_SIGNALS */
		return (result);
	}

	/* Get the response to the command we sent. */
	result = GetResponse(cip, rp);
#ifndef NO_SIGNALS
	if (cip->ctrlTimeout > 0)
		(void) alarm(0);
#endif	/* NO_SIGNALS */

	if (result == kNoErr)
		result = rp->codeType;
	return (result);
}	/* RCmd */



/* Returns -1 if an error occurred, or 0 if not.
 * This differs from RCmd, which returns the code class of a response.
 */

/*VARARGS*/
int
FTPStartDataCmd(const FTPCIPtr cip, int netMode, int type, longest_int startPoint, const char *cmdspec, ...)
{
	va_list ap;
	int result;
	int respCode;
	ResponsePtr rp;

	if (cip == NULL)
		return (kErrBadParameter);
	if (strcmp(cip->magic, kLibraryMagic))
		return (kErrBadMagic);

	result = FTPSetTransferType(cip, type);
	if (result < 0)
		return (result);

	/* Re-set the cancellation flag. */
	cip->cancelXfer = 0;

	/* To transfer data, we do these things in order as specifed by
	 * the RFC.
	 *
	 * First, we tell the other side to set up a data line.  This
	 * is done below by calling OpenDataConnection(), which sets up
	 * the socket.  When we do that, the other side detects a connection
	 * attempt, so it knows we're there.  Then tell the other side
	 * (by using listen()) that we're willing to receive a connection
	 * going to our side.
	 */

	if ((result = OpenDataConnection(cip, cip->dataPortMode)) < 0)
		goto done;

	/* If asked, attempt to start at a later position in the remote file. */
	if (startPoint != (longest_int) 0) {
		if ((startPoint == kSizeUnknown) || ((result = SetStartOffset(cip, startPoint)) != 0))
			startPoint = (longest_int) 0;
	}
	cip->startPoint = startPoint;

	/* Now we tell the server what we want to do.  This sends the
	 * the type of transfer we want (RETR, STOR, LIST, etc) and the
	 * parameters for that (files to send, directories to list, etc).
	 */
	va_start(ap, cmdspec);
#ifndef NO_SIGNALS
	if (cip->ctrlTimeout > 0)
		(void) alarm(cip->ctrlTimeout);
#endif	/* NO_SIGNALS */
	result = SendCommand(cip, cmdspec, ap);
	va_end(ap);
	if (result < 0) {
#ifndef NO_SIGNALS
		if (cip->ctrlTimeout > 0)
			(void) alarm(0);
#endif	/* NO_SIGNALS */
		goto done;
	}

	/* Get the response to the transfer command we sent, to see if
	 * they can accomodate the request.  If everything went okay,
	 * we will get a preliminary response saying that the transfer
	 * initiation was successful and that the data is there for
	 * reading (for retrieves;  for sends, they will be waiting for
	 * us to send them something).
	 */
	rp = InitResponse();
	if (rp == NULL) {
		Error(cip, kDontPerror, "Malloc failed.\n");
		cip->errNo = kErrMallocFailed;
		result = cip->errNo;
		goto done;
	}
	result = GetResponse(cip, rp);
#ifndef NO_SIGNALS
	if (cip->ctrlTimeout > 0)
		(void) alarm(0);
#endif	/* NO_SIGNALS */

	if (result < 0)
		goto done;
	respCode = rp->codeType;
	DoneWithResponse(cip, rp);

	if (respCode > 2) {
		cip->errNo = kErrCouldNotStartDataTransfer;
		result = cip->errNo;
		goto done;
	}

	/* Now we accept the data connection that the other side is offering
	 * to us.  Then we can do the actual I/O on the data we want.
	 */
	cip->netMode = netMode;
	if ((result = AcceptDataConnection(cip)) < 0)
		goto done;
	return (kNoErr);

done:
	(void) FTPEndDataCmd(cip, 0);
	return (result);
}	/* FTPStartDataCmd */




void
FTPAbortDataTransfer(const FTPCIPtr cip)
{
	ResponsePtr rp;
	int result;

	if (cip->dataSocket != kClosedFileDescriptor) {
		PrintF(cip, "Starting abort sequence.\n");
		SendTelnetInterrupt(cip);		/* Probably could get by w/o doing this. */

		result = FTPCmdNoResponse(cip, "ABOR");
		if (result != kNoErr) {
			/* Linger could cause close to block, so unset it. */
			(void) SetLinger(cip, cip->dataSocket, 0);
			CloseDataConnection(cip);
			PrintF(cip, "Could not send abort command.\n");
			return;
		}

		if (cip->abortTimeout > 0) {
			result = WaitResponse(cip, (unsigned int) cip->abortTimeout);
			if (result <= 0) {
				/* Error or no response received to ABOR in time. */
				(void) SetLinger(cip, cip->dataSocket, 0);
				CloseDataConnection(cip);
				PrintF(cip, "No response received to abort request.\n");
				return;
			}
		}

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

		result = GetResponse(cip, rp);
		if (result < 0) {
			/* Shouldn't happen, and doesn't matter if it does. */
			(void) SetLinger(cip, cip->dataSocket, 0);
			CloseDataConnection(cip);
			PrintF(cip, "Invalid response to abort request.\n");
			DoneWithResponse(cip, rp);
			return;
		}
		DoneWithResponse(cip, rp);

		/* A response to the abort request has been received.
		 * Now the only thing left to do is close the data
		 * connection, making sure to turn off linger mode
		 * since we don't care about straggling data bits.
		 */
		(void) SetLinger(cip, cip->dataSocket, 0);
		CloseDataConnection(cip);		/* Must close (by protocol). */
		PrintF(cip, "End abort.\n");
	}
}	/* FTPAbortDataTransfer */




int
FTPEndDataCmd(const FTPCIPtr cip, int didXfer)
{
	int result;
	int respCode;
	ResponsePtr rp;

	if (cip == NULL)
		return (kErrBadParameter);
	if (strcmp(cip->magic, kLibraryMagic))
		return (kErrBadMagic);

	CloseDataConnection(cip);
	result = kNoErr;
	if (didXfer) {
		/* Get the response to the data transferred.  Most likely a message
		 * saying that the transfer completed succesfully.  However, if
		 * we tried to abort the transfer using ABOR, we will have a response
		 * to that command instead.
		 */
		rp = InitResponse();
		if (rp == NULL) {
			Error(cip, kDontPerror, "Malloc failed.\n");
			cip->errNo = kErrMallocFailed;
			result = cip->errNo;
			return (result);
		}
		result = GetResponse(cip, rp);
		if (result < 0)
			return (result);
		respCode = rp->codeType;
		DoneWithResponse(cip, rp);
		if (respCode != 2) {
			cip->errNo = kErrDataTransferFailed;
			result = cip->errNo;
		} else {
			result = kNoErr;
		}
	}
	return (result);
}	/* FTPEndDataCmd */




int
BufferGets(char *buf, size_t bufsize, int inStream, char *secondaryBuf, char **secBufPtr, char **secBufLimit, size_t secBufSize)
{
	int err;
	char *src;
	char *dst;
	char *dstlim;
	int len;
	int nr;
	int haveEof = 0;

	err = 0;
	dst = buf;
	dstlim = dst + bufsize - 1;		/* Leave room for NUL. */
	src = (*secBufPtr);
	for ( ; dst < dstlim; ) {
		if (src >= (*secBufLimit)) {
			/* Fill the buffer. */

/* Don't need to poll it here.  The routines that use BufferGets don't
 * need any special processing during timeouts (i.e. progress reports),
 * so go ahead and just let it block until there is data to read.
 */
			nr = (int) read(inStream, secondaryBuf, secBufSize);
			if (nr == 0) {
				/* EOF. */
				haveEof = 1;
				goto done;
			} else if (nr < 0) {
				/* Error. */
				err = -1;
				goto done;
			}
			(*secBufPtr) = secondaryBuf;
			(*secBufLimit) = secondaryBuf + nr;
			src = (*secBufPtr);
			if (nr < (int) secBufSize)
				src[nr] = '\0';
		}
		if (*src == '\r') {
			++src;
		} else {
			if (*src == '\n') {
				/* *dst++ = *src++; */	++src;
				goto done;
			}
			*dst++ = *src++;
		}
	}

done:
	(*secBufPtr) = src;
	*dst = '\0';
	len = (int) (dst - buf);
	if (err < 0)
		return (err);
	if ((len == 0) && (haveEof == 1))
		return (-1);
	return (len);	/* May be zero, if a blank line. */
}	/* BufferGets */

/* eof */

⌨️ 快捷键说明

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