x_snmp.c

来自「TCP-IP红宝书源代码」· C语言 代码 · 共 654 行 · 第 1/2 页

C
654
字号
/* x_snmp.c - x_snmp */

#include <conf.h>
#include <kernel.h>
#include <network.h>
#include <io.h>
#include <string.h>
#include <mem.h>
#include <stdlib.h>

#ifdef	SNMP
#include <tty.h>
#include <ctype.h>
#include <snmp.h>
#include <asn1.h>
#include <mib.h>

#define EXIT		'\004'		/* \004 is Cntl-d		*/
#define COMPLETE	'\011'		/* \011 is TAB			*/
#define KILLWORD	'\027'		/* \027 is Cntl-w		*/
#define	BELL		'\007'		/* control-g			*/

#define M_COMPL		1		/* completion mode 		*/
#define M_CHARIN	2		/* char-in mode 		*/

#define PROMPT		"\n\rsnmp > "
#define EXITSTR		"exit"

#define BUFSIZE		1024
char	buf[BUFSIZE];			/* buffer to hold the input line*/
char	str2compl[BUFSIZE];		/* string to complete 		*/
int	s2clen;				/* length of str2compl		*/
int	completions[BUFSIZE];		/* array of indices into the mib*/
					/* array to signal completions	*/
int	num_completions;		/* # of indices in completions[]*/
int	next_completion;		/* next completion to try	*/


/* local routine definitions */
LOCAL void echoch(char ch, int stdout);
LOCAL void erase1(int ct, int stdout);
LOCAL void eraseall(int ct, int stdout);
LOCAL void eraseword(int *ct, int stdout);
LOCAL void snusage(int stdout);
LOCAL void initgetword(char *buf);
LOCAL void getword(char **word);
LOCAL void print_completion(int *ct, int stdout);
LOCAL void find_completions(void);
LOCAL int parsevalue(char **word, struct snbentry *bl);
LOCAL int strnequ(char *s1, char *s2, int n);
LOCAL int objd2oid(char *str, struct oid *oip);
LOCAL int dot2oid(u_short id[], char *str);
LOCAL int parseoidlist(struct req_desc *rqdp, char **word);
LOCAL struct snbentry *parseoid(char **word);
LOCAL int sendquery(int stdout, char *server);
LOCAL struct snbentry *getnewbl(void);
LOCAL int parseset(struct req_desc *rqdp, int stdout);


/*------------------------------------------------------------------------
 * x_snmp - SNMP shell that does MIB object name completion
 *------------------------------------------------------------------------
 */
int
x_snmp(int stdin, int stdout, int stderr, int nargs, char *args[])
{
	int	ch;
	char    snmpservstr[BUFSIZE];
	struct	tty	*ttyp;
	int	ct, i, mode;
	IPaddr	destmach;

	if (nargs != 2) {
		snusage(stdout);
		return OK;
	}
	args++;  nargs--;

	sninit();
	if ((destmach = name2ip(*args)) == (IPaddr)SYSERR) {
		fprintf(stdout,"snmp: couldn't resolve name %s\n", *args);
		return OK;
	}
	ip2dot(snmpservstr, destmach);
	sprintf(snmpservstr + strlen(snmpservstr), ":%d", SNMPPORT);
	ttyp = &ttytab[stdin];
	ct = 0;
	mode = M_CHARIN;
	next_completion = num_completions = 0;

	control(stdin, TTC_MODER);	/* put stdin into raw mode */
	write(stdout, PROMPT, strlen(PROMPT));	/* print the prompt */

	while (TRUE) {
		if ((ch = getc(stdin)) == EOF) {
			write(stdout, EXITSTR, strlen(EXITSTR));
			putc(stdout, '\n');
			control(stdin, TTC_MODEC);
			return OK;
		}
		if (ch == SYSERR) {
			return SYSERR;
		}
		if (ch == COMPLETE) {
			if (mode == M_CHARIN) {
				mode = M_COMPL;
				/* find beginning of word */
				for (i=ct-1; i >= 0 && buf[i] != ' ';
						i--)
					/* empty */;
				s2clen = ct - ++i;
				strncpy(str2compl, buf + i, s2clen);
				find_completions();
			}
			if (num_completions == 0) {
				putc(stdout, BELL);
				mode = M_CHARIN;
			} else
				print_completion(&ct, stdout);
			continue;
		}
		if (ch == KILLWORD && mode == M_COMPL) {
			/* kill word in compl. mode goes back to
			   original string to complete. */
			eraseword(&ct, stdout);
			strncpy(buf + ct, str2compl, s2clen);
			write(stdout, buf + ct, s2clen);
			ct += s2clen;
			mode = M_CHARIN;
			next_completion = num_completions = 0;
			continue;
		}
		if (mode == M_COMPL) {	/* && ch != KILLWORD */
			mode = M_CHARIN;
			str2compl[(s2clen = 0)] = '\0';
			num_completions = next_completion = 0;
		}
		if (ch == KILLWORD) {	/* && mode != M_COMPL */
			eraseword(&ct, stdout);
			continue;
		}
		if ((ch == ttyp->tty_tchars.tc_kill)) {
			eraseall(ct, stdout);
			ct = 0;
			continue;
		}
		if ((ch == ttyp->tty_tchars.tc_erase)) {
			if (ct > 0) 
				erase1(--ct, stdout);
			continue;
		}
		if ((ch == '\r') || (ch == '\n')) {
			echoch(ch, stdout);
			buf[ct] = '\0';
			if (strequ(buf, EXITSTR)) {
				control(stdin, TTC_MODEC);
				return OK;
			}
			sendquery(stdout, snmpservstr);
			for (i = 0; i < BUFSIZE; i++)
				buf[i] = '\0';
			write(stdout, PROMPT, strlen(PROMPT));
			ct = 0;
			continue;
		}
		/* all non-special characters */
		if (ct == BUFSIZE - 1) 
			putc(stdout, BELL);
		else {
			echoch(ch, stdout);
			buf[ct++] = ch;
		}
	}

	return OK;
}

