#!/bin/sh
# the next line restarts using wish \
exec wish "$0" "$@"

# where the sources installed is
set libpath [file dirname [info script] ]

wm title . "SCSI initialization"

set tk_strictMotif 1

########################################################################
# That is the documentation, directly in the program, with the 
# small goes that already times. 
#
# Histroy:
# 
# 22.02.2000,  first version 1.0, Helmut Fahrion hefa@gmx.net
# 03.10.2001,  begun the english helping text to insert
#
set hilfetext "

	The SCSI init program
	=====================



A small Tcl/Tk program for the administration of the SCSI bus. A simple
clicking surface for the tap-lazy users.


To me it is frequently occurred which I the computer runs has and my box is,
with SCSI CD-Burner and fixed disk out. Now does one need the fixed disk,
which now? All applications terminate and the computer boats,:-(( functioned,
\"Windoof like is however very complex and time-corrosive, correct \".


Another alternative is to be opened a root Shell and then the command echo
 \"scsi for ADD single DEVICE 0 00 05 00 \" > / proc/scsi/scsi into the
 keyboard already chops and gehts. That is correctly which for keyboard hackers,
 for these people is this program meant! I make that also gladly times, but this
 solution did not satisfy me so correctly.

Additionally, who deals with itself with the Kernel which it white which one on
 / proc/scsi/scsi which wrote so intensively can?

There me the idea of this small Tcl/Tk program came to write, what is to
 facilitate the daily work.

Thus with this program you can the individual DEVICES of the SCSI of bus hang up
 and again notices.

Thus you can do the computer run, which scanners or another device switch on and
 initialize!

Afterwards you can operate with the device, the fixed disk mounten or with the
 scanner scanning.

If you are finished with your work and if the SCSI device wants to again switch
 off whereby the computer to continue is, proceed as follows:


Umounten you the fixed disk or terminate you the work with the scanner then
 remove the device from the bus (menu option removing) and thus can you off the
 device switch.

No device can be removed from the bus if this device is still occupied, which
 does not go simply and also bad errors would generate.


Configuration of the program:
----------------------

Here there are several possibilities:

The computer with all available SCSI devices raising and then the program and
 only on \"scannen \" and then on \"speichern \" go.

Edit click and then the available SCSI DEVICE enter, whereby in one { } always a
 DEVICE is, the numbers are the folgede sequence:

   SCSI-Controller    Channel    ID     LUN

also:    {0 01 02 00}   ->   SCSI-Contoller 0 Channel 1 ID 2 and LUN 0

Whereby the 01 1 should not be, so that those is always alike to width of an
 entry.

Example:
{0 00 00 00} {0 00 01 00}

A computer with a CONTROLLER, a fixed disk ID 0 and a DCRom ID 1. A SCSI scanner
 with ID 5 attached to the bus looks the configuration file as follows now:

{0 00 00 00} {0 00 01 00} {0 00 05 00}

is nevertheless OK ONE like that!  :-\)\)

P.S.  Memory do not forget!


Functionality of the Buttons:
-----------------------------

EXIT: Program terminate

INIT: Desired DEVICES click removing: If the disk is out-hung (umount), the
 DEVICE can be logged out and switched off then.

SCANNING: The bus to scanning, results display. If you select after \"Scannen \" 
\"speichern \", with the next start again the same DEVICES are displayed.

READING: The Konfigdatei reads in and on init goes.

MEMORY: The DEVICES with \"Init \" to be displayed, are entered into the
 Konfigfile and displayed with the next start again.


P.S. On / proc/scsi/scsi only root may write. That is to be operated however
 still for a long time no reason basically as roots. One can start or with sudo
 call it thus more eintweder in one root-brightly.

Much fun thereby!

Helmut


"
################################################################################



####################################################################
# Globale Daten

# Devices Liste, kann modifiziert werden.

#  Host: scsi0  Channel:00 Id:00 Lun:00
#  C = CONTROLLER, B=BUS, T=TARGET SCSI ID, U = UNITD SCSI LUN
set devices {{00 00 00 00} {00 00 01 00} {00 00 02 00} {00 00 03 00} {00 00 04 00} {00 00 05 00} {00 00 06 00} {00 00 07 00} {01 00 00 00} {01 00 07 00}}

