2008年7月1日火曜日

Win2K リモートで使用する

VPNで会社のPCに接続できるようになりました。
で、会社のPCの電源管理をLAN経由で。。。

会社のPCにはMagicPacketからの目覚め機能だけでなく、

Wake Up On Direct Packet

なる機能が。

コンピュータの管理→ネットワークアダプタ→Intel(R) 82566DM Gigabit Network Connection

からプロパティで見たら出てました、以下説明文、

「パケットがアダプタに直接送信されたとき、このデバイスによりコンピュータをスタンバイまたはハイバーネーションからウェークアップ出来るようにします。 たとえば、コンピュータに保存されたファイルにリモート アクセスするように試行すると、ウェークアップします。」

MagicPacket以外のパケットを受信した場合でもWakeupしそう。。。
さっそく機能オン!試してみました。

まずは会社PCをハイバネーションへ入れ。
ノートPCからVPN経由で、ping!

なんと、会社のPCは無事目覚めましたぁ~

これであとは、
コントロールパネル→電源オプションのプロパティ→電源設定
→システムスタンバイ 10分後
→システム休止状態  2時間後
→詳細設定→コンピュータの電源ボタンを押したとき 休止状態
とか適当に休止かスタンバイに入るようにしておく。

とっ自宅でノートPCからVPNに入って、
会社のPCにpingするとお目覚め!
ほっとくと休止!

って具合。めでたい

2008年5月12日月曜日

GTKWave 3.0.0

ここがGTKWaveの本家らしいぃ。知らなかったのですが、すでに3.0.0がありますし、WindowsでもLinuxでも動作しました。
Linuxなら、これ
Windowsなら、こここれと、これの2ファイルを同一ディレクトリに展開すると動きますねぇ。
なんと3.0.0はカラー~
当たり前な気もしますが古いGTKWaveの白黒画面を見慣れていると、カラーなんで売り物?みたいな気分になります。
便利便利。

2008年4月21日月曜日

ゼロディレイ・シミュレーション

これ、FFのRTLから波形を見たところ。RTLはこんな感じです。
module ff;

reg clk,D,R;
initial begin
$dumpfile("ff.vcd");$dumpvars(0,ff);
clk=0;D=0;
#3; D=1;
#2; D=0;
#10 $finish;
end
always #1 clk=~clk;

always @(posedge clk)
R <= D;
endmodule
クロックの立ち上がりのとき、データ(D)の値は`1`と表示されてます。実回路ではディレイが乗って、クロックの立ち上がりではまだD=`0`で、ホールド時間後にD=`1`に変化するはずですが、波形上はこのホールド時間が見えてきません。実負荷シミュレーションなら遅れがでますね。
波形表示ツールはCadenceのSimvisionなのですが、フリーのGTKWaveでも同じように表示されます(当たり前ですが)。しかし私、これ見難い。常にディレイはあるものとして回路を考えていますから、クロックの立ち上がりで即座に値が変化する、って感覚になかなか慣れません。

2008年4月15日火曜日

I2C

ここがI2Cに関する詳しい。

2008年4月13日日曜日

RS232Cコネクタのオス/メス

RS232Cコネクタのオス/メス
電子回路の豆知識にストレートケーブルとクロスケーブルのなぞについて解説がありますし、ググれば沢山出てきます、結局は皆さん苦労しているのでしょうねぇ。LANケーブルについても同じような状況にあるようですね。

2008年3月7日金曜日

PIC 互換マイコン verilogソース

ここにはPICマイコンの互換と称してVerilogソースを作成し、公開している方がいます。

1999/CQ トランジスタ技術で公開されたものらしいぃ 知りませんでした。
(CQ出版社からはすでにサーバが閉鎖されているようです、Googleキャッシュからは辿れますね)

.zipを解凍して見てみると、まあ実に可愛らしいcpuです。
「PIC16C57互換です」
とマニュアルにもありますが、ダウンロードしたファイル名は`risc8.zip`とあり、8bit RISCであることが判ります。

risc8.jpegにブロック図があります。



また、ここには、フリーのVerlog用コードカバレージ・ツールが公開されています。IcarusVerilogといい、フリーのVerilog関連ツールってあるのねぇ

RTLソースを眺めてみると、本当に単相設計になってます。PICの教科書的な電気工作の本には、PICの内部動作の説明として、システムクロックを4回に分けて使っている様子が書かれていますが、どちらが本当の内部動作なのか、はたまた、どちらの表現も本当のことを示しているのか、私には判断が付きません。

それにしても、CPUのソースコードを眺めるのは楽しいものですねぇ。自分が考えるCPUと、他人が考え出すCPUはとっても似ていて、「人は違うようで似通ったことを考えるもんだぁ」と改めえ、感慨深くなるのです。

2008年2月27日水曜日

3state HDL

module top;

initial begin
$dumpfile("a.vcd");
$dumpvars(0,top);
en=1;
repeat (10) #10 en=~en;
end
assign bd=(~en)? 3'b111 : 3'bzzz;

reg en;
wire [2:0] bd;

a a(en, bd);
endmodule

module a(en,bd);
input en;
inout [2:0] bd;
reg [2:0] r,s;
always @ (en)
if(en)
r=3'b101;
else
s=bd;
assign bd=(en)?r:1'bz;
endmodule

2008年2月26日火曜日

TD4.v 3段パイプランのブロック図





これらがブロック図と波形になります。特に3段パイプラインは難しいなぁって感じですが、一番難しいのは本当に正しい3段パイプ動作をしているのか、つまりは検証の網羅性を立証することではないでしょうか。
今回設計してみたTD4の3段パイプライン版は一応それらしく動いています。が、本当の意味でBUGが無い、なんて決して口に出しては言えません。(かつて技術者の後輩が「自分のプログラムにはBUGがありません」と言い切ったことがありましたが、「BUGの無いプログラムであることを証明できますか?」と聞き返したくなったのを覚えています)

検証技術はソフトウェアに比較して並列動作である分高度なものが要求されますよね。なのでソフトウェア以上にコードを良く見る、つまりはコードインスペクションが大切であると思います。また、デザインレビューが重要で、他人の目を通して自分の設計を見ることが非常に役に立ちます。これも、ひとえに、「BUGが無いことを立証することが出来ない」ことに寄ります。

TD4.v CPUの創り方 3段パイプライン版

module rom(oen, rom_address, rom_data);

/*
instruction decode
0000_0000 : add r0,r1
0001_0000 : add r1,r0
0010_.... : add r0,#i
0011_.... : add r1,#i
0100_0000 : move r0,r1
0101_0000 : move r1,r0
0110_.... : move r0,#i
0111_.... : move r1,#i
1000_.... : jmp #i
1100_.... : jnz #i

ld(on)
0001 : r0
0010 : r1
0100 : r2
1000 : r3(PC)
*/
input oen;
input [3:0] rom_address;
output [7:0] rom_data;

wire [3:0] rom_address;
reg [7:0] rom_data;

always @ (rom_address) begin
if (oen) begin
casez(rom_address)
4'h0: rom_data=8'b0110_0001; /* move r0,#0001 */
4'h1: rom_data=8'b0010_0010; /* add r0,#0010 */
4'h2: rom_data=8'b0111_0000; /* move r1,#0000 */
4'h3: rom_data=8'b1100_1111; /* jnz #1111 */
4'h4: rom_data=8'b1000_0001; /* jmp #0001 */
default:
rom_data=8'b0000_0000;
endcase
end else begin
rom_data=8'bxxxx_xxxx;
end
end

endmodule

module dec (
ck,
reset,
i_code,
imidiate,
co,
fetch_en,
ld,
ld_na,
on,
im,
oz,
oi
);
input ck, reset;
input [3:0] i_code, imidiate;
input co;
output fetch_en;
output [3:0] ld, ld_na, on, im;
output oz;
output oi;

reg [3:0] ld_c, on_c;
reg oz_c, oi_c, en_c;
reg [3:0] ld, ld_na, on, im;
reg oz, oi;
reg en, en_na;

always @ (i_code or co or en) begin
if (en) begin
casez (i_code)
4'b0000: begin /* add r0,r1 */ ld_c=4'b0001; on_c=4'b0010; oz_c=0; oi_c=0; en_c=1; end
4'b0001: begin /* add r1,r0 */ ld_c=4'b0010; on_c=4'b0001; oz_c=0; oi_c=0; en_c=1; end
4'b0010: begin /* add r0,#i */ ld_c=4'b0001; on_c=4'b0001; oz_c=0; oi_c=1; en_c=1; end
4'b0011: begin /* add r1,#i */ ld_c=4'b0010; on_c=4'b0010; oz_c=0; oi_c=1; en_c=1; end
4'b0100: begin /* move r0,r1 */ ld_c=4'b0001; on_c=4'b0010; oz_c=0; oi_c=0; en_c=1; end
4'b0101: begin /* move r1,r0 */ ld_c=4'b0010; on_c=4'b0001; oz_c=0; oi_c=0; en_c=1; end
4'b0110: begin /* move r0,#i */ ld_c=4'b0001; on_c=4'b0001; oz_c=0; oi_c=1; en_c=1; end
4'b0111: begin /* move r1,#i */ ld_c=4'b0010; on_c=4'b0010; oz_c=0; oi_c=1; en_c=1; end
4'b1000: begin /* jmp #i */ ld_c=4'b1000; on_c=4'bxxxx; oz_c=1; oi_c=1; en_c=0; end
4'b1100: begin /* jnz #i */
if (co) begin
ld_c=4'b1000; on_c=4'bxxxx; oz_c=1; oi_c=1; en_c=0;
end else begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
end
default: begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
endcase
end else begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
end

always @ (posedge ck or posedge reset) begin
if (reset) begin
ld<=4'b0001; on<=4'b0001; oz<=1; oi<=0; /* add r0,#0 as NOP */
im<=4'b0000;
en<=1;
end else begin
ld<=ld_c; on<=on_c; oz<=oz_c; oi<=oi_c;
im<=imidiate;
en<=en_c;
end
end

always @ (posedge ck) begin
en_na<=en;
end

assign fetch_en=en & en_na;

always @ (posedge ck or posedge reset) begin
if (reset) begin
ld_na<=4'b0000;
end else begin
ld_na<=ld;
end
end

endmodule

module registor (
ck,
reset,
r_bus,
r0_ld, r1_ld, r2_ld, r3_ld,
r0_ld_na, r1_ld_na, r2_ld_na, r3_ld_na,
r0_on, r1_on, r2_on, r3_on,
ra,
rb,
ia
);

input ck, reset;
input r0_ld, r1_ld, r2_ld, r3_ld;
input r0_ld_na, r1_ld_na, r2_ld_na, r3_ld_na;
input r0_on, r1_on, r2_on, r3_on;
input [3:0] r_bus;
output [3:0] ra, rb, ia;
reg [3:0] r0, r1, r2,r3;
wire [3:0] r0_bypass, r1_bypass, r2_bypass, r3_bypass;

always @ (posedge ck) begin
if (reset) begin
r0<=4'h0;
r1<=4'h0;
r2<=4'h0;
r3<=4'h0;
end else begin
if (r0_ld_na) r0<=r_bus;
if (r1_ld_na) r1<=r_bus;
if (r2_ld_na) r2<=r_bus;
if (r3_ld_na) r3<=r_bus; else r3<=r3+1;
end
end

assign r0_bypass = (r0_ld_na==1) ? r_bus : r0;
assign r1_bypass = (r1_ld_na==1) ? r_bus : r1;
assign r2_bypass = (r2_ld_na==1) ? r_bus : r2;
assign r3_bypass = (r3_ld_na==1) ? r_bus : r3;

assign ra =
(r0_on==1) ? r0_bypass :
(r1_on==1) ? r1_bypass :
(r2_on==1) ? r2_bypass :
(r3_on==1) ? r3_bypass : 4'bxxxx ;

assign rb =
(r0_ld==1) ? r0 :
(r1_ld==1) ? r1 :
(r2_ld==1) ? r2 :
(r3_ld==1) ? r3 : 4'bxxxx ;

assign ia = r3;

endmodule

module alu (ck, reset, a, b, im, oz, oi, q_na, of, co);
input ck, reset;
input [3:0] a, b, im;
input oz, oi;
output [3:0] q_na;
output of, co;

wire [3:0] q;
reg [3:0] q_na;

assign {of,q} =
(oi == 1 && oz == 1)? im :
(oi == 1)? a + im :
(oz == 1)? a :
a + b ;
assign co=| {of,q} ;

always @ (posedge ck or posedge reset) begin
if (reset) begin
q_na<=4'b0000;
end else begin
q_na<=q;
end
end

endmodule

module cpu(ck, reset) ;
input ck, reset;

wire fetch_en;
wire [3:0] rom_address;
wire [7:0] rom_data;
wire [3:0] ld_na, ld, on;
wire oz, oi;

wire [3:0] r_bus;
wire [3:0] ra, rb;
wire [3:0] im;
wire rc;
wire co;

rom rom ( .oen(fetch_en), .rom_address(rom_address), .rom_data(rom_data));

