#!/usr/bin/rhswish -f

# WWW and FTP config tool
# (C) Copyright 1994 by Red Hat Software

### Move .tmp_* into place search on email

# Global Variables and initialization stuff
# File that holds the e-mail address we allow changes to
set wwwdir "/usr/lib/httpd/conf/httpd.conf"
# Command to get current email address out of the file is:
#	fgrep "ServerAdmin " httpd.conf | cut -d" " -f2
set wwwaddr {}
set httpd 0
set createlink 0
#set str ""

# File that holds the e-mail address we allow changes to
set ftpdir "/etc/ftpaccess"
# Command to get current email address out of the file is:
#  fgrep "email " ftpaccess | cut -d" " -f2
set ftpaddr {}
set anonftp 0
set prev_anonftp 0
set ftpusers "/etc/ftpusers"
set ftphome ""

if {[catch set env(CONTROL_PANEL_LIB_DIR)] != 0} {
   set env(CONTROL_PANEL_LIB_DIR) /usr/lib/rhs/control-panel
}

if {[catch {source $env(CONTROL_PANEL_LIB_DIR)/dialog.tcl}] != 0} {
    puts "Couldn't load dialog.tcl"
    puts "Start from control-panel or set environment variable"
    puts "CONTROL_PANEL_LIB_DIR to the control-panel library dir."
    puts "(normally this is /usr/lib/rhs/control-panel)"
    exit 0
}

if {[catch {source $env(CONTROL_PANEL_LIB_DIR)/balloon-help.tcl}] != 0} {
    puts "Couldn't load balloon-help.tcl"
    puts "Start from control-panel or set environment variable"
    puts "CONTROL_PANEL_LIB_DIR to the control-panel library dir."
    puts "(normally this is /usr/lib/rhs/control-panel)"
    exit 0
}

# Create a menu for this new window
proc createmenu {} {
   global balloon_help
   frame .menu -relief raised -bd 2
   pack .menu -side top -fill x

   # create the main menu
   menubutton .menu.wwwcfg -text "File" -menu .menu.wwwcfg.menu
   menubutton .menu.help -text "Help" -menu .menu.help.menu
 
   pack .menu.wwwcfg -side left
   pack .menu.help -side right
   
   # Add some elements to the menu
   menu .menu.wwwcfg.menu
   .menu.wwwcfg.menu add command -label "Update FTP Passwd + Group" -command fixftpetcfiles
   .menu.wwwcfg.menu add separator
   .menu.wwwcfg.menu add command -label "Quit" -command menu_quit

   # Add to the help menu
   menu .menu.help.menu
   .menu.help.menu add checkbutton -label "Balloon Help" -variable balloon_help

   tk_menuBar .menu .menu.wwwcfg .menu.help
}

# Create a new canvas to draw on, the other one is still around if
# we came off of it
proc createmainwindow {} {
   # Create a menu
   createmenu

   # Create 2 frames, one for ftp one for WWW
   createwwwframe
   createftpframe

   button .save -text Apply -command doit
   tixAddBalloon .save Button "Select this to apply the changes you have made in the addresses or configuration of the WWW server and Anonymous FTP server.  No changes will be made unless you select this before Exiting."
   pack .save -side top -fill x -padx 2m -pady 2m

   # Give this whole window thng a title
   wm title . "RHS WWW and FTP Manager"

   updatewwwentry
   updateftpentry
}

proc readwwwaddr {} {
   global wwwdir wwwaddr httpd str

   if {[catch {set f [open $wwwdir r]}] != 0} {
      rhs_error_dialog "Couldn't read from $wwwdir."
      return
   }

   catch {exec /usr/bin/fgrep "ServerAdmin " $wwwdir} wwwaddr

   close $f

   # Now chop off the ServerAdmin off wwwaddr
    set wwwaddr [lindex $wwwaddr 1]
}

proc checkhttpd {} {
   global httpd

   # Now try and see if httpd is running?
   catch {exec /sbin/pidof httpd} str

   set str [string trim $str]
   if {$str > 0} {
      set httpd 1
   } else {
      set httpd 0
   }
}

