#!/usr/bin/wish


set root "/etc"
set backupdir "/tmp/tksysv"
set version "0.8"
set lib "/usr/lib/tksysv"
set about $lib/about.txt
set tksysv $lib/tksysv.txt
set sysvinit $lib/sysvinit.txt

exec rm -rf $backupdir
exec mkdir -p $backupdir
exec cp -arf $root/rc.d $backupdir

if {[exec id -un] != "root"} {
	if {[tk_dialog .new "Wrong User" "You aren't the superuser.  You must \
             be root to run this program." "" "0" "Ok"] == "0"} {
		exit 0
	}
}

if {$argv == "" } {
	set levels "0 1 2 3 4 5 6"
} elseif {$argv == "--help"} {
	puts "\n\tUsage: tksysv \[0|1|2|3|4|5|6\] \[--help\]"
	puts "\n\tRun 'tksysv' with no args to view and edit all runlevels."
	puts "\tRun 'tksysv 0 1 2' to view and edit runlevels 0, 1, and 2.\n"
	exit 0
} else {
	set levels $argv
}
set number ""


wm title . "SYSV Runlevel Manager, v$version"

frame .top -relief raised -borderwidth 2
pack .top -side top -padx 1 -pady 1 -fill x
menubutton .top.helpbutton -text Help -underline 0 -menu \
	.top.helpbutton.filemenu
menubutton .top.filebutton -text File -underline 0 -menu \
	.top.filebutton.filemenu
menu .top.filebutton.filemenu
.top.filebutton.filemenu add command -label "Rescan rc.d" -command {readrc}
.top.filebutton.filemenu add separator
.top.filebutton.filemenu add command -label "  Quit  " -command {exit 0}
menu .top.helpbutton.filemenu
.top.helpbutton.filemenu add command -label "About" -command {showit $about}
.top.helpbutton.filemenu add separator
.top.helpbutton.filemenu add command -label "SYSV Init" -command {showit $sysvinit}
.top.helpbutton.filemenu add command -label "tksysv" -command {showit $tksysv}
pack .top.filebutton -side left
pack .top.helpbutton -side right
focus .top.filebutton.filemenu
frame .left -relief groove -borderwidth 3
pack .left -side left -padx 3 -pady 3 -fill y
frame .right
pack .right -side left
frame .right.top -relief groove -borderwidth 3
pack .right.top -side top -padx 3 -pady 3
frame .right.top.lab
pack .right.top.lab -side left
label .right.top.lab.label1 -text "S" -width 2 -justify center
label .right.top.lab.label2 -text "t" -width 2 -justify center
label .right.top.lab.label3 -text "a" -width 2 -justify center
label .right.top.lab.label4 -text "r" -width 2 -justify center
label .right.top.lab.label5 -text "t" -width 2 -justify center
pack .right.top.lab.label1 -side top
pack .right.top.lab.label2 -side top
pack .right.top.lab.label3 -side top
pack .right.top.lab.label4 -side top
pack .right.top.lab.label5 -side top
frame .right.bottom -relief groove -borderwidth 3
pack .right.bottom -side top -padx 3 -pady 3
frame .right.bottom.lab
pack .right.bottom.lab -side left
label .right.bottom.lab.label1 -text "S" -width 2 -justify center
label .right.bottom.lab.label2 -text "t" -width 2 -justify center
label .right.bottom.lab.label3 -text "o" -width 2 -justify center
label .right.bottom.lab.label4 -text "p" -width 2 -justify center
pack .right.bottom.lab.label1 -side top
pack .right.bottom.lab.label2 -side top
pack .right.bottom.lab.label3 -side top
pack .right.bottom.lab.label4 -side top
foreach loc "$levels" {
	frame .right.top.$loc
	pack .right.top.$loc -side left
	frame .right.bottom.$loc
	pack .right.bottom.$loc -side left
	frame .right.bottom.$loc.top
	pack .right.bottom.$loc.top -side top
	label .right.top.$loc.label -text "$loc"
	pack .right.top.$loc.label -side top
	listbox .right.top.$loc.list -height 10 -width 10 -yscrollcommand \
		".right.top.$loc.scroll set"
	scrollbar .right.top.$loc.scroll -command \
		".right.top.$loc.list yview" -width 10
	listbox .right.bottom.$loc.top.list -height 10 -width 10 \
		-yscrollcommand ".right.bottom.$loc.top.scroll set"
	scrollbar .right.bottom.$loc.top.scroll -command \
		".right.bottom.$loc.top.list yview" -width 10
#	button .right.bottom.addstart$loc -text "Add Start" -command \
#		{addstart} -width 10
#	button .right.bottom.addstop$loc -text "Add Stop" -command \
#		{addstop $loc} -width 10
#	button .right.bottom.edit$loc -text "Edit" -command \
#		{edit $loc} -width 10
#	button .right.bottom.remove$loc -text "Remove" -command \
#		{remove $loc} -width 10
	pack .right.top.$loc.list -side left -in .right.top.$loc
	pack .right.top.$loc.scroll -side right -fill y -in .right.top.$loc
	pack .right.bottom.$loc.top.list -side left  -in .right.bottom.$loc.top
	pack .right.bottom.$loc.top.scroll -side right -fill y -in \
		.right.bottom.$loc.top
#	pack .right.bottom.addstart$loc -in .right.bottom.$loc -side top
#	pack .right.bottom.addstop$loc -in .right.bottom.$loc -side top
#	pack .right.bottom.edit$loc -in .right.bottom.$loc -side top
#	pack .right.bottom.remove$loc -in .right.bottom.$loc -side top
}
frame .left.top
pack .left.top -in .left -side top
label .left.top.label -text "Available:" -justify left
pack .left.top.label -side top
button .left.add -text "Add" -command {addit} -width 14 
pack .left.add -side top 
button .left.remove -text "Remove" -command {removeit} -width 14 
pack .left.add -side top 
button .left.edit -text "Edit" -command {editit} -width 14 
pack .left.add .left.remove .left.edit -side top
button .left.execute -text "Execute" -command {execute} -width 14 
pack .left.add .left.execute .left.edit -side top
listbox .left.top.available -height 14 -width 10 -yscrollcommand \
	".left.top.availablescroll set"