dec DEC (
.ck(ck),
.reset(reset),
.i_code(rom_data[7:4]),
.imidiate(rom_data[3:0]),
.co(co),

.fetch_en(fetch_en),
.ld(ld),
.ld_na(ld_na),
.on(on),
.im(im),
.oz(oz),
.oi(oi)
);

registor REG_ (
.ck(ck),
.reset(reset),
.r_bus(r_bus),
.r0_ld(ld[0]),
.r1_ld(ld[1]),
.r2_ld(ld[2]),
.r3_ld(ld[3]),
.r0_ld_na(ld_na[0]),
.r1_ld_na(ld_na[1]),
.r2_ld_na(ld_na[2]),
.r3_ld_na(ld_na[3]),
.r0_on(on[0]),
.r1_on(on[1]),
.r2_on(on[2]),
.r3_on(on[3]),
.ra(ra),
.rb(rb),
.ia(rom_address)
);

alu ALU (
.ck(ck),
.reset(reset),
.a(ra),
.b(rb),
.im(im),
.oz(oz),
.oi(oi),
.q_na(r_bus),
.co(co)
);

endmodule

2008年2月22日金曜日

TD4.v CPUの創り方 2段パイプライン版

module rom(oen, rom_address, rom_data);

/*
instruction decode
0000_0000 : add r0,r1
0001_0000 : add r1,r0
0010_.... : add r0,#i
0011_.... : add r1,#i
0100_0000 : move r0,r1
0101_0000 : move r1,r0
0110_.... : move r0,#i
0111_.... : move r1,#i
1000_.... : jmp #i
1100_.... : jnz #i

ld(on)
0001 : r0
0010 : r1
0100 : r2
1000 : r3(PC)
*/
input oen;
input [3:0] rom_address;
output [7:0] rom_data;

wire [3:0] rom_address;
reg [7:0] rom_data;

always @ (rom_address) begin
if (oen) begin
casez(rom_address)
4'h0: rom_data=8'b0110_0001; /* move r0,#0001 */
4'h1: rom_data=8'b0010_0010; /* add r0,#0010 */
4'h2: rom_data=8'b0111_0000; /* move r1,#0000 */
4'h3: rom_data=8'b1100_0001; /* jnz #0001 */
4'h4: rom_data=8'b1000_0001; /* jmp #0001 */
default:
rom_data=8'b0000_0000;
endcase
end else begin
rom_data=8'bxxxx_xxxx;
end
end

endmodule

module dec (
ck,
reset,
i_code,
imidiate,
co,
fetch_en,
ld,
on,
im,
oz,
oi
);
input ck, reset;
input [3:0] i_code, imidiate;
input co;
output fetch_en;
output [3:0] ld, on, im;
output oz;
output oi;

reg [3:0] ld_c, on_c;
reg oz_c, oi_c, en_c;
reg [3:0] ld, on, im;
reg oz, oi;
reg en;

always @ (i_code or co or en) begin
if (en) begin
casez (i_code)
4'b0000: begin /* add r0,r1 */ ld_c=4'b0001; on_c=4'b0010; oz_c=0; oi_c=0; en_c=1; end
4'b0001: begin /* add r1,r0 */ ld_c=4'b0010; on_c=4'b0001; oz_c=0; oi_c=0; en_c=1; end
4'b0010: begin /* add r0,#i */ ld_c=4'b0001; on_c=4'b0001; oz_c=0; oi_c=1; en_c=1; end
4'b0011: begin /* add r1,#i */ ld_c=4'b0010; on_c=4'b0010; oz_c=0; oi_c=1; en_c=1; end
4'b0100: begin /* move r0,r1 */ ld_c=4'b0001; on_c=4'b0010; oz_c=0; oi_c=0; en_c=1; end
4'b0101: begin /* move r1,r0 */ ld_c=4'b0010; on_c=4'b0001; oz_c=0; oi_c=0; en_c=1; end
4'b0110: begin /* move r0,#i */ ld_c=4'b0001; on_c=4'b0001; oz_c=0; oi_c=1; en_c=1; end
4'b0111: begin /* move r1,#i */ ld_c=4'b0010; on_c=4'b0010; oz_c=0; oi_c=1; en_c=1; end
4'b1000: begin /* jmp #i */ ld_c=4'b1000; on_c=4'bxxxx; oz_c=1; oi_c=1; en_c=0; end
4'b1100: begin /* jnz #i */
if (co) begin
ld_c=4'b1000; on_c=4'bxxxx; oz_c=1; oi_c=1; en_c=0;
end else begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
end
default: begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
endcase
end else begin
ld_c=4'b0001; on_c=4'b0001; oz_c=1; oi_c=0; en_c=1; /* add r0,#0 as NOP */
end
end

always @ (posedge ck or posedge reset) begin
if (reset) begin
ld<=4'b0001; on<=4'b0001; oz<=1; oi<=0; /* add r0,#0 as NOP */
im<=4'b0000;
en<=1;
end else begin
ld<=ld_c; on<=on_c; oz<=oz_c; oi<=oi_c;
im<=imidiate;
en<=en_c;
end
end
assign fetch_en=en;

endmodule

module registor (
ck,reset,r_bus,
r0_ld, r1_ld, r2_ld, r3_ld,
r0_on, r1_on, r2_on, r3_on,
ra,
rb,
ia
);

input ck, reset;
input r0_ld, r1_ld, r2_ld, r3_ld;
input r0_on, r1_on, r2_on, r3_on;
input [3:0] r_bus;
output [3:0] ra, rb, ia;
reg [3:0] r0, r1, r2,r3;

always @ (posedge ck) begin
if (reset) begin
r0<=4'h0;
r1<=4'h0;
r2<=4'h0;
r3<=4'h0;
end else begin
if (r0_ld) r0<=r_bus;
if (r1_ld) r1<=r_bus;
if (r2_ld) r2<=r_bus;
if (r3_ld) r3<=r_bus; else r3=r3+1;
end
end

assign ra =
(r0_on==1) ? r0 :
(r1_on==1) ? r1 :
(r2_on==1) ? r2 :
(r3_on==1) ? r3 : 4'bxxxx ;

assign rb =
(r0_ld==1) ? r0 :
(r1_ld==1) ? r1 :
(r2_ld==1) ? r2 :
(r3_ld==1) ? r3 : 4'bxxxx ;

assign ia = r3;

endmodule

module alu (a, b, im, oz, oi, q, of, co);
input [3:0] a, b, im;
input oz, oi;
output [3:0] q;
output of, co;
assign {of,q} =
(oi == 1 && oz == 1)? im :
(oi == 1)? a + im :
(oz == 1)? a :
a + b ;
assign co=| {of,q} ;
endmodule

module cpu(ck, reset) ;
input ck, reset;

wire fetch_en;
wire [3:0] rom_address;
wire [7:0] rom_data;
wire [3:0] ld, on;
wire oz, oi;

wire [3:0] r_bus;
wire [3:0] ra, rb;
wire [3:0] im;
wire rc;
wire co;

rom rom ( .oen(fetch_en), .rom_address(rom_address), .rom_data(rom_data));

dec DEC (
.ck(ck),
.reset(reset),
.i_code(rom_data[7:4]),
.imidiate(rom_data[3:0]),
.co(co),

.fetch_en(fetch_en),
.ld(ld),
.on(on),
.im(im),
.oz(oz),
.oi(oi)
);

registor REG_ (
.ck(ck),
.reset(reset),
.r_bus(r_bus),
.r0_ld(ld[0]),
.r1_ld(ld[1]),
.r2_ld(ld[2]),
.r3_ld(ld[3]),
.r0_on(on[0]),
.r1_on(on[1]),
.r2_on(on[2]),
.r3_on(on[3]),
.ra(ra),
.rb(rb),
.ia(rom_address)
);

alu ALU (.a(ra), .b(rb), .im(im), .oz(oz), .oi(oi), .q(r_bus), .co(co));

endmodule

2008年2月19日火曜日

TD4.v CPUの創り方

module top;

reg ck, reset;

initial begin

$dumpfile("cpu.vcd");
$dumpvars(0,CPU);

#0 ck=0;
#0 reset=1;

#100 ck=~ck;
#100 ck=~ck;

#0 reset=0;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

#100 ck=~ck;
#100 ck=~ck;

$finish;

end

cpu CPU (.ck(ck), .reset(reset));

initial $monitor ("ck:rs = %b:%b", ck, reset);
endmodule

module rom(rom_address, rom_data);

/*
instruction decode
0000_0000 : add r0,r1
0001_0000 : add r1,r0
0010_.... : add r0,#i
0011_.... : add r1,#i
0100_0000 : move r0,r1
0101_0000 : move r1,r0
0110_.... : move r0,#i
0111_.... : move r1,#i
1000_.... : jmp #i
1100_.... : jnz #i

ld(on)
0001 : r0
0010 : r1
0100 : r2
1000 : r3(PC)
*/
input [3:0] rom_address;
output [7:0] rom_data;

wire [3:0] rom_address;
reg [7:0] rom_data;

always @ (rom_address) begin
casez(rom_address)
4'h0: rom_data=8'b0110_0001; /* move r0,#0001 */
4'h1: rom_data=8'b0010_0010; /* add r0,#0010 */
4'h2: rom_data=8'b0111_0000; /* move r1,#0000 */
4'h3: rom_data=8'b1100_0001; /* jnz #0001 */
4'h4: rom_data=8'b1000_0001; /* jmp #0001 */
default:
rom_data=8'bxxxx_xxxx;
endcase
/*$display("%h:%h",rom_address,rom_data);*/
end

endmodule

module dec (
i_code,
co,
ld,
on,
oz,
oi
);
input [3:0] i_code;
input co;
output [3:0] ld;
output [3:0] on;
output oz;
output oi;

reg [3:0] ld, on;
reg oz, oi;
always @ (i_code) begin
casez (i_code)
4'b0000: begin /* add r0,r1 */ ld=4'b0001; on=4'b0010; oz=0; oi=0; end
4'b0001: begin /* add r1,r0 */ ld=4'b0010; on=4'b0001; oz=0; oi=0; end
4'b0010: begin /* add r0,#i */ ld=4'b0001; on=4'b0001; oz=0; oi=1; end
4'b0011: begin /* add r1,#i */ ld=4'b0010; on=4'b0010; oz=0; oi=1; end
4'b0100: begin /* move r0,r1 */ ld=4'b0001; on=4'b0010; oz=0; oi=0; end
4'b0101: begin /* move r1,r0 */ ld=4'b0010; on=4'b0001; oz=0; oi=0; end
4'b0110: begin /* move r0,#i */ ld=4'b0001; on=4'b0001; oz=0; oi=1; end
4'b0111: begin /* move r1,#i */ ld=4'b0010; on=4'b0010; oz=0; oi=1; end
4'b1000: begin /* jmp #i */ ld=4'b1000; on=4'bxxxx; oz=1; oi=1; end
4'b1100: begin /* jnz #i */
if (co) begin
ld=4'b1000; on=4'bxxxx; oz=1; oi=1;
end else begin
ld=4'b0001; on=4'b0001; oz=1; oi=0; /* add r0,#0 as NOP */
end
end
default: begin
ld=4'bxxxx;
on=4'bxxxx;
oz=1'bx;
oi=1'bx;
end
endcase
end
endmodule

module registor (
ck,reset,r_bus,
r0_ld, r1_ld, r2_ld, r3_ld,
r0_on, r1_on, r2_on, r3_on,
co,
ra,
rb,
rc,
ia
);

input ck, reset;
input r0_ld, r1_ld, r2_ld, r3_ld;
input r0_on, r1_on, r2_on, r3_on;
input [3:0] r_bus;
input co;
output [3:0] ra, rb, ia;
output rc;
reg [3:0] r0, r1, r2,r3;
reg carry;

always @ (posedge ck) begin
#1;
if (reset) begin
r0=4'h0;
r1=4'h0;
r2=4'h0;
r3=4'h0;
carry=0;
end else begin
if (r0_ld) r0=r_bus;
if (r1_ld) r1=r_bus;
if (r2_ld) r2=r_bus;
if (r3_ld) r3=r_bus; else r3=r3+1;
carry=co;
end
$display("r0 = %h r1 = %h r2 = %h r3 = %h", r0,r1,r2,r3);
end

assign ra =
(r0_on==1) ? r0 :
(r1_on==1) ? r1 :
(r2_on==1) ? r2 :
(r3_on==1) ? r3 : 4'bxxxx ;

assign rb =
(r0_ld==1) ? r0 :
(r1_ld==1) ? r1 :
(r2_ld==1) ? r2 :
(r3_ld==1) ? r3 : 4'bxxxx ;

assign rc = carry;

assign ia = r3;

endmodule

module alu (a, b, im, oz, oi, q, of, co);
input [3:0] a, b, im;
input oz, oi;
output [3:0] q;
output of, co;
assign {of,q} =
(oi == 1 && oz == 1)? im :
(oi == 1)? a + im :
a + b ;
assign co=| {of,q} ;
endmodule

module cpu(ck, reset) ;
input ck, reset;