set devicessave $devices
# read file
set scsifile "/proc/scsi/scsi"
set scsitxt "xxxxxxxxx"
set savename "/var/scsibusinit"

#####################################################################


proc positionWindow w { wm geometry $w +100+80 }


# Eine Arbeitsflche und ein Menbalken
frame .mbar -relief raised -bd 2
frame .work -relief sunken -bd 1 -width 12c -height 12c
frame .work.f -relief groove -bd 2
frame .work.bs -relief groove -bd 2

set bus .work.bs

pack .mbar .work -side top -fill x

# die Gre soll konstant bleiben
pack propagate .work 0

pack .work.f -padx 2m -pady 2m


# Menbalken
menubutton .mbar.datei -text "File" -menu .mbar.datei.menu
menubutton .mbar.hilfe -text "Help" -menu .mbar.hilfe.menu
menubutton .mbar.scsi -text "SCSI" -menu .mbar.scsi.menu

pack .mbar.datei .mbar.scsi -side left
pack .mbar.hilfe -side right


# SCSI Men
menu .mbar.scsi.menu
.mbar.scsi.menu add command -label "Initialization" -underline 0 -accelerator Alt+i \
    -command scsiinitdialog
.mbar.scsi.menu add command -label "Remove" -underline 0 -accelerator Alt+e \
    -command scsiremdialog
.mbar.scsi.menu add command -label "Scanning" -underline 0 -accelerator Alt+s \
    -command scsiscandialog
.mbar.scsi.menu add command -label "Information" -underline 3 -accelerator Alt+f \
    -command scsiinfodialog
.mbar.scsi.menu add command -label "Reading" -underline 0 -accelerator Alt+l \
    -command scsiinfodialog

# Quickbuttons 
button $bus.bi -text "Init" -command  scsiinitdialog  -underline 0 
button $bus.ent -text "Remove" -command  scsiremdialog -underline 0
button $bus.sc -text "Scanning" -command  scsiscandialog -underline 0
button $bus.q -text "Exit" -command  "destroy ." -underline 1
button $bus.l -text "Read" -command "uplevel #0 \"source $savename\"; scsiinitdialog " -underline 0

pack $bus -side bottom
pack $bus.l $bus.sc $bus.ent $bus.bi $bus.q -side right


# Keyboard binding
bind . <M-i> scsiinitdialog
bind . <M-e> scsiremdialog
bind . <M-s> scsiscandialog
bind . <M-f> scsiinfodialog
bind . <M-l> "uplevel #0 \"source $savename\"; scsiinitdialog "

# again and again for a new dialog one deletes
frame .work.f.dummy


menu .mbar.datei.menu
.mbar.datei.menu add command -label "Save" -accelerator "F2" -underline 0 \
    -command scsisave
.mbar.datei.menu add command -label "Load..." -accelerator "F3" \
    -command laden
.mbar.datei.menu add command -label "Reset" -accelerator "F8" \
    -command loeschen
.mbar.datei.menu add command -label "Edit Data..." -accelerator "F4" \
    -command editdialog
.mbar.datei.menu add command -label "Edit File..." -accelerator "F5"\
    -command editfile
.mbar.datei.menu add separator
.mbar.datei.menu add command -label "Program leave..." -accelerator Alt+x \
    -command { verlassen }

bind . <F5> editfile
# bind . <F6> saveas
bind . <F4> editdialog
bind . <F2> scsisave
bind . <F8> loeschen
bind . <F3> laden
bind . <M-x> verlassen


proc loeschen { } {
    global savename devices devicessave
    set ret [ catch { exec rm $savename } ]
    set devices $devicessave
    scsiinitdialog
    if { $ret != 0 } {
	tk_messageBox -icon error -message "Errors with delete the file $savename!" -type ok
    }
}

proc editfile { } {
    global savename

    foreach editor { kedit xedit emacs } {
	set ret [ catch { exec sh -c "$editor $savename" & } ]
	if { $ret == 0 } break
    }

}

