Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Initial work to date |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: | cf468d004f4177a54b14f468befb7733e248ac56 |
User & Date: | rkeene 2014-07-02 06:29:00 |
Context
2014-07-02
| ||
06:36 | Updated to use "eval" in the shell for safer execution check-in: 6cdd98d6d0 user: rkeene tags: trunk | |
06:29 | Initial work to date check-in: cf468d004f user: rkeene tags: trunk | |
06:27 | initial empty check-in check-in: 7b1a8cd2f0 user: rkeene tags: trunk | |
Changes
Added .fossil-settings/ignore-glob.
> |
1 |
netexec
|
Added Makefile.
> > > > > > |
1 2 3 4 5 6 |
netexec: bin/netexec lib/getopt/getopt.tcl netexec.sed sed -f netexec.sed bin/netexec > netexec chmod +x netexec clean: rm -f netexec |
Added bin/netexec.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
#! /usr/bin/env tclsh set sshopts [list] lappend sshopts -o ForwardAgent=no -o StrictHostKeyChecking=no -o CheckHostIP=yes -o UserKnownHostsFile=$env(HOME)/.ssh/netexec_known_hosts lappend sshopts -o PasswordAuthentication=no -o BatchMode=yes -o PreferredAuthentications=publickey lappend sshopts -o RequestTTY=no lappend auto_path ../lib package require getopt getopt flag arg $argv { -h - --help { help } -D: { set opts(delay) $arg } -f: { set opts(file) $arg } -g: { lappend opts(groups) $arg } unknown { puts stderr "Unknown option: \"$arg\"" exit 1 } missing { puts stderr "Option (\"$arg\") requires a value" exit 1 } arglist { set argv $arg } } set hosts $opts(file) proc issue_command_to_host {host cmdid} { set sock $::socks($host) catch { puts -nonewline $sock "echo START_$cmdid;" puts -nonewline $sock "$::commands($cmdid);" puts -nonewline $sock "echo;" puts $sock "echo END_$cmdid;" flush $sock } } proc issue_command {cmd hosts} { set cmdid [expr rand()][expr rand()][expr rand()][expr rand()][expr rand()] set ::commands($cmdid) $cmd foreach host $hosts { set ::host_data([list $host $cmdid]) [list] set ::commands_completed($cmdid) [list] issue_command_to_host $host $cmdid } while 1 { vwait ::commands_completed($cmdid) if {[llength $::commands_completed($cmdid)] == [llength $hosts]} { break } } unset ::commands($cmdid) unset ::commands_completed($cmdid) set retval [list] foreach host $hosts { set data $::host_data([list $host $cmdid]) if {[lindex $data end] == ""} { set data [lrange $data 0 end-1] } lappend retval $host $data unset ::host_data([list $host $cmdid]) } return $retval } proc get_data_from_host {host sock} { gets $sock line if {[info exists ::debug]} { puts stderr "$host\($sock) -> $line" flush stderr } foreach cmdid [array names ::commands] { if {$line == "START_$cmdid"} { set ::host_command($host) $cmdid return } if {$line == "END_$cmdid" && $::host_command($host) == $cmdid} { lappend ::commands_completed($cmdid) $host unset ::host_command($host) return } } if {[info exists ::host_command($host)]} { set cmdid $::host_command($host) } if {[eof $sock]} { catch { close $sock } if {[info exists cmdid]} { if {[lsearch -exact $::commands_completed($cmdid) $host] == -1} { lappend ::commands_completed($cmdid) $host } } unset -nocomplain ::host_command($host) unset -nocomplain ::socks($host) } if {![info exists cmdid]} { return } lappend ::host_data([list $host $cmdid]) $line } proc connect_host {host} { set ::socks($host) [open |[list ssh {*}$::sshopts $host 2>@1] "w+"] fileevent $::socks($host) readable [list get_data_from_host $host $::socks($host)] } proc prompt {} { puts -nonewline "netexec$ " flush stdout } proc handle_command {cmd} { switch -- [string trim $cmd] { "exit" { foreach host [array names ::socks] { catch { close $::socks($host) } } exit } "" { return [list] } } set hosts [array names ::socks] # Direct input if {[array names ::commands] != ""} { foreach host $hosts { puts $::socks($host) $cmd flush $::socks($host) } return [list] } # Issue a command return [issue_command $cmd $hosts] } proc get_command {} { gets stdin cmd array set results [handle_command $cmd] foreach host [lsort -dictionary [array names results]] { foreach line $results($host) { puts "$host: $line" } } prompt } foreach host $hosts { connect_host $host } prompt fileevent stdin readable [list get_command] vwait forever |
Added lib/getopt/getopt.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
#! /usr/bin/env tclsh package require Tcl 8.5 proc getopt {optvar argvar list body} { upvar 1 $optvar option $argvar value set arg(missing) [dict create pattern missing argument 0] set arg(unknown) [dict create pattern unknown argument 0] foreach {pat code} $body { switch -glob -- $pat { -- {# end-of-options option} --?*: {# long option requiring an argument set arg([string range $pat 0 end-1]) \ [dict create pattern $pat argument 1] } --?* {# long option without an argument set arg($pat) [dict create pattern $pat argument 0] } -?* {# short options set last ""; foreach c [split [string range $pat 1 end] ""] { if {$c eq ":" && $last ne ""} { dict set arg($last) argument 1 set last "" } else { set arg(-$c) [dict create pattern $pat argument 0] set last -$c } } } } } while {[llength $list]} { set rest [lassign $list opt] # Does it look like an option? if {$opt eq "-" || [string index $opt 0] ne "-"} break # Is it the end-of-options option? if {$opt eq "--"} {set list $rest; break} set option [string range $opt 0 1] set value 1 if {$option eq "--"} { # Long format option if {[info exists arg($opt)]} { set option $opt } elseif {[llength [set match [array names arg $opt*]]] == 1} { set option [lindex $match 0] } else { # Unknown or ambiguous option set value $opt set option unknown } if {[dict get $arg($option) argument]} { if {[llength $rest]} { set rest [lassign $rest value] } else { set value $option set option missing } } } elseif {![info exists arg($option)]} { set value $option set option unknown if {[string length $opt] > 2} { set rest [lreplace $list 0 0 [string replace $opt 1 1]] } } elseif {[dict get $arg($option) argument]} { if {[string length $opt] > 2} { set value [string range $opt 2 end] } elseif {[llength $rest]} { set rest [lassign $rest value] } else { set value $option set option missing } } elseif {[string length $opt] > 2} { set rest [lreplace $list 0 0 [string replace $opt 1 1]] } uplevel 1 [list switch -- [dict get $arg($option) pattern] $body] set list $rest } set option arglist set value $list uplevel 1 [list switch -- arglist $body] } package provide getopt 0.1 |
Added lib/getopt/pkgIndex.tcl.
> |
1 |
package ifneeded getopt 0.1 [list source [file join $dir getopt.tcl]]
|
Added netexec.sed.
> > > > > |
1 2 3 4 5 |
/^lappend auto_path/ d /^package require getopt/{ r lib/getopt/getopt.tcl d } |