wire [3:0] rom_address;
wire [7:0] rom_data;
wire [3:0] ld, on;
wire oz, oi;

wire [3:0] r_bus;
wire [3:0] ra, rb;
wire rc;
wire co;

rom rom (.rom_address(rom_address), .rom_data(rom_data));

dec DEC (.i_code(rom_data[7:4]), .co(rc), .ld(ld), .on(on), .oz(oz), .oi(oi));

registor REG_ ( .ck(ck), .reset(reset), .r_bus(r_bus), .r0_ld(ld[0]), .r1_ld(ld[1]), .r2_ld(ld[2]), .r3_ld(ld[3]), .r0_on(on[0]), .r1_on(on[1]), .r2_on(on[2]), .r3_on(on[3]), .co(co), .ra(ra), .rb(rb), .rc(rc), .ia(rom_address));

alu ALU (.a(ra), .b(rb), .im(rom_data[3:0]), .oz(oz), .oi(oi), .q(r_bus), .co(co));

endmodule

2008年2月14日木曜日

startx/startxwin.bat/startwin.sh

この3つのスクリプトって、

startx :xinitを呼び出してXを起動(shellスクリプト)
startxwin.bat:XWinを呼び出してXを起動(.batファイル)
startxwin.sh :XWinを呼び出してXを起動(shellスクリプト)

がそれぞれの違いになります。
なのでぇ、cmdからはstartxwin.bat、bashからはstartx/startwin.sh、でCygwin Xを起動することになります。
っつと、もっとも大きな違いはと、xinitを使わないと$HOME/.xinitrcが読まれません。

当たり前なんですが、忘れがちです・・・

CygwinX.bat(startwin.bat日本語編)

@echo off
set DISPLAY=127.0.0.1:0.0
set CYGWIN_ROOT=\cygwin
set PATH=.;%CYGWIN_ROOT%\bin;%CYGWIN_ROOT%\usr\X11R6\bin;%PATH%

if not exist %CYGWIN_ROOT%\tmp\.X11-unix\X0 goto CLEANUP-FINISH
attrib -s %CYGWIN_ROOT%\tmp\.X11-unix\X0
del %CYGWIN_ROOT%\tmp\.X11-unix\X0

:CLEANUP-FINISH
if exist %CYGWIN_ROOT%\tmp\.X11-unix rmdir %CYGWIN_ROOT%\tmp\.X11-unix

REM =======================================================================
REM (1)ローカルでCygwinを起動する場合の設定です
REM (2)XWinの書式
REM -rootless:デスクトップが透過します
REM (3)ログイン後にxwinclipコマンドでWindows側とコピー&ペースト可能となります
REM =======================================================================
REM start XWin -engine 4 -clipboard -emulate3buttons
start XWin -engine 4 -clipboard -emulate3buttons -rootless
run xmodmap /home/Administrator/.Xmodmap
run wmaker
run xterm

REM =======================================================================
REM (1)ローカルでCygwinを起動する場合の設定です
REM (2)日本語環境が設定されている場合に利用します
REM (3)XWinの書式
REM -rootless:デスクトップが透過します
REM (4)ログイン後にxwinclipコマンドでWindows側とコピー&ペースト可能となります
REM =======================================================================
REM start XWin -engine 4
REM set LANG=ja_JP.EUC
REM set XMODIFIERS='@im=kinput2'
REM run /usr/local/canna/bin/cannaserver
REM run xset fp+ /usr/X11R6/lib/X11/fonts/TT
REM run xmodmap /home/Administrator/.Xmodmap
REM run xrdb -load /home/Administrator/.Xresources
REM run kinput2 -canna -cannafile /home/Administrator/.canna
REM run wmaker

REM =======================================================================
REM (1)Solarisログインサーバへ接続する場合の設定です
REM (2)XWinの書式(ホスト名を使用する場合はhostsへの登録が必要です)
REM -query :ログインサーバのIPアドレス or ホスト名
REM -from :ローカルのIPアドレス or ホスト名
REM -fp :ログインサーバのIPアドレス or ホスト名
REM -fullscreen -depth 8 :8bitカラーで利用する
REM =======================================================================
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lis4 -from 172.16.245.166 -fp tcp/sv_lis4:7100 -fullscreen -depth 8
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lis4 -from 172.16.245.166 -fp tcp/sv_lis4:7100
REM sleep 30
REM xmodmap /home/Administrator/.Xmodmap

REM =======================================================================
REM (1)Linuxログインサーバへ接続する場合の設定です
REM (2)XWinの書式(ホスト名を使用する場合はhostsへの登録が必要です)
REM -query :ログインサーバのIPアドレス or ホスト名
REM -from :ローカルのIPアドレス or ホスト名
REM -fullscreen -depth 8 :8bitカラーで利用する
REM =======================================================================
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lin11 -from 172.16.245.166 -fullscreen -depth 8
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lin11 -from 172.16.245.166
REM sleep 30
REM xmodmap /home/Administrator/.Xmodmap

REM =======================================================================
REM (1)HP-UXログインサーバへ接続する場合の設定です
REM (2)XWinの書式(ホスト名を使用する場合はhostsへの登録が必要です)
REM -query :ログインサーバのIPアドレス or ホスト名
REM -from :ローカルのIPアドレス or ホスト名
REM -fp :ログインサーバのIPアドレス or ホスト名
REM -fullscreen -depth 8 :8bitカラーで利用する
REM =======================================================================
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lih21 -from 172.16.245.166 -fp tcp/sv_lih21:7000 -fullscreen -depth 8
REM start XWin -kb -screen 0 -clipboard -emulate3buttons -query sv_lih21 -from 172.16.245.166 -fp tcp/sv_lih21:7000
REM sleep 30
REM xmodmap /home/Administrator/.Xmodmap

2008年2月13日水曜日

imeproxy で cygwin日本語入力

WindowsのIMEをproxyしてくれて、cygwinなどからIMEで日本語入力を可能にしてくれるもの、ん~っすばらしいぃ~考え方
ここにプロジェクトがあります。また、ここに解説があります。まだまだβ的ではありますが。

kinput2→canna

がUnix系日本語入力の基本(だった)なのですが、「IMEがある場合(つまりWindowsからLinuxを使用して仕事している場合っね)」辞書サーバが2つあるのも不経済かと思いますよ。なんでLinuxでの日本語入力もIMEで代用出ると経済的。

kinput2→imeproxy→IME

ってパスで日本語変換を達成してしまうようです。
まあ、FrontEndとしてkinput2が必要なことは致し方ない。英語圏の人はFrontEndなんて不要ですから、少なくともkinput2などは必要になってしまいますよねぇ。で、ご一緒に仕事しているメンバの中には、cannaサーバを立ち上げるのが面倒なので、Linux上では日本語一切使用しないって人もいます。昔は自分でcanna立ち上げて利用していたのに、いまや「Windowsでイイじゃん」ってことらしい。それと自分でIMEの辞書を鍛えてたりすると、「WindowsのIMEとcanna、両方を鍛えるのは面倒」となります。一番キツイのは人名シリーズではないでしょうか?。IMEでは出てくるのにcannaではダメっみたいなことが起こるという訳。

で、imeproxyの登場です。Linux上のEmacsからkinput2でWindows上の自分の辞書へアクセスできれば、とってもウレスィイー

2008年2月8日金曜日

dot ファイルにパスワードが散乱

メールサーバのパスワード、有効期限が来たので「変更」。
っとっとーう~ぅ メールが読めんし、送れん状態になったぞぉー

そう、私はズボラですから、パスワードなんてドットファイルに書いちゃってます。

.fetchmailrc
.muttrc
.nbsmtprc

それぞれのファイルにメールサーバのパスワードが散乱しておりました。(当然600ですがぁ)
これを一元管理しようとかなんとか考え出すとうっとおしい。
全部のファイルを書き換えましょう・・・

2008年2月7日木曜日

ベイズ統計理論とPush型情報提供

ディスプレイを眺めていて、コンピュータとのインタフェースについて考え込むことがしばしばあります。

見るために人がアクションする(Pull型)
見たくなくてもコンピュータが見せようと動く(Push型)

このPush型/Pull型という区別はかつて有名になったことがあります。元来はPull型が支配的であったコンピュータの世界に、テレビのようなPush型が加わってきたときに、「これは今までのコンピュータの概念とチト違うぞぉ」ってことで、話題になったと記憶しています。

①見たい情報は何かを人が考えて、アクションして取り出す

②見せたい情報は何かをコンピュータが考えて、画面に表示する

ところが②はうっとうしい場合が多々あります。これは当たり前ですねぇ。
「今は画面の別のところに意識が集中しているのだから、気を散らさないで!」
てなこと。しかし、「メールが届いたら教えてくれぇ」とコンピュータに指示しておいたくせに、教えられた時と場合により、うっとうしい、と感じるわけで、なんともしがたい。

やはり、人の指示に従うだけではなく、「時と場合をコンピュータが理解する、アクションを変える」ことが出来たら良いのでしょう。人の状況をコンピュータが理解できるかどうか。

"ベイズ統計理論"の出番なのかもしれません。

