トップ 追記

Masa's blog

検索キーワード:

2021年10月14日 VMware Workstation Player 16.1.2(vmplayer) on Slackware64-current [長年日記]

_ VMware Workstation Player 16.1.2(vmplayer) on Slackware64-current

Slackware64-currentにvmplayer 16.1.2をインストールした時のメモ。

インストール

以下のスクリプトでインストールを実行するが...

# sh VMware-Player-16.1.2-17966106.x86_64.bundle --ignore-errors

この環境(カーネルバージョン)では必要なモジュールのビルドに失敗する。

$ uname -a
Linux slackware64-current.artie.or.jp 5.14.11 #1 SMP Sat Oct 9 18:30:57 CDT 2021 x86_64 Intel(R) Core(TM) i5-3320M CPU @ 2.60GHz GenuineIntel GNU/Linux

これは既知の問題らしく、解決策も提示されている。

$ git clone -b workstation-16.1.2 https://github.com/mkubecek/vmware-host-modules.git
$ cd vmware-host-modules/
$ make
# make install
# /etc/init.d/vmware restart

以上でインストールは無事完了。

ランスクリプトの設定

# cd /etc/rc.d/rc4.d
# ln -s /etc/rc.d/init.d/vmware K08vmware
# ln -s /etc/rc.d/init.d/vmware-USBArbitrator K08vmware-USBArbitrator
# ln -s /etc/rc.d/init.d/vmware S19vmware
# ln -s /etc/rc.d/init.d/vmware-USBArbitrator S50vmware-USBArbitrator

root以外でのライセンス認証

初回の起動時にライセンス認証が必要だが、バックグラウンドでpolkit-gnome-authentication-agent-1を起動しておかないと成功しない。おそらくデスクトップ環境がgnomeだと問題ないのだろうと想像するが、私はfvwm-1.24rユーザなので :P

$ /usr/libexec/polkit-gnome-authentication-agent-1 &
$ vmplayer

ネットワーク設定

# /usr/lib/vmware/bin/vmware-netcfg
  • vmnet1 for Hostonly network
  • vmnet8 for Nat network

2021年09月05日 Building ClamAV-0.104.0 on Slackware-14.2 [長年日記]

_ Slackware-14.2でClamAV-0.104.0をビルドする

Slackware-14.2でClamAV-0.103.3からClamAV-0.104.0にバージョンアップしたのだけれど、新しめなcmakeやら新たなライブラリやらが必要になっていた。

cmake-3.19.6を/optにインストール

オリジナルのcmake-3.5.2では古すぎて、ClamAV-0.104.0はビルド出来ない。

これで、/opt/cmake-202x/以下にインストールされる。

check-0.15.2のインストール

ClamAV-0.104.0のビルドには、libcheckとやらが必要とのこと...

python-3.7.2のインストール

Python3も必要...

ようやくClamAV-0.104.0のビルド

  • tar xvf clamav-0.104.0.tar.gz
  • cd clamav-0.104.0
  • mkdir build
  • cd build
  • PATH=/opt/cmake-202x/bin:${PATH} cmake ..
  • make
  • sudo make install

定義ファイル格納ディレクトリ(/usr/local/share/clamav/)の準備

  • sudo mkdir /usr/local/share/clamav
  • sudo chown clamav.clamav /usr/local/share/clamav

スキャンデーモンの設定ファイル(/usr/local/etc/clamd.conf)

*** clamd.conf.sample	2021-08-28 07:41:31.000000000 +0900
--- clamd.conf	2021-09-05 15:22:48.245019780 +0900
***************
*** 5,17 ****


  # Comment or remove the line below.
! Example

  # Uncomment this option to enable logging.
  # LogFile must be writable for the user running daemon.
  # A full path is required.
  # Default: disabled
! #LogFile /tmp/clamd.log

  # By default the log file is locked for writing - the lock protects against
  # running clamd multiple times (if want to run another clamd, please
--- 5,17 ----


  # Comment or remove the line below.
! #Example

  # Uncomment this option to enable logging.
  # LogFile must be writable for the user running daemon.
  # A full path is required.
  # Default: disabled
! LogFile /var/log/clamav/clamd.log

  # By default the log file is locked for writing - the lock protects against
  # running clamd multiple times (if want to run another clamd, please
***************
*** 41,52 ****

  # Use system logger (can work together with LogFile).
  # Default: no
! #LogSyslog yes

  # Specify the type of syslog messages - please refer to 'man syslog'
  # for facility names.
  # Default: LOG_LOCAL6
! #LogFacility LOG_MAIL

  # Enable verbose logging.
  # Default: no
--- 41,52 ----

  # Use system logger (can work together with LogFile).
  # Default: no
! LogSyslog yes

  # Specify the type of syslog messages - please refer to 'man syslog'
  # for facility names.
  # Default: LOG_LOCAL6
! LogFacility LOG_MAIL

  # Enable verbose logging.
  # Default: no
***************
*** 74,80 ****
  # It is recommended that the directory where this file is stored is
  # also owned by root to keep other users from tampering with it.
  # Default: disabled
! #PidFile /var/run/clamd.pid

  # Optional path to the global temporary directory.
  # Default: system specific (usually /tmp or /var/tmp).
--- 74,80 ----
  # It is recommended that the directory where this file is stored is
  # also owned by root to keep other users from tampering with it.
  # Default: disabled
! PidFile /var/run/clamav/clamd.pid

  # Optional path to the global temporary directory.
  # Default: system specific (usually /tmp or /var/tmp).
***************
*** 93,111 ****

  # Path to a local socket file the daemon will listen on.
  # Default: disabled (must be specified by a user)
! #LocalSocket /tmp/clamd.socket

  # Sets the group ownership on the unix socket.
  # Default: disabled (the primary group of the user running clamd)
! #LocalSocketGroup virusgroup

  # Sets the permissions on the unix socket to the specified mode.
  # Default: disabled (socket is world accessible)
! #LocalSocketMode 660

  # Remove stale socket after unclean shutdown.
  # Default: yes
! #FixStaleSocket yes

  # TCP port address.
  # Default: no
--- 93,111 ----

  # Path to a local socket file the daemon will listen on.
  # Default: disabled (must be specified by a user)
! LocalSocket /var/run/clamav/clamd.socket

  # Sets the group ownership on the unix socket.
  # Default: disabled (the primary group of the user running clamd)
! LocalSocketGroup clamav

  # Sets the permissions on the unix socket to the specified mode.
  # Default: disabled (socket is world accessible)
! #DEL_LocalSocketMode 660

  # Remove stale socket after unclean shutdown.
  # Default: yes
! FixStaleSocket yes

  # TCP port address.
  # Default: no
