見出し画像

「プログラムが仕事をしています」:SHIFT-JISのSNMP TRAPの文字化け対策

今日から朝の開発再開です。
3日間プログラムを作らなかったのでソースコードを書くのは新鮮な気分です。一昨日のフィードバックSNMP TRAPが文字化けするという問題の改善です。
まずは、SHIFT-JISのTRAPを送ってみるためにGO言語でSHIF-JISを扱うテストプログラムを作ってみました。

package main

import (
	"fmt"
	"log"
	"os"

	g "github.com/gosnmp/gosnmp"
	"golang.org/x/text/encoding/japanese"
	"golang.org/x/text/transform"
)

func main() {
	strSJIS := "\x8e\x64\x8e\x96\x82\xaa\x8e\x64\x8e\x96\x82\xf0\x82\xb5\x82\xc4\x82\xee\x82\xdc\x82\xb7\x0a\x8e\x64\x8e\x96\x82\xcd\x96\x88\x93\xfa\x8c\xb3\x8b\x43\x82\xc5\x82\xb7"
	strUTF := "仕事が仕事をしてゐます\n仕事は毎日元気です"

	enc := japanese.ShiftJIS.NewEncoder()
	dec := japanese.ShiftJIS.NewDecoder()
	a, _, _ := transform.Bytes(enc, []byte(strUTF))
	b, _, _ := transform.Bytes(dec, []byte(strSJIS))
	printHex(a)
	if string(a) == strSJIS {
		fmt.Println("OK")
	}
}

func printHex(a []byte) {
	for _, b := range a {
		fmt.Printf("\\x%02x", b)
	}
	fmt.Println()
}

GO言語だと簡単に文字コードの変換ができます。
文字列がSHIF-JISかどうか判断するプログラムは、オリジナルのTWSNMPのC言語のソースコード

int IsSjis(char *p)
{
	int i;
	int c;
	for( i = 0; p[i]; ) {
		c = (int) p[i++];
		c &= 0x00ff;
		if( c < 0x007f ) continue;
		if( (c >= 0x0081 && c <= 0x9f ) ||
			(c >= 0x00e0  && c <= 0x00ef ) ) {
			c = (int) p[i++];
			c &= 0x00ff;
			if( c < 0x0040 || c > 0x00fc ) return(0);
		} else {
				return(0);
		}
	}
	return(1);
}

からGO言語に移植しました。

func isSjis(p []byte) bool {
	f := false
	for _, c := range p {
		if f {
			if c < 0x0040 || c > 0x00fc {
				return false
			}
			f = false
			continue
		}
		if c < 0x007f {
			continue
		}
		if (c >= 0x0081 && c <= 0x9f) ||
			(c >= 0x00e0 && c <= 0x00ef) {
			f = true
		} else {
			return false
		}
	}
	return true
}

ちょっとロジックが違います。
その後、本題のSHIFT-JISのTRAPを送信するプログラムです。

func sendTrap(ip string) {
	g.Default.Target = ip
	g.Default.Port = 162
	g.Default.Version = g.Version2c
	g.Default.Community = "public"
	g.Default.Logger = g.NewLogger(log.New(os.Stdout, "", 0))
	err := g.Default.Connect()
	if err != nil {
		log.Fatalf("Connect() err: %v", err)
	}
	defer g.Default.Conn.Close()

	v1 := g.SnmpPDU{
		Name:  ".1.3.6.1.6.3.1.1.4.1.0",
		Type:  g.ObjectIdentifier,
		Value: ".1.3.6.1.6.3.1.1.5.1",
	}

	v2 := g.SnmpPDU{
		Name:  ".1.3.6.1.2.1.1.1.0",
		Type:  g.OctetString,
		Value: "\x8e\x64\x8e\x96\x82\xaa\x8e\x64\x8e\x96\x82\xf0\x82\xb5\x82\xc4\x82\xee\x82\xdc\x82\xb7",
		// Value: "仕事が仕事をしてゐます",
	}

	trap := g.SnmpTrap{
		Variables: []g.SnmpPDU{v1, v2},
	}

	_, err = g.Default.SendTrap(trap)
	if err != nil {
		log.Fatalf("SendTrap() err: %v", err)
	}
}

とは、いっても、

をちょっと変更しただけです。
これで送ると、オリジナルのTWSNMPでは、

文字化けしません。UTF-8で送信しても大丈夫です。
TWSNMP FCで受信すると

SHIFT-JISで送信すると文字化けします。下の文字化けしていないものは、UTF-8で送信したものです。
昔作ったもののほうが、ちゃんとしてました。
sysUpTimeの表示も気になります。受信した時に自動でUTF-8に変換しようと思います。

ちなみにテストTRAPで送信した
「仕事が仕事をしてゐます」
は、かみさんのお供で行った

の書斎でみた「仕事のうた」です。何だか気に入りました。

この人は、「仕事」を「職人」と置き換えていますが、私は、「プログラム」にしてみました。

プログラムが仕事をしています
プログラムは毎日元気です
出来ない事のないプログラム
どんな事でもプログラムはします
いやな事でも進んでします
進むことしか知らないプログラム
びっくりする程力出す
知らない事のないプログラム
きけば何でも教へます
たのめば何でもはたします
プログラムの一番すきなのは
くるしむ事がすきなのだ
苦しい事はプログラムにまかせ
さあさ吾等はたのしみましょう

明日に続く


開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。