scrollbar .left.top.availablescroll -command ".left.top.available yview" \
	-width 10
pack .left.top.available -side left -in .left.top
pack .left.top.availablescroll -side right -in .left.top -fill y
pack .left -side left
pack .right -side left
pack .right.top -side top
pack .right.bottom -side top
# button .left.quit -text "Quit" -command {exit} -width 10
# pack .left.quit -side bottom -in .left


foreach n [lsort [glob -nocomplain "$root/rc.d/init.d/*"]] {
	regsub (.*/) "$n" "" a
	if {![regexp "$a" "functions" ]} {
		if {![regexp "$a" "skeleton"]} {
		.left.top.available insert end "$a" } }

	
}


proc findit {} {
global topstring top
global bottomstring
global runnumber
global levels
global leftstring

set topstring ""
set bottomstring ""
set runnumber ""
set leftstring ""

foreach n "$levels" {
	set topselect [.right.top.$n.list curselection]
	if {$topselect != ""} {
		set topstring $topselect
		set runnumber $n
		set top "0"
		return 0
	}
	set bottomselect [.right.bottom.$n.top.list curselection]
	if {$bottomselect != ""} {
		set bottomstring $bottomselect
		set runnumber $n
		set top "1"
		return 0
	}
}
if {$bottomstring == "" && $topstring == ""} {
	set leftselect [.left.top.available curselection]
	if {$leftselect != ""} {
		set leftstring $leftselect
		return 2
	}
}

if {$bottomstring == "" && $topstring == "" && $leftstring == ""} {
	return 1
}


}

proc execute {} {
global topstring top
global bottomstring
global runnumber
global leftstring levels
global addtolevel leftselect


if {[findit] != "2"} {
tk_dialog .new "Select Something" "Please select something from the Available window." "" "0" "Ok"


} elseif {$topstring != "" || $bottomstring != ""} {

# puts "select something from the \"Available\" window please."

} elseif {$leftstring != ""} {
	set leftselect [.left.top.available get $leftstring]
	toplevel .executeit
	focus .executeit
	wm title .executeit "Excute $leftselect"
	label .executeit.label -text "$leftselect" -justify center -width 20 \
		-relief groove -borderwidth 2
	button .executeit.start -text "Start" -command {runcom start}
	button .executeit.stop -text "Stop" -command {runcom stop}
	#button .executeit.restart -text "Restart" -command {runcom restart}
	button .executeit.canc -text "Cancel" -command {destroy .executeit}
	pack .executeit.label -side top
	#pack .executeit.start .executeit.stop .executeit.restart -side top -fill x
	pack .executeit.start .executeit.stop -side top -fill x
	pack .executeit.canc -side top -fill x
	

}
}