***************
*** 117,123 ****
  # from the outside world. This option can be specified multiple
  # times if you want to listen on multiple IPs. IPv6 is now supported.
  # Default: no
! #TCPAddr localhost

  # Maximum length the queue of pending connections may grow to.
  # Default: 200
--- 117,123 ----
  # from the outside world. This option can be specified multiple
  # times if you want to listen on multiple IPs. IPv6 is now supported.
  # Default: no
! #TCPAddr 127.0.0.1

  # Maximum length the queue of pending connections may grow to.
  # Default: 200
***************
*** 210,227 ****
  #ConcurrentDatabaseReload no

  # Execute a command when virus is found. In the command string %v will
! # be replaced with the virus name and %f will be replaced with the file name.
! # Additionally, two environment variables will be defined: $CLAM_VIRUSEVENT_FILENAME
! # and $CLAM_VIRUSEVENT_VIRUSNAME.
  # Default: no
! #VirusEvent /usr/local/bin/send_sms 123456789 "VIRUS ALERT: %v in %f"

  # Run as another user (clamd must be started by root for this option to work)
  # Default: don't drop privileges
! #User clamav

  # Stop daemon when libclamav reports out of memory condition.
! #ExitOnOOM yes

  # Don't fork into background.
  # Default: no
--- 210,225 ----
  #ConcurrentDatabaseReload no

  # Execute a command when virus is found. In the command string %v will
! # be replaced with the virus name.
  # Default: no
! #VirusEvent /usr/local/bin/send_sms 123456789 "VIRUS ALERT: %v"

  # Run as another user (clamd must be started by root for this option to work)
  # Default: don't drop privileges
! #DEL_User clamav

  # Stop daemon when libclamav reports out of memory condition.
! ExitOnOOM yes

  # Don't fork into background.
  # Default: no

定義ファイル更新デーモンの定義ファイル(/usr/local/etc/freshclam.conf)

*** freshclam.conf.sample	2021-08-28 07:41:31.000000000 +0900
--- freshclam.conf	2021-09-05 15:25:26.379098762 +0900
***************
*** 5,11 ****


  # Comment or remove the line below.
! Example

  # Path to the database directory.
  # WARNING: It must match clamd.conf's directive!
--- 5,11 ----


  # Comment or remove the line below.
! #Example

  # Path to the database directory.
  # WARNING: It must match clamd.conf's directive!
***************
*** 14,20 ****

  # Path to the log file (make sure it has proper permissions)
  # Default: disabled
! #UpdateLogFile /var/log/freshclam.log

  # Maximum size of the log file.
  # Value of 0 disables the limit.
--- 14,20 ----

  # Path to the log file (make sure it has proper permissions)
  # Default: disabled
! UpdateLogFile /var/log/clamav/freshclam.log

  # Maximum size of the log file.
  # Value of 0 disables the limit.
***************
*** 35,46 ****

  # Use system logger (can work together with UpdateLogFile).
  # Default: no
! #LogSyslog yes

  # Specify the type of syslog messages - please refer to 'man syslog'
  # for facility names.
  # Default: LOG_LOCAL6
! #LogFacility LOG_MAIL

  # Enable log rotation. Always enabled when LogFileMaxSize is enabled.
  # Default: no
--- 35,46 ----

  # Use system logger (can work together with UpdateLogFile).
  # Default: no
! LogSyslog yes

  # Specify the type of syslog messages - please refer to 'man syslog'
  # for facility names.
  # Default: LOG_LOCAL6
! LogFacility LOG_MAIL

  # Enable log rotation. Always enabled when LogFileMaxSize is enabled.
  # Default: no
***************
*** 51,62 ****
  # It is recommended that the directory where this file is stored is
  # also owned by root to keep other users from tampering with it.
  # Default: disabled
! #PidFile /var/run/freshclam.pid

  # By default when started freshclam drops privileges and switches to the
  # "clamav" user. This directive allows you to change the database owner.
  # Default: clamav (may depend on installation options)
! #DatabaseOwner clamav

  # Use DNS to verify virus database version. FreshClam uses DNS TXT records
  # to verify database and software versions. With this directive you can change
--- 51,62 ----
  # It is recommended that the directory where this file is stored is
  # also owned by root to keep other users from tampering with it.
  # Default: disabled
! PidFile /var/run/clamav/freshclam.pid

  # By default when started freshclam drops privileges and switches to the
  # "clamav" user. This directive allows you to change the database owner.
  # Default: clamav (may depend on installation options)
! DatabaseOwner clamav

  # Use DNS to verify virus database version. FreshClam uses DNS TXT records
  # to verify database and software versions. With this directive you can change
***************
*** 147,153 ****

  # Send the RELOAD command to clamd.
  # Default: no
! #NotifyClamd /path/to/clamd.conf

  # Run command after successful database update.
  # Use EXIT_1 to return 1 after successful database update.
--- 147,153 ----

  # Send the RELOAD command to clamd.
  # Default: no
! NotifyClamd /usr/local/etc/clamd.conf

  # Run command after successful database update.
  # Use EXIT_1 to return 1 after successful database update.

スキャンデーモン(/usr/local/sbin/clamd)の起動

  • sudo mkdir -p /var/run/clamav/
  • sudo chown clamav:clamav /var/run/clamav/
  • sudo chmod 771 /var/run/clamav/
  • sudo /usr/local/sbin/clamd

定義ファイル更新デーモン(/usr/local/bin/freshclam)の起動

  • sudo /usr/local/bin/freshclam -d -l /var/log/clamav/freshclam.log

2021年08月29日 How to get best quality movie by youtube-dl [長年日記]

_ yourtbe-dlで最高画質で動画を取得する方法

youtube-dl --no-playlist -f bestvideo+bestaudio --merge-output-format mp4 'https://www.youtube.com/hogehoge'

2021年08月03日 jupyter notebookでデフォルトの作業フォルダを設定する方法 [長年日記]

_ jupyter notebookでデフォルトの作業フォルダを設定する方法

作業フォルダそのものはシェルからコマンドで作成する。

$ mkdir ~/src
$ mkdir ~/src/jupyter

設定ファイルを作成し、設定する。

$ jupyter notebook --generate-config
$ vim ~/.jupyter/jupyter_notebook_config.py

~/.jupyter/jupyter_notebook_config.py

c.NotebookApp.notebook_dir = '/home/m-ito/src/jupyter/'

jupyter notebookで実行(Run)出来ない場合の対処

jupyter notebookで実行(Run)しても、新しいセルが挿入されるだけで、何も実行されない場合がある。

そんな場合は、カーネルとやらとの接続がうまくできていない可能性があるので、「カーネル」→「再接続」を行ってみると回復するかも...


2021年08月02日 jupyter notebookで起動するブラウザをオプション込で設定する方法 [長年日記]

