#!/bin/sh #------------------------------------------------------------------------------ # /var/install/bin/update-systemfiles - update system files # # Copyright (c) 2002 Frank Meyer # # Creation: 31.07.2004 jed # Last Update: $Id$ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. #------------------------------------------------------------------------------ # exec 2>./updates-trace-$$.log # set -x pgmname=`basename $0` # include eislib . /var/install/include/eislib #------------------------------------------------------------------------------ # check if numeric value # input : $1 - value # return: 0 - numeric # 1 - no numeric #------------------------------------------------------------------------------ function is_numeric () { numeric=0 tmpstr=`echo "$1"|sed 's/[!0-9]*//g'` if [ "$tmpstr" != "" ] then # false numeric=1 fi return $numeric } #------------------------------------------------------------------------------ # check if text value # input : $1 - value # return: 0 - text # 1 - no text #------------------------------------------------------------------------------ function is_text () { text=0 tmpstr=`echo "$1"|sed 's/[!0-9_a-z.A-Z-]*//g'` if [ "$tmpstr" != "" ] then # false text=1 fi return $text } #------------------------------------------------------------------------------ # check if inittab-id value # input : $1 - value # return: 0 - id # 1 - no id #------------------------------------------------------------------------------ function is_inittab_id () { # The id is a unique sequence of 1-4 characters which identifies an entry # in inittab. id=0 len=`expr length "$1"` if [ $len -le 4 ] then tmpstr=`echo "$1"|sed 's/[!0-9a-zA-Z]*//g'` if [ "$tmpstr" != "" ] then # false id=1 fi else # length > 4 => false id=1 fi return $id } #------------------------------------------------------------------------------ # check if runlevel value # input : $1 - runlevel # $2 - action # return: 0 - runlevel # 1 - no runlevel #------------------------------------------------------------------------------ function is_inittab_runlevel () { # The runlevels field may contain multiple characters for different # runlevels. For example, 123 specifies that the process should be # started in runlevels 1, 2, and 3. The runlevels for 'ondemand' # entries may contain an A, B, or C. The runlevels field of 'sysinit', # 'boot', and 'bootwait' entries are ignored. runlevel=0 case "$2" in boot|bootwait|sysinit ) # runlevels will be ignored ;; ondemand ) # allowed runlevels: 0123456ABC tmpstr=`echo "$1"|sed 's/[!0-6ABC]*//g'` ;; * ) # allowed runlevels: 0123456 tmpstr=`echo "$1"|sed 's/[!0-6]*//g'` ;; esac if [ "$tmpstr" != "" ] then # false runlevel=1 fi return $runlevel } #------------------------------------------------------------------------------ # check if inittab process exists # input : $1 - value # return: 0 - process ok # 1 - process error #------------------------------------------------------------------------------ function check_inittab_process () { process=0 # remove leading + sign procstr=`echo "$1"|sed 's/^\+//g'` # check if file exists and is executable if [ ! -f $procstr -o ! -x $procstr ] then # false process=1 fi return $process } #------------------------------------------------------------------------------ # check services line # input : $1 - value # return: 0 - ok # 1 - error #------------------------------------------------------------------------------ function check_services_line () { rtc=0 # strip comments and replace slash line=`echo "$1"|sed 's/\#.*//g'|tr '/' ' '` if [ "$line" != "" ] then echo "$line"|grep "^#" /dev/null if [ $? -ne 0 ] then set $line idx=1 while [ $# -ne 0 -a $rtc -eq 0 ] do case $idx in 1 ) # service name if ! is_text $1 then print_debug -error "parameter $idx - NAME not allowed: $1" rtc=$idx fi ;; 2 ) # service port if ! is_numeric $1 then print_debug -error "parameter $idx - PORT not allowed: $1" rtc=$idx fi ;; 3 ) # service protocol if [ "$1" != "tcp" -a "$1" != "udp" -a "$1" != "ddp" ] then print_debug -error "parameter $idx - PROTOCOL not allowed: $1" rtc=$idx fi ;; * ) # service alias if ! is_text $1 then print_debug -error "parameter $idx - ALIAS not allowed: $1" rtc=$idx fi ;; esac # next parameter shift idx=`expr $idx + 1` done fi fi return $rtc } #------------------------------------------------------------------------------ # check inittab line # input : $1 - value # return: 0 - ok # 1 - error #------------------------------------------------------------------------------ function check_inittab_line () { # id:runlevels:action:process rtc=0 # strip comments and replace slash line=`echo "$1"|sed 's/\#.*//g'|tr ':' ' '` if [ "$line" != "" ] then echo "$line"|grep "^#" /dev/null if [ $? -ne 0 ] then set $line idx=1 while [ $# -ne 0 -a $rtc -eq 0 ] do case $idx in 1 ) # inittab id if ! is_inittab_id $1 then print_debug -error "parameter $idx - ID not allowed: $1" rtc=$idx fi ;; 2 ) # inittab runlevel if ! is_inittab_runlevel $1 $2 then print_debug -error "parameter $idx - RUNLEVEL not allowed: $1:$2" rtc=$idx fi ;; 3 ) # inittab action case "$1" in respawn|wait|once|boot|bootwait|off|ondemand|initdefault|sysinit|powerwait|powerfail|powerokwait|ctrlaltdel|kbrequest ) # ok ;; * ) # error print_debug -error "parameter $idx - ACTION not allowed: $1" rtc=$idx ;; esac ;; 4 ) # inittab process if ! check_inittab_process $1 then print_debug -error "parameter $idx - FILE not found or not executable: $1" rtc=$idx fi ;; * ) # ignore rest ;; esac # next parameter shift idx=`expr $idx + 1` done fi fi return $rtc } #------------------------------------------------------------------------------ # check services file # input : $1 - file name # output: 0 - ok # <>0 - error (line number) #------------------------------------------------------------------------------ function check_services_file () { rtc=0 f_name="$1" idx=1 while read LINE do if ! check_services_line "$LINE" then rtc=$idx break fi idx=`expr $idx + 1` done < $f_name return $rtc } #------------------------------------------------------------------------------ # check inittab file # input : $1 - file name # output: 0 - ok # <>0 - error (line number) #------------------------------------------------------------------------------ function check_inittab_file () { rtc=0 f_name="$1" idx=1 while read LINE do if ! check_inittab_line "$LINE" then rtc=$idx break fi idx=`expr $idx + 1` done < $f_name return $rtc } #------------------------------------------------------------------------------ # print file header # $1 - file name # $2 - program name #------------------------------------------------------------------------------ print_file_header () { f_name="$1" i_str="$2" echo '#----------------------------------------------------------------------' echo "# ${f_name} file generated by '${i_str}'" echo '#' echo "# Creation date: `date '+%d.%m.%Y'` `whoami`" echo '#' echo "# Do not edit this file directly, create a '${f_name}.package-name'" echo "# file and re-run the '${pgmname}' command to update." echo '#----------------------------------------------------------------------' } #------------------------------------------------------------------------------ # print help #------------------------------------------------------------------------------ print_help () { # show help mecho -info "Usage:" mecho -info " $pgmname [-debug] program-name" mecho mecho -info "It can be called under one the following names:" mecho -info " update-hosts.allow program-name -> update /etc/hosts.allow file." mecho -info " update-hosts.deny program-name -> update /etc/hosts.deny file." mecho -info " update-services program-name -> update /etc/services file." mecho -info " update-inittab program-name -> update /etc/inittab file." } #------------------------------------------------------------------------------ # print debug # input: $1 - output string #------------------------------------------------------------------------------ print_debug () { if [ "$debug" = "-debug" ] then mecho $@ fi } #------------------------------------------------------------------------------ # update hosts.allow or hosts.deny file # $1 - file name # $2 - program name #------------------------------------------------------------------------------ update_hosts_allow_deny_file () { fname="$1" istr="$2" ls ${fname} ${fname}.* >/dev/null 2>/dev/null if [ $? -eq 0 ] then # backup file /var/install/bin/backup-file -quiet $fname backup # create new file { # print header print_file_header "$fname" "$istr" for FN in `ls ${fname}.*|grep -v ".backup"` do cat $FN done } > ${fname} fi } #------------------------------------------------------------------------------ # update services file # $1 - file name # $2 - program name #------------------------------------------------------------------------------ update_services_file () { fname="$1" istr="$2" src_work=$fname-work-src dest_work=$fname-work-dest # check if files exist ls ${fname}.*|egrep -v ".backup" >/dev/null 2>/dev/null if [ $? -eq 0 ] then # backup file /var/install/bin/backup-file -quiet $fname backup # create working copy cp $fname.std $src_work # process all files filelist=`ls ${fname}.*|egrep -v -E ".backup|.std"` for FN in $filelist do if check_services_file $FN then # read files line by line while read line do # ignore comments echo $line|grep "^#" > /dev/null if [ $? -ne 0 ] then # get service name sname=`echo $line|cut -d" " -f1|sed 's/ //g'` if [ "$sname" != "" ] then # remove old entry if exist grep -v "^$sname" $src_work > $dest_work # take result as base for next compare mv $dest_work $src_work fi fi done < $FN else # error in file - skip it filelist=`echo $filelist|sed "s#$FN##g"` mecho -warn "warning: skipping file $FN because of syntax errors." fi done # create new file { # print header print_file_header "$fname" "$istr" # use standard file cat $src_work for FN in $filelist do cat $FN done } > ${fname} # remove working copy rm -f $src_work fi } #------------------------------------------------------------------------------ # update inittab file # $1 - file name # $2 - program name #------------------------------------------------------------------------------ update_inittab_file () { fname="$1" istr="$2" src_work=$fname-work-src dest_work=$fname-work-dest # check if files exist ls ${fname}.*|egrep -v ".backup" >/dev/null 2>/dev/null if [ $? -eq 0 ] then # backup file /var/install/bin/backup-file -quiet $fname backup # create working copy cp $fname.std $src_work # process all files filelist=`ls ${fname}.*|egrep -v -E ".backup|.std"` for FN in $filelist do if check_inittab_file $FN then # read files line by line while read line do # ignore comments echo $line|grep "^#" > /dev/null if [ $? -ne 0 ] then # get service name sname=`echo $line|cut -d":" -f1|sed 's/ //g'` if [ "$sname" != "" ] then # remove old entry if exist grep -v "^$sname" $src_work > $dest_work # take result as base for next compare mv $dest_work $src_work fi fi done < $FN else # error in file - skip it filelist=`echo $filelist|sed "s#$FN##g"` mecho -warn "warning: skipping file $FN because of syntax errors." fi done # create new file { # print header print_file_header "$fname" "$istr" # use standard file cat $src_work for FN in $filelist do cat $FN done } > ${fname} # remove working copy rm -f $src_work fi } #============================================================================== # main #============================================================================== if [ $# -eq 0 ] then # show help print_help else # update files while [ 1 ] do case "$1" in -debug) debug='-debug' shift ;; *) infostr="$1" break ;; esac done case $pgmname in update-hosts.allow|hosts.allow) update_hosts_allow_deny_file /etc/hosts.allow "$infostr" ;; update-hosts.deny|hosts.deny) update_hosts_allow_deny_file /etc/hosts.deny "$infostr" ;; update-services|services) update_services_file /etc/services "$infostr" ;; update-inittab|inittab) update_inittab_file /etc/inittab "$infostr" if [ "$debug" != "-debug" ] then /sbin/init q >/dev/null 2>/dev/null else mecho -warn "warning: debug mode enabled, inittab configuration will not be reloaded." fi ;; *) mecho -info 'program name not allowed, use one of the following names:' print_help esac fi #============================================================================== # end #==============================================================================