| #----------------------------- foreach line [split [read -nonewline $fd] "\n"] { puts [string length $line] # we get chomped line by default. } #----------------------------- set lines [split [read -nonewline $fd] "\n"] #----------------------------- set data [read $fd] #----------------------------- # not a direct equivalent but it is not required in tcl. puts $fd [list one two three] #----------------------------- puts {Baa baa black sheep.} #----------------------------- set buffer [read $fd 4096] set rv [string length $buffer] #----------------------------- chan truncate $fd $length # truncating with out a file handle is not possible directly in tcl. #----------------------------- set pos [chan tell $datafd] puts "I am $pos bytes from the start of datafd" #----------------------------- chan seek $logfd 0 end chan seek $datafd $pos start chan seek $outfd -20 current #----------------------------- # in tcl, there is no partial write, as even in non blocking mode, # tcl writes in the background to complete the write. chan configure $datafd -blocking 0 -buffering none puts -nonewline $mystring chan configure $infd -blocking 0 -buffering none set block [read $infd 256] set len [string length $block] expr {($len != 256) ? [puts "only read $len bytes"] : 0 } #----------------------------- set pos [seek $handle 0 current] #dont change position. | 
| #-----------------------------
while {[gets $fd line] >= 0} {
    while {[regexp -- {\\$} $line]} {
        regsub -- {\\$} $line [gets $fd] line
    }
    #process the full $line here.
} | 
| #----------------------------- set count [wc -l $filename] #----------------------------- set fd [open $file] set count [llength [split [read -nonewline $fd] "\n"]] #----------------------------- set count [expr [regsub -all -- "\n" [read -nonewline $fd] {} tmp] + 1] #----------------------------- for {set count 0} {[gets $fd line] > -1} {incr count} {} #----------------------------- # para is just \n\n set count [expr [regsub -all -- "\n\n" [read -nonewline $fd] {} tmp] + 1] | 
| #-----------------------------
while {[gets $fd line] >= 0} {
    foreach word $line {
        #do something with the word.
    }
}
#-----------------------------
while {[gets $fd line] >= 0} {
    foreach word [regexp -all -inline -- {\w[\w'-]*} $line] {
        #do something with the word.
    }
}
#-----------------------------
# word frequency
array set seen {}
while {[gets $fd line] >= 0} {
    foreach word [regexp -all -inline -- {\w[\w'-]*} $line] {
        incr seen([string tolower $word])
    }
}
#-----------------------------
array set seen {}
while {[gets $fd line] >= 0} {
    incr seen([string tolower $line])
}
set names [lsort -command {apply {{a b} {upvar seen seen; expr $seen($a) > $seen($b)}}} [array names seen]]
foreach line $names {
    puts "$line $seen($line)"
} | 
| #----------------------------- package require struct::list set lines [split [read -nonewline $fd] "\n"] foreach line [struct::list reverse $lines] { # do something with the line. } #----------------------------- set lines [split [read -nonewline $fd] "\n"] for {set i [llength $lines]} {$i} {incr i -1} { set line [lindex $lines $i-1] } # same strategy for paragraphs. | 
| #-----------------------------
while 1 {
    myproc [read $fd]
    while {[eof $fd]} {
        after 5000
        seek $fd 0 current
    }
}
#-----------------------------
set naptime 1000
set fd [open {/tmp/logfile}]
while 1 {
    set out [gets $fd]
    if [string length $out] {
        puts $out
    }
    while {[eof $fd]} {
        after $naptime
        seek $fd 0 current
    }
}
#-----------------------------
file stat $logfile info
if {!$info(nlink)} {
    exit 0
} | 
| #----------------------------- set lines [split [read -nonewline $fd] "\n"] set randline [lindex $lines [expr "round(rand() * [llength $lines])"]] #----------------------------- set fd [open {/usr/share/fortune/humorists}] set lines [split [regsub -all -- {%\n} [read -nonewline $fd] "\0"] "\0"] set idx [expr "round(rand() * [llength $lines])"] puts [lindex $lines $idx] | 
| #-----------------------------
set lines [split [read -nonewline $input] "\n"]
foreach line [shuffle $lines] { #assumes shuffle from chapt 4
    puts $output $line
} | 
| #-----------------------------
for {set i 0} {[gets $fd line] >= 0} {incr i} {
    if {$desired_line_number == $i} break
}
#-----------------------------
set lines [split [read -nonewline $input] "\n"]
set line [lindex $lines $desired_line_number]
#-----------------------------
proc build_index {data_file index_file} {
    puts -nonewline $index_file [binary format i 0]
    while {[gets $data_file line] >= 0} {
        puts -nonewline $index_file [binary format i [tell $data_file]]
    }
}
proc line_with_index {data_file index_file line_no} {
    set size [string length [binary format i 0]]
    set i_offset [expr $size * ($line_no - 1)]
    seek $index_file $i_offset start
    if {[tell $index_file] != $i_offset} {
        error "Did not find $line_no"
    }
    set entry [read $index_file $size]
    binary scan $entry i* d_offset
    seek $data_file $d_offset start
    if {[tell $data_file] != $d_offset} {
        error "Did not find $line_no"
    }
    return [gets $data_file]
}
# usage
set dfd [open fortune.dat]
set ifd [open fortune.dat.index w]
build_index $dfd $ifd
close $dfd
close $ifd
set dfd [open fortune.dat]
set ifd [open fortune.dat.index]
puts [line_with_index $dfd $ifd 90]
close $dfd
close $ifd
#-----------------------------
# we dont have a tie.
package require struct::list
expr {([llength $argv] == 2) || [error "usage: print_line FILENAME
LINE_NUMBER\n"]}
::struct::list assign $argv filename linenumber
set fd [open $filename]
for {set i 0} {[gets $fd line] >= 0} {incr i} {
    if {$linenumber == $i} {
        puts $line
        exit 0
    }
}
error "Didn't find line $line_number in $filename\n"
#-----------------------------
package require struct::list
expr {([llength $argv] == 2) || [error "usage: print_line FILENAME LINE_NUMBER\n"]}
::struct::list assign $argv filename linenumber
set dfd [open $filename]
set ifd [open $filename.index]
build_index $dfd $ifd
puts [line_with_index $dfd $ifd] | 
| #-----------------------------
set fields [split [regsub -all -- {PATTERN} $record {\0}] "\0"]
#-----------------------------
set fields [split [regsub -all -- {:} $record {\0}] "\0"]
#-----------------------------
set fields [split [regsub -all -- {\s+} $record {\0}] "\0"]
#-----------------------------
set fields [split [regsub -all -- { } $record {\0}] "\0"] | 
| #-----------------------------
set last 0
while {[gets $fd line] >= 0} {
    if {![eof $fd]} {
        set last [tell $fd]
    }
}
chan truncate $fd $last | 
| #-----------------------------
chan configure $handle -translation binary
#-----------------------------
set gifname "picture.gif"
set gif [open $gifname]
chan configure $gif -translation binary
chan configure stdout -translation binary
while {![eof $gif]} {
    puts -nonewline [read $gif [expr 8 * 2**10]]
} | 
| #----------------------------- set addr [expr $recsize * $recno] seek $fh $addr start set data [read $fh $recsize] binary scan $buffer $format field1 field2 #we can not pass a list/array as argument. #update fields set buffer [binary format $format $field1 $field2] seek $fh -$recsize current puts -nonewline $fh $buffer close $fh #----------------------------- # setting the login date. # @@INCOMPLETE@@ | 
| #-----------------------------
chan configure $fh -translation binary
seek $fh $addr start
set out [read $fh]
#-----------------------------
#not optimal. do not use it for large strings.
proc get_till_null {fh} {
    set out {}
    while {![eof $fh]} {
        set char [read $fh 1]
        set out "$out$char"
        if [regexp -- {\0} $char] break
    }
    return $out
}
foreach addr $addrs {
    #seek will detect the oct if it is prefixed with '0'.
    seek $fh $addr start
    puts [format {%x %o %d "%s"} $addr $addr $addr [get_till_null $fh]]
}
#-----------------------------
set fh [open $argv]
chan configure $fh -translation binary
foreach line [split [read $fh] "\0"] {
    foreach word [regexp -all -inline -- {[\x20-\x7e]+} $line] {
        puts $word
    }
} | 
| #-----------------------------
chan configure $fh -translation binary
while {![eof $fh]} {
    set record [read $fh $recordsize]
    binary scan $data $template field1 field2 field3
} | 
| #-----------------------------
array set user_preferences {}
foreach line [split [read -nonewline $fh] "\n"] {
    regsub -- {#.*$} [string trim $line] {} line
    if [string length $line] {
        array set user_preferences [string map {= { }} $line]
    }
} | 
| #-----------------------------
file stat $filename statinfo
# statinfo now contains the relevant information.
foreach var [array names statinfo] {
    set $var $statinfo($var)
}
set mode [expr $mode & 07777]
#-----------------------------
file stat $filename statinfo
if {!$statinfo(uid)) {
    puts "Superuser owns $filename"
}
if {$statinfo(atime) > $statinfo(mtime)} {
    puts "$filename has been read since it was written."
}
#-----------------------------
proc is_safe path {
    file stat $path info
    # owner neither su nor me
    if {$info(uid) && ![file owned $path]} {
        return 0
    }
    # check if group or other can write file.
    if {$info(mode) & 022} {
        if {![file isdirectory $path]} {
            return 0
        }
        if {!($info(mode) & 01000)} {
            return 0
        }
    }
    return 1
}
#-----------------------------
proc is_verysafe path {
    set build {}
    foreach elem [file split $path] {
        set build [file join $build $elem]
        if {![is_safe $build]} {
            return 0
        }
    }
    return 1
} | 
| #-----------------------------
#struct tmp {
#    short ut_type;                 +2      -> s    short
#                                   +2      -> x2   padding
#    pid_t ut_pid;                  +4      -> i    int
#    //alignment                    +20     -> x20  padding
#    char ut_line[UT_LINESIZE];     +12     -> A12  char
#    char ut_id[4];                 +4      -> A4   char
#    char ut_user[UT_NAMESIZE];     +32     -> A32  char
#    char ut_host[UT_HOSTSIZE];     +256    -> A256 char
#    struct exit_status ut_exit;    +4      -> x4   skip
#
#    long ut_session;               +4      -> x4   skip
#    struct timeval ut_tv;          +8      -> ii   int
#    int32_t ut_addr_v6[4];         +16     -> iiii int
#    char pad[20];                          -> x20  skip
#};
set typedef {s x2 i x20 A12 A4 A32 A256 x4 x4 ii iiii x20}
set sizeof [string length [binary format $typedef 0 0 {} {} {} {} 0 0 0 0 0 0 ]]
set wtmp [open {/var/log/wtmp}]
seek $wtmp 0 end
while 1 {
        set buffer [read $wtmp $sizeof]
        binary scan $buffer $typedef type pid line id user host tsec tmsec addr addr2 addr3 addr4
        scan $user %c ord
        if {!$user || !$time || !$ord} continue
        puts "type:$type user:$user uid:$line id:$id host:$host pid:$pid time:[clock format $tval1]"
        puts [format "->%u.%u.%u.%u" [expr $addr & 0xff] [expr ($addr >> 8) & 0xff] [expr ($addr >> 16) & 0xff] [expr ($addr >> 24) & 0xff]]
} | 
| #----------------------------- # @@INCOMPLETE@@ # @@INCOMPLETE@@ | 
| #----------------------------- # @@INCOMPLETE@@ # @@INCOMPLETE@@ #----------------------------- |