_ jupyter notebookで起動するブラウザをオプション込で設定する方法

$ jupyter notebook --generate-config
$ vim ~/.jupyter/jupyter_notebook_config.py

~/.jupyter/jupyter_notebook_config.py

c.NotebookApp.browser = '/usr/local/firefox/firefox %s -P prof1'

2020年09月22日 C# memo [長年日記]

_ C# memo

HelloWorld.cs

using System;
public class AnyClassYouLike{
	static void Main(string[] args){
		Console.WriteLine("HelloWorld");
		return;
	}
}

変数

sbyte			//8ビット整数(符号付き)
byte			//8ビット整数(符号無し)
short			//16ビット整数(符号付き)
ushort			//16ビット整数(符号無し)
int			//32ビット整数(符号付き)
uint			//32ビット整数(符号無し)
long			//64ビット整数(符号付き)
ulong			//64ビット整数(符号無し)
float			//32ビット浮動小数(例 123.456f)
double			//64ビット浮動小数(例 123.456d)
char			//文字(UNICODE)(例 'あ')
bool			//論理値 (true or false)
decimal		//高精度 10進数浮動小数(例 123.456m)

string			//文字列(UNICODE)(例 "あいうえお")
object			//全ての型の基底となる型

配列

int[] a = new int[3] {1,2,3};
int[,] a = new int[2,3] {{1,2,3},{4,5,6}};

ハッシュ

using System.Collections;
Hashtable ht = new Hashtable();
ht["key1"] = "data1";
// ht.ContainsKey("key1") // True or False
// foreach (string key in ht.Keys){ ... }

標準入出力

using System;
Console.Write("あいうえお");		// 改行無し
Console.WriteLine("あいうえお");	// 改行有り
Console.WriteLine("私は{0}{1}です","伊藤","太郎");

string input = Console.ReadLine();

文字列フォーマット

string str = string.Format("{(インデックス)[,(表示幅)][:(書式)(精度)]}", 値)

// (インデックス)	0オリジン
// ,(表示幅)		整数値、マイナス指定は左寄せ
// :(書式)(精度)	d 整数値の10進表記、(精度)は桁数を表す(先頭ゼロ埋め)
//			e 指数表記、(精度)は仮数部の小数点桁数を表す
//			f 固定小数点表記、(精度)は小数点桁数を表す
//			n 3桁区切り文字入りの数値表記、(精度)は小数点桁数を表す
//			x 整数値の16進表記、(精度)は桁数を表す(先頭ゼロ埋め)
string str = string.Format("{(インデックス):###,###,###}", 値)

// 可変長、先頭ゼロ埋め無し、桁区切り付き、マイナス符号付き
string str = string.Format("{(インデックス):000,000,000}", 値)

// 固定長、先頭ゼロ埋め有り、桁区切り付き、マイナス符号付き

条件分岐

if (a == 1){
}else if (a == 2){
}else{
}

繰返し

using System;
using System.Collections;

while (a < 10){
}

for (int i = 0; i < 10; i++){
}

int[] array = new int[10] {1,2,3,4,5,6,7,8,9,10};
foreach (int i in array){
}

Hashtable hash = new Hashtable() {
	{"key1","value1"},
	{"key2","value2"},
	{"key3","value3"}
};
ArrayList list = new ArrayList (hash.Keys);
list.Sort();
foreach (string key in list){
}

ファイル入出力(テキスト)

using System.IO;
using System.Text;

StreamReader sr = new StreamReader("input.csv", Encoding.GetEncoding("UTF-8"));
bool append_sw = false;
StreamWriter sw = new StreamWriter("output.csv", append_sw, Encoding.GetEncoding("UTF-8"));
string str = null;
while ((str = sr.ReadLine()) != null){
	sw.WriteLine(str);
}
sr.Close();
sw.Close();

ファイル入出力(バイナリ)

using System.IO;

byte[] buf = new byte[1024];
FileStream sr = new FileStream("input.dat", FileMode.Open, FileAccess.Read);
FileStream sw = new FileStream("output.dat", FileMode.Create, FileAccess.Write);
int readsize = 0;
while ((readsize = sr.Read(buf, 0, 1024)) > 0){
	sw.Write(buf, 0, readsize);
}
sr.Close();
sw.Close();

ファイル入出力(バイナリ2)

using System.IO;

byte[] buf = new byte[1024];
byte b;
FileStream srw = new FileStream("output.dat", FileMode.Open, FileAccess.ReadWrite);
int readsize = 0;
srw.Seek(10, SeekOrigin.Begin);
readsize = srw.Read(buf, 0, 5);
b = buf[0];buf[0] = buf[4]; buf[4] = b;
b = buf[1];buf[1] = buf[3]; buf[3] = b;
srw.Seek(10, SeekOrigin.Begin);
srw.Write(buf, 0, 5);
srw.Close();

引数

using System;
public class AnyClassYouLike{
	static void Main(string[] args){
		for (int i = 0; i < args.Length; i++){
			Console.WriteLine(args[i]);
		}
		return;
	}
}

文字列連結

 string str = "あいう" + "えお";

文字列分割

using System.Text.RegularExpressions;

string input = "aa,bb,,cc,,,dd";
string sep = ",+";
string[] array = Regex.Split(input, sep);

部分文字列

string str = "abcあいうdef";
string hiragana = str.Substring(3, 3);

文字列比較(正規表現)

using System.Text.RegularExpressions;

if (Regex.IsMatch("abcdefg", "b.*e")){ ... }

文字列置換(正規表現)

using System.Text.RegularExpressions;

string str = Regex.Replace("abcdefg", "b.*f", "b to f");
string str = Regex.Replace("abcdefg", "^(.)(.*)(.)$", "$3$2$1");

文字列⇒数値変換

int i = int.Parse("123");
float f = float.Parse("123.456");

型変換

int i = (int)123.45;

日時取得

DateTime dt;

dt = new DateTime(2020,9,20,12,59,59);
Console.WriteLine(dt.ToString());
Console.WriteLine(dt.ToString("yyyy/MM/dd HH:mm:ss"));
Console.WriteLine(dt.Year);
Console.WriteLine(dt.Month);
Console.WriteLine(dt.Day);
Console.WriteLine(dt.Hour);
Console.WriteLine(dt.Minute);
Console.WriteLine(dt.Second);

dt = DateTime.Parse("2020/09/20 12:59:59");
dt = DateTime.Now;

DateTime dt2 = dt.AddYears(10);	// AddMonths(), AddDays(), AddHours(), AddMinutes(), AddSeconds()
Console.WriteLine(dt.CompareTo(dt2));	// -1 (-1, 0, 1)

外部コマンド実行

using System;
using System.Diagnostics;