proc readftpaddr {} {
   global ftpdir ftpaddr anonftp ftpusers

   if {[catch {set f [open $ftpdir r]}] != 0} {
      rhs_error_dialog "Couldn't read from $ftpdir."
      return
   }

   catch {exec /usr/bin/fgrep "email " $ftpdir} ftpaddr

   close $f

   # Now chop off the email from the ftpaddr
   set ftpaddr [lindex $ftpaddr 1]
}

proc checkanonftp {} {
   global anonftp ftpusers

   # Now try and see if anonftp is configured?
   catch {exec /usr/bin/fgrep anonymous $ftpusers} str

   set str [string trim $str]
   # If anonymous is there ftp is off
   if {$str == "anonymous"} {
      set anonftp 0
   } else {
      set anonftp 1
   }
}

proc updatewwwentry {} {
   global .www wwwaddr

   # Delete the name in the www address field
   .www.www1.e1 delete 0 end

   .www.www1.e1 insert 0 $wwwaddr
}

proc updateftpentry {} {
   global .ftp ftpaddr

   # Delete whatever is in the place where the ftp email addr goes
   .ftp.ftp1.e1 delete 0 end

   .ftp.ftp1.e1 insert 0 $ftpaddr
}

proc createwwwframe {} {
   global wwwaddr httpd

   # Whole frame
   frame .www -relief groove -bd 2
   pack .www -side top -fill both -expand 1 -padx 2m -pady 2m

   label .www.title -text "WWW Configuration"

   # mail to frame
   frame .www.www1
   label .www.www1.lab -text "Send mail to:"
   entry .www.www1.e1 -width 30 -relief sunken
   tixAddBalloon .www.www1.e1 Entry "Change the user who receives mail if there are problems with the WWW server."
   .www.www1.e1 insert 0 $wwwaddr
   pack .www.www1.lab .www.www1.e1 -side left -padx 10 -pady 10 -in .www.www1

   # Button frame
   frame .www.www2
   radiobutton .www.www2.b1 -text "Httpd On" -variable httpd -value 1
   tixAddBalloon .www.www2.b1 Button "Activates the WWW daemon on your system and updates your startup files so that it will be activated when you boot."
   radiobutton .www.www2.b2 -text "Httpd Off" -variable httpd -value 0
   tixAddBalloon .www.www2.b2 Button "Kills the WWW daemon and modifies your system startup files so that it will not be started when you boot."
   pack .www.www2.b1 .www.www2.b2  -side left -padx 10 -pady 10 -in .www.www2

   pack .www.title .www.www1 .www.www2 -side top -in .www
}


proc createftpframe {} {
   global ftpaddr anonftp

   # Whole frame
   frame .ftp -relief groove -bd 2
   pack .ftp -side top -fill both -expand 1 -padx 2m -pady 2m

   label .ftp.title -text "FTP Configuration"

   # mail to frame
   frame .ftp.ftp1
   label .ftp.ftp1.lab -text "Send mail to:"
   entry .ftp.ftp1.e1 -width 30 -relief sunken
   tixAddBalloon .ftp.ftp1.e1 Entry "This is the address of the FTP archive maintainer."
   .ftp.ftp1.e1 insert 0 $ftpaddr
   pack .ftp.ftp1.lab .ftp.ftp1.e1 -side left -padx 10 -pady 10 -in .ftp.ftp1

   # Button frame
   frame .ftp.ftp2
   radiobutton .ftp.ftp2.b1 -text "Anonymous FTP On" -variable anonftp -value 1
   tixAddBalloon .ftp.ftp2.b1 Button "Sets up Anonymous FTP access to your system."
radiobutton .ftp.ftp2.b2 -text "Anonymous FTP Off" -variable anonftp -value 0
   tixAddBalloon .ftp.ftp2.b2 Button "Disables Anonymous FTP access to your system"
   pack .ftp.ftp2.b1 .ftp.ftp2.b2  -side left -padx 10 -pady 10 -in .ftp.ftp2

   pack .ftp.title .ftp.ftp1 .ftp.ftp2 -side top -in .ftp
}

