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 + -
显示快捷键?