所謂的善意與戰鬥-九把刀被抄襲事件的感想

其實早好幾天前就看完了這個事件的新聞.

剛剛又在終極邊疆看到了RipperL對這個事件的評論善意與戰鬥的選擇, 突然心裡有些想說又說不出來的看法, 像魚刺一樣梗著.

比起書寫文字, 我更多的是書寫程式, 而我的文字或程式被抄襲的次數也是用上雙手雙腳都數不清了. 當然我不是什麼大作家或是程式達人, 加上也不涉及利益問題, 所以肯定的從沒有被「報導」或是「鬧大」.

我從不看九把刀的小說, 這並不表示我不喜歡或是看不起九把刀. 卻因為這個事件讓我讀完了所有涉及抄襲的雙方文字, 讀完後我的意見是: 兩人都是很棒的文字創作者, 在詞彙運用上各有擅場, 不過這不是重點.

純粹從文字角度來說, 事實上真的很難去斷定「這是抄襲」, 畢竟在文字運用上完全採用了另外一種敘述方式, 反而是故事的概念與情節的鋪陳幾乎是相同的, 因此純就法律上來說, 若九把刀要控告這位高中生, 我看是浪費時間甚至「自取其辱」, 最後會因為判決不符合九把刀的正義而讓整個事件導向一種誣指.

看完九把刀的處理過程, 說實在實在我很難想到更好的處理方式了, 而且真正鬧大的是這位高中生的家長與水果日報, 而非九把刀或他的經紀人或出版社. 所以從程序正義來說, 我不覺得九把刀違反任何正義, 而他所追求的正義也僅是維護自己在作品上的原創性, 而不是舖天蓋地的企圖毀滅這位高中生.

以RipperL的看法, 他認為是情境上的相似而非概念上的相似, 這點我尊重卻很難同意. 九把刀的原始概念是混亂而陳姓高中生的則是相反, 但事實上若以陳姓高中生的概念為出發點, 那麼該篇小說會成為bug一堆的不合理作品, 因為誰都可以快速適應一個相反的世界: 把話反過來說誰不會? 以至於後頭跟九把刀原作品相似的橋段與劇情都會變得跟整體概念脫勾.

這讓我想到很多年前發生的一個事件: 幾年前我為了用FreeBSD Server來幫我壓MP3, 而找了一些在command line抓取CDID然後送到CDDB去查詢出整個專輯名稱的小程式, 由於所有找到的都是Linux版, 且用的都是Device Level的codes去抓取, 以至於FreeBSD上完全不同的Device Structure讓這些程式連用Linux Emu都沒辦法正常運作. 所以我花了一個晚上的時間去對照Linux與FreeBSD在CDFS上的運作方式而把這些東西做了FreeBSD patch.

我把這些Patch都commit回去給原作者, 而原作者也很乾脆的把這些Patches都放進了下一個Release中. 有些是GPL, 有些是BSDL, 有些啥都沒說, 而我也僅在Header部份有加上我的Email而已. 我愉快的壓著mp3, 而那些小patch也很愉快的被Release出去.

過了幾個月, 我把我的小工具集分享給友人P君, 請他協助我壓一套CD時, 事情就這麼的發生了. P君告訴我他認為我「抄襲」了某位大陸人的codes, 因為他早就看過類似的作法. 我一時覺得很窘迫, 由於抓取CDID的方法並不會太特殊, 或許人家早就做了類似的東西, 而我還在重造輪子, 於是請P君把這些codes寄給我讓我觀摩一下.

看完後我悲從中來.

這位大陸人並非完整抄襲我的codes而是照樣照句, 他把幾個重複的段落都作成了另外一個Header File, 然後在程式裡頭抓進來用, 但是他在這麼做的同時並沒有把多餘的codes給拿掉, 例如他把


if (i==0) {
switch (devID[i]) {
case MCDSEC:
blah blah;
break;
case CDSEC:
blah blah;
break;
default:
blah blah;
}
if (devID[i] == INVALIDSEC) {
return null;
}
}

整段改成

int checkDevID(int devid) {
switch (devid) {
case MCDSEC:
blah blah;
break;
case CDSEC:
blah blah;
break;
default:
blah blah;
}
if (devid == INVALIDSEC) {
return null;
}
}

if (i==0) {
checkDevID(devID[i]);
if (devID[i] == INVALIDSEC) {
return null;
}
}

會寫程式的都看得出來, 他並沒有把多餘不需要的最後一個if判斷給刪除, 也就是說那一段等於是毫無作用的codes. 由此我直接可以斷言, 他是拿我的codes去改的更洗練然後掛上自己的名字.