# This reads values from the dlg box and does what it says to do!
proc doit {} {
   global wwwaddr ftpaddr httpd anonftp

   # Get the values out of our two entry box things!
   set wwwaddr [.www.www1.e1 get]
   set ftpaddr [.ftp.ftp1.e1 get]

#   rhs_info_dialog "httpd is $httpd anonftp is $anonftp wwwaddr is $wwwaddr  ftpaddr is $ftpaddr"

   modifyemail

   if {$httpd == 1} {
      httpdon
   } else {
      httpdoff
   }

   if {$anonftp == 1} {
      anonftpon
   } else {
      anonftpoff
   }
}

proc modifyemail {} {
   global wwwaddr ftpaddr wwwdir ftpdir

   # Open wwwdir read till get to ServerAdmin and write to tmp file
   if {[catch {set f [open $wwwdir r]}] != 0} {
      rhs_error_dialog "Couldn't read from $wwwdir."
      return
   }

   if {[catch {set t [open /tmp/.tmp_www_email w]}] != 0} {
      rhs_error_dialog "Couldn't write to /tmp/.tmp_www_email"
      return
   }

   # When line begins with ServerAdmin skip it
   while {[gets $f line] >= 0} {
#rhs_info_dialog "line is $line"
      # write to tmp file
      if {[lindex $line 0] != "ServerAdmin"} {
         puts $t $line
      } else {
        # Write your own line ServerAdmin $wwwaddr
        puts $t "ServerAdmin $wwwaddr"
      }
   }

   # Close file
   close $f
   close $t

   # move tmp file in place
   catch {exec /bin/mv /tmp/.tmp_www_email $wwwdir}


   # Open ftpdir read till get to email and write to tmp file
   if {[catch {set f [open $ftpdir r]}] != 0} {
      rhs_error_dialog "Couldn't read to $ftpdir."
      return
   }

   if {[catch {set t [open /tmp/.tmp_ftp_email w]}] != 0} {
      rhs_error_dialog "Couldn't write to /tmp/.tmp_ftp_email"
      return
   }

   # When line begins with email skip it
   while {[gets $f line] >= 0} {
      # write to tmp file
      if {[lindex $line 0] != "email"} {
         puts $t $line
      } else {
        # Write your own line email $ftpaddr
        puts $t "email $ftpaddr"
      }
   }

   # Close file
   close $f
   close $t

   # move tmp file in place
   catch {exec /bin/mv /tmp/.tmp_ftp_email $ftpdir}
}

proc deactivatehttpd {} {
   # Get the pid of running process
   catch {exec /sbin/pidof httpd} str

   # First call /etc/rc.d/init.d/http stop
   # Then use kill to get rid of additional httpd, if any

   # Kill the process
   set str [string trim $str]
   if {$str > 0} {
      catch {exec /bin/kill -9 $str}
   }

   # Unlink links in etc
   catch {exec /bin/rm -f /etc/rc.d/rc3.d/S91httpd}
   catch {exec /bin/rm -f /etc/rc.d/rc5.d/S91httpd}
}

proc checklinks {} {
   global createlink

   # Determine if /etc/rc.d/initd/httpd is linked to /etc/rc.d/rc3.d/S91httpd
   set info [file exists /etc/rc.d/rc3.d/S91httpd]
   if {$info == 1} {
      set info [file type /etc/rc.d/rc3.d/S91httpd]
      if { $info == "link" } {
         set createlink 0
      } else {
         # Create the link
         set createlink 1
      }
   } else {
      # Create the link
         set createlink 1
   }
}