ProcessStartInfo pInfo = new ProcessStartInfo();
pInfo.FileName = "ipconfig.exe";
pInfo.CreateNoWindow = true;		// do not open console window
pInfo.UseShellExecute = false;		// false for console command, true for windows app
pInfo.RedirectStandardOutput = true;
pInfo.RedirectStandardError = true;
pInfo.Arguments = "/all";
Process p = Process.Start(pInfo);
p.WaitForExit();
String stdOut = p.StandardOutput.ReadToEnd();
String stdErr = p.StandardError.ReadToEnd();
int exitCode = p.ExitCode;
p.Close();
Console.WriteLine(stdOut);
Console.WriteLine(stdErr);

終了

Environment.Exit(0);

例外処理

try{
	throw new Exception("エラーだよ");
}catch(Exception e){
	Console.WriteLine(e);
	Console.WriteLine(e.Message);
}finally{
	Console.WriteLine("finally");
}

クラス

using System;

public class AnyClassYouLike{
	static void Main(string[] args){
		MyClass mc = new MyClass("あいう", "えお");
		mc.show();
		MyClass2 mc2 = new MyClass2("あいう", "えお", "かきくけこ");
		mc2.show();
		return;
	}
}

public class MyClass{
	string p1;
	string p2;
	public MyClass(){
		this.p1 = "";
		this.p2 = "";
	}
	public MyClass(string p1, string p2){
		this.p1 = p1;
		this.p2 = p2;
	}
	public virtual void show(){
		Console.WriteLine(this.p1 + "," + this.p2);
	}
}

public class MyClass2 : MyClass{
	string p3;
	public MyClass2(){
	}
	public MyClass2(string p1, string p2, string p3) : base(p1, p2){
		this.p3 = p3;
	}
	public override void show(){
		base.show();
		Console.WriteLine(this.p3);
	}
}

インターフェース

using System;
public class AnyClassYouLike{
	static void Main(string[] args){

		Ianimal a;
		a = new Dog();
		a.talk();
		a = new Cat();
		a.talk();

		return;
	}
}

interface Ianimal{
	void talk();
}

class Dog : Ianimal{
	public void talk(){
		Console.WriteLine("わんわん");
	}
}

class Cat : Ianimal{
	public void talk(){
		Console.WriteLine("にゃー");
	}
}

Oracle

using System;
using System.Data;
using System.Data.OracleClient;

public class AnyClassYouLike{
	static void Main(string[] args){

		string ip = "127.0.0.1";
		string user = "mito";
		string password = "oracle";
		string connectionString = "Data Source=" + ip + ";User ID=" + user + ";Password=" + password + ";Integrated Security=false;";
		OracleConnection connection;
		OracleCommand ocmd;
		OracleParameter bind_id;
		OracleParameter bind_name;
		OracleDataReader ord;
		int	row;
//
		connection = new OracleConnection(connectionString);
		connection.Open();
		ocmd = new OracleCommand();
		ocmd.Connection = connection;
		ocmd.Transaction = connection.BeginTransaction();
//
		ocmd.CommandText = "insert into t_sample (id,name) values(:id,:name)";

		bind_id = new OracleParameter("id", "00000001");
		ocmd.Parameters.Add(bind_id);
		bind_name = new OracleParameter("name", "伊藤 太郎");
		ocmd.Parameters.Add(bind_name);

		row = ocmd.ExecuteNonQuery();

		ocmd.Parameters.Remove(bind_id);
		ocmd.Parameters.Remove(bind_name);
		ocmd.Transaction.Commit();	// or .Rollback();
		ocmd.Transaction = connection.BeginTransaction();
//
		ocmd.CommandText = "select id,name from t_sample where id >= :id";

		bind_id = new OracleParameter("id", "00000000");
		ocmd.Parameters.Add(bind_id);

		ord = ocmd.ExecuteReader();
		while (ord.Read()){
			Console.WriteLine(ord["id"] + "," + ord["name"]);
		}
		ord.Close();

		ocmd.Parameters.Remove(bind_id);
//
		ocmd.CommandText = "update t_sample set name=:name where id = :id";

		bind_id = new OracleParameter("id", "00000001");
		ocmd.Parameters.Add(bind_id);
		bind_name = new OracleParameter("name", "伊藤 花子");
		ocmd.Parameters.Add(bind_name);

		row = ocmd.ExecuteNonQuery();

		ocmd.Parameters.Remove(bind_id);
		ocmd.Parameters.Remove(bind_name);
		ocmd.Transaction.Commit();	// or .Rollback();
		ocmd.Transaction = connection.BeginTransaction();
//
		ocmd.CommandText = "select id,name from t_sample where id >= :id";

		bind_id = new OracleParameter("id", "00000000");
		ocmd.Parameters.Add(bind_id);

		ord = ocmd.ExecuteReader();
		while (ord.Read()){
			Console.WriteLine(ord["id"] + "," + ord["name"]);
		}
		ord.Close();

		ocmd.Parameters.Remove(bind_id);
//
		ocmd.CommandText = "delete from t_sample where id >= :id";

		bind_id = new OracleParameter("id", "00000000");
		ocmd.Parameters.Add(bind_id);

		row = ocmd.ExecuteNonQuery();

		ocmd.Parameters.Remove(bind_id);
		ocmd.Transaction.Commit();	// or .Rollback();
//
		ord.Dispose();
		ocmd.Dispose();
		connection.Close();
		connection.Dispose();

		return;
	}
}

MSSQLServer

using System;
using System.Data;
using System.Data.SqlClient;