proc runcom {what} {
global topstring top root
global bottomstring
global runnumber
global leftstring levels
global addtolevel leftselect

destroy .executeit

toplevel .result
focus .result
wm title .result "Result from \`$leftselect $what\`"
frame .result.top
pack .result.top -side top
text .result.top.text -relief sunken -borderwidth 2 -width 60 \
	-height 10 -yscrollcommand ".result.top.scroll set"
scrollbar .result.top.scroll -command ".result.top.text yview" \
	-width 10	
pack .result.top.text .result.top.scroll -side left -fill y
button .result.quit -text "Done" -command {destroy .result}
pack .result.quit -side top -fill x -padx 2 -pady 2

update idletasks
set f [open "|$root/rc.d/init.d/$leftselect $what" r]
while {[gets $f line] >= 0} {
	update idletasks
	.result.top.text insert end $line
	}

close $f


}


proc addit {} {
global topstring top
global bottomstring
global runnumber
global leftstring levels
global addtolevel leftselect

if {[findit] == "1"} {
	tk_dialog .new "Nothing Selected" "You didn't select anything.\
		Please select something to add/remove." "" "0" "Ok"
} elseif {$topstring != "" || $bottomstring != ""} {

# puts "select something from the \"Available\" window please."
tk_dialog .new "Select Something" "Please select something from the Available window." "" "0" "Ok"

} elseif {$leftstring != ""} {
	toplevel .addwin
	focus .addwin
	frame .addwin.box -relief groove -borderwidth 2
	frame .addwin.box.top
	frame .addwin.box.bottom
	set leftselect [.left.top.available get $leftstring]
	wm title .addwin "Add $leftselect"
#	label .addwin.label -text "Add $leftselect to which runlevel:"
#	entry .addwin.entry -textvar addtolevel -width 4
#	pack .addwin.label .addwin.entry -side top
#	pack .addwin.label -side top
	frame .addwin.two -relief groove -borderwidth 2
	set addtolevel [lindex $levels 0]
	foreach n "$levels" {
		frame .addwin.two.$n
		label .addwin.two.$n.label -text "$n"
		checkbutton .addwin.two.$n.button -onvalue $n \
			-variable addtolevel
		pack .addwin.two.$n.label .addwin.two.$n.button -side left
		pack .addwin.two.$n -side top
	}
	pack .addwin.box -side top -padx 3 -pady 3 -fill x
	label .addwin.label -text "in runlevel:"
	pack .addwin.label -side top
	pack .addwin.two -side top -padx 3 -pady 3 -fill x
	label .addwin.box.top.checkstart -text "Start $leftselect"
	checkbutton .addwin.box.top.startcheck  -onvalue "0" \
		-offvalue "1" -variable top 
	pack .addwin.box.top .addwin.box.bottom -side top
	pack .addwin.box.top.checkstart .addwin.box.top.startcheck -side left
	label .addwin.box.bottom.checkstop -text "Stop $leftselect"
	checkbutton .addwin.box.bottom.stopcheck  -onvalue "1" -offvalue \
		"0" -variable top 
	pack .addwin.box.bottom.checkstop .addwin.box.bottom.stopcheck -side left
	button .addwin.quit -text "Done" -command {addto}
	button .addwin.can -text "Cancel" -command {destroy .addwin}
	pack .addwin.quit .addwin.can -fill x -side top
	if {$top == "1"} {
		set label "Stop"
	}


} else {
	# puts "nothing selected to add"
}


readrc

}



proc removeit {} {
global topstring
global bottomstring
global runnumber root
global leftstring

if {[findit] == "1"} {
	tk_dialog .new "Nothing Selected" "You didn't select anything.\
		Please select something to add/remove." "" "0" "Ok"

} elseif {$topstring != ""} {
	set stringis [.right.top.$runnumber.list get $topstring]
	regsub (.*/) \
		[glob -nocomplain "$root/rc.d/rc$runnumber.d/S*$stringis"] "" a
	exec rm -f "$root/rc.d/rc$runnumber.d/$a"

} elseif {$bottomstring != ""} {
	set stringis [.right.bottom.$runnumber.top.list get $bottomstring]
	regsub (.*/) \
		[glob -nocomplain "$root/rc.d/rc$runnumber.d/K*$stringis"] "" a
	exec rm -f "$root/rc.d/rc$runnumber.d/$a"
} else {
	# puts "nothing selected that is removable"
}

readrc


}