proc activatehttpd {} {
    global createlink

    # Simply run /etc/rc.d/init.d/httpd start

    # Run daemon
    catch {exec /usr/sbin/httpd &}
#    catch {exec sh /etc/rc.d/init.d/httpd start}

    # Check for links
    checklinks

    # Establish links in etc
    if {$createlink == "1"} {
	catch {exec /bin/ln -s ../init.d/httpd /etc/rc.d/rc3.d/S91httpd}
	catch {exec /bin/ln -s ../init.d/httpd /etc/rc.d/rc5.d/S91httpd}
    }
}

proc httpdon {} {
   global httpd createlink

   # Get the pid of running process
   catch {exec /sbin/pidof httpd} str
   if {$str > 0} {
      set res [rhs_dialog .exit "Already Active" "Deactivate and then reactivate server?" question 1 "Yes, Deactivate" "No Don't"]

      if {$res == "0"} {
         # Yes was pressed
         deactivatehttpd
         activatehttpd
         checkhttpd
      } else {
         # Make sure links are setup
         checklinks
         if {$createlink == "1"} {
            # Establish links in etc
            if {$createlink == "1"} {
               catch {exec /bin/ln -s ../init.d/httpd /etc/rc.d/rc3.d/S91httpd}
               catch {exec /bin/ln -s ../init.d/httpd /etc/rc.d/rc5.d/S91httpd}
            }
         }
         checkhttpd
      } 
   } else {	# Not running
      activatehttpd
      checkhttpd
   }
}

proc httpdoff {} {
   deactivatehttpd
   checkhttpd
}

proc anonftpon {} {
   global ftpusers anonftp

   # Check to see if in file already
   catch {exec /usr/bin/fgrep anonymous $ftpusers} str
   
   set str [string trim $str]
   if {$str == "anonymous"} {
      # Delete it 
      # Open file for reading and tmp file for writing
      if {[catch {set f [open $ftpusers r]}] != 0} {
        rhs_error_dialog "Couldn't read to $ftpusers."
        return
      }
      if {[catch {set t [open /tmp/.ftp_tmp w]}] != 0} {
        rhs_error_dialog "Couldn't write to /tmp/.ftp_tmp."
        return
      }
      # REad a line from ftpusers file if != anonymous
      while {[gets $f line] >= 0} {
         # write to tmp file
         if {$line != "anonymous"} {
            puts $t $line
         }
      }

      # close files
      close $f
      close $t

      # mv tmp file to ftpusers
      catch {exec mv -f /tmp/.ftp_tmp /etc/ftpusers}
   } else {
      # Do nothing to the file
   }

   # If it's not there create it
   createftphier

   # Copy the files to the ftp hier
   copyftpfiles

   # Set all permissions
   setftpprivs
}

proc copyftpfiles {} {
   global ftphome

   # to bin
   catch {exec /bin/cp -f /bin/gzip $ftphome/bin}
   catch {exec /bin/cp -f /bin/ls $ftphome/bin}
   catch {exec /bin/cp -f /bin/tar $ftphome/bin}

   # to etc
   catch {exec /bin/cp -f /etc/passwd $ftphome/etc}
   catch {exec /bin/cp -f /etc/group $ftphome/etc}
   
   fixftpetcfiles

   # to lib
   catch {exec /bin/cp -f /lib/ld.so $ftphome/lib}
   catch {exec /bin/cp -R -a -f /lib $ftphome}

   catch {exec /bin/rm -f $ftphome/lib/cpp}
}