public class AnyClassYouLike{
	static void Main(string[] args){

		SqlConnectionStringBuilder builder;
		SqlConnection con;
		SqlCommand com;
		SqlParameter parm_id;
		SqlParameter parm_name;
		SqlDataReader reader;
		SqlTransaction transaction;
		string sqlstr;

		builder = new SqlConnectionStringBuilder();
		builder.DataSource = "127.0.0.1";
		builder.UserID = "mito";
		builder.Password = "sqlserver";
		builder.InitialCatalog = "testdb";
		builder.ConnectTimeout = 15000;	// ms

		con = new SqlConnection(builder.ConnectionString);
		con.Open();
//
		sqlstr = "insert into t_sample (id,name) values(@id,@name)";
		com = new SqlCommand(sqlstr, con);
		com.CommandText = sqlstr;
		transaction = con.BeginTransaction();
		com.Transaction = transaction;
		parm_id = new SqlParameter("@id", "00000001");
		com.Parameters.Add(parm_id);
		parm_name = new SqlParameter("@name", "伊藤 太郎");
		com.Parameters.Add(parm_name);
		com.ExecuteNonQuery();
		com.Parameters.Remove(parm_id);
		com.Parameters.Remove(parm_name);
		com.Dispose();
		transaction.Commit();	// or .Rollback();
//
		sqlstr = "select id,name from t_sample where id >= @id";
		com = new SqlCommand(sqlstr, con);
		com.CommandText = sqlstr;
		transaction = con.BeginTransaction();
		com.Transaction = transaction;
		parm_id = new SqlParameter("@id", "00000000");
		com.Parameters.Add(parm_id);
		reader = com.ExecuteReader();
		while (reader.Read()){
			Console.WriteLine(reader["id"] + "," + reader["name"]);
		}
		reader.Close();
		com.Parameters.Remove(parm_id);
		com.Dispose();
		transaction.Commit();	// or .Rollback();
//
		sqlstr = "update t_sample set name=@name where id = @id";
		com = new SqlCommand(sqlstr, con);
		com.CommandText = sqlstr;
		transaction = con.BeginTransaction();
		com.Transaction = transaction;
		parm_id = new SqlParameter("@id", "00000001");
		com.Parameters.Add(parm_id);
		parm_name = new SqlParameter("@name", "伊藤 花子");
		com.Parameters.Add(parm_name);
		com.ExecuteNonQuery();
		com.Parameters.Remove(parm_id);
		com.Parameters.Remove(parm_name);
		com.Dispose();
		transaction.Commit();	// or .Rollback();
//
		sqlstr = "select id,name from t_sample where id >= @id";
		com = new SqlCommand(sqlstr, con);
		com.CommandText = sqlstr;
		transaction = con.BeginTransaction();
		com.Transaction = transaction;
		parm_id = new SqlParameter("@id", "00000000");
		com.Parameters.Add(parm_id);
		reader = com.ExecuteReader();
		while (reader.Read()){
			Console.WriteLine(reader["id"] + "," + reader["name"]);
		}
		reader.Close();
		com.Parameters.Remove(parm_id);
		com.Dispose();
		transaction.Commit();	// or .Rollback();
//
		sqlstr = "delete from t_sample where id >= @id";
		com = new SqlCommand(sqlstr, con);
		com.CommandText = sqlstr;
		transaction = con.BeginTransaction();
		com.Transaction = transaction;
		parm_id = new SqlParameter("@id", "00000000");
		com.Parameters.Add(parm_id);
		com.ExecuteNonQuery();
		com.Parameters.Remove(parm_id);
		com.Dispose();
		transaction.Commit();	// or .Rollback();
//
		con.Close();
		return;
	}
}

Socket通信(echo server (single thread))

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text.RegularExpressions;

public class AnyClassYouLike{
	static void Main(String[] args){
		string line;
		IPAddress ipAdd = IPAddress.Parse("0.0.0.0");
		int port = 1234;
		TcpListener listener = new TcpListener(ipAdd, port);
		listener.Start();
		while (true){
			TcpClient client = listener.AcceptTcpClient();
			Console.WriteLine("クライアント({0}:{1})と接続しました。",
				((IPEndPoint)client.Client.RemoteEndPoint).Address,
				((IPEndPoint)client.Client.RemoteEndPoint).Port);
			NetworkStream ns = client.GetStream();
			StreamReader sr = new StreamReader(ns, Encoding.UTF8);
			StreamWriter sw = new StreamWriter(ns, Encoding.UTF8);
			while ((line = sr.ReadLine()) != null){
				Console.WriteLine(line);
				sw.WriteLine(line);
				sw.Flush();
				if (Regex.IsMatch(line, "^shutdown")){
					break;
				}
			}
			sr.Close();
			sw.Close();
			ns.Close();
			client.Close();
			if (line != null){
				break;
			}
		}
		listener.Stop();
	}
}

Socket通信(echo client)

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

public class AnyClassYouLike{
	static void Main(String[] args){
		string line;
		string ipAdd = args[0];
		int port = int.Parse(args[1]);
		string str = args[2];
		TcpClient client = new TcpClient(ipAdd, port);
		Console.WriteLine("クライアント({0}:{1})と接続しました。",
			((IPEndPoint)client.Client.RemoteEndPoint).Address,
			((IPEndPoint)client.Client.RemoteEndPoint).Port);
		NetworkStream ns = client.GetStream();
		StreamReader sr = new StreamReader(ns, Encoding.UTF8);
		StreamWriter sw = new StreamWriter(ns, Encoding.UTF8);
		sw.WriteLine(str);
		sw.Flush();
		line = sr.ReadLine();
		Console.WriteLine(line);
		sr.Close();
		sw.Close();
		ns.Close();
		client.Close();
	}
}

Socket通信(echo server (multi thread))

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

public class AnyClassYouLike{
	static void Main(String[] args){
		IPAddress ipAdd = IPAddress.Parse("0.0.0.0");
		int port = 1234;
		TcpListener listener = new TcpListener(ipAdd, port);
		listener.Start();
		while (true){
			TcpClient client = listener.AcceptTcpClient();
			Task.Run(() => communicateClient(client));
			Console.WriteLine("クライアント({0}:{1})と接続しました。",
				((IPEndPoint)client.Client.RemoteEndPoint).Address,
				((IPEndPoint)client.Client.RemoteEndPoint).Port);
		}
		listener.Stop();
	}

	private static void communicateClient(TcpClient client){
		string line;
		NetworkStream ns = client.GetStream();
		StreamReader sr = new StreamReader(ns, Encoding.UTF8);
		StreamWriter sw = new StreamWriter(ns, Encoding.UTF8);
		while ((line = sr.ReadLine()) != null){
			Console.WriteLine(line);
			sw.WriteLine(line);
			sw.Flush();
		}
		sr.Close();
		sw.Close();
		ns.Close();
		client.Close();
	}
}

2020年08月09日 Setting ACPI for suspending machine automatically when battery charge loss [長年日記]

_ ノートPCのバッテリー残量が少なくなったら自動的にサスペンドするためのACPI設定方法

/etc/acpi/acpi_handler.sh

バッテリーに関するイベントを検知したらスクリプト(/etc/acpi/lowbattery.sh)を起動する。

*** acpi_handler.sh.ORG 2020-08-08 23:40:56.530432033 +0900
--- acpi_handler.sh     2020-08-09 01:16:38.793951977 +0900
***************
*** 13,18 ****
--- 13,21 ----
           ;;
      esac
      ;;
+   battery)
+     /etc/acpi/lowbattery.sh &
+     ;;
    *)
      logger "ACPI group $1 / action $2 is not defined"
      ;;

/etc/acpi/lowbattery.sh

バッテリー駆動の間は60秒間隔でバッテリー残量をチェックし、残量が10%を切った場合サスペンドする。ACアダプタ駆動になったら終了する。

#! /bin/sh
trap 'rm -fr /tmp/lowbattery.lock' INT TERM

mkdir /tmp/lowbattery.lock || exit 1

wait=60
threshold_percent=10