當我與這位大陸人聯絡時, 他堅稱那是他的「原創」作品, 而我質疑他的enum tag跟我的一模一樣, 以及那些多餘的null codes為何會這麼相似的出現在那個地方時, 這位先生的回答是:

「Tag一樣不代表我抄你的Tag Name, 多餘的Null codes只是我沒清理罷了, 你憑什麼說我抄你的? 」

他說得對極了, 真的! 我完全沒辦法說他抄我的, 縱使我知道他100%是從我的codes去修改的, 但我卻對自己的權益無能為力, 而這所謂的權益只是在GPL source中有我的名字而已.

回到九把刀事件, 我很清楚的判斷, 九把刀在這個事件中永遠找不到屬於他的正義, 而這位陳姓高中生依然可以大喊著「我沒有抄襲」而繼續他的書寫生活, 那些評審們也不可能受到任何責難, 媒體也不會用上在攻擊九把刀時相同大小的篇幅來為九把刀平反甚至找回他的正義.

這表示九把刀的善意是錯的嗎? 不! 我覺得他對極了; 這表示九把刀為了正義所做出的「戰鬥」是錯的嗎? 不! 我也覺得他對極了!

錯的是什麼? 錯的是這位陳姓高中生的臉皮, 錯的是它厚到了一個程度, 以至於他為了得到虛名而失去了寫作者的自尊與驕傲, 如同那位大陸人一樣.

我想我跟九把刀的想法是接近的, 我寧可因為堅持這些正義而戰鬥, 導致自己必須吃悶虧; 也不願意因為對這些人事物視若無賭而讓那些不義之事在眾人不知的狀況下得到不該屬於他們的各種利益.

樹沒有皮, 必死無疑; 人不要臉, 天下無敵.

Mac OSX Leopard 10.5.2 Update

理論上應該要跟Macbook Air一起出來的10.5.2 Update, 終於這兩天放出來了.

其實我大概早一個禮拜收到Link跟pkg, 只是不大敢先衝, 在這個開發密集時期, 搞掛工作機然後多花兩三天去復原會是致命的錯誤啊!

所以等Apple正式丟上Software Update才動作.

Macbook部份很順利, 整個10.5.2 update package也才180mb左右, 比預期的小很多; AMD Mac Pro就比較累了, 一來沒找到新版的AMD專用Mach Kernel, 二來也還沒看到成功案例. 直到今天看到有人成功更新了, 好吧那就照表操課.

流程跟之前升級到10.5.1沒什麼差別, 先Pacifist把pkg都拆開, 然後用Don’t Panic做出Patcher Pack, 接著用Pacifist去安裝完, 然後上
Patches; 唯一的差別是mach_kernel要沿用舊版的, 所以記得要備份原始的mach_kernel.

假如安裝到一半跑四國語言當機畫面, 通常都是AppleIntelCPUPowerManagement.kext搞的鬼, 用10.5.0安裝片開到single user mode殺掉, 回Leopard後重裝一次然後跳過AppleIntelCPUPowerManagement.kext就好了, 如果還是不行, 那順道把AppleACPIPlatform.kext也換成10.5.1的版本吧.

囉唆的叮嚀是, 做之前先備份一下自己的Kernel 跟 Extensions 吧, 有多餘HDD的做一下TimeMachine備份也是不嫌麻煩的.

媽媽說, 有圖有真相!

Update:
Kalyway 10.5.2 Kernel已經出啦, 包括給EFI_v8用的Vanilla Kernel跟Patched Kernel都有. 需要服用請洽BT.

補: 鮭魚茶泡飯

既然Ellen寫了, 補個食譜.

材料:
1.白飯: 電鍋煮就可以了, 要稍微煮乾一點, 不然泡下去會變成粥
2.鮭魚: 帶骨肉就好, 反正要烤成接近鹹鮭魚, 買帶骨的再來刮會好一點.
3.海苔絲: 去賣場買一大包吧, 可以用很久很久的.
4.山葵: 就是哇殺米啦
5.芝麻或是三島香鬆: 芝麻會麻煩些還要先炒好, 所以要符合茶泡飯簡單快速, 還是三島香鬆之類的飯友就好
6.茶: 最好是煎茶, 沒有的話綠茶也可以. 那個什麼紅茶烏龍茶的就千萬不要了.
7.昆布高湯粉: 當然你很有毅力要自己作昆布高湯也可以. 自己作昆布高湯要準備昆布跟柴魚片喔.