proc fixftpetcfiles {} {
   global ftphome

   # Modify the passwd and group files

   # Open ftphome/etc/group 
   if {[catch {set f [open $ftphome/etc/group r]}] != 0} {
      rhs_error_dialog "Couldn't read to $ftphome/etc/group."
      return
   }

   if {[catch {set t [open /tmp/.tmp_ftp_group w]}] != 0} {
      rhs_error_dialog "Couldn't write to /tmp/.tmp_ftp_group"
      return
   }

   # Modify here!
   while {[gets $f line] >= 0} {
#     ($group, $blank, $gid, $list) = split(/:/);
      set line [split $line :]
      puts $t "[lindex $line 0]::[lindex $line 2]:"
   }

   # Close file
   close $f
   close $t

   # move tmp file in place
   catch {exec /bin/mv /tmp/.tmp_ftp_group $ftphome/etc/group}


   # Open ftphome/etc/passwd 
   if {[catch {set f [open $ftphome/etc/passwd r]}] != 0} {
      rhs_error_dialog "Couldn't read to $ftphome/etc/passwd."
      return
   }

   if {[catch {set t [open /tmp/.tmp_ftp_passwd w]}] != 0} {
      rhs_error_dialog "Couldn't write to /tmp/.tmp_ftp_passwd"
      return
   }

   # Modify here!
   while {[gets $f line] >= 0} {
#    ($login, $passwd, $uid, $gid, $gcos, $home, $shell) = split(/:/);
      set line [split $line :]
      puts $t "[lindex $line 0]:*:[lindex $line 2]:[lindex $line 3]:::"
   }

   # Close file
   close $f
   close $t

   # move tmp file in place
   catch {exec /bin/mv /tmp/.tmp_ftp_passwd $ftphome/etc/passwd}

   # Reset privs just in case!
   catch {exec /bin/chown root.root $ftphome/etc/passwd}
   catch {exec /bin/chown root.root $ftphome/etc/group}
   catch {exec /bin/chmod 0644 $ftphome/etc/passwd}
   catch {exec /bin/chmod 0644 $ftphome/etc/group}
}

proc createftphier {} {
   global ftphome

   set info [file exists $ftphome]
   if {$info == "0"} {
      catch {exec /bin/mkdir $ftphome}
   }

   set info [file exists $ftphome/bin]
   if {$info == "0"} {
      catch {exec /bin/mkdir $ftphome/bin}
   }

   set info [file exists $ftphome/etc]
   if {$info == "0"} {
      catch {exec /bin/mkdir $ftphome/etc}
   }

   set info [file exists $ftphome/lib]
   if {$info == "0"} {
      catch {exec /bin/mkdir $ftphome/lib}
   }

   set info [file exists $ftphome/pub]
   if {$info == "0"} {
      catch {exec /bin/mkdir $ftphome/pub}
   }

   set info [file exists $ftphome/pub/Incoming]
   if {$info == "0"} {
      catch {exec /bin/mkdir $ftphome/pub/Incoming}
   }
}

proc setftpprivs {} {
   global ftphome

   # change ownership and permissions on dir's always just incase
   catch {exec /bin/chown root.root $ftphome}
   catch {exec /bin/chmod 02755 $ftphome}

   catch {exec /bin/chown root.root $ftphome/bin}
   catch {exec /bin/chmod 0755 $ftphome/bin}

   catch {exec /bin/chown root.root $ftphome/etc}
   catch {exec /bin/chmod 0755 $ftphome/etc}

   catch {exec /bin/chown root.root $ftphome/lib}
   catch {exec /bin/chmod 0755 $ftphome/lib}

   catch {exec /bin/chown root.root $ftphome/pub}
   catch {exec /bin/chmod 0755 $ftphome/pub}

   catch {exec /bin/chown root.root $ftphome/pub/Incoming}
   catch {exec /bin/chmod 02755 $ftphome/pub/Incoming}

   # Same for files in them.
   # Bin dir
   catch {exec /bin/chown root.root $ftphome/bin/gzip}
   catch {exec /bin/chown root.root $ftphome/bin/ls}
   catch {exec /bin/chown root.root $ftphome/bin/tar}
   catch {exec /bin/chmod 0111 $ftphome/bin/gzip}
   catch {exec /bin/chmod 0111 $ftphome/bin/ls}
   catch {exec /bin/chmod 0111 $ftphome/bin/tar}

   # etc dir
   catch {exec /bin/chown root.root $ftphome/etc/passwd}
   catch {exec /bin/chown root.root $ftphome/etc/group}
   catch {exec /bin/chmod 0644 $ftphome/etc/passwd}
   catch {exec /bin/chmod 0644 $ftphome/etc/group}
   
   # lib dir
   catch {exec /bin/chown root.root $ftphome/lib/ld.so}
   catch {exec /bin/chmod 0755 $ftphome/lib/ld.so}
}