proc verlassen { } {
    set answer [tk_messageBox -icon question -message "Surely?" -type okcancel]
    case $answer {
	ok { destroy . }
	cancel { puts "Prima idea!" }
    }
}

proc textto { w v } {
    global $v
    set $v [$w get 1.0 end]
}

proc editdialog { } {
    global devices
    set w .editdialog
    catch {destroy $w}
    toplevel $w

    wm title $w "Devices"
    wm iconname $w "dev"
    positionWindow $w
    frame $w.buttons
    pack $w.buttons -side bottom -fill x -pady 2m
    button $w.buttons.ok -text "OK" -command "textto $w.text devices; destroy $w"  -default active
    pack $w.buttons.ok -side left -expand 1
    text $w.text -relief sunken -bd 2 -yscrollcommand "$w.scroll set" -setgrid 1 \
	-height 3
    scrollbar $w.scroll -command "$w.text yview"
    pack $w.scroll -side right -fill y
    pack $w.text -expand yes -fill both
    $w.text insert 0.0 $devices
    $w.text mark set insert 0.0

    bind $w <Return> "textto $w.text devices; destroy $w"
}


menu .mbar.hilfe.menu

if {$tcl_platform(platform) == "macintosh"} {
    .mbar add cascade -menu .mbar.apple
    menu .mbar.apple -tearoff 0
    .mbar.hilfe.menu add command -label "Info..." -command "proginfo"
} else {
    .mbar.hilfe.menu add command -label "Info..." -command "proginfo" \
        -accelerator "Alt+v" -underline 0
}
.mbar.hilfe.menu add command -label "Introduction..." -command einleitung -accelerator "<F1>" 

# Tastatur
bind . <F1> einleitung
bind . <M-v> proginfo


#####################################################################################
# Hilfe, noch sehr sparsam ... :-((

proc proginfo { } {
    tk_messageBox -icon info -title "Infodialog" \
	-message  \
"The SCSI -  Bus managers

Author: Helmut Fahrion

Version: 1.2, by 03.10.2001

(c) GPL" -type ok -parent .
}

proc einleitung { } {
    global hilfetext
    set w .hilfedialog
    catch {destroy $w}
    toplevel $w

    wm title $w "Hilfe"
    wm iconname $w "hilfe"
    positionWindow $w
    frame $w.buttons
    pack $w.buttons -side bottom -fill x -pady 2m
    button $w.buttons.ok -text "OK" -command "destroy $w" -default active
    pack $w.buttons.ok -side left -expand 1
    text $w.text -relief sunken -bd 2 -yscrollcommand "$w.scroll set" -setgrid 1 \
	-height 30
    scrollbar $w.scroll -command "$w.text yview"
    pack $w.scroll -side right -fill y
    pack $w.text -expand yes -fill both
    $w.text insert 0.0 $hilfetext
    $w.text mark set insert 0.0
}


# save 
proc scsisave { } {
    global savename
    global dummy

    set fd [ open $savename w+ ]
    puts $fd "\# gespeicherte SCSI Channels"
    puts $fd "\# {Controller:0  Channel:00 Id:00 Lun:00} { ... } ... "
    #  Host: scsi0  Channel:00 Id:00 Lun:00
    #  C = CONTROLLER, B=BUS, T=TARGET SCSI ID, U = UNITD SCSI LUN

    set vars "devices"

    # Variablen von Main
    foreach v $vars {
	global $v
	puts $fd "set $v [ list [set $v] ] "
    }

    # immer wieder zu !
    close $fd
    
    tk_messageBox -icon info -title "Infodialog" \
	-message  "gespeichert $savename!" -type ok -parent .
}

proc DateifileDialog {w ent operation} {
    global savename
    
    #   Type names		Extension(s)	Mac File Type(s)
    set types {
	{"All files"		*}
	{"SCSI Dateien"		*.scsi}
    }

    if {$operation == "open"} {
	set savename [tk_getOpenFile -filetypes $types -parent $w \
		      -initialfile $savename -defaultextension .scsi ]
   } else {
	set savename [tk_getSaveFile -filetypes $types -parent $w \
		      -initialfile $savename -defaultextension .scsi ]
   }
}