作法:
1.處理鮭魚: 放烤盤上, 灑上一堆鹽抹在魚肉外, 放進烤箱先用100度左右烤個20分鐘; 然後拿出來去皮去骨, 把肉撕碎成小塊後, 再抹上鹽後放回烤箱, 180度烤個30分鐘烤乾就好, 最好的程度是外觀有點焦. 放涼後可以收到保鮮盒或是保鮮袋裡頭, 放進冰箱可以保存很久, 所以建議一次烤多一點.

2.昆布煎茶: 昆布高湯 + 煎茶就可以了, 沒有昆布高湯可以用鰹魚風味的x大師代替, 但是千萬不能用雞湯塊或豬骨湯, 味道會整個差掉.

3.煮好飯, 加進鮭魚碎肉, 上頭鋪上海苔絲跟飯友, 中間放上約一個姆指節大小的山葵(口味隨人高興), 然後把滾燙的昆布煎茶沖下去, 不要沖滿, 大概飯高度的7成就好, 攪拌均勻就可以享受啦.

這個是日本傳統的簡易食物, 妻子都會幫晚上應酬回家的丈夫準備一晚茶泡飯暖身兼填肚, 非常溫暖的料理喔!

Rmail v1.9 正式上線

這篇大概沒多少人看得懂, 所以可以跳過.

原本是不想寫太多跟工作有關的東西, 不過這幾天在做v1.9的release有太多感慨, 寫些無關緊要的算是舒緩身心.


nekobes-mac-pro:~ nekobe$ telnet mx.XXXXXX.com.tw 25
Trying XXX.XXX.XXX.XXX…
Connected to mx.XXXXXX.com.tw.
Escape character is ‘^]’.
220 mx02.XXXXXX.com.tw ESMTP Rmail v1.9 Gaghiel(v1.9p0072-beta)

Rmail v1.9大概是v1.x最後一個Release, v1.8 codes也正式開始不做maintain, 只會出security patch. 而v1.9對我更大的意義是, 正式跨出non-standard的範圍. 在v1.8之前, 我幾乎是攤著RFC在桌上, 一條一條都是照標準的方式去作, 只要是RFC或是已經有確定解法的功能, 都一律沿用, 包含.forward, aliases之類的都如是, 雖然這真的造成很多管理上的困擾, db/filesystem雙軌的管理方式很難如我的競爭者般做出很漂亮的介面.

但是身為一個「特化」過(特化不是指Customize, 而是Specialized)的MTA, 既然已經在超大量的環境下做出很多妥協, 例如非Normalize的查表, 全自訂與全即時的SQL builder, 那麼為了將來更多的features, 還是得跳出Standard的框框.

v1.9最大的改變是, 整個結構已經幾乎清掉了Postfix原始的樣貌; 在build-in的POP3D上新增很多將來開發Webmail時所需要的Functions; 把Forward/Aliases之類的功能完全轉移到資料庫去; 徹底獨立的API Daemon….等等, 雖然大體上還保留著原始filesystem的作業流程, 但是也規劃出了將來v2.0時要尋找的方向, 同時也能把不得不使用的local完全廢除, 改用不需要forking shell的virtual, 甚至會獨立寫一隻更快更精簡的final deliver以節省disk io.

雖然v1.9p0072-beta還是beta level的release, 但是框架都完成了, 正式的code freeze跟release build也會在這幾天, 或者說過年前正式完成. 而這個beta release也是v2.0的前哨, 用上了很多在v1.5階段還在實驗性質的演算法與流程, 雖然還沒有正式的benchmark, 但是我猜至少有5~10%的improve
.

剛剛都做完binary upgrade後, 在整理cvs跟diff時, 稍微wc -l了一下, 跟原始的版本相差了12萬行, 雖然行數不算什麼, 不過已經是Rmail從v0.2到v1.9以來最多的一個變更了. v2.0依舊會從Current Postfix出發, 這次要完全的把原先溝通的protocol完全重寫, 讓MX Layer能夠一次把所有information都查表完成然後embed在queue structure中, 後端完全淨化成storage engine, 類似Exchange 2008 Cluster的方式. 大概預計在Rmail v4誕生(假如會誕生的話啦….), Rmail就要完全脫離Postfix的架構了.

原本Rmail v2只存在於泡浴缸與睡前時的腦袋中, 藉由v1.9的Release, 終於可以描繪出v2的外框了.

自爽自賀! 拼命寫程式才會忘記現實雜事的煩擾.

另外, 出乎意料的, 知道v1.9 Codename 「Gaghiel」是什麼的人, 還出乎意料的多呢.