proc readrc {} {
global levels root
foreach level "$levels" {
	.right.top.$level.list delete 0 end
	.right.bottom.$level.top.list delete 0 end
}
foreach level "$levels" {
	foreach n [lsort [glob -nocomplain "$root/rc.d/rc$level.d/S*"]] {
		regsub (.*/...) "$n" "" a
		.right.top.$level.list insert end "$a" 
	}
	foreach n [lsort [glob -nocomplain "$root/rc.d/rc$level.d/K*"]] {
		regsub (.*/...) "$n" "" a
		.right.bottom.$level.top.list insert end "$a"
	}
}
}

readrc

proc addto {} {
global root addtolevel leftselect var
global number
global top

destroy .addwin

toplevel .whereat
focus .whereat
# wm title . "Place $leftselect"
frame .whereat.top
pack .whereat.top -side top
listbox .whereat.top.list -height 10 -width 20 \
        -yscrollcommand ".whereat.top.scroll set"
scrollbar .whereat.top.scroll -command ".whereat.top.list yview"
pack .whereat.top.list -side left
pack .whereat.top.scroll -side right -fill y
label .whereat.label -text "The Number for $leftselect is:"
entry .whereat.entry -textvar number -width 10
pack .whereat.label .whereat.entry -side top
button .whereat.add -text "Add" -command {addthis;destroy .whereat}
button .whereat.quit -text "Done" -command {destroy .whereat}
pack .whereat.add .whereat.quit -side top -fill x
if {$top == "0"} {
	set var "S"
} else {
	set var "K"
}
loadlevel
}


proc loadlevel {} {
global addtolevel root var

.whereat.top.list delete 0 end

foreach n [lsort [glob -nocomplain "$root/rc.d/rc$addtolevel.d/$var*"]] {
        regsub (.*/.) "$n" "" a
        set b [string range "$a" 0 1]
        set a [string range "$a" 2 end]
        .whereat.top.list insert end "$b - $a"
        }
if {[lsort [glob -nocomplain "$root/rc.d/rc$addtolevel.d/$var*"]] == ""} {
	.whereat.top.list insert end "** Runlevel Empty **"
	}

}




proc addthis {} {

global root addtolevel leftselect
global top number

set base "$leftselect"
set base [string trimright $base ".init"]

if {$top == "0"} {
        # puts "Adding S$number$leftselect to runlevel $addtolevel"
	exec ln -sf "$root/rc.d/init.d/$leftselect" \
		"$root/rc.d/rc$addtolevel.d/S$number$base"
} else {
        # puts "Adding K$number$leftselect to runlevel $addtolevel"
	exec ln -sf "$root/rc.d/init.d/$leftselect" \
		"$root/rc.d/rc$addtolevel.d/K$number$base"
}

loadlevel
readrc


}

proc editit {} {

global topstring top
global bottomstring
global runnumber
global leftstring levels
global addtolevel leftselect

findit

# If you select the available box only
if {$topstring == "" && $bottomstring == "" && $leftstring != ""} {

# puts "Can't pick that stuff"
whichlevel

# if you pick something in the runlevel boxes
} elseif {$leftstring == "" && ($topstring != "" || $bottomstring != "")} {

editlevel $runnumber

# if you didn't pick anything
} else {

whichlevel

}


}

proc whichlevel {} {

global topstring top
global bottomstring
global runnumber
global leftstring levels
global addtolevel leftselect

toplevel .which
focus .which
wm title .which "Which Runlevel?"
label .which.label -text "Which Runlevel?"
frame .which.box
pack .which.box -side top
frame .which.box.top
pack .which.box.top -side top
frame .which.box.bottom
pack .which.box.bottom -side top
label .which.box.top.label -text Start
checkbutton .which.box.top.button  -onvalue "0" \
	-offvalue "1" -variable top
label .which.box.bottom.label -text Stop
checkbutton .which.box.bottom.button -onvalue "1" \
	-offvalue "0" -variable top
pack .which.box.top.label .which.box.top.button -side left
pack .which.box.bottom.label .which.box.bottom.button -side left
pack .which.label -side top
frame .which.top
pack .which.top -side top
set runnumber [lindex "$levels" 0]
foreach n "$levels" {
	frame .which.top.$n
	pack .which.top.$n -side top
	label .which.top.$n.label -text "$n"
	checkbutton .which.top.$n.button -onvalue $n -variable runnumber
	pack .which.top.$n.label .which.top.$n.button -side left
}
button .which.done -text "Done" -command {destroy .which;editlevel $runnumber}
button .which.cancel -text "Cancel" -command {destroy .which}
pack .which.done .which.cancel -fill x -side top


}

