Updated 2018-02-13 13:28:46 by KJN

Alie Tormusa Koroma edit

I come from a Telecoms support background, before that I was a Visual Basic programmer (I know...I'm not proud of it myself). Since entering the support and sys admin arena in 2000, I've scripted a lot and did a tinnie bit of Java along the way. While I can boast of being a Solaris Administrator, a seasoned programmer is definitely not one of my accolades.

I've been a Tcl lover since accidentally bumping into a Tcl 8.5 tutorial four years ago. I say it's accidental because a friend who is not a developer by any means was merely passing some C++ documentations over for me to copy from her memory stick. Long story short, I asked about this Tcl tutorial document and she told me it was a programming language. My development skills were almost dead and was looking to revive it at that time (the reason why I wanted the C++ documents in the first place). I decided to learn Tcl instead of C++.

I won't call it love at first touch but when I read the section of "list handling" and the power packed in them I knew I'd found the language to revive my programming past. It paid off, because shortly after I landed a job in which I programmed telecoms services using Tcl (for Mobile broadband and 4G/LTE services). Yep...Tcl is wild out there in the wild!

Today, I am the self proclaimed biggest Wub fan in my opinion. I struggle with it but I'm new to web development all together and I can see its great potentials. I also dream to influence a Tcl/Tk conference in South Africa someday (dreams do come true I heard).

WUB (Wub Unofficial Bootstrap) Tutorial

WUB Tutorial is an attempt at creating what I called a bootstrapping documentation for Wub.


Is a ftp client program for fetching file from a remote server based on configurations. I used it in a cron job to regularly move nth server logs for post processing. It is based on tcllib::ftp package and can be downloaded here: https://drive.google.com/file/d/0B-bQQ5QcqhhdQS1MS2dyc0FGX2c/view?usp=sharing
# author: alie_tormusa_koroma [datagnius at mail dot com]                         #
# descpt: ftp client for fetching file type (defined pattern), certain date from  #
#          a ftp server. this program is controlled by a config_file and is ideal for
#          internal networks as the config file has to contain the username & password  
# depend: tcllib::ftp
# release: fetchr verions 0.0.1                                                                                                                                           

package require Tcl
package require ftp

set connState {false}
set baseDir "/opt/fetchr"                       # the install directory or script home
set lckFile "/var/tmp/.fetchr.lck"              # name of the lock file
set fetchList "$baseDir/conf/.fetchlist"        # this is where files already fetched will be logged to avoid duplicate fetching
set fetchConf "$baseDir/conf/fetchr.conf"       # the configuration file

set ftpSrv {} ; set ftpuser {} ; set ftppwd {} ; set getDir {} ; set putDir {} ; set getPat {} ; set getWhen {}

# sample configuration file containing all hostnames and file pattern to fetch
if 0 {
        ftpuser: remote ftp username
        ftppassword: ftp user password
        remote_getfile_directory: remote directory containing files to get
        local_putfile_directory: local directory to put files
        getfile_pattern: files pattern to get (e.g 2015_*.sql)
        getWhen_file: file date to get (e.g today=now; yesterday=yesterday)        

proc FtpConnect {ftpServer ftpUser ftpPasswd} {
        # open connection to ftp server 
        puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] FtpConnect(Connect)\
        [info script]::FTP Connection request received. ConnectionString($ftpUser\@$ftpServer)"
        global connState {true}
        return [::ftp::Open $ftpServer $ftpUser $ftpPasswd -blocksize 8192 -timeout 7200]
} ;#endOf::FtpConnect

proc ApproveFileFetch {fileName} { 
        global baseDir ; global fetchList ; set srhResult {yes}
        if {[file exists $fetchList]} { 
           set srhResult {}
           set aff [open $fetchList r]
           set srhResult [lsearch -start 0 -inline [read $aff] $fileName*]
           close $aff
           if { $srhResult == {} } { set srhResult {yes} } else { set srhResult {no} }
        } else {
           set srhResult {no}
        return $srhResult
} ;#endOf::ApproveFileFetch

proc LogGetFile {getFile} { 
        if { $getFile != "" } {
            global fetchList
            set fls [open $fetchList a]
            puts $fls $getFile ; close $fls
} ;#LogGetFile

proc FTPMain {} { 
        global connState {false}
        global baseDir lckFile fetchList fetchConf 
        global ftpSrv ftpuser ftppwd getDir putDir getPat getWhen
        set fls [open $fetchList a+]

        if {[file exists $fetchConf] && [file size $fetchConf] > 0 } {
                set cfg [open $fetchConf r]
                while {![eof $cfg]} {
                        set cfgLine [gets $cfg] ; set ftpSrv [lindex [split $cfgLine :] 0]
                        if  { [string range $ftpSrv 0 0] != "#" } { 
                                set ftpuser [lindex [split $cfgLine :] 1]
                                set ftppwd [lindex [split $cfgLine :] 2]
                                set getDir [lindex [split $cfgLine :] 3]
                                set putDir [lindex [split $cfgLine :] 4]
                                set getPat [lindex [split $cfgLine :] 5]
                                set getWhen [lindex [split $cfgLine :] 6]

                                # set the session attributes on the ftp server
                                if { $connState == {false} && $ftpuser != {} } { 
                                        puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] FTPMain(FTPConnReq)\
                                        [info script]::RequestingFTPConn ConnectionString::ftpSrv:$ftpSrv ftpuser:$ftpuser ftppwd:hidden"
                                        set ftp [FtpConnect $ftpSrv $ftpuser $ftppwd]

                                if { $ftp != -1 } {
                                        puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] FTPMain(FTPConnect) [info script]\
                                        Established connection:: LocalHost:[info hostname] => RemoteHost:$ftpSrv"
                                        ::ftp::Cd $ftp $getDir
                                        ::ftp::Type $ftp binary
                                        foreach {iFile} [::ftp::NList $ftp $getDir] {
                                        if { [string match *$getPat* $iFile] } {        
                                        set indxFile [join [lrange [split [lindex [split $iFile /] end] .] 0 2] .]
                                          switch -glob [string tolower $getWhen] {
                                                 yes* { 
                                                         set ystDay [lindex [split [clock format [expr [clock seconds]-86400]]] 2]
                                                         set filDay [lindex [split [clock format [::ftp::ModTime $ftp $iFile]]] 2]
                                                         if { $filDay == $ystDay && [ApproveFileFetch $indxFile] == {yes} } {
                                                                ::ftp::Get $ftp $iFile $putDir ; LogGetFile $indxFile
                                                                puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] [info script] FTPMain(getYesterday) [info script]::$indxFile"
                                                now* {
                                                        set fTime [clock format [clock seconds] -format %d]
                                                        set mTime [clock format [lindex [split $indxFile .] 1] -format %d]
                                                        if { $fTime == $mTime && [ApproveFileFetch $indxFile] == {yes} } {
                                                                ::ftp::Get $ftp $iFile $putDir ; LogGetFile $indxFile
                                                                #puts stdout "GetFile_NOW:: [clock format [clock seconds] -format {%Y-%m-%d %H:%M:%S}] $indxFile" 
                                                                puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] FTPMain(getNow)::$indxFile [info script]::Fetch success" 
                                                default { 
                                                        set theFile [lindex [split $iFile /] end] 
                                                        set cDay [string range $getWhen 0 1]
                                                        set cMth [string range $getWhen 2 end]
                                                        set fMth [lindex [clock format [lindex [split $theFile .] 1]] 1]
                                                        if { [string totitle $cMth] == [string totitle $fMth] } {
                                                                set fDay [lindex [clock format [lindex [split $theFile .] 1]] 2]
                                                                if { $fDay == $cDay && [ApproveFileFetch $indxFile] == {yes} } {
                                                                        ::ftp::Get $ftp $iFile $putDir ;# puts $fls $indxFile
                                                                        LogGetFile $indxFile
                                                                        puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] [info script] FTPMain(getDate$cDay$cMth) [info script]::$indxFile"
                                          } ;#endOf::Switch_getWhen
                                        } ;#endOf::IfStringMatch
                                        } ;#endOf:Foreach
                                } else {
                                        puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] FTPMain(Connect)\
                                        [info script]:: Unable to connect to FTPServer($ftpSrv)"        
                                } ;#endOf::IfConnstateTrue
                        } ;#endOf::IfStringRange

                } ;#endOf:WhileEOF
                close $cfg
                if {[catch {::ftp::Close $ftp} cerr]} {
                        if {[file exists $lckFile]} {file delete $lckFile}
                        set connState {false}
                set connState {false}
                #if {[file exists $lckFile]} {file delete $lckFile}
                ::ftp::Close $ftp
                puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] FTPMain(::Exiting::) [info script]::Fetch complete CleanExit" ; exit 0

        } else {
                puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] FTPMain(NoConfigFile) [info script]::$fetchConf ZeroBtyesOrMissing"
        } ;#endOf:IfFileExists
        ::ftp::Close $ftp
        if {[file exists $lckFile]} {file delete $lckFile}
        puts stdout "[clock format [clock seconds] -format {%d-%m-%Y %H:%M:%S}] FTPMain(::Exiting::) [info script]::Fetch complete CleanExit" ; exit 0