proc laden { } {
    global platform
    global tcl_platform
    global savename
    global dummy

    set w .filebox
    catch {destroy $w}
    toplevel $w
    wm title $w "Namensauswahl"
    wm iconname $w "Namen"
    positionWindow $w
    
    label $w.msg -justify left -text "Namen angeben"
    pack $w.msg -side top
    
    frame $w.buttons
    pack $w.buttons -side bottom -fill x -pady 2m
    button $w.buttons.dismiss -text "Abbruch" -command "destroy $w"
    
    button $w.buttons.ok -text "ffnen" -command "configread; destroy $w"
    pack $w.buttons.ok $w.buttons.dismiss -side left -expand 1
    focus $w.buttons.ok

    # open save
    foreach i {open} {
	set f [frame $w.$i]
	label $f.lab -text "Dateiname: " -anchor e
	entry $f.ent -width 20 -textvariable savename
	button $f.but -text "Liste..." -command "DateifileDialog $w $f.ent $i"
	pack $f.lab -side left
	pack $f.ent -side left -expand yes -fill x
	pack $f.but -side left
	pack $f -fill x -padx 1c -pady 3
    }
    
    if {$tcl_platform(platform) == "unix"} {
	checkbutton $w.strict -text "Verwende Win Dateidialog" \
	    -variable tk_strictMotif -onvalue 0 -offvalue 1
	pack $w.strict -anchor c
    } else {
	checkbutton $w.strict -text "Verwende Motif Dateidialog" \
	    -variable tk_strictMotif -onvalue 1 -offvalue 0
	pack $w.strict -anchor c
    }
}

proc configread { } {
    global savename

    # global!
    uplevel #0 "source $savename"

    tk_messageBox -icon info -title "Infodialog" \
	-message  "lese $savename!" -type ok -parent .
}