/*------------------------------------------------------------------------
 * print_completion - write the next name completion to stdout
 *------------------------------------------------------------------------
 */
LOCAL void
print_completion(int *ct, int stdout)
{
	if (next_completion >= num_completions) {
		putc(stdout, BELL);
		return;
	}
	eraseword(ct, stdout);

	strcpy(buf + *ct, mib[completions[next_completion]].mi_prefix);
	strcat(buf + *ct, mib[completions[next_completion++]].mi_name);
	write(stdout, buf + *ct, strlen(buf) - *ct);
	*ct = strlen(buf);
}

/*------------------------------------------------------------------------
 * find_completions - find all the completions in the mib for string
 * 		      str2compl.  Put the indices of the completions
 * 		      into the completions array.
 *------------------------------------------------------------------------
 */
LOCAL void
find_completions(void)
{
	int 	i;
	
	for (i = 0; i < mib_entries; i++) 
		if (strnequ(mib[i].mi_name, str2compl, s2clen))
			completions[num_completions++] = i;
	next_completion = 0;
}

/*------------------------------------------------------------------------
 * parsevalue - parse the type and value of variable to set
 *------------------------------------------------------------------------
 */
LOCAL int
parsevalue(char **word, struct snbentry *bl)
{
	if (strequ(*word, "int"))
		SVTYPE(bl) = ASN1_INT;
	else if (strequ(*word, "counter")) 
		SVTYPE(bl) = ASN1_COUNTER;
	else if (strequ(*word, "gauge")) 
		SVTYPE(bl) = ASN1_GAUGE;
	else if (strequ(*word, "timeticks")) 
		SVTYPE(bl) = ASN1_TIMETICKS;
	else if (strequ(*word, "str")) 
		SVTYPE(bl) = ASN1_OCTSTR;
	else if (strequ(*word, "objid")) 
		SVTYPE(bl) = ASN1_OBJID;
	else if (strequ(*word, "ipaddr")) 
		SVTYPE(bl) = ASN1_IPADDR;
	else
		return SYSERR;

	getword(word);
	if (**word == NULLCH)
		return SYSERR;

	switch (SVTYPE(bl)) {
	case ASN1_INT:
	case ASN1_COUNTER:
	case ASN1_GAUGE:
	case ASN1_TIMETICKS:
		SVINT(bl) = atoi(*word);
		break;
	case ASN1_OCTSTR:
		SVSTRLEN(bl) = strlen(*word);
		SVSTR(bl) = (char *) getmem(SVSTRLEN(bl));
		memcpy(SVSTR(bl), *word, SVSTRLEN(bl));
		break;
	case ASN1_OBJID:
		SVOIDLEN(bl) = dot2oid(SVOID(bl), *word);
		break;
	case ASN1_IPADDR:
		SVIPADDR(bl) = dot2ip(*word);
		break;
	default:
		return SYSERR;
	}
	return OK;
}

/*------------------------------------------------------------------------
 *  echoch  --  echo a character with visual and ocrlf options
 *------------------------------------------------------------------------
 */
LOCAL void
echoch(char ch, int stdout)
{
	if (ch == '\n' || ch == '\r') {
		putc(stdout, '\r');
		putc(stdout, '\n');
	} else if (ch < ' ' || ch == 0177) {
		putc(stdout, '^');
		putc(stdout, ch + 0100);	/* make it printable	*/
	} else
		putc(stdout, ch);
}

/*------------------------------------------------------------------------
 *  erase1  --  erase one character honoring erasing backspace
 *------------------------------------------------------------------------
 */
LOCAL void
erase1(int ct, int stdout)
{
	char	ch;

	ch = buf[ct];
	if (ch < ' ' || ch == 0177) {
		putc(stdout, '\b');
		putc(stdout, ' ');
		putc(stdout, '\b');
		putc(stdout, '\b');
		putc(stdout, ' ');
		putc(stdout, '\b');
	} else {
		putc(stdout, '\b');
		putc(stdout, ' ');
		putc(stdout, '\b');
	}
}

/*------------------------------------------------------------------------
 *  eraseall  --  erase all characters honoring erasing backspace
 *------------------------------------------------------------------------
 */
LOCAL void
eraseall(int ct, int stdout)
{
	for (--ct; ct >= 0; ct--) 
		erase1(ct, stdout);
}

/*------------------------------------------------------------------------
 *  eraseword  --  erase the previous word
 *------------------------------------------------------------------------
 */
LOCAL void
eraseword(
    int		*ct,
    int		stdout)
{
	/* if first character behind cursor is a blank, eat it up */

⌨️ 快捷键说明

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