Blame SOURCES/createmodule.sh

d93c5f
#!/bin/bash
d93c5f
#
d93c5f
# createmodule.sh - Takes the name of a environment init script and 
d93c5f
# produces a modulefile that duplicates the changes made by the init script
d93c5f
#
d93c5f
# Copyright (C) 2010-2012 by Orion E. Poplawski <orion@cora.nwra.com>
d93c5f
#
d93c5f
# This program is free software: you can redistribute it and/or modify
d93c5f
# it under the terms of the GNU General Public License as published by
d93c5f
# the Free Software Foundation, either version 2 of the License, or
d93c5f
# (at your option) any later version.
d93c5f
d93c5f
# This program is distributed in the hope that it will be useful,
d93c5f
# but WITHOUT ANY WARRANTY; without even the implied warranty of
d93c5f
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d93c5f
# GNU General Public License for more details.
d93c5f
d93c5f
# You should have received a copy of the GNU General Public License
d93c5f
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
d93c5f
d93c5f
usage="Usage: $0 [-p prefix] <initscript> [args]"
d93c5f
d93c5f
usage() {
d93c5f
  echo $usage 1>&2
d93c5f
  exit 1
d93c5f
}
d93c5f
d93c5f
while getopts "p:" opt
d93c5f
do
d93c5f
  case $opt in
d93c5f
    p) prefix=$OPTARG; shift 2;;
d93c5f
    *) usage;;
d93c5f
  esac
d93c5f
done
d93c5f
d93c5f
# Need a script name
d93c5f
[ -z "$1" ] && usage
d93c5f
d93c5f
# Need to be a readable script
d93c5f
if [ ! -r "$1" ]
d93c5f
then
d93c5f
  echo "ERROR: Cannot read $1" 1>&2
d93c5f
  exit 1 