# source Daten
# lese die SCSI-Konfiguration aus der Datei,
# falls vorhanden 
catch { uplevel #0 "source $savename" }


# source die programmmodule
#source "$libpath/scsiinit.tcl"
###################################################################
proc scsiinit {scsi channel id lun} {
    global scsifile

    #    set fd [ open $scsifile w ]

    set outstr "scsi add-single-device $scsi $channel $id $lun"

    #    puts $fd $outstr
    #    close $fd
    #exec echo $outstr > $scsifile

    set rcode [ catch { exec sh -c "echo $outstr > $scsifile" } ]

    if { $rcode == 1 } {
     tk_messageBox -icon error -title "Return-Dialog" \
	-message  "Device was initialized!" -type ok -parent .
    }
}


proc scsiinitdialog { } {
    set wf .work.f.dummy
    global devices
    set devtxt ""

    # ab dummy alles weg!
    destroy $wf
    frame $wf

    # ab hier die eigentlichen Werbungswidgets
    label $wf.initl -text "SCSI DEVICE initializing:"
    # die Packerei 
    pack $wf
    pack $wf.initl  -pady 3m 

    set i 1
    # Schleife fr einzelne Devices
    foreach xx $devices {


	foreach {scsi channel id lun} $xx { break }
	
	set bb $wf.b$i
	incr i

	set devtxt  "SCSI Karte: $scsi Kanal: $channel ID: $id LUN: $lun"
	button $bb -text $devtxt -command "scsiinit $scsi $channel $id $lun"
	# label $wf.devl  -text $devtxt
	pack $bb
    }
}


# Gleich den Dialog laden
scsiinitdialog



#############################################################################
#source "$libpath/scsirem.tcl"


proc scsirem {scsi channel id lun} {
    global scsifile

    #set fd [ open $scsifile w+ ]

    set outstr "scsi remove-single-device $scsi $channel $id $lun"

    # puts $outstr
    #puts $fd $outstr


    # aus irgendwelchen Grnden gibt es trotz das es geklappt hat, 
    # die Fehlermeldung no such Device !

    #close $fd
    set rcode [ catch { exec sh -c "echo $outstr > $scsifile" } ]

    if { $rcode != 1 } {
     tk_messageBox -icon error -title "Return-Dialog" \
	-message  "Error $rcode recieved!" -type ok -parent .
    }
}



proc scsiremdialog { } {
    set wf .work.f.dummy
    global devices
    set devtxt ""

    # ab dummy alles weg!
    destroy $wf
    frame $wf

    # ab hier die eigentlichen Werbungswidgets
    label $wf.initl -text "SCSI Device removing:"
    # die Packerei 
    pack $wf
    pack $wf.initl  -pady 3m 

    set i 1
    # Schleife fr einzelne Devices
    foreach xx $devices {


	foreach {scsi channel id lun} $xx { break }
	
	set bb $wf.b$i
	incr i

	set devtxt  "SCSI Karte: $scsi Kanal: $channel ID: $id LUN: $lun"
	button $bb -text $devtxt -command "scsirem $scsi $channel $id $lun"
	# label $wf.devl  -text $devtxt
	pack $bb
    }
}


###########################################################################
#source "$libpath/scsiinfo.tcl"


proc neuladen { } {
    global scsifile scsitxt
    set fd [ open $scsifile r ]
    set scsitxt [ read $fd ]
    close $fd
}


proc scsiinfodialog { } {
    set wf .work.f.dummy
    global urlstr
    global urllist

    # ab dummy alles weg!
    destroy $wf
    frame $wf

    # ab hier die eigentlichen Werbungswidgets
    label $wf.initl -text "SCSI Device Information:"

    # SCSI Infos lesen
    neuladen

    # Anzeigen
    scsiprocdialog

    # die Packerei 
    pack $wf
    pack $wf.initl  -pady 3m 
}


proc scsiprocdialog { } {
    global scsifile scsitxt
    set w .logdialog
    catch {destroy $w}
    toplevel $w
    
    wm title $w "SCSI-Devices"
    wm iconname $w "scsi"
    positionWindow $w
    
    frame $w.buttons
    pack $w.buttons -side bottom -fill x -pady 2m

    button $w.buttons.ok -text "OK" -command "destroy $w"  -default active
    # button $w.buttons.lesen -text "Neu lesen" -command neuladen
    
    pack $w.buttons.ok -side left -expand 1
    # pack $w.buttons.lesen -side left -expand 1
        
    text $w.text -relief sunken -bd 2 -yscrollcommand "$w.scroll set" \
	-setgrid 1 -height 20
    
    scrollbar $w.scroll -command "$w.text yview"
    pack $w.scroll -side right -fill y
    pack $w.text -expand yes -fill both
    $w.text insert 0.0 $scsitxt
    $w.text mark set insert 0.0
}



########################################################################
#source "$libpath/scsiscan.tcl"

# Scannt die Scsi-Devices durch und merkt sich die Devices
# in einer Liste. 
# Die Devices in dieser Liste knnen dann Entfernt und wieder
# hinzugeladen werden.


proc scanladen { } {
    global scsifile scsitxt
    set fd [ open $scsifile r ]
    set scsitxt [ read $fd ]
    close $fd
}


proc scsiscandialog { } {
    set wf .work.f.dummy
    global scsifile
    global scsitxt
    global devices
    set devtxt ""

    # ab dummy alles weg!
    destroy $wf
    frame $wf

    # Anzeigen
    frame $wf.anzeige

    # ab hier die eigentlichen Werbungswidgets
    label $wf.initl -text "SCSI Device scanning:"

    # SCSI Infos lesen
    scanladen
   
    # Liste aufbauen
    set devices ""
    set yyy [split $scsitxt "\n"]
    foreach xx $yyy {
	# Host: scsi0 Channel: 00 Id: 01 Lun: 00  
	if {[regexp -- "^Host: scsi\(\[0-9\]\) Channel: \(\[0-9\]+\) Id: \(\[0-9\]+\) Lun: \(\[0-9\]+\)\$" $xx dummy scsi channel id lun]} {
	  lappend devices [list $scsi $channel $id $lun]
    set devtxt  "$devtxt SCSI Karte: $scsi Kanal: $channel ID: $id LUN: $lun\n"
	}
    }

    # Anzeigen
    #frame $wf.anzeige
    label $wf.anzeige.device -text $devtxt

    # die Packerei 
    pack $wf    
    pack $wf.initl  -pady 3m 

    pack $wf.anzeige
    pack $wf.anzeige.device
 
}


