2018-03-19

Get Linux Distribution Name (Tcl exec 版)

在最後嘗試 Bash 的版本。在嘗試以後,寫好了 Bash 版,使用 cat, grep 和 sed 取得結果。
#!/bin/bash

if [ -f '/etc/os-release' ]; then
    cat '/etc/os-release' | grep -w "^NAME" | sed -e 's/NAME=//g'
fi


於是我就想,那我可以使用同樣的方式在 Tcl  嗎?答案是可以。
#!/usr/bin/env tclsh
#
# Execute external program to get result
#

package require Tcl 8.6

set myfunction {{} {
    return [exec cat /etc/os-release | grep -w "^NAME" | sed -e "s/NAME=//g"]
}}

if {[file exists "/etc/os-release"]==1} {
    puts [apply $myfunction]
}

為了增加變化,所以我使用了匿名函式的寫法。

2018-03-15

Tcl double quotes and string map

這只是 string map 的測試。

set doublequotes {"It is double quotes"}
string map [list {"} {\"}] $doublequotes
string map [list {\"} {"}] $doublequotes

進行雙引號的改寫,從 " 改寫為 \",以及改回來,從 \" 改成 "。

2018-03-13

Use uname to get info

在 Unix-like 的系統可以使用 uname 來取得一些系統資料。下面是使用 uname -s 來取得目前的 OS 資訊。

proc getKernelName {} {
    set mychannel [open "|/usr/bin/uname -s"]
    set name [chan gets $mychannel]
    chan close $mychannel

    return $name
}

如果在 Linux 上,會得到的回傳值是 Linux。

我把其它的部份也寫成函式,結果就是下面的 tcl module:
uname-tcl

Get Linux Distribution Name

使用 /etc/os-release 來取得 Linux Distribution 的相關資訊。應該可以適用於: CentOS, RedHat, Fedora, openSUSE, SUSE, Debian/Ubuntu, ArchLinux

proc getDistributionName {} {
    set OSName ""

    if {[file exists "/etc/os-release"]==1} {
        set release [open "/etc/os-release" r]
        while {1} {
            if {[chan gets $release line] > 0} {
                set info [split $line "="]
                if {[string compare [lindex $info 0] "NAME"]==0} {
                    set OSName [lindex $info 1]
                    break;
                }
            } else {
                if {[chan eof $release]} {
                    break;
                } else {
                    puts "Something is wrong."
                    break;
                }
            }
        }

        chan close $release
    } else {
        return -code error "/etc/os-release not exist!!!" 
    }
    
    return $OSName
}


參考資料:
os-release — Operating system identification

2018-03-12

Tcllib and Tklib

開始準備 openSUSE Leap 15.0,雖然我會等一下才升級,但是放在 openSUSE build service 的部份可以開始準備。

Tcllib 和 Tklib 遇到同一個問題,就是 openSUSE build service 會將下面的寫法視為錯誤:
#!/usr/bin/env tclsh


所以我只好用 sed 改寫 examples 下的範例,改成 #!/usr/bin/tclsh。這似乎是 openSUSE Leap 15.0 才出現的檢查。

(* 有疑問的地方在於,其實 #!/usr/bin/env tclsh 是比較推薦的寫法,所以我搞不懂為什麼會加這個檢查)

2018-03-06

Critcl and TCLLIBPATH

critcl-spec


在最近使用的過程中,我意外的發現我之前並沒有全部搞定。在最後編譯 md5c 的時候沒有成功,只是 openSUSE build service 還是成功的建立 RPM,所以可以使用部份的功能。

經過研究 critcl 的安裝過程,在 RPM spec 加入下列的修正:
+export TCLLIBPATH=" %{buildroot}/usr/lib64/tcl/critcl-app3.1.17 %{buildroot}/usr/lib64/tcl/critcl3.1.17 \
+%{buildroot}/usr/lib64/tcl/dict841 %{buildroot}/usr/lib64/tcl/lassign841.0.1 \
+%{buildroot}/usr/lib64/tcl/lmap841"


在安裝過程中,Critcl 會複製本身的套件到 Tcl library 目錄下,所以最後的步驟編譯 md5c 的時候,所有需要的套件都可以被 Tcl 找到。

而製造 RPM 的過程中,套件會被複製到 buildroot 目錄下,所以在這個時候 Tcl 會找不到需要的套件。因此只要讓 Tcl 可以找到套件,就可以完成編譯 md5c 的步驟。

在嘗試以後,既然我知道這些套件的安裝地點,就表示我可以使用設定 TCLLIBPATH 的方式解決,所以在安裝以前先設定環境變數,然後再執行安裝程式,這樣 Tcl 就會找到需要的套件完成編譯。

Tclqrencode v0.9

連結網址:
Tclqrencode


更新 libqrencode 的 code base,花了幾個版本整合,所以版本從 v0.7 開始一路修正 merge 所造成的問題,目前版本是 v0.9(希望我一切都搞定了)。

這個版本加入 XPM 的支援。然後我放一個 BSD 2-Clause License 的檔案在 source code package。

2018-03-05

Get Linux kernel version

練習程式,讀取 /proc/version 並且輸出資料。/proc/version 記錄著 Linux kernel 的版本資訊。

#!/usr/bin/env tclsh

set version [open "/proc/version" r]
while {1} {
    if {[chan gets $version line] > 0} {
        puts $line
    } else {
        if {[chan eof $version]} {
            break;
        } else {
            puts "Something is wrong."
            break;
        }
    }
}

chan close $version

procfs

The proc filesystem (procfs) is a special filesystem in Unix-like operating systems that presents information about processes and other system information in a hierarchical file-like structure, providing a more convenient and standardized method for dynamically accessing process data held in the kernel than traditional tracing methods or direct access to kernel memory.

List current processes (Linux)

練習程式,讀取 /proc 下的目錄,如果存在 /proc/*/cmdline,就輸出資料。

#!/usr/bin/env tclsh

set dirs [glob -dir /proc * -type d *]
foreach dir $dirs {
    if {[file exists $dir/cmdline]} {
        set psinfo [open $dir/cmdline r]
        while {1} {
            if {[chan gets $psinfo line] > 0} {
                puts "$dir ---> $line"
            } else {
                if {[chan eof $psinfo]} {
                    break;
                } else {
                    puts "Something is wrong."
                    break;
                }
            }
        }

        chan close $psinfo
    }
}


而 /proc/PID/status 就是這個 process 目前的資訊,所以我們也可以查詢 /proc/self/status 取得自己的資料:
#!/usr/bin/env tclsh

set status [open "/proc/self/status" r]
while {1} {
    if {[chan gets $status line] > 0} {
        puts $line
    } else {
        if {[chan eof $status]} {
            break;
        } else {
            puts "Something is wrong."
            break;
        }
    }
}

chan close $status

2018-03-03

tcl-promise

tcl-promise-spec

tcl-promise implements the promise abstraction for asynchronous programming.

Promises are concurrency primitives that let you write asynchronous code in a sequential style. This Tcl based implementation is mostly modeled on the Javascript/ECMAScript standard.

* 而且 tcl-promise 在 1.0.3 還實作了 async/await。
* 因為 SourceForge 剛好出現問題,所以我複製了一份到 GitHub 上


我在嘗試使用 openSUSE zypper 作為 Tcl 套件管理的時候,就發現 Tcl module file (*.tm) 不是很好處理。這是因為如果放到 /usr/lib64/tcl,openSUSE build service 會檢查是否有包含 native 檔案,如果完全沒有會編譯失敗(至少我試的時候是這樣)。但是如果放到 /usr/share/tcl,則會需要建立一個 pkgIndex.tcl 才行。

所以大多數的 Tcl module file (*.tm) 我都用複製的(而不用 zypper 管理),只有少數要放上去 openSUSE build service 做編譯測試的套件我會做特別處理。tcl-promise 這個套件也使用了 work-around 的方式,在 /usr/share/tcl 目錄下建立套件目錄,並且建立 pkgIndex.tcl 檔案。


2018/03/07 更新
因為 SourceForge 恢復正常,所以刪除了複製的部份,build script 改用 wget 取得檔案的方式。

2018-03-02

Tcl3D

tcl3d-spec


Tcl3D offers the 3D functionality of OpenGL and other 3D libraries at the Tcl scripting level.


因為 BAWT-Tcl 包含了 Tcl3D 套件,所以我有試著 build 看看。Tcl3D 在 SourceForge 上放的檔案是 0.5 版和 0.6 版,但是在 BAWT 網站上放的是 0.9.1 版,所以最後拿 BAWT 提供的版本來使用。

在寫 RPM spec 的時候加了二個 patch,CMakeLists.patch 用來設定我們要安裝的目錄,CMakeModules.patch 則是用來複製各個子目錄下的 pkgIndex.tcl,在 Windows 平台上使用 Visual C++ 編譯是有 Release/Debug 的分別,我不太確定 Linux 平台上有沒有,但是因為沒有正確複製,所以我加了一小段修改讓 pkgIndex.tcl 可以正確複製。

2018-03-01

tcllibc

我之前有聽過,只是沒有實際安裝過,不過經過閱讀 Tcler's wiki 的資料,知道怎麼編譯了。先置條件是需要 Critcl 有安裝才行。

可以使用下列的指令:
./sak.tcl critcl

或者是使用 configure/make 的組合:
./configure
make critcl


The packages using Tcllibc are:
  • base32
  • crc32
  • ip
  • md4
  • md5
  • md5crypt
  • rc4
  • ripemd128
  • ripemd160
  • sha1
  • struct::graph
  • struct::sets
  • struct::tree
  • sum
  • uuencode
  • uuid
  • yencode
這就是目前關於 Tcllibc 的簡單資料。


更新:
使用者不用特別指定使用,而是如果有使用的套件在有安裝的時候,就會使用 C 的版本,沒有的時候使用 pure Tcl 版本。

為了驗證,所以我寫了 openSUSE RPM spec,這樣就比較好裝:
tcllibc-spec