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

📄 moncmd.c

📁 umon bootloader source code, support mips cpu.
💻 C
字号:
/** \file moncmd.c:
 *	\brief The guts of the moncmd UDP client.
 *	\author Ed Sutter esutter@lucent.com
 *
 *	This tool is used to support simple UDP communication between a host and
 *	a target running MicroMonitor.  The target is listening on port 
 *	IPPORT_MONCMD (777) for incoming command strings just as they would be
 *	seen if typed in at the RS-232 console port.  When the monitor receives
 *	this, it processes the string through the same mechanism as the console.
 *	The only addition is that all output is copied to the sender of the UDP
 *	packet (one line at a time).  Once the command has been processed, the
 *	final packet returned to the sender is a packet of size 1 with the data
 *	being zero.  This is what tells moncmd that the command has completed
 *	on the target.
 *
 *	\attention
 *	This code is part of a boot-monitor package developed as a generic base
 *	platform for embedded system designs.  As such, it is likely to be
 *	distributed to various projects beyond the control of the original
 *	author.  Please notify the author of any enhancements made or bugs found
 *	so that all may benefit from the changes.  In addition, notification back
 *	to the author will allow the new user to pick up changes that may have
 *	been made by other users after this version of the code was distributed.
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#ifdef BUILD_WITH_VCC
#include <windows.h>
#include <winsock2.h>
#else
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

#include "moncmd.h"

#ifdef BUILD_WITH_VCC
#define sleep(n) Sleep(n*1000)
#define SOCKET_INVALID(s)	(s == INVALID_SOCKET)
#else
#define SOCKET_INVALID(s)	(s < 0)
#endif

typedef unsigned char uchar;

extern	void err(char *);

/** \var char *thisProgname
 *	\brief String containing the value of argv[0] when the program was
 *	\brief executed.
 */
char *thisProgname;
				
/**	\var char *msgString
 *	\brief Pointer to the message that this program is 
 *	\brief to send to the target host.
 */
char *msgString;

/**	\var char *targetHost
 *	\brief Ip address or DNS name of host that this
 *	\brief program is to communicate with.
 */
char *targetHost;

/**	\var int retryFlag
 *	\brief If set, then the program will retry.
 */
int	retryFlag;


/**	\var int retryCount
 *	\brief Running total number of retries.
 */
int	retryCount;

/**	\var int quietMode
 *	\brief If set, then don't output status message at
 *	\brief the end of the program.
 */
int	quietMode;

/**	\var int	interactiveMode
 *	\brief If set, then moncmd runs similar to netcat, in
 *	\brief an interactive mode where each line typed is passed
 *	\brief to the target.
 */
int	interactiveMode;

/**	\var int	multirespMode
 *	\brief If set, then it is possible that more than one
 *	\brief target will respond, so don't quit after one
 *	\brief response is received.
 */
int	multirespMode;

/**	\var int waitTime
 *	\brief This is the amount of time that program will
 *	\brief wait for a response prior to giving up.
 */
int waitTime;

/**	\var int	socketFd
 *	\brief File descriptor of the open socket used to
 *	\brief communicate with the target host.
 */
int	socketFd;

/** \var int verbose
 *	\brief Set for more verbosity.
 */
int verbose;

/**	\var int	cmdRcvd
 *	\brief Set if the command has been received by the target, but no
 *	\brief additional response has been received.
 */
int	cmdRcvd;

/**	\var int binMode
 *	\brief If set, then moncmd is sending/receiving binary.
 */
int binMode;

/** \var struct sockaddr_in targetAddr
 *	\brief This structure is used to hold the socket
 *	\brief address info related to the target host.
 */
struct sockaddr_in targetAddr;

#ifdef BUILD_WITH_VCC
WSADATA WsaData;
DWORD	tid = (DWORD)0;
HANDLE	tHandle;
#else
pthread_attr_t attr;
pthread_t tid = (pthread_t)0;
#endif

/** \fn void Giveup(int sig)
 *	\brief This function is called if the alarm worker determines that
 *	\brief it is time to call it quits.
 */
void
Giveup(int sig)
{
	if (!quietMode) {
		if (cmdRcvd) {
			fprintf(stderr,
				"\n%s timeout: command received but not completed.\n",
				thisProgname);
		}
		else {
			fprintf(stderr,"\n%s timeout: command not received.\n",
				thisProgname);
		}
	}
	else {
							/* If quiteMode is set, then we just exit with */
		exit(EXIT_SUCCESS);	/* success because the user chooses to ignore */
							/* the error. */
	}

	if (cmdRcvd)
		exit(EXIT_CMP_TIMEOUT);
	else
		exit(EXIT_ACK_TIMEOUT);
}

/**	\var int	AlarmCount
 *	\brief If allowed to decrement to zero, the program gives up.
 */
int	AlarmCount;

/** \fn DWORD WINAPI AlarmWorker(LPVOID notused)
 *	\brief This is a thread that is created to provide a timeout if moncmd
 *	\brief does not receive a response within a specified amount of time.
 *  \brief For Cygwin, when the alarmworker times out, it sends a SIGUSR1
 *  \brief signal to the main process so that the recvfrom() call is 
 *  \brief interrupted.
 */