d93c5f
fi
d93c5f
d93c5f
#Will print out array assignment list
d93c5f
printenvarray () {
d93c5f
  env | while read x
d93c5f
  do
d93c5f
    key=${x%%=*}
d93c5f
    value=`printenv "$key"`
d93c5f
    if [ $? -eq 0 ]
d93c5f
    then
d93c5f
      echo [$key]="'$value'"
d93c5f
    fi
d93c5f
  done
d93c5f
}
d93c5f
d93c5f
#Apparently we need to declare the associative arrays
d93c5f
declare -A env1 env2
d93c5f
d93c5f
#Record starting environment
d93c5f
eval env1=(`printenvarray`)
d93c5f
d93c5f
#Source the environment script
d93c5f
. "$@"
d93c5f
d93c5f
#Record ending environment
d93c5f
eval env2=(`printenvarray`)
d93c5f
d93c5f
#Print out the modulefile
d93c5f
echo "#%Module 1.0"
d93c5f
d93c5f
#Prefix
d93c5f
[ -n "$prefix" ] && echo -e "\nset prefix $prefix\n"
d93c5f
d93c5f
# dedup - remove duplicate entries from a list
d93c5f
#Subshell so we can sort the output
d93c5f
(
d93c5f
dedup() {
d93c5f
  list=`mktemp`
d93c5f
  [ -n "$2" ] && sep=$2 || sep=:
d93c5f
  echo $1 | sed -r -e 's,[^/]+/\.\./,,g' -e 's,[^/]+/\.\./,,g' -e "s/\\$sep/\n/g" |
d93c5f
    while read x
d93c5f
    do
d93c5f
      grep -Fx ${x} $list && continue
d93c5f
      if [ -n "$prefix" ]
d93c5f
      then
d93c5f
        echo $x | sed -e s,$prefix,\$prefix,
d93c5f
      else
d93c5f
        echo $x
d93c5f
      fi
d93c5f
      echo $x >> $list
d93c5f
    done | tr '\n' $sep | sed -e "s/\\$sep\$//"
d93c5f
  rm $list
d93c5f
} 
d93c5f
    
d93c5f
#Keys that changed
d93c5f
for key in "${!env1[@]}"
d93c5f
do
d93c5f
  if [ "${env1[$key]}" != "${env2[$key]}" ]
d93c5f
  then
d93c5f
    #Working directory change
d93c5f
    if [ "$key" = PWD ]
d93c5f
    then
d93c5f
      if [ -n "$prefix" ]
d93c5f
      then
d93c5f
        echo -e "chdir\t\t${env2[PWD]}" | sed -e s,$prefix,\$prefix,g
d93c5f
      else
d93c5f
        echo -e "chdir\t\t${env2[PWD]}"
d93c5f
      fi
d93c5f
    #Test for delete
d93c5f
    elif [ -z "${env2[$key]}" ]
d93c5f
    then
d93c5f
      echo -e "unsetenv\t${key}\t${env2[$key]}"
d93c5f
    #Test for prepend
d93c5f
    elif [ "${env2[$key]%${env1[$key]}}" != "${env2[$key]}" ]
d93c5f
    then
d93c5f
      added=${env2[$key]%${env1[$key]}}
d93c5f
      sep=${added: -1}
d93c5f
      added=${added%$sep}
d93c5f
      added=$(dedup $added $sep)
d93c5f
      if [ $sep = : ]
d93c5f
      then
d93c5f
        echo -e "prepend-path\t$key\t${added}"
d93c5f
      else
d93c5f
        echo -e "prepend-path\t--delim $sep\t$key\t${added}"
d93c5f
      fi
d93c5f
    #Test for prepend plus : added at end (MANPATH)
d93c5f
    elif [ "${key: -4}" = PATH -a "${env2[$key]%${env1[$key]}:}" != "${env2[$key]}" ]
d93c5f
    then
d93c5f
      added=$(dedup ${env2[$key]%${env1[$key]}:})
d93c5f
      echo -e "prepend-path\t$key\t${added}"
d93c5f
    #Test for append
d93c5f
    elif [ "${env2[$key]#${env1[$key]}}" != "${env2[$key]}" ]
d93c5f
    then
d93c5f
      added=${env2[$key]#${env1[$key]}}
d93c5f
      sep=${added:0:1}
d93c5f
      added=${added#$sep}
d93c5f
      added=$(dedup $added $sep)
d93c5f
      if [ $sep = : ]
d93c5f
      then
d93c5f
        echo -e "append-path\t$key\t${added}"
d93c5f
      else
d93c5f
        echo -e "append-path\t--delim $sep\t$key\t${added}"
d93c5f
      fi
d93c5f
    #Test for prepend plus append
d93c5f
    elif [ "${env2[$key]%${env1[$key]}*}" != "${env2[$key]}" ]
d93c5f
    then
d93c5f
      prepended=${env2[$key]%${env1[$key]}*}
d93c5f
      presep=${prepended: -1}
d93c5f
      prepended=${prepended%$presep}
d93c5f
      prepended=$(dedup $prepended $presep)
d93c5f
      appended=${env2[$key]#*${env1[$key]}}
d93c5f
      appsep=${appended:0:1}
d93c5f
      appended=${appended#$appsep}
d93c5f
      appended=$(dedup $appended $appsep)
d93c5f
      if [ $presep != $appsep -o -z "$prepended" -o -z "$appended" ]
d93c5f
      then
d93c5f
        #Unhandled
d93c5f
        echo "Unhandled change of $key" 1>&2
d93c5f
        echo "Before <${env1[$key]}>" 1>&2
d93c5f
        echo "After  <${env2[$key]}>" 1>&2
d93c5f
      else
d93c5f
        if [ $presep = : ]
d93c5f
        then
d93c5f
          echo -e "prepend-path\t$key\t${prepended}"
d93c5f
          echo -e "append-path\t$key\t${appended}"
d93c5f
        else
d93c5f
          echo -e "prepend-path\t--delim $presep\t$key\t${prepended}"
d93c5f
          echo -e "append-path\t--delim $appsep\t$key\t${appended}"
d93c5f
        fi
d93c5f
      fi
d93c5f
    else
d93c5f
      #Unhandled
d93c5f
      echo "Unhandled change of $key" 1>&2
d93c5f
      echo "Before <${env1[$key]}>" 1>&2
d93c5f
      echo "After  <${env2[$key]}>" 1>&2
d93c5f
    fi
d93c5f
  fi
d93c5f
  #Delete keys we have handled
d93c5f
  unset env1[$key]
d93c5f
  unset env2[$key]
d93c5f
done
d93c5f
d93c5f
#New keys
d93c5f
for key in "${!env2[@]}"
d93c5f
do
d93c5f
  if [ "$key" = OLDPWD ]
d93c5f
  then
d93c5f
    continue
d93c5f
  fi
d93c5f
  #Use prepend-path for new paths
d93c5f
  if [ "${key: -4}" = PATH -o "${key: -4}" = DIRS -o "${key: -4}" = FILES ]
d93c5f
  then
d93c5f
    # TODO - Need to handle stripping of default MANPATH
d93c5f
    echo -e "prepend-path\t${key}\t"$(dedup ${env2[$key]})
d93c5f
  else
d93c5f
    if [ -n "$prefix" ]
d93c5f
    then
d93c5f
      echo -e "setenv\t\t${key}\t${env2[$key]}" | sed -e s,$prefix,\$prefix,g
d93c5f
    else
d93c5f
      echo -e "setenv\t\t${key}\t${env2[$key]}"
d93c5f
    fi
d93c5f
  fi
d93c5f
done
d93c5f
) | sort