while [ X = X ]
do
        if [ X`cat /proc/acpi/ac_adapter/ACAD/state | egrep off-line` = "X" ]
        then
                off_line=no
        else
                off_line=yes
        fi

        if [ ${off_line} = yes ]
        then
                last_full_capacity=`cat /proc/acpi/battery/BAT1/info |\
                        egrep 'last full capacity' |\
                        sed -e 's/: */:/;s/ mAh//' |\
                        cut -d: -f2`
                remaining_capacity=`cat /proc/acpi/battery/BAT1/state |\
                        egrep 'remaining capacity' |\
                        sed -e 's/: */:/;s/ mAh//' |\
                        cut -d: -f2`
                battery_percent=`expr ${remaining_capacity} \* 100 / ${last_full_capacity}`

                if [ ${battery_percent} -le ${threshold_percent} ]
                then
                        logger "ACPI /etc/acpi/lowbattery.sh suspend(${battery_percent}%/${threshold_percent}%)"
                        sync;sync;sync
                        echo -n mem > /sys/power/state
                fi
        else
                break
        fi

        sleep ${wait}
done

rm -fr /tmp/lowbattery.lock

2020年08月01日 Brother PRIVIO DCP-J552N with Slackware64-14.2 [長年日記]

_ Brother PRIVIO DCP-J552N with Slackware64-14.2

家のDCP-J552Nは無線接続で利用している(IP=192.168.0.52)。

$ host dcpj552n
dcpj552n.artie.or.jp has address 192.168.0.52

Install printer driver

プリンタードライバーのインストール

dcpj552nlpr-3.0.0-1.i386.rpmをダウンロードし、root権限でrpmからtgzに変換する。

# rpm2tgz dcpj552nlpr-3.0.0-1.i386.rpm

dcpj552nlpr-3.0.0-1.i386.tgzをインストールする。

# installpkg dcpj552nlpr-3.0.0-1.i386.tgz

/opt/brother/Printers/dcpj552n/inf/brdcpj552nrcを編集し、既定の用紙タイプをA4に変更する。

*** /opt/brother/Printers/dcpj552n/inf/brdcpj552nrc.ORG    2020-07-26 15:19:23.953998715 +0900
--- /opt/brother/Printers/dcpj552n/inf/brdcpj552nrc        2020-07-26 23:31:06.169810664 +0900
***************
*** 3,9 ****
  BRResolution=600
  BResolution=PlainNormal
  BiDirPrint=ON
! PaperType=Letter
  PaperThick=Regular
  ColorOrMono=Color
  ColorMatch=Vivid
--- 3,9 ----
  BRResolution=600
  BResolution=PlainNormal
  BiDirPrint=ON
! PaperType=A4
  PaperThick=Regular
  ColorOrMono=Color
  ColorMatch=Vivid

/opt/brother/Printers/dcpj552n/lpd/filterdcpj552nを編集し、日本語対応のa2psを利用するように変更する。

*** /opt/brother/Printers/dcpj552n/lpd/filterdcpj552n.ORG  2020-07-26 14:57:13.307761817 +0900
--- /opt/brother/Printers/dcpj552n/lpd/filterdcpj552n      2020-07-26 23:44:28.009693405 +0900
***************
*** 77,84 ****
                rm -f $PS_TEMP
                ;;
        * )
!               A2PS_OP="--output=- -q -1 --no-header --borders no"
!               eval cat $INPUT_TEMP | a2ps $A2PS_OP | $PSCONV $PSCONV_OP | $BRCONV $BRCONV_OP
                RET=$?
                ;;
  esac
--- 77,86 ----
                rm -f $PS_TEMP
                ;;
        * )
! ##            A2PS_OP="--output=- -q -1 --no-header --borders no"
! ##            eval cat $INPUT_TEMP | a2ps $A2PS_OP | $PSCONV $PSCONV_OP | $BRCONV $BRCONV_OP
!               A2PS_OP=""
!               eval cat $INPUT_TEMP | /usr/local/bin/a2ps-j $A2PS_OP | $PSCONV $PSCONV_OP | $BRCONV $BRCONV_OP
                RET=$?
                ;;
  esac

a2ps.pl-1.45と日本語 UTF-8 パッチのインストール

a2ps Japanese UTF-8 patch (日本語 UTF-8 パッチ): 十四松のブログからありがたくダウンロードしインストールしa2ps-jにリンクを張る。

# cd /usr/local/bin/ && ln -s a2ps.pl-1.45 a2ps-j

/usr/local/etc/printcap for LPRng

LPRng用のprintcapを編集する。

.common:
   :sd=/var/spool/lpd/%P
   :sh:mx=0:mc=0
#
lp:rm=dcpj552n:\
        :tc=.common:\
        :if=/usr/libexec/filters/lp-filter.sh:
#
lpraw|lpr:rm=dcpj552n:\
        :tc=.common:\
        :filter=/bin/cat:
        :ff=:
# written for dcpj552n
dcpj552n:\
        :mx=0:\
        :sd=/var/spool/lpd/dcpj552n:\
        :sh:\
        :rm=dcpj552n:\
        :if=/opt/brother/Printers/dcpj552n/lpd/filterdcpj552n:
# dcpj552n end

LPRng用のスプールディレクトリを作成する。

# cd /var/spool/lpd && mkdir lp lpraw dcpj552n
# chown daemon.daemon lp lpraw dcpj552n
# chmod 700 lp lpraw dcpj552n
# checkpc

/usr/libexec/filters/lp-filter.sh

LPRng用のフィルタースクリプトを作成する。

#! /bin/sh

# Create rcfile start
#
# Ex. lpr -Zmd=Plain:reso=PlainNormal:bidir=ON
#
md=Plain
reso=PlainNormal
bidir=ON
pt=A4
thick=Regular
corm=Color
cm=Vivid
jpeg=Recommended
ht=Diffusion
ce=OFF
sd=OFF
duplex=None
duplexmode=Normal
brit=0
cont=0
red=0
green=0
blue=0
rcfile=/tmp/brdcpj552nrc.1.$$.tmp
#
for i in `echo $* | sed -e 's/^.* -Z//;s/  *.*$//;s/:/ /g'`
do
	key=`echo $i | cut -d= -f1`
	value=`echo $i | cut -d= -f2`
	case ${key} in
	md)
		md=${value}
		;;
	reso)
		reso=${value}
		;;
	bidir)
		bidir=${value}
		;;
	pt)
		pt=${value}
		;;
	thick)
		thick=${value}
		;;
	corm)
		corm=${value}
		;;
	cm)
		cm=${value}
		;;
	jpeg)
		jpeg=${value}
		;;
	ht)
		ht=${value}
		;;
	ce)
		ce=${value}
		;;
	sd)
		sd=${value}
		;;
	duplex)
		duplex=${value}
		;;
	duplexmode)
		duplexmode=${value}
		;;
	brit)
		brit=${value}
		;;
	cont)
		cont=${value}
		;;
	red)
		red=${value}
		;;
	green)
		green=${value}
		;;
	blue)
		blue=${value}
		;;
	*)
		;;
	esac
