NET-SNMPのソースコードからMIBの値をうまく表示する処理の写経をした
今朝は5時半から開発開始です。最近は新人助手の猫さんが起きる時間を完全にコントロールしています。かなり優秀な開発助手です。
さて、
の問題のチケットに対応するために、NET-SNMPのソースコードを、真面目に読んでみました。ソースコードは、GitHUBに移転してきたようで入手しやすくなっていました。
この中で、整数をDISPLAY-HINTに対応して表示する処理を探しました。
/**
* Prints an integer according to the hint into a buffer.
*
* If allow_realloc is true the buffer will be (re)allocated to fit in the
* needed size. (Note: *buf may change due to this.)
*
* @param buf Address of the buffer to print to.
* @param buf_len Address to an integer containing the size of buf.
* @param out_len Incremented by the number of characters printed.
* @param allow_realloc if not zero reallocate the buffer to fit the
* needed size.
* @param val The variable to encode.
* @param decimaltype 'd' or 'u' depending on integer type
* @param hint Contents of the DISPLAY-HINT clause of the MIB.
* See RFC 1903 Section 3.1 for details. may _NOT_ be NULL.
* @param units Contents of the UNITS clause of the MIB. may be NULL.
*
* @return 1 on success, or 0 on failure (out of memory, or buffer to
* small when not allowed to realloc.)
*/
int
sprint_realloc_hinted_integer(u_char ** buf, size_t * buf_len,
size_t * out_len, int allow_realloc,
long val, const char decimaltype,
const char *hint, const char *units)
{
char fmt[10] = "%l@", tmp[256];
int shift = 0, len, negative = 0;
if (!strchr("bdoux", decimaltype)) {
snmp_log(LOG_ERR, "Invalid decimal type '%c'\n", decimaltype);
return 0;
}
switch (hint[0]) {
case 'd':
/*
* We might *actually* want a 'u' here.
*/
if (hint[1] == '-') {
shift = atoi(hint + 2);
if (shift < 0)
shift = 0;
}
fmt[2] = decimaltype;
if (val < 0) {
negative = 1;
val = -val;
}
snprintf(tmp, sizeof(tmp), fmt, val);
break;
case 'o':
case 'x':
fmt[2] = hint[0];
snprintf(tmp, sizeof(tmp), fmt, val);
break;
case 'b': {
unsigned long int bit = 0x80000000LU;
char *bp = tmp;
while (bit) {
*bp++ = val & bit ? '1' : '0';
bit >>= 1;
}
*bp = 0;
break;
}
default:
return 0;
}
if (shift != 0) {
len = strlen(tmp);
if (shift <= len) {
tmp[len + 1] = 0;
while (shift--) {
tmp[len] = tmp[len - 1];
len--;
}
tmp[len] = '.';
} else if (shift < sizeof(tmp) - 1) {
tmp[shift + 1] = 0;
while (shift) {
if (len-- > 0) {
tmp[shift] = tmp[len];
} else {
tmp[shift] = '0';
}
shift--;
}
tmp[0] = '.';
}
}
if (negative) {
len = strlen(tmp)+1;
while (len) {
tmp[len] = tmp[len-1];
len--;
}
tmp[0] = '-';
}
return snmp_cstrcat(buf, buf_len, out_len, allow_realloc, tmp);
}
という関数でした。久しぶりにC言語のソースコードを読むと戸惑うことが多いです。なんとか読み解いてGO言語で書いてみました。
func printHintedInt(val int32, hint string, us bool) string {
if hint == "" {
if us {
return fmt.Sprintf("%d", uint32(val))
}
return fmt.Sprintf("%d", val)
}
h := hint[0:1]
switch h {
case "d":
r := ""
n := false
if us {
r = fmt.Sprintf("%d", uint32(val))
} else {
if val < 0 {
n = true
val = -val
}
r = fmt.Sprintf("%d", val)
}
if len(hint) > 2 && hint[1:2] == "-" {
s, err := strconv.Atoi(hint[2:])
if err == nil && s != 0 {
if s <= len(r) {
r = r[0:s] + "." + r[s:]
} else {
tmp := "."
for len(tmp) < s-len(r)+1 {
tmp += "0"
}
r = tmp + r
}
}
}
if n {
r = "-" + r
}
return r
case "x":
return fmt.Sprintf("%x", val)
case "o":
return fmt.Sprintf("%o", val)
case "b":
r := ""
for b := 0x80000000; b != 0; b >>= 1 {
if int32(b)&val != 0 {
r += "1"
} else {
r += "0"
}
}
return r
}
return ""
}
ちょっと短くなりました。簡単にテストした感じでは問題なさそうです。
TWSNMP FCとシン・TWSNMPに組み込んでみました。でも、この処理は、ほとんど使われないようです。
TEXTUAL-CONVENTIONで定義したデータの型のEnumも対応しました。
とりあえず、TWSNMP FCのDocker版を組み込んだものに更新しました。
のように表示できています。
明日に続く
いいなと思ったら応援しよう!
開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。
ソフトウェアのマニュアルをnoteの記事で提供しています。
サポートによりnoteの運営にも貢献できるのでよろしくお願います。