proc anonftpoff {} {
   global ftpusers anonftp

    # Just go and append anonymous to file
   catch {exec /usr/bin/fgrep anonymous $ftpusers} str

   set str [string trim $str]
   if {$str == "anonymous"} {
      # Do nothing cause ftp already off anonymous already in the file
      checkanonftp
      return
   } else {
      # Append anonymous to the file $ftpusers
      if {[catch {set f [open $ftpusers a]}] != 0} {
        rhs_error_dialog "Couldn't write to $ftpusers."
        return
      }
      puts $f anonymous
      close $f
      checkanonftp
   }
}

# Check we have privs on the files we need to r/w to
proc checkfiles {} {
   global ftphome

   set nowww 0
   set noftp 0

   # For WWW
   # Is /etc/rc.d/init.d/httpd readable by person running the script?
   set info [file readable /etc/rc.d/init.d/httpd]
   if { $info == 0 } {
      set nowww 1
   }

   # Is /etc/rc.d/rc3.d a directory and writable by person running the script?
   set info [file isdirectory /etc/rc.d/rc3.d]
   if { $info == 0 } {
      rhs_error_dialog "/etc/rc.d/rc3.d should be a directory!"
      set nowww 1
   }

   set info [file writable /etc/rc.d/rc3.d]
   if { $info == 0 } {
      set nowww 1
   }
   
   # Is /usr/sbin/httpd executable by person running the script?
   set info [file executable /usr/sbin/httpd]
   if { $info == 0 } {
      set nowww 1
   }


   if {$nowww == 1} {
      rhs_info_dialog "You do not have permission to activate or deactivate the WWW daemon!"
   }

   # Info is an array
#   file stat /etc/rc.d/init.d/httpd info
#   rhs_error_dialog "$info(mode)"
#   rhs_error_dialog "$info(uid)"
#   rhs_error_dialog "$info(size)"

   # For anonymous ftp
   # Need read and possible write permission to /etc/ftpusers
   set info [file readable /etc/ftpusers]
   if {$info == 0} {
      set noftp 1
   }

   set info [file writable /etc/ftpusers]
   if {$info == 0} {
      set noftp 1
   }

   # Need write privs to /tmp for tmp files
   set info [file writable /tmp]
   if {$info == 0} {
      set noftp 1
   }

   # Need read privs on the passwd file to find ftp's home dir
   set info [file readable /etc/passwd]
   if {$info == 0} {
      set noftp 1
   }

   getftphomedir

   # Need read privs to copy the following files...
   set info [file readable /bin/gzip]
   if {$info == 0} {
      set noftp 1
   }
   set info [file readable /bin/ls]
   if {$info == 0} {
      set noftp 1
   }
   set info [file readable /bin/tar]
   if {$info == 0} {
      set noftp 1
   }
   set info [file readable /etc/group]
   if {$info == 0} {
      set noftp 1
   }
   set info [file readable /lib/ld.so]
   if {$info == 0} {
      set noftp 1
   }
#   set info [file readable /lib/libc*]
#   if {$info == 0} {
#      set noftp 1
#   }

   if {$noftp == 1} {
      rhs_info_dialog "You do not have permission to activate or deactivate Anonymous FTP!"
   }

   if {$nowww == 1} {
      if {$noftp == 1} {
         exit 1
      }
   }
}

proc getftphomedir {} {
   global ftphome

   # Does the ftp user exist in the passwd file?
   catch {exec /usr/bin/fgrep ftp /etc/passwd} tmphome

   set listhome [split $tmphome :]
#   rhs_error_dialog "$listhome"

   set ftphome [lindex $listhome 5]
   rhs_info_dialog "Anonymous ftp access will be setup under $ftphome"
}

proc initialize {} {
   checkfiles
   readwwwaddr
   readftpaddr
   checkhttpd
   checkanonftp
   createmainwindow
}

proc menu_quit {} {
   exit 0;
}
### MAIN ####
initialize
