#!/usr/bin/sh #---------------------------------------------------------------------------- # /var/install/bin/update-systemfiles - update system files # # Creation: 2004-07-31 jed # Last Update: $Id$ # # Copyright (c) 2001-@@YEAR@@ the eisfair team, team(at)eisfair(dot)org # # 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. #---------------------------------------------------------------------------- pgmname=$(basename $0) # include eislib . /var/install/include/eislib #exec 2>./updates-trace-$$.log #set -x #---------------------------------------------------------------------------- # check if numeric value # input : $1 - value # return: 0 - numeric # 1 - no numeric #---------------------------------------------------------------------------- is_numeric() { echo "$1" | grep -q '^[0-9]*$' } #---------------------------------------------------------------------------- # check if text value # input : $1 - value # return: 0 - text # 1 - no text #---------------------------------------------------------------------------- is_text() { # used for service and service aliases # space and tab are not allowed # a-z, 0-9, and hyphen (-) would seem a sensible choice. echo "$1" | grep -q '^[[:alnum:]_.-]*$' } #---------------------------------------------------------------------------- # check service port and protocol # input : $1 - value port/protocol # return: 0 - values ok # 1 - values error #---------------------------------------------------------------------------- check_port_and_protocol() { values=0 oldifs="$IFS" IFS='/' set $1 IFS="$oldifs" # service port if ! is_numeric $1 then print_debug --error "parameter $idx - PORT not allowed: $1" values=1 fi # service protocol if [ "$2" != "tcp" -a "$2" != "udp" -a "$2" != "ddp" -a "$2" != "sctp" ] then print_debug --error "parameter $idx - PROTOCOL not allowed: $2" values=1 fi return $values } #---------------------------------------------------------------------------- # check services line # input : $1 - value # return: 0 - ok # 1 - error #---------------------------------------------------------------------------- check_services_line() { check_services_line_rtc=0 # strip comments line=$(echo "$1"|sed 's/\#.*//g') if [ "$line" != "" ] then echo "$line"|grep -q "^#" if [ $? -ne 0 ] then set $line idx=1 while [ $# -ne 0 -a $check_services_line_rtc -eq 0 ] do case $idx in 1 ) # service name if ! is_text $1 then print_debug --error "parameter $idx - NAME not allowed: $1" check_services_line_rtc=$idx fi ;; 2 ) # service port and protocol if ! check_port_and_protocol $1 then check_services_line_rtc=$idx fi ;; * ) # service alias if ! is_text $1 then print_debug --error "parameter $idx - ALIAS not allowed: $1" check_services_line_rtc=$idx fi ;; esac # next parameter shift idx=$(($idx + 1)) done fi fi return $check_services_line_rtc } #---------------------------------------------------------------------------- # check services file # input : $1 - file name # output: 0 - ok # <>0 - error (line number) #---------------------------------------------------------------------------- check_services_file() { check_services_file_rtc=0 f_name="$1" idx=1 while read LINE do if ! check_services_line "$LINE" then check_services_file_rtc=$idx # no break, check whole file #break fi idx=$(($idx + 1)) done < $f_name return $check_services_file_rtc } #---------------------------------------------------------------------------- # print file header # $1 - file name # $2 - package name #---------------------------------------------------------------------------- print_file_header() { f_name="$1" i_str="$2" echo '#----------------------------------------------------------------------' echo "# ${f_name} file generated by '${i_str}'" echo '#' echo "# Creation date: ${EISDATE} `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 "Usage:" mecho " $pgmname cannot be called directly. Please use one of the following names:" mecho mecho " update-at.allow [-debug] package-name -> update /etc/at.allow file." mecho " update-at.deny [-debug] package-name -> update /etc/at.deny file." mecho " update-hosts.allow [-debug] package-name -> update /etc/hosts.allow file." mecho " update-hosts.deny [-debug] package-name -> update /etc/hosts.deny file." mecho " update-services [-debug] package-name -> update /etc/services file." mecho " update-nsswitch [-debug] package-name -> update /etc/nsswitch.conf file." } #---------------------------------------------------------------------------- # print debug # input: $1 - output string #---------------------------------------------------------------------------- print_debug() { if [ "$debug" = "-debug" ] then mecho $@ fi } #---------------------------------------------------------------------------- # update at.allow or at.deny file # $1 - file name # $2 - package name #---------------------------------------------------------------------------- update_at_allow_deny_file() { fname="${1}" fname_dir=$(dirname ${fname}) fname_base=$(basename ${fname}) fname_tmp=$fname.$$ istr="${2}" find ${fname_dir} -maxdepth 1 -type f -name "${fname_base}.*" | grep -qvE ".backup|.std|~" if [ ${?} -eq 0 ] then # backup file /var/install/bin/backup-file --quiet ${fname} backup # create fname_tmp with same file access permission like fname if [ -f ${fname} ] then cp -p ${fname} ${fname_tmp} else # create new file and set initial file permissions > ${fname_tmp} chmod 0640 ${fname_tmp} chown root:at ${fname_tmp} fi # create new file (temporary one) { # print header print_file_header "${fname}" "${istr}" for FN in $(ls ${fname}.*|grep -vE ".backup|~|.$$") do cat ${FN} done } > ${fname_tmp} # copy file, preserve access permissions cp -p ${fname_tmp} ${fname} rm -f ${fname_tmp} else # create stadard entry if [ -f ${fname}.std ] then # backup file /var/install/bin/backup-file --quiet ${fname} backup { # print header print_file_header "${fname}" "${istr}" cat ${fname}.std } > ${fname} chmod 0640 ${fname} chown root:at ${fname} fi fi } #---------------------------------------------------------------------------- # update hosts.allow or hosts.deny file # $1 - file name # $2 - package name #---------------------------------------------------------------------------- update_hosts_allow_deny_file() { fname="$1" fname_dir=$(dirname ${fname}) fname_base=$(basename ${fname}) fname_tmp=$fname.$$ istr="$2" find ${fname_dir} -maxdepth 1 -type f -name "${fname_base}.*" | grep -qvE ".backup|.std|~" if [ $? -eq 0 ] then # backup file /var/install/bin/backup-file --quiet $fname backup # create fname_tmp with same file access permission like fname if [ -f $fname ] then cp -p $fname $fname_tmp else # create new file and set initial file permissions > $fname_tmp chmod 644 $fname_tmp fi # create new file (temporary one) { # print header print_file_header "$fname" "$istr" for FN in $(ls ${fname}.*|grep -vE ".backup|~|.$$") do cat $FN done } > ${fname_tmp} # copy file, preserve access permissions cp -p ${fname_tmp} ${fname} rm -f ${fname_tmp} else # remove file if [ -f ${fname} ] then # backup file /var/install/bin/backup-file --quiet $fname backup rm -f ${fname} fi fi } #---------------------------------------------------------------------------- # update services file # $1 - file name # $2 - package name #---------------------------------------------------------------------------- # # format of services file: # # service-name port/protocol [aliases ...] # # separator spaces or tabs # ignore blank line # comments start by # # # old style format (port,protocol) is not supported # update_services_file() { fname="$1" fname_dir=$(dirname ${fname}) fname_base=$(basename ${fname}) fname_tmp=$fname.$$ istr="$2" src_work=$fname-work-src.$$ dest_work=$fname-work-dest.$$ # backup file /var/install/bin/backup-file --quiet $fname backup # create working copy cp $fname.std $src_work # process all files filelist=$(find ${fname_dir} -maxdepth 1 -type f -name "${fname_base}.*" | grep -vE ".backup|.std|~") for FN in $filelist do if check_services_file $FN then # read files line by line while read line do # ignore blank or empty lines echo "$line" | grep -q '^[[:space:]]*$' && continue # ignore comment only lines echo "$line" | grep "^#" > /dev/null if [ $? -ne 0 ] then # get service name and service protocol sname=$(echo $line|cut -d" " -f1|sed 's/ //g') sprotocol=$(echo $line|cut -d" " -f2|sed 's/ //g'|sed 's|[0-9]*/||') if [ -n "$sname" ] then # remove old entry if exist grep -v "^$sname[[:space:]]*[0-9]*/$sprotocol" $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 fname_tmp with same file access permission like fname cp -p $fname $fname_tmp # create new file (temporary one) { # print header print_file_header "$fname" "$istr" # use standard file cat $src_work for FN in $filelist do cat $FN done } > ${fname_tmp} # copy file, preserve access permissions cp -p ${fname_tmp} ${fname} rm -f ${fname_tmp} # remove working copy rm -f $src_work } #---------------------------------------------------------------------------- # update nsswitch.conf # $1 - file name # $2 - package name #---------------------------------------------------------------------------- # # format of nsswitch.conf: # # hosts: files wins dns # # separator : # update_nsswitch_file() { fname="$1" fname_dir=$(dirname ${fname}) fname_base=$(basename ${fname}) fname_tmp=$fname.$$ istr="$2" src_work=$fname-work-src.$$ # backup file /var/install/bin/backup-file --quiet $fname backup # create working copy without comments grep -v "^#" ${fname}.std > ${src_work} # process all files filelist=$(find ${fname_dir} -maxdepth 1 -type f -name "${fname_base}.*" | grep -vE ".backup|.std|~") # create fname_tmp with same file access permission like fname cp -p $fname $fname_tmp # create new file (temporary one) { # print header print_file_header "$fname" "$istr" while read a do id_a='' id_b='' id_a=$(echo $a | cut -d":" -f1 | sed 's/ //g') if [ -n "$filelist" ] then id_b=$(grep -h "^${id_a}:" ${filelist}) wcl=$(grep -h "^${id_a}:" ${filelist} | wc -l) fi if [ -n "$id_a" -a -n "$id_b" ] then if [ "$wcl" -gt "1" ] then mecho --error "More than one entry for $id_a:!" >&2 #echo "id_a is $id_a, id_b is $id_b, wcl is $wcl" echo "$a" else echo "$id_b" fi else echo "$a" fi done < $src_work } 1> ${fname_tmp} # copy file, preserve access permissions cp -p ${fname_tmp} ${fname} rm -f ${fname_tmp} # remove working copy rm -f $src_work } #============================================================================ # main #============================================================================ if [ ${#} -eq 0 ] then # show help print_help else # update files while [ 1 ] do case "${1}" in -debug|--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-nsswitch|nsswitch) update_nsswitch_file /etc/nsswitch.conf "${infostr}" ;; update-at.allow|at.allow) update_at_allow_deny_file /etc/at.allow "${infostr}" ;; update-at.deny|at.deny) update_at_allow_deny_file /etc/at.deny "${infostr}" ;; *) mecho --info 'program name not allowed, use one of the following names:' print_help ;; esac fi #============================================================================ # end #============================================================================