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

set programname "Printing System Switcher"
set progname "print-switch"
set version "0.4"
set verdate " 19 May 2005"
set authors "M.Shino"

proc debug { msg } {
	global debug progname
	if $debug {puts "$progname:debug:$msg"}
}

proc status { msg } {
	global mwn statusline
	$statusline configure -text "$msg"
	update
	if { "$msg" != "" } { debug $msg }
}

proc warning { msg } {
  global mwn progname
  return [tk_messageBox -type {yesno} -default {yes} -icon {warning} \
	-message $msg -parent {.} -title "$progname warning"]
}

proc error { msg } {
	global mwn progname
	tk_messageBox -icon error -message $msg -parent . -title "$progname error"
}


set debug 0
if  [ info exists  env(DEBUG) ] { set debug $env(DEBUG) }
set arg1 [lindex $argv 0]
switch -- $arg1 {
    --debug -
    -debug  { set debug 1 }
}


set credit "$programname $version\n$verdate by $authors"
set alternatives "/sbin/update-alternatives"
set printsystems {cups lprng}
set rcname(cups) cups
set rcname(lprng) lpd
set dispname(cups) CUPS
set dispname(lprng) LPRng
set printcap /etc/printcap
set printcap_save "${printcap}.save"

proc main_window { w } {
    global env mwn statusline
    global progname programname credit printsystems dispname
    global printsystem printsystem_before
    set mwn "$w"
    wm title $mwn. $progname
    # title
    pack [label $mwn.l1 -text $programname -width 32] -pady 4
    # line
    frame $mwn.f0 -height 2 -borderwidth 2 -relief sunken
    pack $mwn.f0 -fill x
    # radio button
    foreach i $printsystems {
	pack [radiobutton $mwn.c_$i -text $dispname($i) -variable printsystem -value $i] -pady 4
    }
   # buttons
   frame $mwn.f1
   pack [button $mwn.f1.b1 -text "Excute" -command set_alternatives] \
        [button $mwn.f1.b2 -text "Cancel" -command main_exit] \
	-side left -padx 20 -pady 4 
   pack $mwn.f1
   # status
   frame $mwn.f2 -borderwidth 2 -relief groove -background white
   set statusline $mwn.f2.m
   pack [message $statusline -width 200 -background white]
   pack $mwn.f2 -fill x -padx 4 -pady 2

   # Initialize
    update_radio
    status $credit
    daemon_status
    set printsystem_before $printsystem
}

proc update_radio {} {
    global mwn alternatives printsystems printsystem listed
    if { [ file executable $alternatives ] == 0 } {
	error "package 'alternatives' may not be installed"
	main_exit
    }
    set command "$alternatives --config print </dev/null 2>/dev/null || :"
    set lines [exec sh -c $command]
    debug "$lines"
    set num 0
    foreach i $printsystems {
	set listed($i) 0
    }
    foreach line [split $lines \n] {
      foreach i $printsystems {
	if [string match "*${i}*" "$line"] {
		incr num
		set listed($i) $num
	}
	if [string match "\\**${i}" "$line"] { $mwn.c_$i select }
      }
    }
    if { $num == 0 } {
	error "Print system seems not to be handled with 'alternatives'"
    } elseif { $num == 1 } {
	foreach i $printsystems {
	    if $listed($i) {
		$mwn.c_$i select
	    } else {
		$mwn.c_$i configure -state disabled
	    }
	}
    }
    foreach i $printsystems {
	debug "listed($i) = $listed($i)"
    }
    debug "selected print system is $printsystem"
}

proc set_alternatives {} {
    global mwn alternatives printsystems rcname listed
    global printsystem printsystem_before
    set levels {2345}
    if [exec id -u] {
	error {Only root user can do it.}
	return
    }
    if { $printsystem != $printsystem_before } {
        if { $printsystem_before == {lprng} } { save_printcap }
        if { $printsystem == {lprng} } { restore_printcap }
    }
    set command "echo $listed($printsystem) |$alternatives --config print 2>/dev/null || :"
    set lines [exec sh -c $command]
    debug "$lines"
    foreach i $printsystems {
	set command "/sbin/chkconfig --level $levels $rcname($i) off"
	debug $command
	if [catch {exec sh -c "$command"} msg] {
		error $msg
	}
	set command "/sbin/service $rcname($i) stop || :"
	catch {exec sh -c "$command"} msg
	debug "$command\n$msg"
    }
	set command "/sbin/chkconfig --level $levels $rcname($printsystem) on"
	debug $command
	if [catch {exec sh -c "$command"} msg] {
		error $msg
	}
   set command "BOOTUP=serial /sbin/service $rcname($printsystem) start"
	debug $command
	if [catch {exec sh -c "$command"} msg] {
		error $msg
	} else {
		status $msg
   	}
	update_radio
  daemon_status
  after 5000
  startup_config
}

proc save_printcap {} {
    global printcap printcap_save
    file copy -force -- $printcap $printcap_save
    status "saved $printcap_save"
}

proc restore_printcap {} {
    global printcap printcap_save
    if { ! [file exists $printcap_save] } return
    if { [warning "Saved printcap found.\nRestore it?"] == {yes} } {
	file copy -force -- $printcap_save $printcap
        status "restored $printcap"
    }
}

proc daemon_status {} {
    global mwn alternatives printsystems rcname printsystem listed
    foreach i $printsystems {
	set command "/sbin/chkconfig --list $rcname($i)"
	debug $command
	if [catch {exec sh -c "$command"} msg] {
		debug "error $msg"
	} else {
		debug "status $msg"
	}
   set command "BOOTUP=serial /sbin/service $rcname($i) status"
	debug $command
	if [catch {exec sh -c "$command"} msg] {
		debug "error $msg"
	} else {
		debug "status $msg"
   	}
    }
}

proc startup_config {} {
    global mwn
    global printsystem printsystem_before
    set command {}
    debug "$printsystem_before --> $printsystem"
	if { "$printsystem" != "$printsystem_before" } {
	   switch -- $printsystem {
		{lprng} { set command {/usr/sbin/printtool} }
		{cups}	{ set command {/usr/bin/gnome-cups-manager} }
	   }
	   if [file executable "$command"] {
	     set msg "Print system is changed. Start up configuration? ($command)"
	     if { [warning $msg] != {yes} } {
		set command {}
	     }
	   }
	}
	if { "$command" != {} } {
	    status "Starting up $command"
	    set pid [exec $command &]
	    after 1000
	    set cmd "ps x | grep '^\[^1-9\]*$pid\[^0-9\]'"
	    if [catch {set line [exec sh -c "$cmd"]} msg] {
	        debug "PID=$pid stopped"
		status "$command failed"
		error "$command failed.
Hint: X server may refuse local connection. Try; 
xhost +local:"
	    } else {
	    	status {}
	        debug "PID=$pid is running"
	    }
	}
	main_exit
}

proc main_exit {} {
    global mwn
	if { "$mwn" == "" } { destroy . } else { destroy $mwn }
}


proc init {} {
    global  alternatives
    if { ! [ file excutable $alternatives ] } {
	error "package 'alternatives' may not installed"
	main_exit
    }
}

set printsystem_before {}
main_window {}