「明日死ぬ確率というのは、これから起こる現象の確からしさを表すものだが、確率は将来の予測ばかりに利用されるとは限らない。...既に起こった現象が特定の原因によってもたらされた確率というものもある。ベイズ Bayes,T.という統計学者は、この原因の確率を『ベイズの定理(Bayes' theorem)』として定式化した。」

とある通り、現象から原因の尤度(もっと(尤)もらしさ)を求めてしまう考え方だとさ。

Bなる現象が確認された場合、過去がAであった確率を P(A|B)
過去がAであったならばBの現象が起こる確率を P(B|A)
過去がAであった確率 P(A)
現在、Bが確認される確率 P(B)

このとき、P(A|B) は、
P(A|B) ∝ P(B|A)
P(A|B) ∝ P(A)
P(A|B) ∝ 1/P(B)
となるそうなぁ(これベイズの定理ね)。例えば、

A:インフルエンザに罹った
B:高熱が出ている

では、
P(A|B):高熱が出ているのだからインフルエンザに罹っていた。現在の高熱の原因はインフルエンザである確率
P(B|A):インフルエンザに罹ると高熱がでる確率(医学的に確率は求まるけれど個体差がある)
P(A):インフルエンザであった確率(インフルエンザ流行の度合いで確率は求まるけれども、最近インフルエンザの人と接触があった場合など個人差がある)
P(B):現在高熱が出ている確率(なぞの伝染病が高熱を伴って流行していると高熱出している人は沢山いる)
となるけど、それぞれの確率は主観的に決めてしまいましょってことぉ。

カッコ内を考察すると、現在の高熱の原因がインフルエンザである確率は、
昔インフルエンザに罹った経験があり、高熱を伴ったので、P(B|A)は高い
最近インフルエンザの流行は少ないが、インフルエンザに罹った友達がいるからP(A)は高い
昨日風呂上りに裸で眠ってしまい、寒くて目が覚めた。P(B)は高い

その他の例題と解説に感染者問題などが詳しく説明されてます。

主観的確率に従って「今の操作者の時と場合」を判断することはできないものでしょうか?
P(暇そう) P(忙しそう)
それぞれの主観的確率をはじき出して、アクションを変える。なんだかできそうな・できなさそうな。

procmail スプール先を毎月変える

けっこうズボラな私としては、たっくさん送られてくるメールを一々振り分けることはせず、ぜーんぶ、一箇所に集めてしまっています。.procmailrcがこう、

PATH=/bin:/usr/bin:/usr/local/bin:.
MAILDIR=$HOME/.Mail/Maildir # You'd better make sure it exists
DEFAULT=$MAILDIR/inbox/.
LOGFILE=$MAILDIR/from/procmail.log
LOCKFILE=$HOME/.lockmail

なんで全部のメールがinboxにMH形式で(/.)溜まってゆきます。さすがに数万通ではmuttで開くのが遅くて困るので、毎月溜める先を変えてみます(Maildir形式で)。

:0
$MAILDIR/inbox-`date +%Y%m`/

これを.procmailrcに足しておきます。procmailのログ(LOGFILE=$MAILDIR/from/procmail.log)を見ると、

Subject: [MFP09_ML:00892] Re: =?ISO-2022-JP?B?GyRCIVo+ZU4uQF8bKEI=?=
Folder: /svhome/ogurak/.Mail/Maildir/inbox-2008_02/new/1202364704.52 4361
Subject: [rt_jitsumu_caiman.maestro:10384] =?ISO-2022-JP?B?RFNN?=
Folder: /svhome/ogurak/.Mail/Maildir/inbox-2008_02/new/1202364705.52 3582
Subject: [MFP09_ML:00893] Re: =?ISO-2022-JP?B?GyRCIVpKIUtcJDUbKEI=?=
Folder: /svhome/ogurak/.Mail/Maildir/inbox-2008_02/new/1202364705.52 6964

どうやら振り分けられている様子。メデタイ

2008年2月6日水曜日

透明Window その2

透明Window その1でも触れましたが、「透明なWindow」に興味が湧く大きな理由に、

「WindowsやX Windowでの`枠(タイトルバーと言うのかしら)`が嫌いっ ダサイっ」

てのがありますねぇ。

このタイトルバーってダサいです。なぜかと言えば、飽きたから、そして、デザインが悪いから、そして、なーにもしないから。

もしタイトルバーが無いと、「マウスでWindowを操作できないじゃ~ん」などと考えません。マウスでWindowを操作すること自体がダサい。もちろん、マウスでなきゃ無理っつー作業も沢山あります。これを無理してキーボードで操作しようなんて考えません。

まず飽きが来ていることは確かでしょう。Mac Book Airの複数本指先インタフェースみたいな新しいものも出てきてます(実用的とは思えませんがぁ:-p)。それから皆がマウスでクリクリしながら仕事している姿を眺めていると、異常ーって感覚に陥ります(私だけ?)。キーボードを叩くのにも皆さん「無くて七癖」ですが、異常には感じません(これも私だけ?)。まあこれは個人の感覚的過ぎるので置いといて。マウスは未来的では無い、古びたものに感じられてしまいます。

タイトルバーのデザインは最悪です。滅多に使わないくせにいつも画面に表示されていて、好きに色を変えられてもあまり機能的な意味合いは無いですよねぇ。タイトルバーに、
「時間を表示する」
「アラーム機能がある」
「日程管理ができる」
「新着メールのヘッダーを表示する」
「季節や時間に応じて変化する」
「天気予報を表示する」
なんだって機能的にくっつけられそうなものではありませんかぁ~
ググってみますと、
MicroSoftではこーんなTipsがありますが、タイトルバーにフォルダーのフルパス表示しても嬉しさ微小ですねぇ~
こーんなフリーソフトもありますねぇ~

アクティブウィンドウのタイトルバーにランチャー機能を付加するソフト
日付や時間、モデムの送受信速度などをタイトルバーに表示「以心伝心」
タイトルバーでメールの着信通知を行ってくれるソフト
タイトルバーに列車が走る!?「何でも走る!!」(??電車マニアにはたまらん??/-)

色々できるじゃぁないですかっ。

ディスプレイの一部を常に占有しているわけですから、「もうちょっと働いてくれっ」と思うワケです。

2008年2月3日日曜日

w3m なぜか.tclファイルがWindowsへ転送されて・・・

hogehoge.tclファイルがWindowsへ転送されてしまう~

私はw3m設定の~/.w3./mailcapで、

application/* fview.tcl %s

としてあります。ところが、application/*とファイル・サフィックスの対応付けを示す~/.mime.type に、

application/x-tcl tcl

などと書き込んでしまっていたため、
w3m hogehoge.tcl でw3mを起動すると、

w3mの頭の中:「hogehoge.tcl は サフィックスが.tclなので~/.mime.typeを見ると mimeタイプがapplication/x-tclだなぁ・ならば~/.w3m/mailcapを見ると application/*に相当するから、fview.tclを起動してファイル名hogehoge.tclを渡そうぅ」

fview.tclの頭の中:「hogehoge.tclですかぁ、Windowsへ転送しておきましょう」

ってなわけで、hogehoge.tclがWindowsへ転送後適当なWindows上のアプリケーションで表示されていた、っつーワケでした。

~/.mime.type に.tclに関するエントリーを書き込んだの、誰だっ?私っ?
私が書き込んだわけではなく、~/.mime.typeは私が/etc/mime.typeからコピーして来たもので、/etc/mime.typeには、tclに関するエントリーがあったのです。

まあ私しか書き込み権ありませんから、犯人は自分ですね。
削除するとOKとなりました。

2008年1月30日水曜日

mutt 添付ファイル名がヘンテコリンな場合

muttでattachmentの画面で、ファイル名のサフィックス部分にスペース文字を含んでしまって、

I 2 ホゲホゲ定例_080130.p df [applica/pdf, base64, 32K]
とか、
I 2 ホゲホゲ定例_080130. p df [applica/pdf, base64, 32K]

こんな感じになる場合がありますねぇ~これって送り先が変なファイル名で送ってきているのか、mutt側の問題なのか、私には判定できませんがぁ。この場合添付ファイルを保存してWindowsにfview.tclで転送・表示させようとしても、サフィックスがこの有様だとうまく行きません。

付け焼刃ではありますが、fview.tclを修正して対応!
こんな感じのprocをつけたして、

proc validate_suffix {euc} {
regexp {\.([\w\s]+)$} $euc all sfx
regsub -all {\s+} $sfx {} sfx2
regsub $sfx $euc $sfx2 euc
return $euc
}

転送する直前にファイル名のサフィックスを訂正しておきます。

file rename -force $path [set path $path_valid]

こうしておくと、
ホゲホゲ定例_080130.p df
こんなのや、
ホゲホゲ定例_080130. p df
なのも↓
ホゲホゲ定例_080130.pdf
にファイル名を変更してからWindowsに転送できますので、対策完っとなりますねぇ。

2008年1月29日火曜日

mutt bindとmacro

.muttrcに下記のように書き込んでみますと、


bind pager \cd half-down
bind pager \cu half-up
macro pager + <enter-command>^aset<space>pager_index_lines=20^e\n
macro pager - <enter-command>^aset<space>pager_index_lines=6^e\n
macro pager = <enter-command>^aset<space>pager_index_lines=6^e\n

動作は簡単ですね。CTRL-Dでページのハーフダウン、CTRL-Uでページのハーフアップ。
+ でインデックス・ウィンドウの拡大、-や=で縮小。

.muttrcのここでのポイントは<space>って記法。ホントにスペースを打ち込むと,<enter-command>は1引数なので、そこで引数が切れたと判断されてしまいます。これを防いでいます。

2008年1月24日木曜日

screen bell_msgでバナー表示

screenのbell_msgって、結構色々と利用方法のアイディアが思いつきます。
「新着メールが届いたときbell_msgを鳴らす」の他にも、

「新着メールの確認スクリプトを作って、screenのbindに割り当て、bell_msgで表示」
「長時間JOBの終了をbell_msgで知らせる」

など考えちゃいますぅ。デフォルト5秒間しか表示されないbell_msgですが、screenのlastmsgコマンドで再表示できますから、bell_msgは端末の利用者になにかを知らせるには良い方法です。

さらにbell_msgの表示時間も自由に設定できますから(但し秒単位)、bell_msgだけで凝った"お知らせバナー"だって考えられますねぇ~:-)

やりすぎだとは思いますが、
#!/bin/csh -f

set msg=""
screen -X msgwait 1
screen -X msgminwait 0
foreach n (N e w " " M a i l)
set msg="${msg}${n}"
screen -X bell_msg " $msg"
screen -X bell
sleep 1
end
screen -X msgwait 5
screen -X msgminwait 1
screen -X bell_msg "$msg Comes!"
screen -X bell

これで、"New Mail" のメッセージを一文字ずつ、8秒間かかって表示していきます。それから"New Mail Comes!"と5秒間表示して消えます。ちょっとバナーっぽい表示にはできるんですが、不連続な表示と、CPUの状況で動作がぎこちないぃ~:-<
まあ、ホントに利用しようは思っていませんしぃ、こんなことも出来るのねぇ的サンプルです。もちろんbell_msgでは日本語表示できません。

2008年1月22日火曜日

日本語エディタ ng

ここで開発されている軽量版emacs風日本語エディタ。

「Ngとは、Nihongo micro Gnu emacsの略であり、決してNo Goodの略ではありません。一言でいうと、NgはGNU Emacsライクな小型日本語エディタです。 Ngは、吉田さんによって、1990年ごろ、 mg(micro GNU Emacs/これもmicro Emacsの改良版です)を改造する形で作られました。その後、多くの人達の協力によって、 Ng 1.3.1(最後の公式版)/1.3L(最も多く使われている版)まで改良、バージョンアップされました。その後、マシンパワーの増大、Demacsの登場、MS-DOS/Human68kの衰退等によって、 Ngが使われる機会は少なくなり、開発も下火になりました。

しかし、中にはNgを使い続ける輩(私もその一人です)もおり、そのような人達によって、便利な非公式パッチや、新しいOSへの移植などが作られました。
私もこれらのパッチを当てたり、自分でソースをいじったりしていました。
自分のためにNgに手をいれていく内に、Ng 1.3Lより便利になって(自画自賛)、新たな機種にも対応したので(私の力ではありませんが)、 Ngの新たなバージョンとして公開する事にしました。」とあります。

Emacs嫌いの私、その理由は「なんせ重いのよぉ」なのとCRTL押し続けたくない、のと、lispが嫌い、なことですぅ。で、軽量Emacsモドキのngです。日本語エディタとして目に付くのは、Emacsやvim、ne、そしてこのngなど、このくらいでしょうかぁ。vimを日本語エディタとして使わないのは、viは英語圏に最適化されている、つまり単語の区切りはスペースだっつーことを最大限利用したキーマップやコマンド体系になっているように感じられるから。これを日本語みたいに単語の区切りがハッキリしない言語へ適用してもメリットはあんまり無いっと思うぅ。「日本語」を扱う観点から考えるとなにもviでなくても良い。neを長らく使ってきたが、なにせ最大の欠点が「コピペで段落が乱れてしまう」ってことです。これは辛い。で、ngなワケです。

私C-xをscreenのプレフィックスに使っちゃってます:-P
で、コマンド・プレフィックスをC-rへ変更。C-zは「Ng をサスペンドするには、C-z をタイプします」なのですが、screenの元ではサスペンドはまず使いませんし、私はよくUndoと勘違いします。

makeは至って簡単で、linux用は、ln -s sys/sysv/Makefile .;make で完成し設定ファイルを cp dot.ng ~/.ng で置いておきます。

プレフィックス文字をCTRL-x から CTRL-rに変更するため、~/.ngへ下記を追加します。

(global-set-key "\^r" "c-x prefix")

ふぅ~、Emacsのlispとちょっと似ていますが、マニュアルが見当たらないので一苦労です。起動すると、おっ、コピペもバッチリ:-)

ne同様、ngって名前、短すぎますねぇ、ググるとノイズがひどい。

ターミナル(2) kterm

お仕事でログインしているマシーンにktermが無いっ。まぁ私はあまり困りませんが。

ktermっとは一体誰が開発しているのでしょう。ググるとpatchが沢山ありますねぇ、Cygwin用やらlinux用やら。特にフォント関係ではFAQとしてここが詳しいようです。

xset q でフォントパスを調べて使えそうなフォントを探すっ。きっと名前は kなんとか、kanji*とかねっ。で、その名前で、

$kterm -km euc -fk k14 -fn 7x14

こんな感じでktermを起動します。因みに-fk(漢字) -fn(英字) -km(漢字モードeuc/sjis)。
これでファイルの中身なんかはちゃんと見えますが、日本語ファイル名なんかをlsしても化けます。これは/bin/lsが日本語を通さないためでしょう。fdcloneなら表示してしまいます。

2008年1月20日日曜日

X Window 上でUSBキーボードから/や_を入力できない?

X Window 上でUSBキーボードから/や_を入力できないことがあります。.xmodmapを修正すれば良いのですが、日本語キーボード用の.xmodmapなんて大概どっかのWebで公開されているものを引っ張ってきたものを使ってたりして内容なんて見てませんでしたぁ:-)

いざ使えないとなると、とっても困るので、.xmodmapの内容についてちょっとだけっ。中身は、

keycode 数字 = キー

みたいになっていますので、例えば`_`が入力できなければ、そのキーコードが.xmodmapに書かれていないと思われます。
まずは、キーボードを打った時にX Window Systemへ伝わるキーコードをxevで調べます。xevを立ち上げて、`シフト+_`を打つと、

KeyPress event, ....
...... , keycode 211 (keysym 0x5c, backslash), ....
......

分け解らんメッセージですが、`シフト+_`はどうやら
「keycodeが211でbackslash付き」
と想像できます。これを.xmodmapへ書き込んでやりましょう。

keycode 211 = backslash underscore

Xをリスタートすると、`_`が打てるようになります。他のキーでも同様になっていますので、.xmodmapを自前で全て作成することができます(フツーやりませんけどねぇ、公開してくださっている方、ありがとう:-)

新着メールが届いたらscreenに知らせる -Xオプション

screen上で作業中に新着メールが届いたら、screenに知らせるっ、便利ですぅ。
動作中のscreenでコマンドを実行するには、screenの-Xオプションを使えば簡単に実現できますね。

screen -X bell_msg "New Mail New Mail!"
screen -X bell
これで現在起動しているscreen のWindowの右隅、ちぃっちゃくメッセージが5秒間出て消えます。

screenのセッションが現在のホスト上に複数立ち上がっていると-Xオプションがエラーを返します。
screenは、セッション名(sessionname)、WindowID(番号またはタイトル)で状態を管理しています。セッション名は、pid.tty.hostです(pidは省略可)。現在のホスト上にあるscreenのセッションリストは、screen -lsで表示されます(存在しない場合1を返します)。特定のセッションを選択してコマンドを送信するためには-Sオプションでセッション名を指定します。

screen -S pid.tty.host -X bell_msg "New Mail New Mail!"
sceen -S pid.tty.host -X bell

すべてのセッションにメッセージを送るには、
[hogemailyo]
#!/bin/csh -f
foreach s (`screen -ls|awk '{print $1;}'|grep "\.")
screen -S $s -X bell_msg "$*"
screen -S $s -X bell
end
こんな感じになります。

私はfetchmailが新着メールを受け取ったとき、procmailへ振り分けたりしていますので、

[procmail_with_screen_bell.shスクリプト]
#!/bin/csh -f
cat | procmail
foreach sss (`screen -ls | egrep '[0-9]+\..+\..+' | awk '{print $1}'`)
screen -S $sss -X bell_msg "New Mail Comes!"
screen -S $sss -X bell_msg
end

のようなprocmailのラッパ・スクリプトを作っておいて、fetchmailから新着メールを渡すように、.fetchmailrcのmdaの部分を

[.fetchmailrc内]
mda "procmail_with_screen_bell.sh"

としてしまいます。
これで、
fetchmailが新着メールを受け取り、procmail_with_screen_bell.shスクリプトへ渡す
procmail_with_screen_bell.shがprocmailへメールを渡す
procmail_with_screen_bell.shがscreenへメッセージを表示する


メールが届くと、左下にちぃッちゃく、"New Mail Comes!"と表示されますねぇ。

mutt POP3フォルダ

mutt 1.4辺りから、POP3 フォルダ機能がサポートされ、spoolfile設定に、pop3サーバを直接指定できるようになっています。

set spoolfile=pop://pophost.com:110/

同様にimapサーバも扱えます。

set spoolfile=imap://imaphost.com:143/

フツーのpop3アクセスの場合、
set spoolfile=~/Mail
set folder=+inbox

のようにして置いて、まずpop3サーバからメールをinboxへフェッチしてから閲覧していましたが、POP3フォルダはフェッチ無しで直接pop3サーバを見に行きます。当然ローカルディスクを使用しないので、既読/未読の状態を保存することがでません。

mutt attachファイルを特定の場所へ保存する

linux上でmuttを走らせてメールを読んでいて、doc添付メールを開こうと思う。このときlinux上のmuttで何が出来るでしょう?かつては意地でもdocファイルをlinuxで見えるようにしようとがんばってましたが、完全あきらめ。
で、Windows用のファイルなのだからWindowsで見れば良いでしょう、ってことにしてます。linux上で添付ファイルを保存する場所を一箇所に決めてしまい、いつも添付ファイルはo同じ場所へセーブしています。muttでは、下記のようにmacroを使って、

macro attach s <save-entry>^a~/.Mail/attached_files/^e
macro attach <return> <save-entry>^a~/.Mail/attached_files/^e\n

これで、添付ファイルの参照モードからリターン・キーやsキーに対してデフォルトの保存先がいつも一箇所になります。このmacroの定義記述は、
attachモードで
sキーを押すと
save-entry関数が呼ばれ
ctrl-aでミニバッファの先頭へ移動し
/.Mail/attached_files/とキー入力を擬似し
ctrl-eで行末へ移動し
改行を打つ
ところまでやってくれるmacroの定義です。

添付ファイルがいつも一箇所に保存されているので、fdcloneで、
fd ~/.Maildir/attached_files/
で参照できます。またfdcloneの.fd2rcに、

# launcher definition
launch ".html" "w3m %C"
launch ".htm" "w3m %C"
launch ".exe" "fview.tcl %C"
launch ".xls" "fview.tcl %C"
launch ".csv" "fview.tcl %C"
launch ".ppt" "fview.tcl %C"
launch ".doc" "fview.tcl %C"
launch ".pdf" "fview.tcl %C"
launch ".zip" "fview.tcl %C"
launch ".lzh" "fview.tcl %C"
launch ".cab" "fview.tcl %C"
launch ".jpg" "fview.tcl %C"
launch ".tif" "fview.tcl %C"
launch ".bmp" "fview.tcl %C"
launch ".gif" "fview.tcl %C"

と記述しておくと、ftp転送スクリプトへ選んだファイルが転送されます。

また、いちいち確認せずにWindowsへ転送してしまうためには、

macro attach <return> <save-entry>^a/svhome/ogurak/.Mail/attached_files/^e\n<shell-escape>^afview.tcl<space>~/.Mail/attached_files/^e\n

とするとリターンを打つと即座にWindows上で表示できます。
これは最初の<save-entry>でファイルを所定の場所へ保存後<shell-escape>で所定の場所で最新のファイルをWindowsへ転送・表示することになります。ここでのfview.tclはファイル名ではなく、ディレクトリを引数として最新のファイルを探し出して処理しています。

2008年1月18日金曜日

どこへいった? fetchmailのdaemon

linuxサーバセンタみたいな環境で数十台のlinuxを相手に仕事をしていると、使うlinuxマシーンを変えた時に「昨日Loginしていたマシーンっ、、どれだった?」状態になります。GNU Screenなんかで作業を保存していたりして、困るときがありますぅ。まあscreenの復帰はあきらめるとして、一番困るのはfetchmailのdaemonではないでしょうか。どっかで動いて、spoolにどんどんとメールが届くのは良いのですが、止めたくても止められない。

$ chmod 000 .fetchids

としてみてもダメ。勝手にchmod 700 .fetchidsに変更して使っちゃうぅ~。どこにいるのかいなぁ~私のfetchmail daemonクンは?
片っ端から知ってるlinuxマシーンへLoginして自分のfetchmail daemonを探す羽目にならないように、fetchmail daemonを起動する時はラッパを噛ませて起動したマシーンのipアドレスを保存しておきましょう。

#!/bin/csh -f
ifconfig | grep 'inet addr' > ~/.fetchmail.ip
fetchmail -U -s -d 600

こんなものを使っていますぅ、fetchmail自信、同じようなことをしているのでしょうか?

メール送信プログラム nbsmtp

sendmailを祖先とする沢山のsendmailクローン達。
ホント沢山いますよねぇ

exim
im

等使用経験があるのですが、最近はSMTP Auth対応のsmtpに出会う機会が増えています。ここでもimのimputにSMTP Authと無理やり会話させる修正など書いています。

nbsmtp
コレ簡単にSMTP Authと会話できるMTAです。
.muttrcに、
set sendmail="nbsmtp -d hogehoge.com -h smtp.hogehoge -f ogura.kenji@hogehoge.com -V"
って感じ。SMTP-Auth経由でメール送信できます。

~/.nbsmtprcにユーザ名とパスを書き込みます。
auth_user = user-hogehoge
auth_pass = pw-hogetta

chmod 600を忘れずに。

muttの弱点と克服

muttの弱点。
思うに1つありますねぇ。

「新規メールを書きながら、他のメールからコピペすることができない」

Windowsのメーラでは送信メールを書く場合、新規Windowが伴って作成されることが多いです。なので、他のメールを参照したり、コピペしたりは簡単。対してmuttはフツーに使うと、muttがエディタの終了を待ってしまいます。

[エディタ立上げ]→編集&保存→[送信確認]→[送信]

のフローでメール処理が進みますから、他のメールからコピペできないです。
ググっても良い解答はなかなか得られませんでした。

幾つか方法があるように思われます。
①別メールの参照用にmuttをもう一つ立ち上げる
②別メールの作成用にmuttをもう一つ立ち上げる
③別メールの参照機能をmuttに付加する(mutt改造)

③は重いので考えないっ。
②は別メールの作成といっても、全員返信やら、個別返信、転送、中継など色々な状況によってmuttは動きを変えます。別メールの作成用にmuttを立ち上げる時、いろんな立ち上げ方法を実装する必要が有りそうで、実現は難しいそうぅ。
ってことで①でしょうか。。。

単純にmuttを2つ立ち上げるのは、智慧が無いように思われるので、もう少しカッコよく、参照用またはメール作成用に別プロセスでmuttを立ち上げる方法を考えてみす。mutt(1.4)のコマンドラインオプションを見てみると下記。

引数なしに muttを実行すると Mutt はスプールメールボックスを読みに行きます。しかし、コマンドラインから指定してやることで他のメールボックスを読んだりコマンドラインから直接メールを送ったりすることも可能です。

-a メールにファイルを添付する
-b BCCのアドレスを指定
-c カーボンコピー (Cc) の宛先を指定する
-e 初期化ファイルが読まれた後に実行する設定コマンドを指定
-f 読み込むメールボックスを指定
-F 指定したファイルから初期化コマンドを読み込む
-h コマンドラインオプションについてのヘルプを表示
-H ドラフトとしてヘッダと本文を読み出すファイルを指定
-i メッセージ作成時に取り込むファイルを指定
-m デフォルトのメールボックスの種類を指定
-n システムの Muttrc を読まない
-p 延期していたメールを呼び出す
-R メールボックスを読み取り専用で開く
-s subject を指定 (空白を含むときは引用符で囲む)
-v バージョンとコンパイル時の定義を表示
-x mailx(1) の作成モードを真似る
-y mailboxes コマンドで指定されたファイルを含んだメニューを表示させる
-z メールボックスにメッセージが存在しないなら直ちに終了する
-Z 新しいメッセージのある最初のフォルダを開く、無いなら直ちに終了する

ほぅ~けっこうあるんですねぇ:-)

でっ、ちょっとだけ閃きましたぁ
muttがmコマンドやgコマンドでメール作成に取り掛かるとき、一時ファイルを作成し、このファイルを引数としてエディタ(set editot=プログラム で指定したもの)を起動します。エディタが終了してファイルがセーブされると、送信/保存の選択を聞いてきます。エディタが終了しても渡したファイルの内容に変化がないと、メール閲覧モードに移行します。なので、エディタとして例えば常に1を返すだけのtrueコマンドを使用すると、メール作成モードに入り、宛先とサブジェクトを指定した後すぐにメール閲覧モードに戻ってしまいます。
この動きを利用できそうです。エディタとして例えば下のようなスクリプト(hogetto)を指定します。

[editorhogex]
#!/bin/csh -f
xterm -e mutt -H $1 -e 'set editor=ne' &
sleep 1

上のhogettoスクリプトはメール作成モードの新しいmutt(-Hオプション)をxterm上で起動して、1秒待って終了します。なので元々のmuttは渡したファイルに変化がなかったのでメール作成モードを終了してメール閲覧モードへ戻ります。
メール作成モードで立ち上げたxterm上の新しいmuttは、一時ファイルを引数に与えて、エディタとしてこの場合`ne`を立ち上げます。

元々のmuttが作った一時ファイルを消去する前に新しいmuttがそれを確実に読み込んで立ち上がるために、sleep 1を入れて元々のmuttが動き出すまでに1秒の`待て`をいれてあります。

mutt -Hオプションは、与えられた一時ファイルからヘッダと本文をインクルードしますから、ヘッダ部分に宛先とサブジェクトが書かれていれば、それを用いてメールの雛型を作ってくれます。なので一時ファイルにヘッダを含めておく必要が有ります。このために、edit_header=yesとしておきます(muttのdefaultではedit_header=no)。

これで元々のmuttはメール参照モードへ戻り、新たにメール作成・送信用のmuttがxterm上で別ウィンドウとして立ち上がります。コピペも楽になりました。ここではxtermを使用していますが、ウィンドウマネージャとしてGNU screenを使用しているのであれば、-X オプションで立ち上がっているscreenへコマンドを送ることで別のセッションが作成できますね。またscreenは起動していると環境変数TERMにscreenを設定、環境変数STYに現在のscreenセッション名を設定してますので、この場合、

[editorhogescreen]
#!/bin/csh -f
if ($TERM == "screen") then
screen -S $STY -X screen mutt -H $1 -e 'set editor=ne'
else
ne $1
endif
sleep 1

このhogeronは、screenプロセスに対して、「screenを一面追加してそこでメール作成モードのmuttを起動させる」ことができます。screen の-Xオプションは即座にリターンしてきますので、この例では、&を付けてプロセスを分ける必要はありません。

一点、メール作成モードでmuttを立ち上げたとき、一時ファイルの内容から割り出した宛先でメール作成するかどうかをmuttが聞いてきます。これは不要なのですが。まぁリターンを2度叩くだけなので気にはなりませんが。

透明 Window その1

すけすけウィンドウ。
Windowsの世界ではWindows2Kぐらいから、 ここにもあるように透明なウィンドウが流行った時期がありましたねぇ。私もさんざっぱら色々試してみまて、「ほぅ~(^^)こんな感 じになんるんだぁ~」と。

結局、ウィンドウが重なって下の画面がうっすら見えるんだけど、3重、4重とウィンドウが重なると、なにがなにやらわっかりにく~いデスクトップになって しまったような。2重ぐらいが限度かなぁと思いました。相当大きなディスプレイなら3重4重でもイイかもしれませんね。まあ使い方の問題なのでしょう。

すけすけウィンドウの話題は未来的なコンピュータへの想像を掻き立てた面があります。新しいユーザインタフェースを感じさせるような。iPodに代表され るような新しいUIの出現をPC上でも予感させましたが、実際、すけすけ機能だけでは、斬新ってだけで、PC環境として成熟してゆくことは無かった気が します。

アイディアも色々ありますねぇ
①「タスクトレイアイコンの右クリックメニューから、半透明表示したいウィンドウの名前を選択する
②「ドラッグ操作で移動中のウィンドウだけを半透明表示する」
③「アクティブウィンドウ以外のウィンドウやダイアログを半透明表示にする」
④「画面の四隅にマウスポインタを動かすだけでアクティブウィンドウを半透明表示する」
⑤「ウィンド ウを広げた時に隠れてしまうデスクトップアイコンを、一時的にウィンドウの上に浮かび上がらせて表示し、クリックしやすくする」

ratpoisonなどの環境下では、④辺りが馴染むでしょうか。全画面表示の状況でマウスを四隅へ持っていくと半透明化して下のウィンドウがすけて見えるってこと。
ですが、X windowのクライアントはすけすけにはなりません。まあそうでしょうねぇ。無理があるのでしょう、きっとぉ。
telnet(PuTTY)を全画面で使用している場合は、ちゃんとすけますねっ。願わくば、
「四隅に持って行くだけでなく、何かのキーに透明化/解除を割り当てられると、ぴったり使用感になりそうです」が。rxvtでの「すける」とは単にデスクトップの背景を自分のウィンドウサイズ分切り取って自分の背景に設定しているだけみたいなのですが、この「④のすけすけ」は(っていうか、Windows2Kの透過機能は)全然違ってウィンドウの下で動作している他のアプリの様子が判ります。すばらしい。何か時間のかかる処理を待っている間、別の仕事を全画面表示で(-:やるには最適な感じですねぇ。
ところで、透明化したウィンドウをcapcapみたいな画面キャプチャソフトが無視してしまうのは困ったものですぅ、皆さんどうやってカッコいい画面をWebで公開しているのでしょうか。。。とほほぉぉ

すけすけ話しはまだまだ続きます。ToBeCotinued

2008年1月16日水曜日

ratpoison i18n: The Simplest Window Manager

こんなCUI Window Managerもあるんですねぇ。
ratpoison

「殺鼠剤」というだけあって、ひと癖もふた癖もあるウィンドウマネージャーなので万人にはおすすめできない。
* キーボードを叩くのが好きな人
* マウス操作は面倒だと思っている人
* Emacs使い
* GNU Screen大好きな人
* ウィンドウマネージャーをスクリプト言語で遠隔操縦するのが好きな人
* 変わったソフトを試すのが好きな人
っとあります。(まさに私のことではないかいなぁ、但しEmacsの部分は除く:-)

でもでも、結局X Windw上でごちゃごちゃやってるって感じですね。ratpoison以上に作者のShawn Bettsって人のほうに興味を惹かれます。だって紹介文が、
「GUI嫌い・マウス嫌いで有名なカナダ人プログラマ。マニア好みなフリーソフトウェアの作者」
ですよぉ:-o

で、インストール(on cygwin)。
ここからダウンロードして、

$ gunzip ratpoison-1.4.2.tar.gz
$ tar xvf ratpoison-1.4.2.tar
$ cd ratpoison-1.4.2
$ ./configure --x-includes=/usr/X11R6/include --x-libraries=/usr/X11R6/lib/
$ make
$ make install

と、なんなくmakeに成功。
.xinitrcを、

xhost +
xeyes &
xterm &
exec openbox "$@"

# exec openbox "$@"
exec ratpoison "$@"

としてXを起動する、、、おおぉデッカイ xeyes !続いてxterm がフルスクリーン!
巨大xeyesに睨まれてビックリしました(^|^)が、無事起動。

がっ。やっぱり下記の通り、

「ratpoisonは慣れれば十分実用的なウィンドウマネージャーなのだが、どうしても相性の悪いソフトは存在する。
  • たくさんのウィンドウを開くソフト。主にgimp
  • 最大化すると表示がゆがんでしまうソフト。主に画像ビューワ

前者の代表としてはgimpが有名である。 ratpoisonの天敵ともいえるgimpをどう対処するかについて述べる。」

とあるように、ratpoisonではつらいX プログラムもある、って、私のX プログラム(以下hogehoge)がまさにこれに当てはまってしまった。ん~っと、ここはXnestで乗り切るしかないねぇ~(だんだんツボにハマッテてきてないだろうかぁ:-o

Xnest -geometry 1024x768 -kb :1 &
DISPLAY=:1 openbox &
DISPLAY=:1 hogehoge &
(cshの場合は、
env
DISPLAY=:1 openbox &
env DISPLAY=:1 hogehoge &
)

これでhogehogeクンはopenboxの元、無事最大化されずにratpoisonの管理下に入れました。

2008年1月15日火曜日

Winodwsは X Protocolを理解しない 当たり前?

WindowsはX Protocolを理解しない。
当たり前すぎるけれど、理解したとしても不思議でもない。Windows上で走れるX Serverが市販ソフトとして存在すれけれど、なにもWindowsって名のWindow管理ソフトをインストールした上に更に、X Windows Serverって名のWindow管理ソフトをインストールするのも無駄といえば無駄。

WindowsがX Protocolをサポートして販売してくれると、ユーザとしてはウレシイ。ついでに日本語入力やらフォント環境やらも共通化ってのはどうでしょう。もっとウレシイ。そんでもってX Window向けに作ったプログラムがWindowsでも走れると更にプログラムの節約にもなる。

X Serverソフトが売れなくなるなんて心配する必要は無いでしょう?だって既に売れていないからねぇ。大概はcygwinで間に合っちゃう。高速な描画が必要なlinuxソフト(レイアウトやらグラフィックス)の場合、やっぱり最適化されたX Serverが必要だろうけど、ニッチ、ニッチ。この際、WindowsにX Protocol載せてくれないんでしょうか?

cygwin X の起動スクリプト.bat

cygwin Xを起動する場合、cygwin bashから、startx を起動するとcygwin bashのウィンドウが残ります。このウィンドウを終了させると Cygwin Xも終了してしまうぅ。ので最初のcygwin bashのウィンドウを残しておく必要がありそうなんですが、なんか目障りです:-<

まずは、startxスクリプト中のxinitを起動している部分を cygwin runで包みましょう。

xinit "$@"

run xinit "$@"

これでcygwin bashは不要になりますので、cygwin bashを起動する.batファイルを
@echo off
C:
chdir C:\cygwin\bin
bash --login -i C:\cygwin\home\ogurak\startx

こんな風に作っておくと、Windowsからこの.batを起動することでcygwin Xが立ち上がりますねぇ:-)
runコマンドに関して、

run コマンドはコンソール・ウィンドウを隠してプログラムを実行する Cygwin 独特のコマンドです。 Cygwin プログラムのほとんどはコンソール・モード・アプリケーション *14ですから,本来ならば,標準入出力のためのコンソール・ウィンドウがまとわりつきます。 run コマンドは,このコンソール・ウィンドウを隠して,あたかも GUI モード・アプリケーションのような見かけにします。 run コマンドはもともと Cygiwn 用 X11 プログラムのひとつでした。しかし,今年 (2005年) 11月に改編され, base カテゴリの独立パッケージになりました。今は X11 を導入しなくてもデフォルトでインストールされます。
などとあります。

てことで、更にこんなサンプルも・・・
@echo off
C:
chdir \cygwin\bin
run bash -l -c 'cd /usr/local/lib/pysol-4.81/src; python pysol.py --nosound'

なので、startxのように、startxを編集せんでも、start.batを
bash --login -i C:\cygwin\home\ogurak\startx

run bash --login C:\cygwin\usr\X11R6\bin\startx
としておけばOKです。

vim の vi互換モード

最近のlinuxディストリビューションで、viを起動するとvimが立ち上がりますよね。
でもvimは嫌いです。viなんてエディタ以上のことを期待してません。
高機能な環境みたいなものが必要ならEmacsenを使えばいい。で、vimのvi互換モードですが、

~/.exrc
に、
set tag=tags
set tabstop=4
set shiftwidth=4
set compatible
set backspace=0
set noswapfile

こんな指定を入れています。特に、
set noswapfile
を入れたことで、編集中に「ファイル名~」なファイルが作成されなくなります。
バックアップファイルが無くなって困ることがあるのでしょうか?私がつかいこなしていないだけでしょうかねぇ・・・

[Tips]viで制御文字を入力する。
ここから
Cntrl-V
に続けて制御文字を入力できます。
例えば、dos2unixと同じことが、
:%s/Cntrl-VEnter//
で可能です。

2008年1月13日日曜日

色々なプロセス構成

linux上で動くプログラムを書くことがお仕事だとして、screenやmutt、w3m、telnet、fdなどをcygwin上かlinux上か、どこで動ごかすと使い勝手は良いのだろうか?という疑問。
状況を整理してみますうぅ。

構成①として、
cygwin上で、bash→screen/mutt/w3m/telnet→linux上で、fd

また、私が推奨する構成②は、
windows上で、telnet→linux上で、screen/mutt/w3m/fd

構成①では、まず、Cygwinのターミナル(rxvtとかcygwin bashとか)を起動し、その上でscreenを起動します。screenからmuttやw3m、そしてtelnetでlinuxへ接続しfdを起動します。つまりメールやウェブはWindows上で動作させます。

対して、構成②は、まずPuTTYなどのWindowsのtelnetソフトでlinuxへ接続します。接続先のlinux上で、muttやw3mやfdを起動します。つまりtelnet以外は全てlinux上で動作させます。

構成①でも②でもあまり使い勝手に違いは無いのでしょうか?

screenはCtrl-Dでサスペンド、screen -rで復帰することができます。当たり前ですが、サスペンドしたscreenプロセスがdaemon化するなどの状態で生きていないと画面の復帰が出来ません(screenはdaemonとして行き続ける事で、対話動作のサブプロセスなどを制御しています)。例えば、cygwin bashから、rxvtを立ち上げてscreenを起動し、お仕事をして、中断のためCtrl-Dでサスペンド。もしその後でrxvtやcygwin bashを終了してしまうと、Ctrl-Dで中断しておいたはずのお仕事の続き画面がscreen -rで復帰できなくなります。cygwin bashを常に起動しておけばscreen -rで復帰できます。
linux上では、Ctrl-Dで中断したscreenプロセスがdaemon化してlinux上で生き続けている状態にありますので、telnetを切断しても、後程再接続すればscreen -rで続き画面を復帰できます。

linuxであろうがWindowsであろうが、システムの電源が落ちてしまえば、プロセステーブルは消えて無くなるので復帰できなくなることは同じなのですが、最近のlinuxサーバなど常時稼動が普通ですから、screenプロセスを生かしておくにはlinuxサーバ上が便利です。

一方、Cygwin上でmuttが走っていれば、ftpを経由した添付ファイルの転送など不要ですから便利です。

結局は、Windows用のプログラムを書くのか、linux用のプログラムを書くのか?ターゲット側でscreenを使用するのがよいようですねぇ

2008年1月12日土曜日

w3m

telnet先で動作させるページャ w3m。

w3mは「www(w3)を見る(m)」から命名されたそうです。ページャとしてhtmlを見る着想はとっても面白いです。xlsやらwordやらをhtmlへ変換して、見れるところだけw3mで見る、なんてことも出来ます。
lessがhtmlフォーマッティングをサポートした感覚です。

ここで開発されています。

ググればたくさんの情報が得られます。
ここ では、WordやExcelをw3mと絡めて表示させるヒントがあります。(って私のページですけど:0) xlHtml, pptHtml,wvHtml等など

w3mの~/.w3m/mailcapでエントリを追加することでw3mはリンク先のアドレスを判定して、対応するプログラムを呼び出すようになります。

こ れでMS-Officeが不要になるわけもありませんね、だってMS-Officeの文書には画像やらグラフやら、テキストベースではない表現が沢山入っ ていますし、第一ファイルの文字部分だけが見えるだけで編集は出来ません。だからlinux側で全てを完結するのは困難だと思えます。

しかし、大切なのはw3mがリンク先のファイルをテンポラリ場所へ保存してくれて、そのパスを外部プログラムへ渡してくれることですね。この機能を利用して、ファイルをftpでPCへ飛ばし、PC側で表示することが簡単に出来るわけです。
こ のブログにもあるような( ②linux側のftpクライアントスクリプト)ものを~/.w3m/mailcapに指定しておけば、w3mでpdfを見よ うとすると、ローカルにセーブされたファイルがPCへftp転送されて、PC上のAcrobatで表示される仕組みが簡単に作れる。たとえば、

application/* ②linux側のftpクライアントスクリプト %s

み たいなエントリを~/.w3m/mailcapに書き込めば良い。勿論PC側ではちょっと特別なftpd( ①PC側のftpdサーバスクリプト)を立ち上 げておく必要があるがぁ。上のエントリ で/*とあるのは強力だろう?だってPCで表示できそうなものは全てPCで表示するってわけだから。「だったらWebページもw3mではなく、PCで見れ ば?」とは考えないでほしいっ。PCで見る必要がないページはw3mで十分だと`私`は思っているから。。。

fdclone

telnet先で動作させるファイラーfdclone。
便利ですし、コンパイルで工夫する必要はまったくありません、Cygwin上でも動きます。
DOS時代のFDをlinuxのクローンとして作成されたものらしいです。

ここで開発されています。

ググればいろいろと情報はありますが、開発元のページですべて事足ります。
このファイラーは強力ですから、設定次第で色々な場面で大活躍します。日本語ファイル名も難なく表示しますし、.fd2rc次第です。

telnet(1) PuTTY

Windos telnetとしても選択肢は広いような狭いような。
Windows上で使用するtelnetの話です。

PuTTY

「すけすけ」telnetが可能です。"puttyjp"でググると情報が得られます(まずはここ)。 フルスクリー ン・モードがあって、完全にWindowsが見えなくなります(見えなく出来ます:-)。ALT-Enterでフルスクリーン・モードがトグルします。フルス クリーン・モードに入ったら、他のWindowsアプリとの切り替えに、ALT-Tabが便利でしょう。

これはターミナルソフトではないので、お仕事先linuxへ接続して使用します。安定感も日本語も問題なくスバラシイ。

ターミナル(1) rxvt 非X版

ターミナルとしても選択肢は広いような狭いような。
Windows上で使用するテキストターミナルの話です。

cmd(コマンドプ ロンプト)では話になりマシェ~ん。「すけすけターミナル」にあこがれますねぇ~背景が透けて見えるやつです。Enlightment をつかったカッコイイデスクトップのスクリーンショットがWebのあちこちに掲載されてます。ちょっと未来的な想像を掻き立ててくれます。理想のターミナ ルへの探索。

cygwinのbash
cygwinのrxvt.exe

Cygwin インストールが必要になります。まあbashは当たり前なので割愛。画面サイズが自由に変えられないので選択肢外です。rxvtはcygwin1.dll さえあれば動くので、bashから立ち上げではなくて、非X Windowモードでrxvtを使うことができます。一応「すけすけ」も実現できます。非X Windowモードって、ようするにbashを立ち上げずにエクスプローラからバイナリを直接クリックっです。

「すけすけ」設定は、cmdで
rxvt -xrm '*inheritPixmap=true'
!これでWindowsの背景画像の一部がターミナルの背景になります。単にターミナルの背景画像をWindowsのものと同じに指定して立ち上げたときとは全然見た目が異なりますから、ちょっと感動できますねぇ。
cygwinを入れた場所に依存しますが、バッチファイルは、
@echo off
C:\cygwin\bin\rxvt.exe -bg black -fg white -xrm '*inheritPixmap=true' -e /usr/bin/bash
でしょうか、上は私の例。
-fgで選ぶ色は「すけすけ」ターミナルの場合重要です。Windowsの背景が黒っぽいとまるで文字が見えなくなりますので、白っぽい-fgとしますね。逆もあります。

で、rxvtを起動して自分自身のWindowsにLoginしてみます。
$telnet 127.0.0.1
$ telnet 127.0.0.1
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

Server allows NTLM authentication only
Server has closed connection
Connection closed by foreign host.
$
と 「接続不可」応答が返ってきます。がポート25へ接続を試みたことは確認できます(本当に自分のPCに接続したいならここを参考に telnetdの設定を変更しましょう)。後はお仕事するマシーンへ接続すれば本業に移れます。

非X-Windowで動けるものはCygwinのバイナリの中にいくつもあるでしょうから、試してみても面白いでしょう。私はやってませんが、かたっぱしからクリックしてみて何が起こるのかなぁってことです。

で もCygwinのインストールは必要になりそうですから、結局はPC X WindowとMS-Windowsの両方がPC上にあることになります。なんか無駄に感じますねぇ。cygwin1.dll無しで(または含んでしまう ような)rxvt.exeもどこかにあるのでしょうが(簡単なことなのですが)。

2008年1月11日金曜日

解決したかったこと Windows vs linux

解決したかったことは、なんだったのか。
問題に目を奪われると、「結局なんだったんだ?」と自問自答しないと虚しい結末となる。このブログで何がわかるのか?ってことだ。

linuxマシーンのX Window System代わりにWindowsを使えないものだろうか?
ってのが始まりのように感じられる。UNIX時代からCUIで色んな仕事をしてきたけれど、X Windowが現れ、「ほぅ~便利なもんだ」と思い、X Windowのプログラムも仕事で沢山書きはじめた。まだWindows3.1の頃のお話だ。

そ して、MacOSが現れた。会社中がAppleコンピュータとAppleTalkの世界があった。Appleの上でもtelnetを使って、UNIXマ シーンへLoginして仕事していたなぁ。MacDrawも使いましたねぇ。ドキュメントをワープロで書いていた頃のお話。全部のワープロが消滅しまし た。

そしてWindows95が現れた。会社中がWindows95 PCとEtherに変わった。さてとこのWindows95が気に入らなかった。不安定の一言。Macとの対比があって「Macの方が使いやすいし頑丈 だ、Appleがんばれ~ぇ」。だけどMacの負けでしたね。MS-Office問題が発生したためです。電子メールでmS-Office文書が送りつけ られてきてはお手上げ状態です。仕事するにはWindows95が必要になりました。だけど95からtelnetしてお仕事してました。

そ してWindows2000とlinuxが現れました。WindowsNTはまぁ使いにくかったですがWindows2000はいたって親切設計!コレ でよいかぁと思わせるものです。ですがWindows2000からtelnetしてお仕事してました。そしてtelnet先がUNIXからlinuxへ変 わっていました。

つまり、私にはWindows上での開発話しが回ってこなかっただけのことではあるのですが、ずぅ~とtelnetで仕事してます。

でも不思議に思いませんかぁ?

「ウィンドウシステムが2つ、世の中に存在する必要性」
X Window systemとWindows2000

どっちにも良いところ・悪いところっあるでしょうが、似たり寄ったりのものです。
ホントに2つ必要でしょうかねぇ?

さ て、linux派はX Window上でMS-Officeの互換ソフトでなんとかなるんじゃぁないかと考えて、OpenOffice.orgへと進みますね。最近では MacOSX用にNeoOfficeなんてのもある。ヴェトナムで設計センタを立ち上げたとき、経費節減目的でOpenOfficeを導入しました。それ はそれで良いけれど、どのPCにもMS-Officeがインストールされている日本の状況で、OpenOffice使うのって、なんか無駄な気がしませ んっ?個人的なお小遣いの節約ならよい選択肢でしょう。でも仕事となると信頼性やら効率やら気になりますし、本業は経費削減ではありませんよねぇ~

このブログでは、(無理やりですが)メールをlinux上で読み書きすると仮定した時、一番便利な環境ってどんなものでしょうか、ってことが主題となっています。

mutt ja インストール

非rootでセットアップする。
~/bin/linux/以下にコマンドを配置
~/bin/linux/lib/以下にダイナミックライブラリを配置
~/bin/linux/lib/IM/以下にIMのperlのモジュール(.pm)を配置

(2) muttja, alien, slangのrpmを準備、muttはソース、alienはperl、slangはバイナリ。rpmmkは私のスクリプト。
ls
muttja-1.4-1SDRI.src.rpm
slang-1.4.5-11.i386.rpm
alien_8.56.tar.gz
rpmmk

・rpmmk でrpm/以下のディレクトリを事前に掘って(ダサイ)、バイナリを配置
rpmmk
cp alien_8.56.tar.gz rpm/RPMS/i386/
cp slang-1.4.5-11.i386.rpm rpm/RPMS/i386/

(3) muttjaはソースパッケージなのでバイナリを作る
rpmrebuild --rebuild muttja-1.4-1SDRI.src.rpm
cd rpm/RPMS/i386

・バイナリの展開とインストール
gtar xvzf alien_8.56.tar.gz
cd alien
./alien.pl -t ../muttja-1.4-1SDRI.i386.rpm
gtar xvzf muttja-1.4.tgz
cp usr/bin/mutt/* ~/bin/linux

(4) slangバイナリの展開
alien -t ../slang-1.4.5-11.i386.rpm
gtar xvzf slang-1.4.5.tgz

(5) ダイナミックライブラリの準備
cd usr/lib
ln -s libslang-utf8.so.1 libslang.so.1
cp libslang* ~/bin/linux/lib
setenv LD_LIBRARY_PATH /svhome/ogurak/bin/linux/lib:$LD_LIBRARY_PATH

(6) imputのインストール
gtar -xvzf im-148.tar.gz
cd im-148
./configure

#IM/Smtp.pmを編集して、IMをSMTP-AUTHに対応させる。
#まずはパスワードをutf-8に変換する
perl -MMIME::Base64 -e "print encode_base64('a0203718');"
YTAyMDM3MTg=
#このパスワードをsmtp_openするさいに認証タイプに続けて送信するようにpm 72行目に追加
&tcp_command(\*SMTPd, "AUTH LOGIN", '');
&tcp_command(\*SMTPd, "YTAyMDM3MTg=", '');
&tcp_command(\*SMTPd, "YTAyMDM3MTg=", '');
#pmをインストール
cp -r IM ~/bin/linux/lib

#imputがコピー先のSmtp.pmを参照するように13行目を変更する
use lib '/svhome/ogurak/work5/Package/im-148'; ###DELETE-ON-INSTALL###

use lib '/svhome/ogurak/bin/linux/lib'; ###DELETE-ON-INSTALL###

#これでIM本体は完成したのでimputをインストール
cp imput ~/bin/linux

#muttがimputを呼ぶときに、imput -- mail-addressとなっているのでimput.shで避ける

vi imput.sh
#!/bin/csh -f
set arguments=()
while($#argv > 0)
set a=$argv[1]
if ($a == '--') then
else
set arguments=($arguments $a)
endif
shift
end
cat - | imput $arguments
exit 0

cp imput.sh ~/bin/linux

Mozilla ThunderBird のメールボックスをlinuxへ移行する

ThunderBirdのメールボックスをlinux側でバックアップしたくなり、ThunderBird FAQを調べると、

Thunderbird のメールファイルは、プレーンテキストの標準的な「mbox」形式なので、たいていのメールクライアントでインポートできます。多くの商用メールクライア ントには、同じく「mbox」形式を使用している Eudora からメールをインポートできる機能が付いており、この機能を使って Thunderbird のメールファイルを読み込むことができるはずです。

Thunderbird のメールファイルは、プロファイル (プロファイルフォルダ を参照) の中にある Mail フォルダと (IMAP アカウントをお使いの場合) ImapMail フォルダにあります。メールフォルダ (受信トレイ、送信済みトレイなど) はそれぞれ 2 つのファイルとして保存されています。一つは (INBOX など) 拡張子の付いていないファイルで、(「mbox」形式の) メールファイルそのものです。もう一つは (INBOX.msf など) .msf という拡張子の付いたファイルで、メールファイルの見出し (メール要約ファイル) になっています。他のメールクライアントに、拡張子の付いていないファイルからメールをインポートさせてください。

他のプロファイルにメールを移行したい場合は、単純にメールファイルをそのプロファイルの Mail フォルダにコピーしてください。」

とある。「へぇ~linuxのmbox形式であったとはぁ」といまさらながら知る私でした。
ftpしてmuttで見てみよう。

$ mutt mbox1
Value too large for defined data type (errno = 75)

と落ちました。mbox1がデカすぎでしょうか、2GB以上あります。
ThunderBirdでもそうなのですが2GBオーバーのメールボックスを作ると動作が不安定になります、これっNetscapeの頃から変わっていないのでしょうか。

では、mbox形式をMaildir形式に変換。
ここをセーブ
このperlスクリプトは、

$ mbox2maildir
usage: mbox2maildir [ ]

らしいので、
$ mbox2maildir mbox1 maildir1

でmaildir1/new/以下に分離したファイルが出来上がります。

これで変換は終了。

screen VT100/ANSI 端末エミュレーション機能を持つ画面管理ソフトウェア

screenコマンドをJMで引くと、先頭に、

VT100/ANSI 端末エミュレーション機能を持つ画面管理ソフトウェア

と出る。termベースのWindowManagerだと言いたいところです。それほど便利。
が、ウィンドウ・マネージャって言葉、X WindowのWMを連想させてしまうので少々使いづらい面もありますね。

で、元来screenを使うのが好きです、私は。軽いし、作業状態を保存できるのが有り難いですよねぇ~
あるところで「今日はコレまで」って、^X^D打ってログアウト。。。翌朝はtelnetで接続して、screen -r 打って、昨晩の状況を復帰して続きを・・・

以下私の.screenrc

startup_message off
escape ^X^X # C-x C-x : send ^Z to process
vbell on

bind 'm' screen mutt
bind 'i' screen w3m -B
bind 'f' screen fd ~/.Mail/attached_files
bind 'C' screen w3m 'file:///cgi-bin/cal.cgi'

bind o focus
bind 2 split
bind 1 only

term vt100

簡単ですねぇ~これだけで複数の画面イメージを切り替え(^xpとか^xo)ながら作業ができます。意外と使われていないのでしょうか、それともscreenってコマンド名がググるのに障害となっているのでしょうか。
まあ今の時代、GUIが便利ですもんね!

この.screenrcでは、
デフォルトの^aエスケープを(^aは私的には打ち難いので)^xへ変更して、bindでキーマッピングをしています。
これで、screenから、mutt(^xm)とfd(^xf)とw3m(^xi)を新規画面で起動させることが出来ます。また、^x2で2画面分割、^x1で1画面に戻り、2画面のときのカーソル移動を^xoにしています。

日本語エディタ ne

linux/CUIの世界で、日本語エディタといえば、、、結構無い・・・
Emacsen, vimとかでしょうか?ググっても沢山情報は出てきますが、で、「結局どうするのが簡単か?」となると趣味やら経緯やら人それぞれですね。
何でも良いのですがEmacsenはscreenと相性が悪そうだし重い。ストールマンがオタク過ぎて意見を聞きたくない。vimはプログラム書くためのエディタでしょっ。ワープロとして使うのはねぇ・・・

screenと相性が良くて、軽くて、日本語がある程度正確に扱える、、、neを使ってます。Vzエディタと互換性を持つとかなんとか、、、どうでも良いのでキーマップ(~/.ne/key.vz)を書き換えてEmacsen風に。
ここがneのホーム?
これで十分ですね。
#それにしてもプログラム名がneとは、googleで探し難いのなんのって。

以下オリジナルのkey.vzを変更したものになります。

# エディタキーアサイン (Vzエディタライクな定義)
# 左にキー、:の右に実行する命令を書きます。
# キーは複数をまとめて指定する事もできます。
!R Key

^KW [F02] : file_toggle #62 カレントファイルの交換
^KT [F03] : file_select #63 カレントファイルの変更

[ESC]O : file_open #70 ファイルのオープン
[ESC]C : file_close #73 カレントファイルの編集終了
[ESC]L : file_copen #74 colse and open
[ESC]S : file_save #75 カレントファイルのセーブ
[ESC]Q : file_quit #77 プロファイル保存終了

[ESC]P : file_rename #82 ファイル名の変更
[ESC]W : file_profile #83 プロファイル情報セーブ

[ESC]U : file_undo #M7 カレントの編集のやり直し
[ESC]I : file_insert #M8 ファイルを挿入
[ESC]X : file_aclose #M9 全ファイルのクローズ


^P [UP] : cursor_up #05 カーソルを上へ
^N [DOWN] : cursor_down #06 カーソルを下へ
^H [LEFT] : cursor_left #07 カーソルを左へ
^L [RIGHT] : cursor_right #08 カーソルを右へ
# ^B \[LEFT] : cursor_tkprev #09 前のトークンへ
# ^W \[RIGHT] : cursor_tknext #10 次のトークンへ
^QS [HOME] ^[LEFT]: cursor_sleft #11 カーソルを行頭へ
^QD [END] ^[RIGHT]: cursor_sright #12 カーソルを行末へ

^U \[PGUP] : cursor_rup #31 ロールアップ
^D \[PGDN] : cursor_rdown #32 ロールダウン
^B [PGUP] \[UP] : cursor_pup #35 ページアップ
^F [PGDN] \[DOWN] : cursor_pdown #36 ページダウン
^QE ^[UP] : cursor_sup #39 カーソルを画面の一番上へ
^QX ^[DOWN] : cursor_sdown #40 カーソルを画面の一番下へ
^QR ^[PGUP] : cursor_top #41 カーソルをファイルの先頭へ
^QC ^[PGDN] : cursor_bottom #42 カーソルをファイルの末尾へ


^QP : jump_before #43 直前のカーソル位置
^QM : jump_mark #44 カーソル行マーク
^QJ : Jump_line #45 指定行ジャンプ

^K1 : jump_Mark 1 #M16 マーク #1~#4
^K2 : jump_Mark 2 #
^K3 : jump_Mark 3 #
^K4 : jump_Mark 4 #

^Q1 : Jump_before 1 #M17 マークジャンプ #1~#4
^Q2 : jump_before 2 #
^Q3 : Jump_before 3 #
^Q4 : Jump_before 4 #

^QG \[F10] : jump_tag #M18 タブジャンプ



[CR] : line_cr #04 改行

^Z : char_undo #20 削除文字のアンドゥ
^K : char_input #22 制御文字の入力

\[CR] : line_new #53 新しい行の挿入
^QL \[F02]U : line_undo #54 行編集の取消。


# ^H [BS] : del_bs #14 カーソル前の文字を削除
# ^G [DEL] : del_char #15 カーソル上の文字を削除
# ^QH \[BS] : del_tkprev #16 語の先頭まで削除
# ^T \[DEL] : del_tknext #17 語の終りまで削除
# ^QT ^[BS] : del_sleft #18 行頭まで削除
# ^QY ^[DEL] : del_sright #19 行末まで削除


^Y [F10] : block_start #46 ブロックモード
^X [F08] : block_cut #47 ブロックへ移動
# ^I [F09] : block_paste #48 ブロックから移動
^C \[F08] : block_yanc #49 ブロックへ複写
^V \[F09] : block_copy #50 ブロックから複写
^KY \[F02]C : block_kill #51 ブロックバッファの消去
^QB \[F02]B : block_chlast #52 ブロックのtop/end

^KD : block_dup #M19 カーソル行複写


^@ \[INS] : search_paging #30 ページングモード

^QF [F06] : search_in #55 検索文字列の入力
^QA [F07] : search_repl #56 文字列の置換
^QO : search_repl_redo #57 前回の置換の実行

^L [F05] : search_getword #M24検索文字列の連続取得



^_ ^\ : misc_kmacro #02 キーボードマクロ
^V [INS] : opt_set "OverWrite" #13 入力モードon/off
[ESC]E : misc_exec #78 シェルコマンドの実行
[ESC]G : misc_insert_output # コマンドの実行結果の取り込み

[F01] : menu_file #M2 ファイルメニュー
[F04] \[F01] : menu_opt #
^KI : opt_tab #M15 タブの切替え

[ESC]D : misc_redraw #

2008年1月10日木曜日

PC⇔Linux をtclの ftpd(tcllib)で繋ぐ

普段、仕事ではWindowsからtelnetでlinux接続がメイン。
だけどやはりWindowsで文書は管理したいし、メールの添付ファイルは99%MS-Officeで書かれているから、Windows使わないと。
なにせ、telnet上ではscreen + mutt + fdclone + w3mでほとんど全てのことをやっているから、Windows不要的感覚に囚われてしまう。
で、 telnet先のlinux上でmutt使ってメール読んでると、「付いて来た添付ファイルが開けん」ので、Windows上で改めてメールボックス 開いて、pdfとか表示させるはめになる。これもなんかバカらしいというか、マウス使うのが億劫というか、なんとも「全部linux上で」と世間でよくあ るlinuxかっこいい・症候群に瞬間、ハマルわけ。
「な~んか良い方法はないものか」と、さらに深くlinux症候群へ

これま で何度となく、PCとlinux間をftpで繋ぐ方法を考えたような。良い方法はなかなか無いものです。かつてftpmount(だったかな)って のを見たとき「good idea!」、そう感じたのを思い出します。結局安定感がないやら、日本語無視だったりで使い物にならなかった。

だけど今でも諦めていません・・というわけで。PC⇔linux結合をば、また考えています。

[方針]

①PC上でftpdを走らせる
②telnet先のlinuxでftpクライアントを使う

ま あ当たり前の状況ですが、①のPC上のftpサーバでは、転送されてきたファイルをWindows上で実行してしまうという細工をすると良いことがある と考えます。通常のftpサーバは転送されてきたファイルを所望の場所へ保存する機能を持ちますが、実行出来そうなファイルは開いて欲しいと。

linux上のftpクライアントがhoge.pdfをputしてきたら、.pdfに関連図けられた実行コマンドを探し出して、(ここではAcrobat)それを実行してPC画面に表示するということ。

簡単に実現したい。
①TCLのTCLLIBにあるftpdとftpパッケージをいじって使用します。
②PCではActiveStateのTCLをインストール
③linuxではtcllib.sourceforge.netからtcllibをインストール

tclilib のftpdサーバ/ftpクライアント・サンプルスクリプトを多少改造したのが下記2つのスクリプトになります。PC上のftpdサーバ側 スクリプトをActiveTCLのwish.exeに食わせると、例では7777ポートが接続可能になります。telnet先からはftpクライアントプ ログラムへ表示したいファイルを指定してあげると、WindowsPC上の適切なプログラム(Exce,WordやAcrobatなどなど)が立ち上がり ftp転送されてきたファイルを表示します。後はWindowsPC上での作業の世界ですね。

[①PC側のftpdサーバスクリプト]

#! /bin/sh
# -*- tcl -*- \
exec wish "$0" ${1+"$@"}
# Custom FTP daemon to talk WindowsPC and Linux.

package require Tcl 8.3
package require ftpd
package require log

variable docRoot {c://Tcl/tmp}
variable store_path {}

proc ftplog {level text} {
if {[string equal $level note]} {set level notice}
log::log $level $text
}
proc noauth {args} {
return 1
}
proc fakefs {cmd path args} {
# Use the standard unix fs, i.e. "::ftpd::fsFile::fs",
# but rewrite the incoming path
# to stay in the /tmp directory.

variable docRoot
set path [file join $docRoot [file tail $path]]
variable store_path $path
eval [linsert $args 0 ::ftpd::fsFile::fs $cmd $path]
}
proc exapp {s s2 f b name e} {
variable store_path
if {$store_path!={}} {
regsub -all -- {/} $store_path {\\} store_path
.name configure -text "Filename:$store_path"
} else {
.name configure -text "Filename:nothing"
}
if {$store_path!={} && [set app [get_appli $store_path]]!={}} {
.ftype configure -text "HelperApplication:$app"
if {[regexp {(exefile|batfile)} $app]} {
exec $store_path
} else {
exec $app $store_path
}
} else {
.ftype configure -text "HelperApplication:unknown"
}
set store_path {}
return 1
}
proc get_appli {path} {
set type {}
if {[set extension [file extension [file tail $path]]]!={}} {
if {[regexp {\S+=(.+)} [exec cmd /C assoc $extension] all assoc]} {
.assoc configure -text " Assoc-Command:$assoc"
if {[regexp {exefile} $assoc]} {return $assoc}
if {[regexp {batfile} $assoc]} {return $assoc}
if {[regexp {\S+=(.+)} [exec cmd /C ftype $assoc] all ftype]} {
regsub -all {\"} $ftype {} type
regsub -all {\\} $type {/} type
regexp -nocase -- {(^.*.exe)} $type all type
}
}
}
return $type
}

::ftpd::config -authUsrCmd noauth -authFileCmd noauth -fsCmd fakefs -logCmd ftplog -xferDoneCmd exapp
set ::ftpd::welcome {Welcome HOMEPC FTPd}
set ::ftpd::port 7777 ; # Listen on user port
set ::ftpd::cwd $docRoot

::ftpd::server

button .b -command "exit" -text {<>}
label .name -text " Filename:nothing"
label .assoc -text " Assoc-Command:nothing"
label .ftype -text " HelperApplication:unknown"
pack .b .name .assoc .ftype -side top
wm iconify .
wm title . "PC<=>Linux"

[②linux側のftpクライアントスクリプト]

#!/usr/bin/tclsh
package require ftp

# SAMPLE convmv : proc euc-jp2sjis {euc} { return [set sjis [lindex [exec convmv -f euc-jp -t shiftjis $euc |& grep mv] end]] }
proc euc-jp2sjis {euc} { return [exec echo $euc | nkf -s] }
proc latest_file {dir} {
set latest {}
if {[catch {set files [glob ${dir}/*]}]} {puts "Directory empty :$dir";return {}}
foreach f [set files $files] { if {[file isfile $f]} {set mtime([file mtime $f]) $f }}
return [set latest $mtime([lindex [lsort -decreasing -integer [array names mtime]] 0])]
}

if {[llength $argv]>0} {
set ip $env(REMOTEHOST)
set port 7777
while {[regexp -- {(-port\s+(\d+)|-ip\s+(\d+[\d\.]+))} $argv a 1]} {
regsub -- ${a} $argv {} argv
set argv [string trim $argv]
}
set path [join $argv]
if {[file isdirectory $path]} {
if {[set path [latest_file $path]]=={}} { exit 0 }
}
if {[file isfile $path]} {
set euc_path $path
set sjis_path [euc-jp2sjis $euc_path]
puts "ip=$ip port=$port path=$euc_path"
if {$euc_path != $sjis_path} {
file rename $euc_path $sjis_path
}
set path $sjis_path
} else {
set start_bat /tmp/start.bat
puts "creating $start_bat about $path"
set sb [open $start_bat w]
puts $sb "@echo off"
puts $sb "start $path"
close $sb
set path $start_bat
}
if {[set srv [::ftp::Open $ip no no -port $port]]>=0} {
::ftp::Put $srv $path
::ftp::Close $srv
} else {
puts "FTPservice unavailable"
}
if {[info exists euc_path] && $euc_path != $sjis_path} {
file rename $sjis_path $euc_path
} else {
file delete $start_bat
}
exit 1
}