done
#
touch ${rcfile}
/usr/bin/brprintconf_dcpj552n -md ${md} \
				-reso ${reso} \
				-bidir ${bidir} \
				-pt ${pt} \
				-thick ${thick} \
				-corm ${corm} \
				-cm ${cm} \
				-jpeg ${jpeg} \
				-ht ${ht} \
				-ce ${ce} \
				-sd ${sd} \
				-duplex ${duplex} \
				-duplexmode ${duplexmode} \
				-brit ${brit} \
				-cont ${cont} \
				-red ${red} \
				-green ${green} \
				-blue ${blue} \
				-rcfile ${rcfile}
BRPRINTERRCFILE=${rcfile}; export BRPRINTERRCFILE
#
#------------------------------------------------------------
/opt/brother/Printers/dcpj552n/lpd/filterdcpj552n $*
RET=$?
#------------------------------------------------------------
#
rm -f ${rcfile}
exit $RET
#
# /usr/bin/brprintconf_dcpj552n <[option command] [setting]>...
#  -md    : Media
#    PlainDuplex : Plain Duplex Paper
#    Plain     : Plain Paper
#    Inkjet    : Inkjet Paper
#    BrotherGlossyR : Brother BP71 Photo Paper
#    BrotherBP60Matte : Brother BP60 Matte Paper
#    Glossy    : Other Photo Paper
#    Transparencies : Transparencies
#    HagakiAtena : HagakiAtena
#    HagakiUra : HagakiUra
#    PrintableDisc : PrintableDisc
#  -reso  : BResolution
#    PlainFast : Plain Fast
#    PlainNormal : Plain Normal
#    Fast      : Fast
#    Normal    : Normal
#    Photo     : Photo
#    Best      : Best
#    DiscSlow  : Slow Drying
#    DiscNormal : Disc Normal
#  -bidir : BiDirPrint
#    OFF       : Off
#    ON        : On
#  -pt    : PaperType
#    A4        : A4
#    BrA4_B    : A4 (Borderless)
#    Letter    : Letter
#    BrLetter_B : US Letter (Borderless)
#    Legal     : Legal
#    Executive : Executive
#    B5        : JIS B5
#    A5        : A5
#    A6        : A6
#    BrA6_B    : A6 (Borderless)
#    BrPostC4x6_S : 4 x 6 in
#    BrPostC4x6_B : 4 x 6 (Borderless)
#    BrIndexC5x8_S : 5 x 8 in
#    BrIndexC5x8_B : 5 x 8 in (Borderless)
#    BrPhotoL_S : 3.5 x 5 in
#    BrPhotoL_B : 3.5 x 5 in (Borderless)
#    BrPhoto2L_S : 5 x 7 in
#    BrPhoto2L_B : 5 x 7 in (Borderless)
#    Postcard  : Postcard 1
#    BrHagaki_B : Postcard 1 (Borderless)
#    DoublePostcardRotated : Postcard 2 (Double)
#    EnvC5     : C5 Envelope
#    Br12cmDisc_B : 12 cm Disc
#    EnvDL     : DL Envelope
#    Env10     : Com-10
#    EnvMonarch : Monarch
#    EnvYou4   : Y4 Envelope
#    EnvChou3  : N3 Envelope
#    EnvChou4  : N4 Envelope
#    EnvC6     : C6 Envelope
#  -thick : PaperThick
#    Regular   : Regular
#    Thick     : Thick
#    Env       : Envelope
#  -corm  : ColorOrMono
#    Color     : Color
#    Mono      : Grayscale
#  -cm    : ColorMatch
#    Natural   : Natural
#    Vivid     : Vivid
#    None      : None
#  -jpeg  : JpegPrinting
#    Recommended : Recommended Setting
#    QualityPrior : Improved Print Quality
#    SpeedPrior : Improved Print Speed
#  -ht    : HalfTone
#    Diffusion : Diffusion
#    Dither    : Dither
#  -ce    : ColorEnhance
#    OFF       : Off
#    ON        : On
#  -sd    : SlowDrying
#    OFF       : Off
#    ON        : On
#  -duplex : BRDuplex
#    None      : Off
#    DuplexNoTumble : Long-Edge Binding
#    DuplexTumble : Short-Edge Binding
#  -duplexmode : BRDuplexMode
#    Normal    : Normal
#    Duplex1   : Duplex 1 (Slower print speed)
#    Duplex2   : Duplex 2 (Slower print speed & less ink)
#  -brit  : Brightness
#    numerical value
#  -cont  : Contrast
#    numerical value
#  -red   : RedKey
#    numerical value
#  -green : GreenKey
#    numerical value
#  -blue  : BlueKey
#    numerical value
#  -rcfile
#  The rc file full path

lpr

一般的な設定(A4, 普通紙)で印刷する場合は以下の用に。

$ lpr foo.ps foo.pdf foo.txt

高品質(写真紙)で印刷する場合は以下のように。

$ lpr -Zmd=Glossy:reso=Photo:bidir=OFF:pt=BrPhotoL_B photo.ps

_ DCP-J552Nのスキャナー設定

スキャナードライバーのインストール

以下のドライバーをダウンロードし、root権限でrpmからtgzに変換する。

# rpm2tgz brother-udev-rule-type1-1.0.2-0.noarch.rpm
# rpm2tgz brscan-skey-0.2.4-1.x86_64.rpm
# rpm2tgz brscan4-0.4.9-1.x86_64.rpm

tgzをインストールする。

# installpkg brother-udev-rule-type1-1.0.2-0.noarch.tgz
# installpkg brscan-skey-0.2.4-1.x86_64.tgz
# installpkg brscan4-0.4.9-1.x86_64.tgz

/opt/brother/scanner/brscan4/brsanenetdevice4.cfgの設定

# /usr/bin/brsaneconfig4 -a name=dcp-j552n model=DCP-J552N ip=192.168.0.52
# cat /opt/brother/scanner/brscan4/brsanenetdevice4.cfg
DEVICE=dcp-j552n , "DCP-J552N" , 0x4f9:0x2e3 , IP-ADDRESS=192.168.0.52

/etc/sane.d/net.conf

DCP-J552NのIPアドレスを設定する。

192.168.0.52

/etc/sane.d/dll.conf

スキャナードライバの種類を設定する。

brother4

動作確認