proc editlevel {level} {

global topstring top
global bottomstring
global runnumber  var
global leftstring levels
global addtolevel leftselect change


toplevel .edit
wm title .edit "Edit Window"
focus .edit
frame .edit.top
pack .edit.top -side top
label .edit.top.label -text "Select an entry to change:"
listbox .edit.top.list -width 20 -height 14 -yscrollcommand ".edit.top.scroll set"
scrollbar .edit.top.scroll -command ".edit.top.list yview"
pack .edit.top.label -side top
pack .edit.top.list .edit.top.scroll -side left -fill y
if {$top == "0"} {
	set var "S"
} else {
	set var "K"
}
reloadedit $level
label .edit.label -text "Change selected item's number to:"
entry .edit.entry -width 4 -textvar change
pack .edit.label .edit.entry -side top
button .edit.apply -text "Apply" -command {changeit}
button .edit.done -text "Cancel" -command {destroy .edit}
pack .edit.apply .edit.done -side top -fill x
focus .edit.entry
}

proc reloadedit {level} {
global topstring top root
global bottomstring
global runnumber
global leftstring levels
global addtolevel leftselect var



foreach n [lsort [glob -nocomplain "$root/rc.d/rc$level.d/$var*"]] {
        regsub (.*/.) "$n" "" a
        set b [string range "$a" 0 1]
        set a [string range "$a" 2 end]
        .edit.top.list insert end "$b - $a"
        }
if {[lsort [glob -nocomplain "$root/rc.d/rc$level.d/$var*"]] == ""} {
	.edit.top.list insert end ""
	.edit.top.list insert end "    Nothing to edit."
	.edit.top.list insert end "      Press Cancel."
	}
}

proc changeit {} {

global topstring top root
global bottomstring
global runnumber var
global leftstring levels
global addtolevel leftselect change

set temp "[.edit.top.list curselection]"

if {$temp == ""} {
	# puts "nothing selected"
	tk_dialog .new "Nothing Selected" "You must select something to change." "" "0" "Ok"

} else {
	if {![regexp {^[0-9][0-9]$} "$change"]} {
		puts "error -- $change doesn't match regex"
		return
	}
	set line [.edit.top.list get $temp]
	# puts " changing $change to $line "
	set selectnum [string range $line 0 1]
	set selectwhat [string range $line 5 end]
	set select "$var$selectnum$selectwhat"
	# puts $select
	set base "$selectwhat"
	set base [string trimright $base ".init"]
	set linkto [file readlink "$root/rc.d/rc$runnumber.d/$var$selectnum$selectwhat"]
	exec rm -f "$root/rc.d/rc$runnumber.d/$var$selectnum$selectwhat"
	exec ln -sf "$linkto" "$root/rc.d/rc$runnumber.d/$var$change$base"
	destroy .edit

	
	
}

	
readrc



}


proc showit {text} {
global version

toplevel .showit
focus .showit
wm title .showit "Help"

frame .showit.top
text .showit.top.text -relief raised -bd 3 -yscrollcommand ".showit.top.scroll set" -font -*-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*
scrollbar .showit.top.scroll -command ".showit.top.text yview"
pack .showit.top.scroll -side right -fill y
pack .showit.top.text -side left
pack .showit.top -side top
button .showit.button -text "Done" -command {destroy .showit}
pack .showit.button -side top -fill both

set w .showit

focus $w

set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
        - [winfo vrootx [winfo parent $w]]]
set y [expr [winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
        - [winfo vrooty [winfo parent $w]]]
wm geom $w +$x+$y


.showit.top.text delete 1.0 end
set f [open $text]
while {![eof $f]} {
	.showit.top.text insert end [read $f 1000]
}
close $f

}