#ifdef BUILD_WITH_VCC
DWORD WINAPI AlarmWorker(LPVOID notused)
#else
void * AlarmWorker(void *notused)
#endif
{
	while(1) {
		sleep(1);
		if (AlarmCount) {
			if (AlarmCount == 1) {
				if ((retryFlag) && (!cmdRcvd)) {
					retryCount++;
					if (verbose)
						fprintf(stderr,"Retry %d: <%s> to %s...\n",
							retryCount, msgString,targetHost);
					if (sendto(socketFd,msgString,(int)strlen(msgString)+1,0,
					    (struct sockaddr *)&targetAddr,sizeof(targetAddr))<0) {
						close(socketFd);
						err("re-sendto failed");
					}
					AlarmCount = waitTime+1;
				}
				else
#ifdef BUILD_WITH_VCC
					Giveup(0);
#else
					kill(0,SIGUSR1);	/* Interrupt the recvfrom below */
					pthread_exit(0);
#endif
			}
			AlarmCount--;
		}
	}
	return(0);
}

#ifndef BUILD_WITH_VCC
/* This handler doesn't have to do anything except "exist".  The
 * purpose of this SIGUSR1 signal is to interrupt the recvfrom() call.
 */
void
handler(int sig)
{
}
#endif

/**	\fn int do_moncmd(char *hostname, char *command_to_monitor, short portnum)
 *	\param hostname Name or IP of target.
 *	\param command_to_monitor String to be sent to the target.
 *	\param portnum UDP port number to use.
 *	\brief Open a socket and send the command to the specified port of the
 *	\brief specified host.  Wait for a response if necessary.
 */
int
do_moncmd(char *hostname, char *command_to_monitor, short portnum)
{
	int	i, lasterr;
	int	msglen;
	unsigned long	inaddr;
	struct	hostent	*hp, host_info;
	char	rcvmsg[4096*4], cmdline[128];

#ifdef BUILD_WITH_VCC
	if (WSAStartup (0x0101, &WsaData) == SOCKET_ERROR)
		err("WSAStartup Failed");
#endif

	cmdRcvd = 0;
	retryCount = 0;
	targetHost = hostname;

	/* Accept target name as string or internet dotted-decimal address:
	 */
	memset((char *)&targetAddr,0,sizeof(struct sockaddr));
	if ((inaddr = inet_addr(targetHost)) != INADDR_NONE) {
		memcpy((char *)&targetAddr.sin_addr,(char *)&inaddr,sizeof(inaddr));
		host_info.h_name = NULL;
	}
	else {
		hp = gethostbyname(targetHost);
		if (hp == NULL)
			err("gethostbyname failed");
		host_info = *hp;
		memcpy((char *)&targetAddr.sin_addr,hp->h_addr,hp->h_length);
	}
	targetAddr.sin_family = AF_INET;
	targetAddr.sin_port = htons(portnum);

	socketFd = socket(AF_INET,SOCK_DGRAM,0);

	if (SOCKET_INVALID(socketFd))
		err("socket failed");

	do {
		if (interactiveMode) {
			do {
				gets(cmdline);
				command_to_monitor = cmdline;
			} while (strlen(command_to_monitor) == 0);
		}

		if (verbose)
			printf("Sending <%s> to %s...\n",command_to_monitor,targetHost);

		msgString = command_to_monitor;
		if (sendto(socketFd,msgString,(int)strlen(msgString)+1,0,
		    (struct sockaddr *)&targetAddr,sizeof(targetAddr)) < 0) {
			close(socketFd);
			err("sendto failed");
		}

		/* If the -w option says that wait time is zero, then don't bother
		 * waiting for a response, just return here.
		 */
		if (waitTime <= 0) {
			close(socketFd);
			return(EXIT_SUCCESS);
		}

		AlarmCount = waitTime;
#ifdef BUILD_WITH_VCC
		if (tid == (DWORD)0) {
			tHandle = CreateThread(NULL,0,AlarmWorker,(LPVOID)0,0,&tid);
#else
		if (tid == (pthread_t)0) {
			pthread_attr_init(&attr);
			pthread_attr_setstacksize(&attr,0x8000);
			pthread_create(&tid,&attr,AlarmWorker,(void *)0);
			signal(SIGUSR1,handler);
#endif
		}

		while(1) {
			int	j;
	
			/* Wait for incoming message: */
			msglen = sizeof(struct sockaddr);
			i = recvfrom(socketFd,rcvmsg,sizeof(rcvmsg),0,
				(struct sockaddr *)&targetAddr,&msglen);

			if (i == 0) {
				fprintf(stderr,"Connection closed\n");
				close(socketFd);
				exit(EXIT_ERROR);
			}
			else if (SOCKET_INVALID(i)) {
				//perror("socket invalid");
				close(socketFd);
				Giveup(0);
			}
			else  {
				/* Each time something is received, restart the timeout.
		 		 */
				AlarmCount = waitTime;
			}

			/* If ANY response is received from the target, then the command
			 * was received...
			 */
			cmdRcvd = 1;

			/* If size is 1 and 1st byte is 0 assume that's the target
			 * saying "I'm done".
			 */
			if ((i==1) && (rcvmsg[0] == 0)) {
				if (multirespMode)
					continue;
				break;
			}

			/* Print the received message:
			 */
			for(j=0;j<i;j++)
				putchar(rcvmsg[j]);
			fflush(stdout);
		}
	} while (interactiveMode);

	AlarmCount = 0;
	close(socketFd);
	return(EXIT_SUCCESS);
}

/**	\fn void moncmd_init(char *progname)
 *	\brief Initialize globals at startup
 *	\param progname Value of argv[0] at startup.
 */
void
moncmd_init(char *progname)
{
	thisProgname = progname;
	binMode = 0;
	waitTime = 10;
	verbose = 0;
	multirespMode = 0;
	interactiveMode = 0;
	retryFlag = quietMode = 0;
}

⌨️ 快捷键说明

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