$ scanimage --list-devices
device `brother4:net1;dev0' is a Brother dcp-j552n DCP-J552N

スキャンする!

$ xsane &

2020年06月04日 Shell script to convert nega film to posi [長年日記]

_ nega2posi.sh - ネガフィルム画像をポジ画像に変換するシェルスクリプト(のつもり)

#! /bin/sh
trap "rm /tmp/nega2posi.$$.*.tmp.*; exit 1" INT TERM
#
if [ "X$1" = "X-h" -o "X$1" = "X--help" ]
then
	echo "Usage: $0 [-b X,Y] [-aw | -w X,Y] [-i input] [-o output]"
	echo "Convert input(nega film) to output(posi)."
        echo ""
	echo "-b X,Y              Specify position of black."
	echo "-aw                 Adjust white balance automatically."
	echo "-w X,Y              Specify position of white and adjust white balance."
	echo "-i input            If this option is omitted or - is specified, stdin is assumed."
	echo "-o output           If this option is omitted or - is specified, stdout is assumed."
        exit 0
fi
#
AutoWhiteSw="n"
white=""
black=""
input="-"
output="-"
#
while [ $# -ne 0 ]
do
	case $1 in
	-aw)
		AutoWhiteSw="y"
		;;
	-w)
		shift
		white=`echo $1 |\
		       tr ',' '+'`
		;;
	-b)
		shift
		black=`echo $1 |\
		       tr ',' '+'`
		;;
	-i)
		shift
		input="$1"
		;;
	-o)
		shift
		output="$1"
		;;
	esac
	shift
done
#
if [ "X${black}" = "X" ]
then
	convert ${input} txt: >/tmp/nega2posi.$$.3.tmp.txt
	darkestXYC=`cat /tmp/nega2posi.$$.3.tmp.txt |\
		egrep -v '^#' |\
		tr ',:()' '    ' |\
		tr -s ' ' |\
		awk 'BEGIN{
			FS=" ";
		}
		{
			printf("%d %d %d\n",$1,$2,($3+$4+$4));
		}
		END{
		}' |\
		sort -t ' ' -k 3,3nr |\
		head -1`
	x=`echo ${darkestXYC} | cut -d ' ' -f 1`
	y=`echo ${darkestXYC} | cut -d ' ' -f 2`
	black="${x}+${y}"
fi
#
if [ "X${AutoWhiteSw}" = "Xy" ]
then
	if [ ! -r /tmp/nega2posi.$$.3.tmp.txt ]
	then
		convert ${input} txt: >/tmp/nega2posi.$$.3.tmp.txt
	fi
	brightestXYC=`cat /tmp/nega2posi.$$.3.tmp.txt |\
		egrep -v '^#' |\
		tr ',:()' '    ' |\
		tr -s ' ' |\
		awk 'BEGIN{
			FS=" ";
		}
		{
			printf("%d %d %d\n",$1,$2,($3+$4+$4));
		}
		END{
		}' |\
		sort -t ' ' -k 3,3n |\
		head -1`
	x=`echo ${brightestXYC} | cut -d ' ' -f 1`
	y=`echo ${brightestXYC} | cut -d ' ' -f 2`
	white="${x}+${y}"
fi
#
convert +repage ${input} /tmp/nega2posi.$$.1.tmp.png
size=`convert /tmp/nega2posi.$$.1.tmp.png -format "%wx%h" info:`
convert +repage /tmp/nega2posi.$$.1.tmp.png -crop 1x1+${black} -resize ${size}! -negate -strip /tmp/nega2posi.$$.2.tmp.png
convert +repage /tmp/nega2posi.$$.1.tmp.png /tmp/nega2posi.$$.2.tmp.png \
	-compose blend -composite -negate -equalize /tmp/nega2posi.$$.4.tmp.png
#	-compose blend -composite -negate -auto-level ${output}
#	-compose blend -composite -negate -normalize ${output}
#
if [ "X${white}" = "X" ]
then
	convert +repage /tmp/nega2posi.$$.4.tmp.png ${output}
else
	convert +repage /tmp/nega2posi.$$.4.tmp.png -crop 1x1+${white} -resize ${size}! -negate -strip /tmp/nega2posi.$$.5.tmp.png
	convert +repage /tmp/nega2posi.$$.4.tmp.png /tmp/nega2posi.$$.5.tmp.png \
		-compose blend -composite -equalize ${output}
#		-compose blend -composite -auto-level ${output}
#		-compose blend -composite -normalize ${output}
fi
#
rm /tmp/nega2posi.$$.*.tmp.*

2020年05月23日 Shell script to reboot BUFFALO AirStation NFINITI WHR-G301N [長年日記]

_ reboot_whrg301n.sh - 無線AP(WHRG301N)をリブートするシェルスクリプト

#! /bin/sh
trap "rm /tmp/reboot_whrg301n.$$.*.tmp; exit 1" INT TERM

whrg301n_ip=_IP_ADDRESS_
user=root
password=_PASSWORD_

random=`printf "%10.10d" ${RANDOM}${RANDOM}`
wget --http-user=${user} \
	--http-password=${password} \
	-O /tmp/reboot_whrg301n.$$.1.tmp \
	"http://${whrg301n_ip}/cgi-bin/cgi?req=frm&frm=init.html&rand=${random}" 2>/dev/null

reboot_url=`cat /tmp/reboot_whrg301n.$$.1.tmp |\
		tr '<>' '\n\n' |\
		egrep 'method="POST"' |\
		head -1 |\
		sed -e 's/^.*action="//;s/".*$//'`
reboot_url="http://${whrg301n_ip}${reboot_url}"

reboot=`cat /tmp/reboot_whrg301n.$$.1.tmp |\
	tr '<>' '\n\n' |\
	LC_ALL=C egrep reboot |\
	sed -e 's/^.*value="//;s/".*$//' |\
	od -tx1 |\
	egrep '^0000000 ' |\
	tr -s ' ' |\
	cut -d ' ' -f 2-7 |\
	sed -e 's/^/%/;s/ /%/g'`

sWebSessionnum=`cat /tmp/reboot_whrg301n.$$.1.tmp |\
	tr '<>' '\n\n' |\
	egrep 'sWebSessionnum' |\
	head -1 |\
	sed -e 's/^.*value=//;s/>.*$//'`

sWebSessionid=`cat /tmp/reboot_whrg301n.$$.1.tmp |\
	tr '<>' '\n\n' |\
	egrep 'sWebSessionid' |\
	head -1 |\
	sed -e 's/^.*value=//;s/>.*$//'`

wget --http-user=${user} \
	--http-password=${password} \
	--post-data="sWebSessionnum=${sWebSessionnum}&sWebSessionid=${sWebSessionid}&reboot=${reboot}" \
	-O /dev/null \
	"${reboot_url}" 2>/dev/null

rm -f /tmp/reboot_whrg301n.$$.*.tmp