summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c803c94)
raw | patch | inline | side by side (parent: c803c94)
author | cajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8> | |
Thu, 24 Nov 2005 13:24:13 +0000 (13:24 +0000) | ||
committer | cajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8> | |
Thu, 24 Nov 2005 13:24:13 +0000 (13:24 +0000) |
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@2046 594d385d-05f5-0310-b6e9-bd551577e9d8
18 files changed:
diff --git a/contrib/fai/goto-fai/Makefile b/contrib/fai/goto-fai/Makefile
--- /dev/null
@@ -0,0 +1,19 @@
+all:
+ @echo "Nothing to do for all"
+
+install:
+ mkdir -p $(DESTDIR)/usr/sbin
+ mkdir -p $(DESTDIR)/etc/goto
+ mkdir -p $(DESTDIR)/usr/lib/goto
+ mkdir -p $(DESTDIR)/fai/hooks
+ cp secret $(DESTDIR)/etc/goto
+ cp -a get_fai_dir faimond $(DESTDIR)/usr/sbin
+ cp -a goto-support.lib $(DESTDIR)/usr/lib/goto
+ cp -a ldap2fai $(DESTDIR)/usr/sbin
+ cp confdir.DEFAULT.source $(DESTDIR)/fai/hooks
+ chmod go-rwx $(DESTDIR)/etc/goto/secret
+
+ # Install diversions
+ mkdir -p $(DESTDIR)/usr/lib/fai/sbin
+ cp diversions/setup_harddisks $(DESTDIR)/usr/lib/fai/sbin
+
diff --git a/contrib/fai/goto-fai/confdir.DEFAULT.source b/contrib/fai/goto-fai/confdir.DEFAULT.source
--- /dev/null
@@ -0,0 +1,19 @@
+# undef default shell subroutine get_fai_dir
+# instead the new script get_fai_dir will be used
+
+setterm -cursor off >/dev/tty3
+/usr/sbin/faimond >/dev/tty3 &
+chvt 3
+unset get_fai_dir
+unset sndmon
+
+sndmon() {
+ # send message to monitor daemon
+ [ "$faimond" -eq 0 ] && return 0
+ if [ "$debug" ];then
+ echo "$sndhostname $*" | nc localhost 4711
+ else
+ echo "$sndhostname $*" | nc localhost 4711 2>/dev/null
+ fi
+ return $?
+}
diff --git a/contrib/fai/goto-fai/debian/README.debian b/contrib/fai/goto-fai/debian/README.debian
--- /dev/null
@@ -0,0 +1,6 @@
+goto-fai for Debian
+-------------------
+
+Comments regarding the Package
+
+Cajus Pollmeier <pollmeier@gonicus.de>, Thu, 17 Mar 2005 09:05:17 +0100
diff --git a/contrib/fai/goto-fai/debian/changelog b/contrib/fai/goto-fai/debian/changelog
--- /dev/null
@@ -0,0 +1,5 @@
+goto-fai (2.0-1) unstable; urgency=low
+
+ * Initial release.
+
+ -- Cajus Pollmeier <pollmeier@gonicus.de> Thu, 17 Mar 2005 09:05:17 +0100
diff --git a/contrib/fai/goto-fai/debian/control b/contrib/fai/goto-fai/debian/control
--- /dev/null
@@ -0,0 +1,12 @@
+Source: goto-fai
+Section: lhm/main
+Priority: optional
+Maintainer: Cajus Pollmeier <pollmeier@gonicus.de>
+Standards-Version: 3.6.1
+Build-Depends: debmake
+
+Package: goto-fai
+Architecture: any
+Depends: ${shlibs:Depends}, libnet-ldap-perl, hwdata-knoppix, hwsetup, ddcxinfo-knoppix
+Description: GOto support scripts
+ Support and build scripts for terminal server
diff --git a/contrib/fai/goto-fai/debian/copyright b/contrib/fai/goto-fai/debian/copyright
--- /dev/null
@@ -0,0 +1,8 @@
+This package was debianized by cajus cajus@ots-2.gonicus.local on
+Thu, 17 Mar 2005 09:05:17 +0100.
+
+It was downloaded from <fill in ftp site>
+
+Copyright:
+
+<Must follow here>
diff --git a/contrib/fai/goto-fai/debian/dirs b/contrib/fai/goto-fai/debian/dirs
--- /dev/null
@@ -0,0 +1,2 @@
+usr/bin
+usr/sbin
diff --git a/contrib/fai/goto-fai/debian/postrm b/contrib/fai/goto-fai/debian/postrm
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh -e
+
+#DEBHELPER#
+
+if [ "remove" = "$1" ]; then
+ dpkg-divert --package goto-fai --remove --rename \
+ --divert /usr/lib/fai/sbin/setup_harddisks.goto-fai \
+ /usr/lib/fai/sbin/setup_harddisks
+fi
+
+exit 0
diff --git a/contrib/fai/goto-fai/debian/preinst b/contrib/fai/goto-fai/debian/preinst
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh -e
+
+#DEBHELPER#
+#
+if [ ! -e /usr/lib/fai/sbin/setup_harddisks.goto-fai ]; then
+ dpkg-divert --package goto-fai --add --rename \
+ --divert /usr/lib/fai/sbin/setup_harddisks.goto-fai \
+ /usr/lib/fai/sbin/setup_harddisks
+fi
+
+exit 0
diff --git a/contrib/fai/goto-fai/debian/rules b/contrib/fai/goto-fai/debian/rules
--- /dev/null
@@ -0,0 +1,50 @@
+#!/usr/bin/make -f
+# Made with the aid of debmake, by Christoph Lameter,
+# based on the sample debian/rules file for GNU hello by Ian Jackson.
+
+package=goto
+
+build:
+ $(checkdir)
+
+ $(MAKE) CFLAGS="-O2 -g -Wall"
+ touch build
+
+clean:
+ $(checkdir)
+ rm -f build
+ -$(MAKE) clean
+ rm -f `find . -name "*~"`
+ rm -rf debian/tmp debian/files* core debian/substvars
+
+binary-indep: checkroot build
+ $(checkdir)
+# There are no architecture-independent files to be uploaded
+# generated by this package. If there were any they would be
+# made here.
+
+binary-arch: checkroot build
+ $(checkdir)
+ rm -rf debian/tmp
+ install -d debian/tmp
+ cd debian/tmp && install -d `cat ../dirs`
+ $(MAKE) install DESTDIR=`pwd`/debian/tmp
+# Must have debmake installed for this to work. Otherwise please copy
+# /usr/bin/debstd into the debian directory and change debstd to debian/debstd
+ debstd
+ dpkg-gencontrol -isp
+ chown -R root:root debian/tmp
+ chmod -R go=rX debian/tmp
+ dpkg --build debian/tmp ..
+
+define checkdir
+ test -f debian/rules
+endef
+
+binary: binary-indep binary-arch
+
+checkroot:
+ $(checkdir)
+ test root = "`whoami`"
+
+.PHONY: binary binary-arch binary-indep clean checkroot
diff --git a/contrib/fai/goto-fai/diversions/fai b/contrib/fai/goto-fai/diversions/fai
--- /dev/null
@@ -0,0 +1,272 @@
+#!/bin/bash
+# $Id: fai,v 1.9 2005/05/05 21:56:24 lange Exp $
+#*********************************************************************
+#
+# fai -- main installation script executed after booting
+#
+# This script is part of FAI (Fully Automatic Installation)
+# (c) 1999-2005 by Thomas Lange, lange@informatik.uni-koeln.de
+# Universitaet zu Koeln
+#
+#*********************************************************************
+# 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.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# A copy of the GNU General Public License is available as
+# `/usr/share/common-licences/GPL' in the Debian GNU/Linux distribution
+# or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You
+# can also obtain it by writing to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#*********************************************************************
+
+#set -xv # for full debugging
+
+export PATH=/usr/local/sbin:/usr/local/bin:/usr/lib/fai:/bin:/sbin:/usr/bin:/usr/sbin:
+# some variables
+export FAI_VERSION="FAI 2.8.4, 25 May 2005"
+rundir=/var/run/fai
+stamp=$rundir/FAI_INSTALLATION_IN_PROGRESS
+romountopt="-o async,noatime,nolock,ro,actimeo=1800"
+fstab=fstab # Solaris uses vfstab
+
+# the type of operating system (linux, sunos)
+oclass=$(uname -s | tr /a-z/ /A-Z/)
+# $classes is now set so we can call hooks before fai-class defines the classes
+classes="DEFAULT $oclass $HOSTNAME LAST"
+faimond=0
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+prcopyleft() {
+
+ cat <<-EOF
+ -----------------------------------------------------
+ Fully Automatic Installation for $osname
+ $FAI_VERSION Copyright (c) 1999-2005
+
+ Thomas Lange <lange@informatik.uni-koeln.de>
+ -----------------------------------------------------
+EOF
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+fai_init() {
+
+ local sub osname
+ set -a # now export all variables
+
+ umask 022
+ # read fai.conf
+ # linux dir
+ [ -f /etc/fai/fai.conf ] && . /etc/fai/fai.conf
+ # solaris dir
+ [ -f /tmp/install_config/fai/fai.conf ] && . /tmp/install_config/fai/fai.conf
+
+ if [ -f /boot/RUNNING_FROM_FAICD ]; then # we are booting from fai cd
+ umount /initrd
+ romountopt=
+ FAI_DEBMIRROR="--bind /media/mirror"
+ MNTPOINT=/media/mirror
+ FAI_LOCATION=
+ fi
+
+ # some variables from are not needed any more
+ unset NFSROOT FAI_CONFIGDIR installserver
+
+ # read subroutine definitions
+ sub=/usr/share/fai/subroutines
+ [ -f $sub ] && . $sub
+ [ -f $sub-$OS_TYPE ] && . $sub-$OS_TYPE
+
+ [ -f "$stamp" ] && {
+ echo "$0 already running, aborting"
+ exit 1
+ }
+
+ # HG: are we called as an init substitute ?
+ DO_INIT_TASKS=0
+ [ "$0" = "/etc/init.d/rcS" ] && DO_INIT_TASKS=1
+ [ $DO_INIT_TASKS -eq 1 ] && renewclass=1 # always renew class list when installing
+
+ # color logo only if initial install
+ COLOR_FAI_LOGO=$DO_INIT_TASKS
+
+ DEBIAN_FRONTEND=noninteractive
+ # local disks are mounted to $FAI_ROOT
+ if [ -z "$FAI_ROOT" ] ; then
+ [ $DO_INIT_TASKS -eq 1 ] && FAI_ROOT=/tmp/target || FAI_ROOT=/
+ fi
+ # executed command in the environment of the new system
+ ROOTCMD="chroot $FAI_ROOT"
+ # no chroot needed
+ [ "$FAI_ROOT" = '/' ] && ROOTCMD=
+
+ # Solaris has already a writable /tmp directory
+ [ "$oclass" = LINUX -a $DO_INIT_TASKS -eq 1 ] && create_ramdisk
+ unset oclass
+
+ # directory where temporary log files are stored
+ # set default value if nothing is set in fai.conf
+ if [ -z "$LOGDIR" -a $DO_INIT_TASKS -eq 1 ]; then
+ LOGDIR=/tmp/fai
+ mkdir -p $LOGDIR
+ fi
+ [ $DO_INIT_TASKS -eq 0 ] && LOGDIR=$(mktemp -t -d fai.XXXXXX)
+ ln -s $LOGDIR $rundir/current_log
+
+ # several log files
+ diskvar=$LOGDIR/disk_var.sh
+ moduleslog=$LOGDIR/modules.log
+ rcslog=$LOGDIR/fai.log
+
+ # variables for cfengine
+ files=$FAI/files
+ target=$FAI_ROOT
+
+ if [ $DO_INIT_TASKS -eq 1 ]; then
+# trap 'echo "Now rebooting";faireboot' INT QUIT ;
+ trap 'echo "Now rebooting";/bin/bash' INT QUIT ;
+ else
+ trap "echo 'Aborted';rm -f $stamp" INT QUIT ;
+ fi
+
+ # if HOST was specified on the commandline, set hostname to it
+ eval_cmdline
+ if [ -n "$HOST" ]; then
+ HOSTNAME=$HOST
+ hostname $HOST
+ echo "Hostname set to $HOST" | tee -a $rcslog
+ sleep 3
+ fi
+ export HOSTNAME
+
+ if [ X$OS_TYPE = Xlinux ]; then
+ osname='Debian GNU/Linux'
+ if [ $DO_INIT_TASKS -eq 1 ]; then
+ grep -q '[[:space:]]sysfs' /proc/filesystems && mount -t sysfs sysfs /sys
+ ifup lo
+ [ -x /sbin/portmap ] && /sbin/portmap
+ mount -t devpts devpts /dev/pts
+ # add other options for nfs mount of /dev/root to root-path in dhcpd.conf
+ mount -o remount,noatime,ro /dev/root /
+ cat /proc/kmsg >/dev/tty4 &
+ fi
+ fi
+ if [ X$OS_TYPE = Xsunos ]; then
+ osname='Sun Solaris'
+ fi
+
+ # set red color, but not on some archs
+ [ -e /.nocolorlogo ] && COLOR_FAI_LOGO=0
+ case $HOSTTYPE in
+ sparc*|powerpc*) COLOR_FAI_LOGO=0 ;;
+ esac
+
+ [ $COLOR_FAI_LOGO -eq 1 ] && echo -ne "\ec\e[1;31m"
+
+ prcopyleft | tee -a $rcslog
+
+ if [ $COLOR_FAI_LOGO -eq 1 ]; then
+ echo -ne "\e[7;0r"
+ echo -ne "\e[9B\e[1;m"
+ fi
+ save_dmesg
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+usage() {
+ cat <<-EOF
+ fai $FAI_VERSION. Copyright (C) 1999-2005 Thomas Lange
+ Usage: $0 [options] [action]
+
+ Options:
+ -v|--verbose display more information during the update
+ -h|--help display this help message
+ -N|--new renew list of classes
+EOF
+ exit 0
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+fstart() {
+
+ # these tasks can define variables, that are needed later
+ task confdir
+ task setup
+ task defclass
+ set_disk_info
+ task defvar
+ [ $DO_INIT_TASKS -eq 1 ] && load_keymap_consolechars
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Main routine
+
+export renewclass=0
+# Parse commandline options
+TEMP=$(getopt -o Nhv --long new,help,verbose -n "$0" -- "$@")
+if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
+# Note the quotes around `$TEMP': they are essential!
+eval set -- "$TEMP"
+
+while true ; do
+ case "$1" in
+ -h|--help)
+ shift
+ usage
+ ;;
+ -v|--verbose)
+ shift
+ verbose=1
+ ;;
+ -N|--new)
+ shift
+ renewclass=1
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ echo "$0: command line parsing error ! $@"
+ exit 1
+ ;;
+ esac
+done
+
+fai_init
+
+lpipe=$LOGDIR/logfifo
+mkfifo $lpipe
+tee -a $rcslog < $lpipe &
+# in bash &> redirect stdout and stderr to file
+fstart &> $lpipe
+rm $lpipe
+unset lpipe
+sleep 1 # wait for tee to complete. One second should be ok
+
+# old code
+# {
+# # a bash group command with { does not work on sparc
+# task confdir
+# task setup
+# task defclass
+# task defvar
+# load_keymap_consolechars
+# set_disk_info
+# } > >( tee -a $rcslog ) 2>&1
+
+# override FAI_ACTION if a command line argument is given
+[ "$1" ] && FAI_ACTION=$1
+
+task action 2>&1 | tee -a $rcslog
+
+# not quiet happy with it
+[ "$FAI_CVSROOT" ] && rm -rf $FAI
+rm -rf $LOGDIR
+
+[ -L "$rundir/current_log" ] && rm -f "$rundir/current_log"
+[ -L "$rundir/current_config" ] && rm -f "$rundir/current_config"
+
+echo "End of $0"
diff --git a/contrib/fai/goto-fai/diversions/setup_harddisks b/contrib/fai/goto-fai/diversions/setup_harddisks
--- /dev/null
@@ -0,0 +1,954 @@
+#!/usr/bin/perl
+
+# $Id: setup_harddisks,v 1.41 2005/04/08 10:08:54 lange Exp $
+#*********************************************************************
+#
+# setup_harddisks -- create partitions and filesystems on harddisk
+#
+# This script is part of FAI (Fully Automatic Installation)
+# Copyright (c) 1999, 2000 by ScALE Workgroup, Universitaet zu Koeln
+# Copyright (c) 2000-2005 by Thomas Lange, Uni Koeln
+#
+#*********************************************************************
+# 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.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING. If not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA.
+#*********************************************************************
+#
+# This program first read the configfiles, partitions and formats the harddisks,
+# produces fstab and FAI-variables-file. It uses sfdisk, mke2fs, mkswap
+#
+# Parameters:
+# [-X] no test, your harddisks will be formated
+# default: only test, no real formating
+# [-f<config-filename>] default: parse classes
+# [-c<class-path>] default: $FAI/disk_config/
+# [-d] default: no DOS alignment
+#
+#---------------------------------------------------
+# Last changes: 31.3.2005 by Thomas Lange add sub mapdisk{}
+# Last changes: 8.11.2004 by Thomas Lange add $devdisklist when calling sfdisk
+# Last changes: 3.2.2004 by Thomas Lange typos
+# Last changes: 14.07.2003 by Thomas Lange add xfs filesystem support
+# Last changes: 23.01.2003 by Thomas Lange print info data to stdout
+# Last changes: 03.12.2002 by Thomas Lange remove ida, cciss stuff. Just match everything
+# Last changes: 27.11.2002 by Thomas Lange allow more that 3 primary partitions
+# Last changes: 14.05.2002 by Thomas Lange use strict
+# Last changes: 04.05.2002 by Thomas Lange use strict
+# Last changes: 29.04.2002 by Thomas Lange add swaplist
+# Last changes: 12.01.2002 by Thomas Lange
+# /dev/ida/ patch 12.01.2002 by Marc Martinez <lastxit+fai@technogeeks.org>
+# Last changes: 9.11.2001 by Thomas Lange
+# reiserfs patch 8.11.2001 by Diane Trout <diane@caltech.edu>
+# Last changes: 25.10.2001 by Thomas Lange
+# Last changes: 09.07.2001 by Thomas Lange
+# Last changes: 04.07.2001 by Thomas Lange
+# Last changes: 06.05.2001 by Thomas Lange
+# Last changes: 09.03.2001 by Thomas Lange
+# Last changes: 05.12.2000 by Thomas Lange
+# Last changes: 03.05.2000 by Thomas Lange
+# Last changes: 03.04.2000 by Mattias Gaertner
+#---------------------------------------------------
+#
+# config-file format:
+# lines beginning with # are comments
+#
+# "disk_config <device>|first|end"
+# The disk_config command starts the parsing.
+# It has to be the first command.
+# <device> is the harddisk to format in short form like "hda" or "sdc".
+# if first is used, the first of $ENV{disklist} is used
+# "end" = end parsing here
+# Example: "disk_config hdb"
+# Example: "disk_config first"
+#
+# Defining one partition:
+# "primary|logical mountpoint|swap|- <size in mb>|preserve<No> [fstab-options][;extraordinary options]"
+# "primary|logical":
+# "primary": this are the bootable partitions like the
+# root directory "/" or the DOS "C:" disk.
+# "logical": this are all other partitions like a linux
+# "/var" or a swap partition or a DOS disk.
+#
+# "mountpoint|swap|-":
+# "mountpoint":
+# This is the mount-point for fstab.
+# For example "/","/var","/usr". There must not
+# be a space in the mountpoint.
+# "swap":
+# swap-partitions
+# "-":
+# do not mount this partition.
+#
+# "<size in mb>|preserve<No>":
+# "<size in mb>":
+# The size of the partition in megabyte
+# Examples:
+# "30" = 30 mb
+# "10-100" = 10 to 100 mb
+# "20-" = minimum of 20 mb
+# "-500" = 1 to 500 mb
+# The megabytes will be rounded up to cylinders.
+# "preserve<No>":
+# This is the alternative for the size attribute.
+# <No> is the partition number. For example
+# preserve3 for the third partition. If the
+# <device> was hda then this results in hda3.
+# The partition will be left unchanged. This
+# is useful if you have partitions that do not
+# need re-installation or if you want to have
+# other operation systems on the device together
+# with Linux. Extended Partitions can not be preserved.
+# The bootable flag will not be preserved.
+# Preserved partitions are mounted readonly during
+# installation.
+#
+# "fstab-options":
+# These options are copied to the fstab-file. The
+# default is "default"
+#
+# After the semicolon there could be extra options like:
+# -i <bytes> : Bytes per inodes
+# (only ext2/3 filesystem)
+# -m <blocks>% : reserved blocks percentage for superuser
+# (only ext2/3 filesystem)
+# -j : format in ext3
+# -c : check for bad blocks
+# format : Always format this partition even if preserve
+# lazyformat : Do not format if partition has not moved
+# (useful for testing the installation)
+# boot : make this partition the boot-partition (the
+# linux root filesystem is the default)
+# ext2 : Extended 2 filesystem (this is the default)
+# swap : swap partition
+# dosfat16 : DOS 16bit FAT file system
+# winfat32 : Win95 FAT32 file system
+# writable : mounts a preserved partition writable
+# xfs : xfs
+# reiser : reiserfs
+# -h <hash> : set reiserfs hash
+# -v <ver> : set reiserfs version
+#
+use strict;
+# getopts variables:
+our ($opt_X, $opt_f, $opt_c, $opt_d);
+my $test;
+
+$| = 1; # flush always
+
+#****************************************************
+# Variables
+#****************************************************
+
+my $Version = "version 0.35fai";
+
+my $megabyte = 1024 * 1024; # guess
+# $gigabyte = 1024 * $megabyte;
+my $sectorsize = 512;
+
+# used programs
+my $sfdisk_options = "-q $ENV{sfdisk}"; # be quiet
+my $mke2fs_options = "-q"; # be quiet
+my $mkreiserfs_options = "";
+my $mkxfs_options = "-f";
+my $mkswap_options = "";
+
+# FAI input variables
+my $ClassPath = "$ENV{FAI}/disk_config";# this directory contains the classes
+my $ConfigFileName = ""; # alternative classfile, only for tests
+my $DOS_Alignment = ""; # align partitions for tracks
+
+# FAI output variables
+my $BootPartition = ""; # the boot partition like "hda1"
+my $BOOT_DEVICE = ""; # the root device like "hda" or "sdb"
+my $FAIOutputFile = $ENV{diskvar}; # write output variables to this file
+
+# old partition tables
+my %DiskUnits = (); # unit size of each disk in sectors
+my %DiskSize = (); # size of every disk in units
+my %SectorsAlignment = (); # tracksize in sectors
+my %PartOldBoot = (); # partition was bootable. "yes"=yes
+my %PartOldStart = (); # old startunit of partition
+my %PartOldEnd = (); # old endunit of partition
+my %PartOldStartSec = (); # old startsector of partition
+my %PartOldEndSec = (); # old endsector of partition
+my %PartOldID = (); # old ID of partition
+my %OldNotAligned = (); # "yes" if old partition boundaries are not DOS aligned
+
+# mountpoints ("/<path>" or "swap<No>" or "no<No>" or "extended<disk>")
+my $NofSwapPart = 0; # number of swap partitions
+my $NofNotMoPart = 0; # number of not mountet partitions
+my %DiskMountpoints = (); # mountpoints of every disk. separated by spaces
+my %MountpointPart = (); # partition of every mountpoint. e.g. "hda2"
+my %PartMountpoint = (); # mountpoint of every partition.
+my @swaplist; # list of all swpa devices
+
+# size of partition/mountpoint
+my %MPMinSize = (); # minimum size of mountpoint in units
+my %MPMaxSize = (); # maximum size of mountpoint in units
+my %MPPreserve = (); # preserve partition: "yes"=yes
+my %MPPrimary = (); # primary partition: "yes"=yes
+my %MPStart = (); # start of partition in units
+my %MPSize = (); # size of partition in units
+my %MPID = (); # id of partition
+
+# options
+my %MPfstaboptions = (); # fstab options for every mountpoint
+my %MPOptions = (); # extra options for every mountpoint
+
+# sfdisk partition tables
+my %sfdiskTables = (); # partition tables for sfdisk
+
+my $verbose = 0;
+$verbose = $ENV{verbose} if $ENV{verbose};
+
+# Parse command line
+
+use Getopt::Std;
+&getopts('Xf:c:d') || die "
+USAGE: [-X] no test, your harddisks will be formated
+ default: only test, no real formating
+ [-f<config-filename>] default: parse classes
+ [-c<class-path>] default: \$FAI/disk_config/
+ [-d] default: no DOS alignment
+";
+
+print "setup_harddisks $Version\n";
+if (defined $opt_X){
+ $test = 2;
+} else {
+ print "TEST ONLY - no real formating\n\n";
+ $test = 1;
+}
+$ConfigFileName = $opt_f if $opt_f;# alternative config file
+$ClassPath = $opt_c if $opt_c;# search classes here
+$DOS_Alignment = "yes" if $opt_d; # track alignment
+
+# main part
+&GetAllDisks;
+&ParseAllConfigFiles;
+&BuildNewPartTables;
+&PartitionPersfdisk;
+&FormatDisks;
+&WriteFSTab;
+&WriteFAIVariables;
+exit 0;
+#****************************************************
+
+#****************************************************
+# get a partition pathname
+#****************************************************
+sub PartName {
+ my ($disk, $partno) = @_;
+ my $ppath;
+ for ($disk) {
+ /^[a-z]+$/ and $ppath = "${disk}${partno}";
+ /\d$/ and $ppath = "${disk}p${partno}";
+ }
+ return $ppath;
+}
+
+#****************************************************
+# Read all partition tables of this machine
+#****************************************************
+sub GetAllDisks{
+ my $line=""; my $disk=""; my $device=""; my $rest; my $result; my $divi;
+ my $devdisklist="";
+
+ foreach my $device(split(/\s/,$ENV{disklist})){
+ $devdisklist = "$devdisklist /dev/$device";
+ }
+ print "Probing disks: $devdisklist\n";
+ print "Disks found:";
+ $result = `sh -c "LC_ALL=C sfdisk -g -q $devdisklist"`;
+ foreach my $line(split(/\n/,$result)){
+ if($line =~ m'^/dev/(.+?):\s+(\d+)\s+cylinders,\s+(\d+)\s+heads,\s+(\d+)\s+sectors'i){
+ $disk = $1;
+ $DiskUnits{$disk} = $3 * $4;# heads * sectors = cylinder size in sectors
+ $DiskSize{$disk} = $2; # cylinders
+ ($DOS_Alignment eq "yes") ? ($SectorsAlignment{$disk} = $4) : ($SectorsAlignment{$disk} = 1);
+ print " $disk";
+ }
+ }
+ $result = `sh -c "LC_ALL=C sfdisk -d -q $devdisklist"`;
+ foreach my $line(split(/\n/,$result)){
+# if($line =~ m'# partition table of /dev/(cciss/c\dd\d|ida/c\dd\d|rd/c\dd\d|[a-z]+)'i){
+# now just match all devices
+ if($line =~ m'# partition table of /dev/(\S+)$'i){
+ $disk = $1;
+ }
+ if($line =~ m#^/dev/(.+?)\s*:\s+start=\s*(\d+),\s+size=\s*(\d+),\s+Id=\s*([a-z0-9]+)\b(.*)$#i){
+ $device = $1;
+ # Sectors
+ $PartOldStartSec{$device} = $2;
+ $PartOldEndSec{$device} = $2 + $3 - 1;
+ # DiskUnits
+ $PartOldStart{$device} = int ($2 / $DiskUnits{$disk});
+ $PartOldEnd{$device} = int (($2 + $3 - 1) / $DiskUnits{$disk});
+ $divi = $2 / $SectorsAlignment{$disk};
+ ($divi != int ($divi)) && ($OldNotAligned{$device} = "yes");
+ $divi = $3 / $SectorsAlignment{$disk};
+ ($divi != int ($divi)) && ($OldNotAligned{$device} = "yes");
+ $PartOldID{$device} = $4;
+ $rest = $5;
+ $PartOldBoot{$device} = ($rest =~ /bootable/) ? "yes" : "";
+ }
+ }
+ print "\n\n";
+}
+
+#****************************************************
+# parse config file or all class files
+#****************************************************
+sub ParseAllConfigFiles{
+ my $ConfigFileExists = 0; # no config file parsed yet
+ if ($ConfigFileName){
+ # Read config filename
+ &ParseConfigFile($ConfigFileName);
+ $ConfigFileExists = 1;
+ } else {
+ # Read classes
+ foreach my $classfile (reverse split(/\s+/,$ENV{"classes"})){
+ my $filename = "$ClassPath/$classfile";
+ if (($classfile) && (-r $filename)) {
+ &ParseConfigFile($filename);
+ $ConfigFileExists = 1;
+ }
+ ($ConfigFileExists) && last;
+ }
+ }
+ ($ConfigFileExists == 0) && die "ERROR: no config file for setup_harddisk found. Please check you classes and files in disk_config.\n";
+}
+
+#****************************************************
+# map "disk_config first" to real disk device
+#****************************************************
+sub mapdisk {
+
+ my ($disk) = @_;
+ my @dlist = split /\s+/,$ENV{disklist};
+
+ if ($disk eq "disk1") {
+ print "Mapping disk name disk1 to $dlist[0]\n";
+ $disk = $dlist[0];
+ }
+ if ($disk eq "disk2") {
+ print "Mapping disk name disk2 to $dlist[1]\n";
+ $disk = $dlist[1];
+ }
+ return $disk;
+}
+
+#****************************************************
+# parse config-file
+#****************************************************
+sub ParseConfigFile{
+ my $size=""; my $mountpoint=""; my $device ="";
+ my $fstaboptions=""; my $options=""; my $disk=""; my $command = "";
+ my $LogPartNo; my $PrimPartNo; my $NoMoreLogicals;
+ my $LastPresPart; my $extmp; my $Min; my $Max;
+ my $filename = shift;
+ open (FILE,"$filename")
+ || die "config file not found: $filename\n";
+ (print "Using config file: $filename\n");
+ $disk = "";
+ my $a = 1, my $paras ="", my $number=0;
+ while (my $line = <FILE>){
+ chomp($line);
+ $a++;
+ next if( $line =~ /^#|^\s*$/ );
+
+ # disk_config - command
+ if ($line =~ /^disk_config(.*)/i){
+ $paras = $1;
+ if ($paras =~ / end/i){
+ $disk = "";
+ } else {
+# if($paras =~ m# (/dev/)?(cciss/c\dd\d|ida/c\dd\d|rd/c\dd\d|[a-z]+)#i){
+# now match all devives
+ if($paras =~ m# (/dev/)?(\S+)#i){
+ $disk = mapdisk($2);
+ ($DiskMountpoints{$disk})
+ && die "ERROR: there are more than one configuration of disk $disk.\n";
+ ($DiskSize{$disk}) || die "ERROR: could not read device /dev/$disk\n";
+ ($test != 1) || (print "config: $disk\n");
+ $DiskMountpoints{$disk} = "";
+ $MPPrimary{"extended$disk"} = "";
+ $LogPartNo = 4;
+ $PrimPartNo = 0;
+ $NoMoreLogicals = 0;
+ $LastPresPart = "";
+ $extmp = "extended$disk";
+ } else {
+ die "SYNTAX ERROR: in config file line $a, unknown disk_config parameter $paras\n$line\n";
+ }
+ }
+ }
+
+ if ($disk){
+ # primary|partition - command
+ if($line =~ /^\s*(primary|logical)\s+(.*)$/i){
+ $command = $1;
+ # split variables
+ $paras = $2;
+ $options = "";
+ if($paras =~ /(.*?)\s*;\s*(.*)$/){
+ $paras = $1;
+ $options = $2;
+ }
+ $size="";
+ $mountpoint ="";
+ $fstaboptions = "";
+ ($mountpoint,$size,$fstaboptions)=split(/\s+/,$paras);
+ # mountpoint
+ ($mountpoint =~ m#^/.*|^swap$|^-$#i)
+ || die "SYNTAX ERROR in config file line $a, mountpoint: $mountpoint\n$line\n";
+ ($MountpointPart{$mountpoint})
+ && die "SYNTAX ERROR in config file line $a. Mountpoint $mountpoint redefined.\n$line\n";
+ if($mountpoint eq "/"){
+ ($BootPartition) || ($BOOT_DEVICE = $disk);
+ }
+ if($mountpoint eq "-"){
+ $NofNotMoPart++;
+ $mountpoint = "no$NofNotMoPart";
+ }
+ if($mountpoint eq "swap"){
+ $NofSwapPart++;
+ $mountpoint = "swap$NofSwapPart";
+ ($options !~ /\bswap\b/i) && ($options .= " swap");
+ ($fstaboptions) || ($fstaboptions = "sw");
+ }
+ if($mountpoint =~ m#^/#){
+ ($fstaboptions) || ($fstaboptions = "defaults");
+ }
+ if ($command eq "primary") {
+ ($MPPrimary{$extmp} eq "yes") && ($NoMoreLogicals = 1);
+ $MPPrimary{$mountpoint} = "yes";
+ $PrimPartNo++;
+# ($PrimPartNo == 3) && ($disk =~ /^sd/) && ($PrimPartNo++);
+ ($PrimPartNo >4 ) && die "ERROR: Too much primary partitions (max 4).".
+ " All logicals together need one primary too.\n";
+ $MountpointPart{$mountpoint} = PartName($disk,$PrimPartNo);
+ if($options =~ /\bboot\b/i){
+ ($BootPartition) && die "ERROR: only one partition can be bootable at a time.";
+ $BootPartition = $MountpointPart{$mountpoint};
+ $BOOT_DEVICE = $disk;
+ }
+ } else {
+ ($NoMoreLogicals != 0) && die "ERROR: the logical partitions must be together.\n";
+ $MPPrimary{$mountpoint} = "";
+ $LogPartNo++;
+ $MountpointPart{$mountpoint} = PartName($disk,$LogPartNo);
+ if (!$MPPrimary{$extmp}){
+ $MPPreserve{$extmp} = "";
+ $MPPrimary{$extmp} = "yes";
+ $MPMinSize{$extmp} = 0;
+ $MPMaxSize{$extmp} = 0;
+ $MPID{$extmp} = 5;
+ $PrimPartNo++;
+ ($PrimPartNo == 3) && ($disk =~ /^sd/) && ($PrimPartNo++);
+ ($PrimPartNo >4 )
+ && die "ERROR: too much primary partitions (max 4).".
+ " All logicals together need one primary too.\n";
+ $MountpointPart{$extmp} = PartName($disk,$PrimPartNo);
+ $DiskMountpoints{$disk} .= " $extmp";
+ }
+# ($options =~ /\bboot\b/i) && die "ERROR: line $a, only primary partitions can be bootable.\n";
+ }
+ $DiskMountpoints{$disk} .= " $mountpoint";
+ # size
+ ($size =~ /^preserve\d+$|^\d+\-?\d*$|^-\d+$/i)
+ || die "SYNTAX ERROR in config file line $a, size: $size\n$line\n";
+ if($size =~ /^preserve(\d+)$/i){
+ my $number = $1;
+ $device = PartName($disk,$number);
+ ($OldNotAligned{$device} eq "yes")
+ && die "ERROR: unable to preserve partition /dev/$device. Partition is not DOS aligned.";
+ ($command eq "primary") && ($number != $PrimPartNo)
+ && die "NUMERATION ERROR in line $a, the number of the partition can not be preserved:\n$line\n";
+ ($command eq "logical") && ($number != $LogPartNo)
+ && die "NUMERATION ERROR in line $a, the number of the partition can not be preserved:\n$line\n";
+ if ($PartOldEnd{$device}){
+ (($PartOldID{$device} == 5) || ($PartOldID{$device} == 85)) &&
+ die "ERROR in config file line $a.".
+ " Extended partitions can not be preserved. /dev/$device\n$line\n";
+ $MPPreserve{$mountpoint}="yes";
+ $MPMinSize{$mountpoint} = $PartOldEnd{$device}-$PartOldStart{$device}+1;
+ $MPMaxSize{$mountpoint} = $MPMinSize{$mountpoint}; # Max=Min
+ $MPStart{$mountpoint} = $PartOldStart{$device};
+ $MPSize{$mountpoint} = $MPMinSize{$mountpoint};
+ $MPID{$mountpoint} = $PartOldID{$device};
+ } else {
+ die "ERROR: cannot preserve partition $device. partition not found.$PartOldEnd{$device}\n";
+ }
+ if ($LastPresPart) {
+ ($PartOldStart{$device} < $PartOldStart{$LastPresPart}) &&
+ die "ERROR: misordered partitions: cannot preserve partitions $LastPresPart and $device\n".
+ " in this order because of their positions on disk.";
+ }
+ $LastPresPart = $device;
+ ($MPMinSize{$mountpoint} < 1)
+ && die "ERROR: unable to preserve partitions of size 0.\n$line\n ";
+ } else {
+ # If not preserve we must know the filesystemtype
+ ($options !~ /\b(ext2|ext3|auto|swap|dosfat16|winfat32|reiser|xfs)\b/i ) && ($options .= " auto");
+ }
+ if($size =~ /^(\d*)(\-?)(\d*)$/){
+ $Min = $1;
+ $Min||= 1;
+ $Max = $3;
+ $MPMinSize{$mountpoint} = int (($Min * $megabyte - 1) / ($DiskUnits{$disk} * $sectorsize)) + 1;
+ if ($2 eq "-"){
+ if($Max =~ /\d+/){
+ $MPMaxSize{$mountpoint} = int (($Max * $megabyte - 1) / ($DiskUnits{$disk} * $sectorsize)) + 1;
+ } else {
+ $MPMaxSize{$mountpoint} = $DiskSize{$disk};
+ }
+ } else {
+ $MPMaxSize{$mountpoint} = $MPMinSize{$mountpoint}; # Max=Min
+ }
+ ($MPMinSize{$mountpoint} > $DiskSize{$disk})
+ && die "ERROR in config file line $a: Minsize larger than disk.\n$line\n";
+ ($MPMinSize{$mountpoint} > $MPMaxSize{$mountpoint})
+ && die "SYNTAX ERROR in config file line $a, MIN-MAX-size: $MPMinSize{$mountpoint}-$MPMaxSize{$mountpoint}\n$line\n";
+ ($MPMinSize{$mountpoint} < 1)
+ && die "SYNTAX ERROR in config file line $a. Minsize must be greater than 1.\n$line\n";
+ $MPPreserve{$mountpoint} = "";
+ }
+ # fstaboptions
+ $MPfstaboptions{$mountpoint} = $fstaboptions;
+ # extra options
+ ($options =~ /\b(ext[23]|auto)\b/i) && ($MPID{$mountpoint} = 83); # Linux native
+ ($options =~ /\bswap\b/i) && ($MPID{$mountpoint} = 82); # Linux swap
+ ($options =~ /\bdosfat16\b/i) && ($MPID{$mountpoint} = 6); # DOS FAT 16bit (>=32MB, will be changed later)
+ ($options =~ /\bwinfat32\b/i) && ($MPID{$mountpoint} = "b"); # Win 95 FAT 32
+ $MPOptions{$mountpoint} = $options;
+ if($test == 1){
+ print "$mountpoint,$MPMinSize{$mountpoint}-$MPMaxSize{$mountpoint},";
+ print "$fstaboptions,$options";
+ ($MPPreserve{$mountpoint} eq "yes") && (print " Preserve: $MountpointPart{$mountpoint}");
+ print "\n";
+ }
+ }
+ }
+ }
+ close(FILE);
+}
+
+#****************************************************
+# Build all partition tables
+#****************************************************
+sub BuildNewPartTables{
+ my ($disk, $mountpoint, $part, $PrimaryMP, $LogicalMP);
+ ($test != 1) || (print "\nBuilding partition tables:\n");
+ # Build PartMountpoint array
+ foreach $disk(keys %DiskMountpoints) {
+ $DiskMountpoints{$disk} =~ s/\s(\s)/$1/g;
+ $DiskMountpoints{$disk} =~ s/^\s//;
+ $DiskMountpoints{$disk} =~ s/\s$//;
+ foreach $mountpoint(split(/\s/,$DiskMountpoints{$disk})) {
+ $PartMountpoint{$MountpointPart{$mountpoint}} = $mountpoint;
+ }
+ }
+ foreach $disk(keys %DiskMountpoints) {
+ &SetPartitionPositions($disk);
+ # change units to sectors
+ foreach $mountpoint(split(/\s/,$DiskMountpoints{$disk})) {
+ if($MPPreserve{$mountpoint} eq "yes"){
+ $MPStart{$mountpoint} = $PartOldStartSec{$MountpointPart{$mountpoint}};
+ $MPSize{$mountpoint} = $PartOldEndSec{$MountpointPart{$mountpoint}} - $MPStart{$mountpoint} + 1;
+ } else {
+ $MPStart{$mountpoint} *= $DiskUnits{$disk};
+ $MPSize{$mountpoint} *= $DiskUnits{$disk};
+ # align first partition for mbr
+ if($MPStart{$mountpoint} == 0){
+ $MPStart{$mountpoint} += $SectorsAlignment{$disk};
+ $MPSize{$mountpoint} -= $SectorsAlignment{$disk};
+ }
+ }
+ }
+ # align all logical partitions
+ foreach $mountpoint(split(/\s/,$DiskMountpoints{$disk})) {
+ next if ($MPPrimary{$mountpoint} eq "yes");
+ if ($MountpointPart{$mountpoint} eq "${disk}5") {
+ # partition with number 5 is first logical partition and start of extended partition
+ $MPStart{"extended$disk"} = $MPStart{$mountpoint};
+ ($MPPreserve{$mountpoint} eq "yes") && ($MPStart{"extended$disk"} -= $SectorsAlignment{$disk});
+ }
+ if ($MPPreserve{$mountpoint} ne "yes") {
+ $MPStart{$mountpoint} += $SectorsAlignment{$disk};
+ $MPSize{$mountpoint} -= $SectorsAlignment{$disk};
+ }
+ }
+ &CalculateExtPartSize($disk);
+ # sort mountpoints of partition number
+ $PrimaryMP = "";
+ $LogicalMP = "";
+ foreach $mountpoint(split(/\s/,$DiskMountpoints{$disk})) {
+ ($MPPrimary{$mountpoint} eq "yes") ? ($PrimaryMP .= " $mountpoint") : ($LogicalMP .= " $mountpoint");
+ }
+ $DiskMountpoints{$disk} = "$PrimaryMP$LogicalMP";
+ $DiskMountpoints{$disk} =~ s/^\s//;
+ # print partition table
+ ($test != 1) || (PrintPartitionTable($disk));
+ }
+ if (!$BootPartition){
+ $BootPartition = $MountpointPart{"/"};
+ }
+}
+
+#****************************************************
+# set position for every partition
+#****************************************************
+sub SetPartitionPositions{
+ my $disk = shift;
+ my $mountpoint; my $DynGroup =""; my $StartPos; my $EndPos;
+ # Build groups of unpreserved partitions between
+ # preserved partitions
+ $StartPos = 0;
+ foreach $mountpoint(split(/\s/,$DiskMountpoints{$disk})) {
+ if ($MPPreserve{$mountpoint} eq "yes") {
+ $EndPos = $PartOldStart{$MountpointPart{$mountpoint}} - 1;
+ &SetGroupPos($DynGroup,$StartPos,$EndPos);
+ $DynGroup = "";
+ $StartPos = $PartOldEnd{$MountpointPart{$mountpoint}} + 1;
+ } else {
+ $DynGroup .= " $mountpoint";
+ }
+ }
+ $EndPos = $DiskSize{$disk} - 1;
+ &SetGroupPos($DynGroup,$StartPos,$EndPos);
+ foreach $mountpoint(split(/\s/,$DiskMountpoints{$disk})) {
+ ($MPOptions{$mountpoint} =~ /\bdosfat16\b/i)
+ && (($MPSize{$mountpoint} * $DiskUnits{$disk} * $sectorsize) < 32 * $megabyte)
+ && ($MPID{$mountpoint} = 4); # DOS 16-bit FAT <32MB
+ }
+}
+
+#****************************************************
+# set position for a group of unpreserved partitions
+# between start and end
+#****************************************************
+sub SetGroupPos{
+ my ($PartGroup,$Start,$End) = @_;
+ $PartGroup =~ s/^ //;
+ ($PartGroup) || return;
+ my $totalsize = $End - $Start + 1;
+ ($totalsize <= 0) && return;
+ my $mountpoint; my $mintotal = 0; my $maxmintotal = 0; my $rest = 0; my $EndUnit = 0;
+ # compute total of MinSizes and difference to MaxSizes
+ foreach $mountpoint (split(/\s/,$PartGroup)) {
+ $mintotal += $MPMinSize{$mountpoint};
+ $maxmintotal += ($MPMaxSize{$mountpoint} - $MPMinSize{$mountpoint});
+ $MPSize{$mountpoint} = $MPMinSize{$mountpoint};
+ }
+ # Test if partitions fit
+ ($mintotal > $totalsize)
+ && die "ERROR: Mountpoints $PartGroup do not fit.\n";
+ # Maximize partitions
+ $rest = $totalsize - $mintotal;
+ ($rest > $maxmintotal) && ($rest = $maxmintotal);
+ if ($rest > 0) {
+ foreach $mountpoint (split(/\s/,$PartGroup)) {
+ $MPSize{$mountpoint} += int ((($MPMaxSize{$mountpoint} - $MPMinSize{$mountpoint}) * $rest) / $maxmintotal);
+ }
+ }
+ # compute rest
+ $rest = $totalsize;
+ foreach $mountpoint (split(/\s/,$PartGroup)) {
+ $rest -= $MPSize{$mountpoint};
+ }
+ # Minimize rest
+ foreach $mountpoint (split(/\s/,$PartGroup)) {
+ if (($rest >0) && ($MPSize{$mountpoint} < $MPMaxSize{$mountpoint})){
+ $MPSize{$mountpoint}++;
+ $rest--;
+ }
+ }
+ # Set start for every partition
+ foreach $mountpoint (split(/\s/,$PartGroup)) {
+ $MPStart{$mountpoint} = $Start;
+ $Start += $MPSize{$mountpoint};
+ $EndUnit = $MPStart{$mountpoint} + $MPSize{$mountpoint} - 1;
+ }
+}
+
+#****************************************************
+# calculate extended partition size
+#****************************************************
+sub CalculateExtPartSize{
+ my ($disk) = @_;
+ my $extmp = "extended$disk";
+ my $mountpoint; my $ExtEnd; my $NewEnd;
+ ($MPPrimary{$extmp}) || return;
+ $ExtEnd = $MPStart{$extmp};
+ foreach $mountpoint(split(/\s/,$DiskMountpoints{$disk})) {
+ next if ($MPPrimary{$mountpoint} eq "yes");
+ $NewEnd = $MPStart{$mountpoint} + $MPSize{$mountpoint} - 1;
+ ($NewEnd > $ExtEnd) && ($ExtEnd = $NewEnd);
+ }
+ $MPSize{$extmp} = ($ExtEnd - $MPStart{$extmp} + 1);
+}
+
+#****************************************************
+# Print partition "number - mountpoint" table
+#****************************************************
+sub PrintPartitionTable{
+ my ($disk) = @_;
+ my $part; my $mountpoint; my $mountpointname; my $end;
+ foreach $part (sort %MountpointPart) {
+ next if($part !~ /^$disk/);
+ $mountpoint = $PartMountpoint{$part};
+ if ($mountpoint =~ /^no(.*)/){
+ $mountpointname = "no mountpoint ($1)";
+ } else {
+ $mountpointname = $mountpoint;
+ }
+ $end = $MPStart{$mountpoint} + $MPSize{$mountpoint} - 1;
+ print <<"EOM";
+/dev/$part $mountpointname start=$MPStart{$mountpoint} size=$MPSize{$mountpoint} end=$end id=$MPID{$mountpoint}
+EOM
+ }
+}
+
+#****************************************************
+# build all partition tables for sfdisk
+#****************************************************
+sub PartitionPersfdisk{
+ my ($disk, $mountpoint, $line, $part, $PrimaryNo);
+ my ($command, $result, $filename, $number);
+ print "Creating partition table: ";
+ foreach $disk(keys %DiskMountpoints) {
+ $sfdiskTables{$disk} = "# partition table of device: /dev/$disk\nunit: sectors\n\n";
+ $PrimaryNo = 1;
+ foreach $mountpoint(split(/\s/,$DiskMountpoints{$disk})) {
+ $part = $MountpointPart{$mountpoint};
+ $part =~ /(\d+)$/;
+ ($1 < 5) && ($PrimaryNo++);
+ if ( ($1 == 5) && ($PrimaryNo < 5) ){
+ for my $number($PrimaryNo..4) {
+ $sfdiskTables{$disk} .= BuildsfdiskDumpLine(PartName($disk,$number),0,0,0)."\n";
+ }
+ }
+ $line = BuildsfdiskDumpLine($MountpointPart{$mountpoint},$MPStart{$mountpoint},$MPSize{$mountpoint},$MPID{$mountpoint});
+ ($part eq $BootPartition) && ($line .= ", bootable");
+ $sfdiskTables{$disk} .= "$line\n";
+ }
+# print $sfdiskTables{$disk};
+ $filename = "$ENV{LOGDIR}/partition." . (($disk=~ m#/#) ? join('_', split('/', $disk)) : $disk);
+ if(($test != 1) && ($filename)){
+ open(FILE, ">$filename") || die "unable to write temporary file $filename\n";
+ print FILE $sfdiskTables{$disk};
+ close(FILE);
+ }
+ $command = "LC_ALL=C sfdisk $sfdisk_options /dev/$disk < $filename";
+ if($test != 1){
+ print "$command\n";
+ $result = `sh -c "$command"`;
+ (($? >> 8) == 0) || (die "\nSFDISK ERROR:\n $result\n");
+ }
+ }
+}
+
+#****************************************************
+# build a sfdisk dump line
+#****************************************************
+sub BuildsfdiskDumpLine{
+
+ sprintf "/dev/%-5s: start=%10s, size=%10s, Id=%3s",@_;
+}
+
+#****************************************************
+# Format all disks
+#****************************************************
+sub FormatDisks{
+ my ($disk, $device, $mountpoint, $mountpointname, $command, $result);
+ print "Creating file systems:\n";
+ foreach $disk(keys %DiskMountpoints) {
+ foreach $mountpoint (split(/\s/,$DiskMountpoints{$disk})) {
+ $device = $MountpointPart{$mountpoint};
+ if ($mountpoint =~ /^no/){
+ $mountpointname = "no mountpoint";
+ } else {
+ $mountpointname = $mountpoint;
+ }
+ # preserved partition
+ if ( ($MPPreserve{$mountpoint} eq "yes") && ($MPOptions{$mountpoint} !~ /\bformat\b/i)){
+ print "Preserve partition $device";
+ if ($mountpoint =~ /^no$1/){
+ print " with no mountpoint\n";
+ } else {
+ print " with mountpoint $mountpoint\n";
+ }
+ next;
+ }
+ # lazy format
+ if ( ( $MPOptions{$mountpoint} =~ /\blazyformat\b/i )
+ && ($MPStart{$mountpoint} == $PartOldStartSec{$device})
+ && (($MPStart{$mountpoint} + $MPSize{$mountpoint} - 1) == $PartOldEndSec{$device}) ){
+ print "Lazy format: $device";
+ if ($mountpoint =~ /^no$1/){
+ print " with no mountpoint";
+ } else {
+ print " with mountpoint $mountpoint";
+ }
+ print " was neither moved nor formated.\n";
+ next;
+ }
+ # swap
+ if ($mountpoint =~ /^swap/i) {
+# print "Make swap partition:\n";
+ $command = "mkswap $mkswap_options";
+ ($MPOptions{$mountpoint} =~ /(\-c)\b/i) && ($command .= " $1");
+ push @swaplist, "/dev/$device";
+ $command .= " /dev/$device";
+ print " $command\n";
+ if($test != 1){
+ $result = `$command`;
+ (($? >> 8) == 0) || (die "\nMKSWAP ERROR:\n $result\n");
+ }
+ next;
+ }
+ # Linux Reiser file system
+ if ($MPOptions{$mountpoint} =~ /\breiser\b/i) {
+# print "Make Reiser Filesystem:\n";
+ $command = "echo y | mkreiserfs $mkreiserfs_options";
+ ($MPOptions{$mountpoint} =~ /(\-h\s*\w+)\b/) && ($command .= " $1");
+ ($MPOptions{$mountpoint} =~ /(\-v\s*\d+)\b/) && ($command .= " $1");
+ $command .= " /dev/$device";
+ print " $command\n";
+ if ($test != 1){
+ $result = `$command`;
+ (($? >> 8) == 0) || die "\nMKREISERFS ERROR:\n $result\n";
+ }
+ next;
+ }
+ # Linux XFS file system
+ if ($MPOptions{$mountpoint} =~ /\bxfs\b/i) {
+# print "Make XFS Filesystem:\n";
+ $command = "mkfs.xfs $mkxfs_options";
+ $command .= " /dev/$device";
+ print " $command\n";
+ if ($test != 1){
+ $result = `$command`;
+ (($? >> 8) == 0) || die "\nMKFS.XFS ERROR:\n $result\n";
+ }
+ next;
+ }
+ # Linux Extended 2 file system
+ if ($MPOptions{$mountpoint} =~ /\b(ext[23]|auto)\b/i) {
+# print "Make Extended 2/3 Filesystem:\n";
+ $command = "mke2fs $mke2fs_options";
+ ($MPOptions{$mountpoint} =~ /(\-c)\b/i) && ($command .= " $1");
+ ($MPOptions{$mountpoint} =~ /(\-i\s*\d+)\b/) && ($command .= " $1");
+ ($MPOptions{$mountpoint} =~ /(\-m\s*\d+)\b/) && ($command .= " $1");
+ ($MPOptions{$mountpoint} =~ /(\-j)\b/) && ($command .= " $1");
+ $command .= " /dev/$device";
+ print " $command\n";
+ if ($test != 1){
+ $result = `$command`;
+ (($? >> 8) == 0) || die "\nMKE2FS ERROR:\n $result\n";
+ }
+ next;
+ }
+ # DOS 16bit FAT / Win95 FAT 32
+ if ($MPOptions{$mountpoint} =~ /\b(dosfat16|winfat32)\b/i) {
+ print "Clear first sector for DOS/Windows\n";
+ $command = "dd if=/dev/zero of=/dev/$MountpointPart{$mountpoint} bs=512 count=1";
+ print " $command\n";
+ if ($test != 1){
+ $result = `$command`;
+ (($? >> 8) == 0) || die "\nDD ERROR:\n $result\n";
+ }
+ next;
+ }
+ }
+ }
+}
+
+#****************************************************
+# Build fstab and write it to <root>/etc/fstab
+#****************************************************
+sub WriteFSTab{
+ my ($FileSystemTab, $device, $type, $filename);
+ $FileSystemTab = << "EOM";
+# /etc/fstab: static file system information.
+#
+#<file sys> <mount point> <type> <options> <dump> <pass>
+EOM
+ # 1. /
+ $type = "ext2";
+ ($MPOptions{'/'} =~ /\b(reiser)\b/i) && ($type = "reiserfs");
+ ($MPOptions{'/'} =~ /\b(xfs)\b/i) && ($type = "xfs");
+ ($MPOptions{'/'} =~ /\b(ext3)\b/i) && ($type = "ext3");
+ ($MPOptions{'/'} =~ /\b(ext2)\b/i) && ($type = "ext2");
+ $FileSystemTab .= BuildfstabLine("/dev/$MountpointPart{'/'}","/",$type,$MPfstaboptions{'/'},0,1);
+ # 2. swap partitions
+ foreach my $mountpoint (%PartMountpoint){
+ next if( $mountpoint !~ /^swap/i);
+ $FileSystemTab .= BuildfstabLine("/dev/$MountpointPart{$mountpoint}",
+ "none","swap",$MPfstaboptions{$mountpoint},0,0);
+ }
+ # 3. /proc
+ $FileSystemTab .= BuildfstabLine("none","/proc","proc","defaults",0,0);
+ # 4. sorted others
+ foreach my $mountpoint (sort %PartMountpoint){
+ next if ( ($mountpoint !~ m#^/#) || ($mountpoint eq "/"));
+ $device = $MountpointPart{$mountpoint};
+ $type = "ext2";
+ ($MPOptions{$mountpoint} =~ /\b(dosfat16|winfat32)\b/i) && ($type = "vfat");
+ ($MPOptions{$mountpoint} =~ /\b(reiser)\b/i) && ($type = "reiserfs");
+ ($MPOptions{$mountpoint} =~ /\b(xfs)\b/i) && ($type = "xfs");
+ ($MPOptions{$mountpoint} =~ /\b(ext3)\b/i) && ($type = "ext3");
+ ($MPOptions{$mountpoint} =~ /\b(ext2)\b/i) && ($type = "ext2");
+ $FileSystemTab .= BuildfstabLine("/dev/$device",$mountpoint,$type,$MPfstaboptions{$mountpoint},0,2);
+ }
+ # write it
+ $filename = "$ENV{LOGDIR}/fstab";
+# print $FileSystemTab;
+ print "Write fstab to $filename\n" if $verbose;
+ if($test != 1){
+ open(FILE, ">$filename") || die "unable to write fstab $filename\n";
+ print FILE $FileSystemTab;
+ close(FILE);
+ }
+}
+
+#****************************************************
+# Build fstab line
+#****************************************************
+sub BuildfstabLine{
+
+ sprintf "%-10s %-15s %-6s %-8s %-4s %-4s\n",@_;
+}
+
+#****************************************************
+# Write all FAI variables of this program to file
+#****************************************************
+sub WriteFAIVariables{
+
+ my $swaps;
+
+ print "Write FAI variables to file $FAIOutputFile\n" if $verbose;
+ return if ($test == 1);
+ $swaps = join ' ',@swaplist;
+ open(FILE, ">$FAIOutputFile") || die "Unable to write file $FAIOutputFile\n";
+ print FILE << "EOM";
+BOOT_DEVICE=/dev/$BOOT_DEVICE
+ROOT_PARTITION=/dev/$MountpointPart{'/'}
+BOOT_PARTITION=/dev/$BootPartition
+SWAPLIST="$swaps"
+EOM
+ close(FILE);
+}
diff --git a/contrib/fai/goto-fai/diversions/subroutines b/contrib/fai/goto-fai/diversions/subroutines
--- /dev/null
@@ -0,0 +1,449 @@
+#! /bin/bash
+
+# $Id: subroutines,v 1.65 2005/04/06 19:03:46 lange Exp $
+#*********************************************************************
+#
+# subroutines -- useful subroutines for FAI
+#
+# This script is part of FAI (Fully Automatic Installation)
+# (c) 2000-2005 by Thomas Lange, lange@informatik.uni-koeln.de
+# Universitaet zu Koeln
+#
+#*********************************************************************
+# 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.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# A copy of the GNU General Public License is available as
+# `/usr/share/common-licences/GPL' in the Debian GNU/Linux distribution
+# or on the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You
+# can also obtain it by writing to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#*********************************************************************
+
+# source this file, then you have these function available in the shell
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+die() {
+
+ # echo comment and exit installation
+ task_savelog
+ echo "$@"
+ exec bash
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+defnop() {
+
+ # define given list of subroutine names as dummy function;
+ # this will fake unknown commands
+
+ local name
+ for name in "$@";do
+ eval "$name () { :;}"
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ifclass() {
+
+ [ "$debug" ] && echo "Test if class $1 is in $classes"
+ # test if a class is defined
+ local cl
+ local ret=1
+
+ for cl in $classes; do
+ [ x$cl = x$1 ] && ret=0 && break
+ done
+ [ "$debug" ] && echo "ifclass returns $ret"
+ return $ret
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+rwmount() {
+
+ # remount partition read/write
+ mount -o rw,remount $1
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+save_dmesg() {
+
+ dmesg > $LOGDIR/dmesg.log
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+wait_for_jobs() {
+
+ # can be an extern script
+ # wait for running (background) jobs to finish (e.g. update-auctex-elisp)
+ local i=0
+ while jobsrunning; do
+ [ $(($i % 3)) -eq 0 ] && echo "Waiting for background jobs to finish."
+ i=$(($i+1))
+ sleep 10
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task() {
+
+ # hooks are called before a task is called
+ # if a task is skipped, also its hooks are skipped
+ # a hook can set the flag, so the accociated task is skipped
+
+ local taskname=$1
+
+ [ -f $LOGDIR/skip.$taskname ] || call_hook $taskname
+
+ if [ -f $LOGDIR/skip.$taskname ]; then
+ # skip task
+ rm $LOGDIR/skip.$taskname
+ [ "$verbose" ] && echo "Skiping task_$taskname"
+ sndmon "TASKSKIP $taskname"
+ else
+ echo "Calling task_$taskname"
+ sndmon "TASKBEGIN $taskname"
+ terror=0 # task can set this variable to indicate an error
+ task_$taskname
+ sndmon "TASKEND $taskname $terror"
+ fi
+ # since the subroutine is not needed any more, we can undefine it
+ unset task_$taskname
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+call_hook() {
+
+ local hook=$1
+ local cl dflag hfile
+ [ "$debug" ] && dflag="-d"
+
+ for cl in $classes; do
+ hfile=$FAI/hooks/$hook.$cl
+ if [ -x $hfile ]; then
+ echo "Calling hook: $hook.$cl"
+ sndmon "HOOK $hook.$cl"
+ # execute the hook
+ $hfile $dflag
+ check_status $hook.$cl $?
+ fi
+ if [ -x $hfile.source ]; then
+ echo "Source hook: $hook.$cl.source"
+ sndmon "HOOK $hook.$cl.source"
+ # source this hook
+ . $hfile.source $dflag
+ check_status $hook.$cl.source $?
+ fi
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+skiptask() {
+
+ # mark all given tasks, so they will be skipped
+ local tasklist="$@"
+ local task
+
+ for task in $tasklist; do
+ > $LOGDIR/skip.$task
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+get_fai_dir() {
+
+ /usr/sbin/get_fai_dir
+ ln -s $FAI $rundir/current_config
+ if [ ! -d $FAI/class ]; then
+ echo "WARNING: directory $FAI/class not found."
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+get_fai_cvs() {
+
+ # subroutine which gets $FAI (/fai) configuration directory from
+ # a cvs repository. You can redefine this subroutine if you need
+ # access via ftp, http, or from a database
+
+ if [ "$FAI_CVSROOT" ] ; then
+ local TAG=""
+ [ -n "$FAI_CVSTAG" ] && TAG="-r $FAI_CVSTAG"
+ export FAI_CONFIG_AREA=$FAI_ROOT$FAI
+ export FAI=$(mktemp -t -d fai-config.XXXXXX)
+
+ [ "$debug" ] && echo "\$FAI now points to $FAI"
+
+ if [ -d "$FAI_CONFIG_AREA/CVS" -a -z "$FORCE" ] ; then
+ echo "Config found at $FAI_CONFIG_AREA: Copying"
+ cp -a $FAI_CONFIG_AREA/. $FAI
+ echo "Updating CVS"
+ cd $FAI
+ cvs -q -d"$FAI_CVSROOT" up -P $TAG -d -C > $LOGDIR/cvs.log
+ else
+ echo "Checking out CVS"
+ cd /tmp
+ cvs -q -d"$FAI_CVSROOT" co -P -d $(basename "$FAI") \
+ $TAG $FAI_CVSMODULE > $LOGDIR/cvs.log
+ fi
+ else
+ echo "Warning $0: Neither \$FAI_LOCATION nor \$FAI_CVSROOT are defined."
+ fi
+ cd /
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+define_fai_flags() {
+
+ local flag
+ # FAI_FLAGS are comma separated, define all flags
+ FAI_FLAGS=${FAI_FLAGS//,/ }
+ [ "$verbose" ] && echo "FAI_FLAGS: $FAI_FLAGS"
+ for flag in $FAI_FLAGS; do
+ # define this flag as 1
+ eval "$flag=1"
+ done
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_setup() {
+
+ # source user specific subroutines
+ [ -f $FAI/hooks/subroutines ] && . $FAI/hooks/subroutines
+ if [ $DO_INIT_TASKS -eq 1 ]; then
+ # set the system time and date using rdate or/and ntpdate
+ [ "$TIMESRVS_1" ] && rdate $TIMESRVS_1
+ [ "$NTPSRVS_1" ] && ntpdate -b -v $NTPSRVS
+ fi
+
+ define_fai_flags
+ DNSDOMAIN=$DOMAIN # cfengine 1.5.3 can't use $DOMAIN
+
+ if [ $DO_INIT_TASKS -eq 1 ] ; then
+ [ "$createvt" ] && {
+ # create two virtual terminals; acces via alt-F2 and alt-F3
+ echo "Press ctrl-c to interrupt FAI and to get a shell"
+ openvt -c2 /bin/bash ; openvt -c3 /bin/bash
+ trap 'echo "You can reboot with faireboot";bash' INT QUIT
+ }
+
+ # start secure shell daemon for remote access
+ [ "$sshd" -a -x /usr/sbin/sshd ] && /usr/sbin/sshd
+ fi
+
+ # when did FAI start, using localtime
+ FAI_RUNDATE=$(date +'%Y%m%d_%H%M%S')
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_action() {
+
+ if [ -z "$FAI_ACTION" ]; then
+ echo "No action in \$FAI_ACTION defined."
+ sndmon "TASKERROR action 21"
+ task_faiend
+ exit
+ fi
+ echo "FAI_ACTION: $FAI_ACTION"
+ case $FAI_ACTION in
+
+ install)
+ if [ $DO_INIT_TASKS -eq 0 ]; then
+ echo "Cowardly refusing to run a FAI installation on a running system."
+ return
+ fi
+ echo Performing FAI installation. All data may be overwritten!
+ echo -ne "\a"; sleep 1
+ echo -ne "\a"; sleep 1
+ echo -e "\a"; sleep 5
+ task install
+ task faiend
+ ;;
+ softupdate)
+ echo Performing FAI system update. All data may be overwritten!
+ task softupdate
+ ;;
+ sysinfo)
+ echo Showing system information.
+ task sysinfo
+ task_faiend
+ die Now you have a shell.
+ ;;
+ *)
+ if [ -f $FAI/hooks/$FAI_ACTION ]; then
+ echo "Calling user defined action: $FAI_ACTION"
+ $FAI/hooks/$FAI_ACTION
+ else
+ echo "ERROR: User defined action $FAI/hooks/$FAI_ACTION not found."
+ sndmon "TASKERROR action 22"
+ task_faiend
+ fi
+ ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_defclass() {
+
+ if [ ! -d $FAI/class ]; then
+ sndmon "TASKERROR defclass 21"
+ echo "Directory $FAI/class not found. Following subdirectories are found:"
+ find $FAI -type d -maxdepth 1 -printf "%p\n"
+ die "Aborting."
+ fi
+
+ # new script for defining classes; variables imported: $LOGDIR, $verbose, $debug
+ if [ $renewclass -eq 1 ]; then
+ # reevaluate new list of classes
+ fai-class -T $FAI/class $LOGDIR/FAI_CLASSES
+ classes=$(< $LOGDIR/FAI_CLASSES)
+ else
+ # use classes defined at installation time
+ if [ ! -f /var/log/fai/FAI_CLASSES ]; then
+ die "Try to read classes from /var/log/fai/FAI_CLASSES. Failed. Aborting."
+ fi
+ classes=$(< /var/log/fai/FAI_CLASSES)
+ fi
+
+ # define classes as: a.b.c.d for cfengine -D
+ # this doesn't work without echo
+ cfclasses=$(echo $classes)
+ cfclasses=${cfclasses// /.}
+ [ "$debug" ] && echo "cfclasses: $cfclasses"
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_defvar() {
+
+ cd $FAI/class
+ for class in $classes ; do
+ if [ -f $class.var ]; then
+ [ "$verbose" ] && echo "Executing $class.var"
+ [ "$debug" ] && set -vx
+ . $class.var </dev/null
+ [ "$debug" ] && set +vx
+ fi
+ done
+
+ # /fai/class/S* scripts or hooks can write variable definitions
+ # to additonal.var. now source these definitions
+ [ "$debug" ] && set -vx
+ [ -f $LOGDIR/additional.var ] && . $LOGDIR/additional.var
+ [ "$debug" ] && set +vx
+ unset class
+ # now all variables are defined. Dump them to variables.sh
+ set | perl -ne 'print if /^\w\w+=/' | egrep -v "^BASH_VERSINFO|^EUID|^PPID|^SHELLOPTS|^UID|^rootpw|^HOME|^PWD" > $LOGDIR/variables.sh
+ cd /
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_mountdisks() {
+
+ [ ! -f $LOGDIR/$fstab ] && die "No $LOGDIR/$fstab created."
+ # mount swap space
+ local sd
+ for sd in $SWAPLIST; do
+ swapon $sd && [ "$verbose" ] && echo "Enable swap device $sd"
+ done
+ mount2dir $FAI_ROOT $LOGDIR/$fstab
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_configure() {
+
+ fai-do-scripts $FAI/scripts
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_savelog() {
+
+ [ -d $target/var/log/fai ] || mkdir -p $target/var/log/fai
+ [ -d $target/var/log/fai ] && fai-savelog -l
+ cd $LOGDIR && cp -p FAI_CLASSES variables.sh $diskvar $target/var/log/fai
+ fai-savelog -r
+ cd /
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_faiend() {
+
+ [ $DO_INIT_TASKS -eq 0 ] && exit 0
+ wait_for_jobs
+ echo "Press <RETURN> to reboot or ctrl-c to execute a shell"
+ # reboot without prompting if FAI_FLAG reboot is set
+ [ -z $reboot ] && read
+ echo "Rebooting $HOSTNAME now"
+ sndmon REBOOT
+ cd /
+ sync
+
+ case $(uname -s) in
+ Linux)
+ killall -q sshd
+ umount $target/proc
+ umount -ar
+ exec reboot -dfi
+ ;;
+ esac
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_backup() {
+
+ die "Task backup not yet used. But you can use the hook backup."
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_install() {
+
+ > $stamp
+
+ save_dmesg
+
+ task partition
+ task mountdisks
+ task extrbase
+ task mirror
+ task debconf
+ task prepareapt
+ task updatebase
+ task instsoft
+ task configure
+ task finish
+ task chboot
+
+ rm -f $stamp
+ # save again, because new messages could be created
+ save_dmesg
+ task savelog
+
+ if [ -f $stamp ]; then
+ echo "Error while executing commands in subshell."
+ echo "$stamp was not removed."
+ sndmon "TASKERROR install 21"
+ die "Please look at the log files in $LOGDIR for errors."
+ fi
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+task_softupdate() {
+
+ > $stamp
+
+ save_dmesg
+
+ local start_seconds=$(cut -d . -f 1 /proc/uptime)
+ task mirror
+ task debconf
+ task prepareapt
+ task updatebase
+ task instsoft
+ task configure
+ date
+ echo "The update took $[$(cut -d . -f 1 /proc/uptime)-$start_seconds] seconds."
+
+ rm -f $stamp
+ # save again, because new messages could be created
+ save_dmesg
+ task savelog
+
+ if [ -f $stamp ]; then
+ echo "Error while executing commands in subshell."
+ echo "$stamp was not removed."
+ sndmon "TASKERROR softupdate 21"
+ die "Please look at the log files in $LOGDIR for errors."
+ fi
+ umount $FAI_ROOT/fai
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+catnc() {
+ # cat but no comment lines
+ egrep -v "^#" $@
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/contrib/fai/goto-fai/faimond b/contrib/fai/goto-fai/faimond
--- /dev/null
@@ -0,0 +1,93 @@
+#!/usr/bin/perl
+
+# $Id: faimond,v 1.2 2004/06/27 11:18:55 lange Exp $
+#*********************************************************************
+#
+# faimond -- monitor daemon which collects client status info
+#
+# This script is part of FAI (Fully Automatic Installation)
+# (c) 2003-2004 by Thomas Lange, lange@informatik.uni-koeln.de
+# Universitaet zu Koeln
+#
+#*********************************************************************
+
+#use strict;
+use Socket;
+
+$| = 1;
+my $port = 4711;
+
+@tasklist = qw/confdir defclass defvar partition mountdisks extrbase updatebase instsoft configure finish/;
+
+%tasks = (
+confdir => [' ', "Beziehe System-Einstellungen"],
+defclass => [' ',"Definieren von Klassen"],
+defvar => [' ',"Definieren von Variablen"],
+partition => [' ',"Paritionieren der Festplatten"],
+mountdisks => [' ',"Einbinden der Dateisysteme"],
+extrbase => [' ',"Installieren des Basis-Systems"],
+updatebase => [' ',"Aktualisieren des Basis-Systems"],
+instsoft => [' ',"Installieren der Software"],
+configure => [' ',"Abschließende Konfiguration"],
+finish => [' ',"Abschließen der Installation"]
+);
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub server_init() {
+
+ my $proto = getprotobyname('tcp');
+ socket(SERVER, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
+ setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1) or die "setsock: $!";
+
+ my $paddr = sockaddr_in($port, INADDR_ANY);
+
+ bind(SERVER, $paddr) or die "bind: $!";
+ listen(SERVER, SOMAXCONN) or die "listen: $!";
+# print "FAI monitoring daemon started on port $port\n";
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub big_loop() {
+
+ # accept a connection, print message received and close
+ my ($client_addr,$inp);
+ while ($client_addr = accept(CLIENT, SERVER)) {
+ $inp = <CLIENT>;
+ close CLIENT;
+ ($host,$begend,$task,$ecode) = split /\s+/,$inp;
+ chomp $ecode;
+ $strecode = sprintf "%-3s",$ecode;
+ $sym = ($begend =~ /TASKEND/) ? " \\Z2OK\\Zn" : " ->";
+ $tasks{$task}[0] = $ecode ? " \\Z1E$strecode\\Zn" : $sym;
+ showtab();
+
+ # Stop if we've reached faiend
+ if ( $task =~ /faiend/ ){
+ system("dialog --timeout 60 --msgbox '\nDie Installation wurde abgeschlossen. Drücken Sie die Eingabetaste um das System neu zu starten.' 8 60");
+ break;
+ }
+ }
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub showtab() {
+
+# nach taskbeg soll es blinken, bei taskend, X oder error code
+
+ my $pre = '--colors --title " Aktueller Installationsverlauf "';
+ my $s2 = " --infobox \"\n";
+ # show tabular %tasks
+
+ $str = "$pre $s2";
+ foreach (@tasklist) {
+ $x = sprintf "%5s $tasks{$_}[1]\n", $tasks{$_}[0];
+ $str .= $x;
+ }
+
+ $str .= "\" 14 50\n";
+# print $str;
+ system("dialog $str");
+
+}
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+server_init;
+big_loop;
diff --git a/contrib/fai/goto-fai/get_fai_dir b/contrib/fai/goto-fai/get_fai_dir
--- /dev/null
@@ -0,0 +1,128 @@
+#!/bin/sh
+# FAI script for preparing LDAP objects. It calls ldap2fai to generate
+# the config space after everything is done.
+#
+# (C) 2005 Cajus Pollmeier <pollmeier@gonicus.de>
+echo 0 > /proc/sys/kernel/printk
+trap '' INT
+PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH
+LANG=C
+
+. /usr/lib/goto/goto-support.lib
+
+#dialog() {
+# echo $*
+#}
+
+abort() {
+ setterm -cursor off
+ while true; do sleep 60; done
+}
+
+# Try to figure out which interface is configured, in doubt
+# choose the first one.
+interfaces=$(ifconfig | awk '/^[a-z0-9]/ {print $1}' | grep -v "lo")
+for int in $interfaces; do
+ ip=$(v=`ifconfig $int | awk '/inet addr/ {print $2}'`; echo ${v##*:})
+ mac=$(ifconfig $int | awk '/HWaddr/ {print $5}')
+ [ -n "$ip" ] && break
+done
+
+# Cancel if there's no IP available
+if [ -z "$ip" ]; then
+ dialog --title 'Fehler' --no-shadow --infobox 'Fehler: Das System konnte keine Netzwerk-Adresse ermitteln.\n\nDie Installation kann ohne diese Adresse nicht fortgesetzt werden.' 5 60
+ abort
+fi
+
+# Check if DNS setup is correct and set the hostname
+hostname=$(get_hostname_from_ip $ip)
+if [ "$hostname" == "unknown" ]; then
+ dialog --title 'Fehler' --no-shadow --infobox 'Fehler: Das System konnte keinen Rechner-Namen ermitteln.\n\nDie Installation kann ohne diese Information nicht fortgesetzt werden.' 5 60
+ abort
+fi
+
+echo "* setting hostname: $hostname"
+hostname "$hostname"
+mount -t tmpfs tmpfs /etc/ldap
+
+
+# Look for interesting parameters on kernel commandline
+ldap=""; splash=""
+for v in $(cat /proc/cmdline); do
+ case $v in
+ ldap=*)
+ echo -n "* found LDAP information, adapting configuration: "
+ ldap=$(echo ${v##ldap=}|base64-decode)
+
+ # ldap://hostname:389/basedn
+ LDAP_HOST=$(echo $ldap|sed 's!^[^:][^:]*://\([^:/][^:/]*\).*$!\1!g')
+ LDAP_PORT=$(echo $ldap|sed 's!^[^:]*://[^:][^:]*:\([0-9]*\)/.*$!\1!g')
+ echo -n $ldap_port | grep -q '^[0-9]*$' || LDAP_PORT=389
+ LDAP_BASE=$(echo $ldap|sed 's!^[^:][^:]*://[^/][^/]*/\(.*\)$!\1!g')
+ echo -e "BASE $LDAP_BASE\nURI ldap://$LDAP_HOST:$LDAP_PORT\n" > /etc/ldap/ldap.conf
+ echo "ok"
+ ;;
+ splash=*)
+ echo -n "* setting splash mode: "
+ splash=$(echo ${v##splash=})
+ [ $splash == "silent" ] && echo "silent" || echo "normal"
+ ;;
+ esac
+done
+
+[ -z "$ldap" ] && exit 0
+
+# Check if autosetup is needed at this point
+echo -n "* configurator: "
+if ! terminal_has_hardware_profile $mac; then
+ setterm -cursor off
+ echo "not configured yet - please wait, detecting hardware"
+
+ # Switch from bootsplash to normal screen, show dialog
+ [ -f /proc/splash ] && echo "verbose" > /proc/splash
+
+ setterm -blank 60
+ chvt 1
+ dialog --infobox 'Bitte warten, die installierte Hardware wird untersucht...' 3 64
+
+ # Get common config
+ hwsetup
+ terminal_alsa_setup
+ terminal_autofs_setup
+
+ # Save hardware profile
+ terminal_save_hardware_profile $mac
+fi
+
+if ! terminal_activated $mac; then
+ # wait till we get activated
+ setterm -blank 60
+ chvt 1
+ dialog --infobox 'Warte auf Aktivierung durch den Systemadministrator.' 3 60
+
+ while ! terminal_activated $mac; do
+ sleep 2
+ done
+
+ # GOsa writes the GOto entry in three steps. To continue, we check
+ # if XDRIVER is present.
+ dialog --infobox 'System wurde aktiviert. Eintr�e werden nun bernommen.' 3 60
+ while ! terminal_load_hardware_profile $mac &> /dev/null; do
+ cat /etc/sysconfig/GOto | grep -v 'XDRIVER="unknown"' | grep -q 'XDRIVER'
+ sleep 2
+ done
+
+ # Enable splash if it was enabled before
+ [ -f /proc/splash ] && echo "silent" > /proc/splash
+
+ echo -n "* configurator (pass2): "
+ setterm -cursor on
+fi
+
+# Mount configuration space
+[ ! -d /tmp/goto-fai ] && mkdir /tmp/goto-fai
+mount -obind /tmp/goto-fai /fai
+ldap2fai $mac
+
+chvt 3
+exit 0
diff --git a/contrib/fai/goto-fai/goto-support.lib b/contrib/fai/goto-fai/goto-support.lib
--- /dev/null
@@ -0,0 +1,510 @@
+#!/bin/sh
+###############################################################################
+# GOsa agent library #
+###############################################################################
+
+SSH='ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile /dev/null" -o "BatchMode yes" '
+
+get_hostname_from_ip() {
+ v=$(host -i $1); w=${v##*[ ]}
+ echo ${w%%.*} | grep -q 'NX'
+ if [ $? -eq 0 ]; then
+ echo "unknown"
+ else
+ echo "$v" | grep -q ';;'
+ if [ $? -eq 0 ]; then
+ if [ -n "$HOSTNAME" ]; then
+ echo "$HOSTNAME"
+ else
+ echo "unknown"
+ fi
+ else
+ echo ${w%%.*}
+ fi
+ fi
+}
+
+get_hostname_from_display()
+{
+ if [ -n "$DISPLAY" ]; then
+
+ HOST=${DISPLAY%%:*}
+ NUMBER=${DISPLAY##*:}
+
+ # IP addresses are not supported here
+ echo $HOST | grep -q '^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$'
+ if [ $? -ne 0 ]; then
+ echo ${DISPLAY%%.*}
+ else
+ get_hostname_from_ip $HOST
+ fi
+
+ else
+ echo "unknown"
+ fi
+}
+
+
+kill_user_processes() {
+ # don't let root do this
+ if [ "$USER" == "root" -o $UID -eq 0 ]; then
+ return
+ fi
+
+ # Preset, or load from file
+ candidates="kdeinit\: soffice.bin mozilla-bin"
+ [ -r /etc/goto/kill-process.conf ] && candidates=$(cat /etc/goto/kill-process.conf)
+
+ # kill old existing user processes
+ for process in $candidates; do
+ ps -fu $USER | grep "$process" | grep -v 'kprogress' | awk ' FS=" " { system("kill "$2) } '
+ done
+
+ # kill old existing user processes that didn't left us with SIGTERM
+ for process in $candidates; do
+ ps -fu $USER | grep "$process" | grep -v 'kprogress' | awk ' FS=" " { system("kill "$2) } '
+ done
+}
+
+fix_ldif() {
+ (cat -; echo "bank") | awk '
+/^[a-zA-Z]/ {
+ if(line!=""){
+ print line
+ }
+
+ line = $0
+}
+/^ / {
+ line = line substr($0,2)
+}
+'
+}
+
+
+ldap_init() {
+ if [ $# -ne 2 ]; then
+ for config in /etc/*ldap/ldap.conf /etc/ldap.conf; do
+
+ # Not readable? Continue
+ [ ! -r $config ] && continue
+
+ # Try to read config
+ touch /tmp/agent.$$
+ cat $config | while read line; do
+ echo $line | grep -q '^BASE'
+ [ $? -eq 0 ] && echo LDAP_BASE="\"$(echo $line|tr '\t' ' '|cut -d\ -f2-)\"" >>/tmp/agent.$$
+ echo $line | grep -q '^HOST'
+ [ $? -eq 0 ] && echo LDAP_HOST="$(echo $line|tr '\t' ' '|cut -d\ -f2-)" >>/tmp/agent.$$
+ echo $line | grep -q '^URI'
+ [ $? -eq 0 ] && echo LDAP_HOST="$(v=`echo $line|tr '\t' ' '|cut -d\ -f2-`;echo ${v##*://})" >> /tmp/agent.$$
+ done
+ eval $(cat /tmp/agent.$$)
+ rm /tmp/agent.$$
+
+ # One successful configuration should be enough
+ break
+ done
+ if [ -z "$LDAP_HOST" -o -z "$LDAP_BASE" ]; then
+ echo "Critical: no LDAP configuration found!"
+ exit
+ fi
+ else
+ LDAP_HOST=$1
+ LDAP_BASE=$2
+ fi
+}
+
+
+ldap_count() {
+ ldapsearch -x -LLL -h "$LDAP_HOST" -b "$LDAP_BASE" "$1" dn | grep '^dn:' | wc -l
+}
+
+
+decode_blob() {
+ base64-decode > /tmp/agent-lib-decode.$$
+ file /tmp/agent-lib-decode.$$ 2>/dev/null| grep -qi 'text'
+ [ $? -eq 0 ] && cat /tmp/agent-lib-decode.$$ | recode 'utf8..latin1'
+ [ -f /tmp/agent-lib-decode.$$ ] && rm /tmp/agent-lib-decode.$$
+}
+
+ldap_import() {
+ for v in $(set grep ldap_import_ | cut -d= -f1); do unset $v; done
+ vname_lastrun=""
+ counter=0
+ > /tmp/agent-lib.$$
+ (ldapsearch -x -LLL -h "$LDAP_HOST" -b "$LDAP_BASE" $2 "$1" $3 2> /dev/null) | fix_ldif | sed 's/^\([^:]*\):\(.*\)$/\1="\2"/' | while read line; do
+ vname=$(echo $line|cut -d= -f1)
+ vvalue=$(echo $line|cut -d= -f2-)
+
+ echo $line | grep -q '=": '
+ if [ $? -eq 0 ]; then
+ vvalue=`echo $line|sed 's/^[^="]*=": //'|decode_blob`
+ vvalue="$vvalue\""
+ else
+ vvalue=`echo $line|sed 's/^[^="]*=" //'`
+ fi
+
+ if [ "$vname_lastrun" == "$vname" ]; then
+ counter=$(( $counter + 1 ));
+ else
+ counter=0
+ vname_lastrun=$vname
+ fi
+
+ echo "ldap_import_$vname[$counter]=\"$vvalue" >> /tmp/agent-lib.$$
+ done
+
+ eval $(cat /tmp/agent-lib.$$)
+ rm /tmp/agent-lib.$$
+}
+
+ldap_cat() {
+ vname_lastrun=""
+ counter=0
+ > /tmp/agent-lib.$$
+ (ldapsearch -x -LLL -h "$LDAP_HOST" -b "$1" -s base 2> /dev/null) | fix_ldif | sed 's/
+^\([^:]*\):\(.*\)$/\1="\2"/' | while read line; do
+ vname=$(echo $line|cut -d= -f1)
+ vvalue=$(echo $line|cut -d= -f2-)
+
+ echo $line | grep -q '=": '
+ if [ $? -eq 0 ]; then
+ vvalue=`echo $line|sed 's/^[^="]*=": //'|decode_blob`
+ vvalue="$vvalue\""
+ else
+ vvalue=`echo $line|sed 's/^[^="]*=" //'`
+ fi
+
+ if [ "$vname_lastrun" == "$vname" ]; then
+ counter=$(( $counter + 1 ));
+ else
+ counter=0
+ vname_lastrun=$vname
+ fi
+
+ echo "ldap_import_$vname[$counter]=\"$vvalue" >> /tmp/agent-lib.$$
+ done
+
+ eval $(cat /tmp/agent-lib.$$)
+ rm /tmp/agent-lib.$$
+ }
+
+
+
+ldap_get_group_membership_of() {
+ ldapsearch -x -LLL -h "$LDAP_HOST" -b "$LDAP_BASE" "(memberUid=$1)" \
+ cn 2> /dev/null | fix_ldif | awk '/^cn: / {print $2}'
+}
+
+
+ldap_get_applications_of() {
+ ldapsearch -x -LLL "(memberUid=$1)" gosaMemberApplication | fix_ldif | \
+ awk '/^gosaMemberApplication:/ {print $2}'| sort | uniq
+}
+
+
+ldap_get_appservers() {
+ ldapsearch -x -LLL "(objectclass=goTerminalServer)" cn | fix_ldif | grep -w cn: |cut -d' ' -f 2
+}
+
+
+translate() {
+ # Look for translation
+ while read line; do
+ string="${line%%=*}"
+ if [ "$string" == "$*" ]; then
+ echo "${line##*=}"
+ return
+ fi
+ done < /etc/goto/goto-locales.dat
+ echo $*
+}
+
+
+show_progress() {
+ # No translation available
+ echo $PROGRESS $(translate "$*")
+}
+
+
+create_desktop_link() {
+ echo "$gosaApplicationFlags" | grep -q "D"
+ if [ $? -eq 0 ]; then
+ [ $DEBUG -eq 1 ] && echo "goto_setup: creating desktop link for application $application" 1>&2
+ cat << EOF > ~/Desktop/$cn
+[Desktop Entry]
+Comment=$description
+Encoding=UTF-8
+Exec=$gosaApplicationExecute
+Icon=$HOME/.kde/share/icons/${cn}.png
+Name=$gosaApplicationName
+Type=Application
+EOF
+ fi
+}
+
+
+create_menu_entry() {
+ echo "$gosaApplicationFlags" | grep -q "M"
+ if [ $? -eq 0 ]; then
+ [ $DEBUG -eq 1 ] && echo "goto_setup: creating menu link for application $application" 1>&2
+ cat << EOF > ~/.local/share/applications/$cn.desktop
+[Desktop Entry]
+Type=Application
+Encoding=UTF-8
+Exec=$gosaApplicationExecute
+Name=$gosaApplicationName
+GenericName=
+Comment=$description
+Icon=$HOME/.kde/share/icons/${cn}.png
+Terminal=false
+Categories=$appcat;
+EOF
+ fi
+}
+
+
+delete_all_applinks() {
+ list=`ldapsearch -x "objectClass=gosaApplication" cn | fix_ldif | awk '/^cn: / {print $2}'`
+ for link in $list; do
+ [ -f $HOME/Desktop/$link ] && rm -f $HOME/Desktop/$link
+ [ -f $HOME/.kde/share/applnk/$link.desktop ] && rm -rf $HOME/.kde/share/applnk/$link.desktop
+ done
+}
+
+
+function terminal_load_hardware_profile() {
+ rm -f $RAM/etc/sysconfig/GOto && touch $RAM/etc/sysconfig/GOto
+ ldapsearch -x -LLL -h $LDAP_HOST -b "$LDAP_BASE" -D "cn=terminal-admin,$LDAP_BASE" -w "$(cat /etc/goto/secret)" "(&(objectClass=gotoWorkstation)(macAddress=$1))" 2> /dev/null | fix_ldif | sed -e 's/^\([^:]*\): \(.*\)$/\U\1\E="\2"/' -e 's/^GOTO//g' >> /etc/sysconfig/GOto
+
+ # Get DN and load all parent defaults from tree
+ current=$(grep "^DN=" /etc/sysconfig/GOto|sed 's/\"//g;s/, /,/g;s/^.*,ou=terminals,ou=systems,//g')
+
+ # Load potential object group entries
+ ldapsearch -x -LLL -h $LDAP_HOST -b "$LDAP_BASE" -D "cn=terminal-admin,$LDAP_BASE" -w "$(cat /etc/goto/secret)" "(&(objectClass=gosaGroupOfNames)(member=$(echo -n $current|sed 's/^DN=//')))" 2> /dev/null | fix_ldif | sed -e 's/^\([^:]*\): \(.*\)$/\U\1\E="\2"/' -e 's/^GOTO//g' >> /etc/sysconfig/GOto
+
+ # get reverse list of potential default entries - for backward compatibility
+ { while true; do
+ # write out current value
+ echo "ou=terminals,ou=systems,$current"
+
+ # prepare next entry
+ echo $current | grep -q ','
+ [ $? -ne 0 ] && break
+ [ "$LDAP_BASE" == "$current" ] && break
+ current=${current#*,}
+ done } | tac | while read line; do
+
+ # Read potential default entries and append
+ # them to sysconfig/GOto
+ ldapsearch -x -LLL -h $LDAP_HOST -D "cn=terminal-admin,$LDAP_BASE" -w "$(cat /etc/goto/secret)" -b $line "(&(objectClass=gotoWorkstation)(cn=wdefault))" 2> /dev/null | fix_ldif | sed -e 's/^\([^:]*\): \(.*\)$/\U\1\E="\2"/' -e 's/^GOTO//g' >> /etc/sysconfig/GOto
+ done
+
+ # Reverse sysconfig/GOto
+ tac /etc/sysconfig/GOto > /etc/sysconfig/GOto.tmp
+ mv /etc/sysconfig/GOto.tmp /etc/sysconfig/GOto
+}
+
+
+terminal_has_hardware_profile() {
+ # Do we have a configuration?
+ terminal_load_hardware_profile $1
+ grep -v "cn=default," /etc/sysconfig/GOto | grep -q "DN="
+}
+
+
+terminal_activated() {
+ # Do we have a configuration?
+ terminal_load_hardware_profile $1
+ grep -v ',ou=incoming,' /etc/sysconfig/GOto | grep -v 'cn=default,' | grep -q "DN="
+}
+
+
+terminal_dump_hwprofile() {
+ # Save mac address
+ mac=$1
+ name=$(hostname)
+
+ # Source hardware information detected by hwsetup
+ for module in xserver sound netcard mouse; do
+ [ -f /etc/sysconfig/$module ] && . /etc/sysconfig/$module
+ done
+
+ # Get hardware information directly from /proc
+ cpu=$(cat /proc/cpuinfo | awk 'BEGIN { FS=": "; ORS="" } /^vendor_id/ {print $2" / "} /^model name/{print $2" - "} /^cpu MHz/ {print $2" MHz"}')
+ mem=$(cat /proc/meminfo | awk '/^MemTotal:/ {print $2" KB"}')
+ modlist=$(lsmod | sed -e '/^Module/d;/^snd/d;s/^\(\w*\).*$/\1/g')
+ hsync=$(ddcxinfo-knoppix -hsync|tr -d ' ')
+ vsync=$(ddcxinfo-knoppix -vsync|tr -d ' ')
+
+ # USB support?
+ [ -d /proc/bus/usb ] && usb="true" || usb="false"
+
+ # Add floppy/cdrom
+ grep -q 'floppy' /etc/sysconfig/autofs && FLOPPY='YES' || FLOPPY='NO'
+ grep -q 'cdrom' /etc/sysconfig/autofs && CDROM='YES' || CDROM='NO'
+
+ cat << EOF
+dn: cn=$name,ou=incoming,$LDAP_BASE
+objectClass: gotoWorkstation
+objectClass: goHard
+cn: $name
+macAddress: $mac
+gotoMode: locked
+gotoXDriver: $XMODULE
+gotoXMouseType: $XMOUSETYPE
+gotoXMouseport: $DEVICE
+gotoXHsync: $hsync
+gotoXVsync: $vsync
+ghUsbSupport: $usb
+gotoFloppyEnable: $FLOPPY
+gotoCdromEnable: $CDROM
+gotoSndModule: $SNDMODULE
+EOF
+
+ # Insert IDE-Devices
+ for f in /proc/ide/ide?/hd?/model; do
+ [ -f $f ] && echo "ghIdeDev: "$(cat $f)
+ done
+
+ (cat /proc/scsi/scsi | sed -ne 's/.*Vendor: \([^ ]*\) *Model: \([^ ]*\) *.*$/\1 \2/p') 2> /dev/null|while read line; do
+ echo ghScsiDev: $line
+ done
+
+ # Insert modules
+ for m in $modlist; do
+ echo "gotoModules: $m"
+ done | sort | uniq
+
+ # Add potential swap filesystems
+ [ -f /etc/sysconfig/swap ] && cat /etc/sysconfig/swap | while read line; do
+ echo "gotoFilesystem: $line"
+ done
+
+ # Add autofs devices
+ [ -f /etc/sysconfig/autofs ] && cat /etc/sysconfig/autofs | while read line; do
+ echo "gotoAutoFs: $line"
+ done
+
+ cat << EOF
+ghGfxAdapter: $XDESC
+ghNetNic: `cat /etc/sysconfig/netcard|grep "^FULLNAME"|cut -d= -f2|tr -d "\""`
+ghSoundAdapter: `cat /etc/sysconfig/sound|grep "^FULLNAME"|cut -d= -f2|tr -d "\""`
+ghMemSize: $mem
+ghCpuType: $cpu
+EOF
+}
+
+
+terminal_save_hardware_profile() {
+ # Get hardware ldif and strip out possibly broken entries
+ terminal_dump_hwprofile $1 | grep -v '^[^:]*: *$' &> /tmp/upload.ldif
+
+ # Upload ldif
+ while true; do
+ error=$(ldapadd -x -h "$LDAP_HOST" -D "cn=terminal-admin,$LDAP_BASE" -w "$(cat /etc/goto/secret)" < /tmp/upload.ldif 2>&1)
+ if [ $? -ne 0 ]; then
+ dialog --msgbox "Das Terminal konnte sich nicht am LDAP anmelden. Bitte prüfen Sie de Einstellungen: $error" 14 60
+ else
+ break
+ fi
+ done
+}
+
+
+terminal_alsa_setup() {
+ audio=$(lspci -n | awk '/ 0401/ {print $3}' | sed 's/://g' | head -1)
+ KVER=$(uname -r)
+ MODULE=$(cat /lib/modules/$KVER/modules.pcimap | (while read driver vendor device dummy; do
+ if expr $driver : 'snd-.*' > /dev/null; then
+ printf '%04x%04x %s\n' $vendor $device $driver | grep "^$audio" | cut -d\ -f2
+ fi
+ done))
+ echo "SNDMODULE=\"$MODULE\"" >> /etc/sysconfig/sound
+}
+
+
+terminal_autofs_setup(){
+ wcount=1
+ lcount=1
+
+ # Remove old ones
+ rm -f /etc/sysconfig/autofs /etc/sysconfig/swap
+
+ # Generate autofs entries for removable devices
+ for d in /dev/floppy/?; do
+ [ "$d" == "/dev/floppy/?" ] && break
+ nr=$(echo $d | sed 's/^.*\/\([^/]*$\)/\1/g')
+ echo "floppy$nr -fstype=auto,sync,nodev,nosuid,umask=000,quiet,rw :$d" >> /etc/sysconfig/autofs
+ done
+
+ for d in /dev/cdroms/*; do
+ [ "$d" == "/dev/cdroms/*" ] && break
+ name=`echo $d | sed 's/^.*\/\([^/]*$\)/\1/g'`
+ echo "$name -fstype=iso9660,sync,nodev,nosuid,umask=000,quiet,ro :$d" >> /etc/sysconfig/autofs
+ done
+
+ # Generate autofs entries for fixed drives
+ (sfdisk -qLl | grep "^/" | tr -d '\*') | while read device d1 d2 d3 d4 type d5; do
+ case $type in
+ [4bce])
+ echo "win$wcount -fstype=vfat,sync,nodev,nosuid,umask=000,quiet,rw :$device" >> /etc/sysconfig/autofs
+ wcount=$(( $wcount + 1 ))
+ ;;
+ 7)
+ echo "win$wcount -fstype=ntfs,sync,nodev,nosuid,umask=000,quiet,ro :$device" >> /etc/sysconfig/autofs
+ wcount=$(( $wcount + 1 ))
+ ;;
+ 83)
+ echo "linux$lcount -fstype=ext3,sync,nodev,nosuid,umask=000,quiet,rw :$device" >> /etc/sysconfig/autofs
+ lcount=$(( $lcount + 1 ))
+ ;;
+ 82)
+ echo "$device none swap sw 0 0" >> /etc/sysconfig/swap
+ ;;
+ esac
+ done
+}
+
+
+get_xdmcp_server(){
+ SERVERS=$(ldapsearch -LLL -b "$LDAP_BASE" -H $LDAP_HOST -x '(&(objectclass=goTerminalServer)(goXdmcpIsEnabled=true))'| awk '/^cn/{print $2}' 2> /dev/null)
+
+ # Generate load sorted server list
+ { for s in $SERVERS; do
+ xdmping $s -v -t 1 2> /dev/null | awk '!/contacting/ {print $5"|"$1"|"$2}' | sed 's/[:,]//g'
+ done } | egrep "^[0-9]" | sort -n > /tmp/xservers.tmp
+
+ case $(cat /tmp/xservers.tmp | wc -w | awk '{print $1}') in
+ 0)
+ return
+ ;;
+ 1)
+ cat /tmp/xservers.tmp | cut -d\| -f2
+ return
+ ;;
+ *)
+ AVAILABLE=""
+ for i in $(cat /tmp/xservers.tmp); do
+ NEW=$(echo "$i" | awk -F "|" '{if ($1 < 0.5) print $1"|"$2}')
+ [ -n "$NEW" ] && AVAILABLE="$NEW\n$AVAILABLE"
+ done
+ if [ -n "$AVAILABLE" ]; then
+ echo -e "$AVAILABLE" > /tmp/xservers.tmp
+ NUM=$(cat /tmp/xservers.tmp | wc -l | awk '{print $1 - 1}')
+ ROW=$(echo $NUM | awk '{print rand() * $1 + 1 ;}' | cut -d . -f1)
+ cat /tmp/xservers.tmp | sed -n "${ROW}p" | cut -d\| -f2
+ else
+ cat /tmp/xservers.tmp|egrep "^[0-9]"|tr "." ","|sort -n|head -1|cut -d\| -f2
+ fi
+ ;;
+ esac
+}
+
+
+get_fontpath() {
+ ldapsearch -x -LLL -h $LDAP_HOST -b "$LDAP_BASE" "(&(objectClass=goTerminalServer)(cn=$1))" |
+ grep "^goFontPath" | cut -d\ -f2- | sed 's!\/!\/!g'
+}
+
diff --git a/contrib/fai/goto-fai/ldap2fai b/contrib/fai/goto-fai/ldap2fai
--- /dev/null
@@ -0,0 +1,630 @@
+#!/usr/bin/perl
+# $Id$
+#*********************************************************************
+#
+# ldap2fai -- read FAI config from LDAP and create config space
+#
+# This script is part of FAI (Fully Automatic Installation)
+# (c) 2005, Thomas Lange <lange@informatik.uni-koeln.de>
+# (c) 2005, Jens Nitschke <jens.nitschke@2int.de>
+# (c) 2005, Jan-Marek Glogowski <glogow@fbihome.de>
+# (c) 2005, Cajus Pollmeier <pollmeier@gonicus.de>
+#
+#*********************************************************************
+
+use strict;
+use Net::LDAP;
+use MIME::Base64;
+use Getopt::Std;
+use File::Path;
+use File::Copy;
+use vars qw/ %opt /;
+
+my $base;
+my $ldapuri;
+my $ldapdir = "/etc/ldap/ldap.conf";
+my $outdir = "/fai";
+my $verbose = 0;
+my $opt_string = 'c:d:hv';
+my $hostname;
+
+getopts( "$opt_string", \%opt ) or usage("Hello");
+usage("Help") if $opt{h};
+
+$verbose = $opt{v} ? 1 : 0;
+$outdir = $opt{d} ? $opt{d} : $outdir;
+$ldapdir = $opt{c} ? $opt{c} : $ldapdir;
+
+# Get MAC from cmdline
+my $mac = shift @ARGV;
+$mac eq '' && usage("MAC address not specified.");
+
+# Is outdir a directory
+-d "$outdir" || usage("'$outdir' is not a directory.\n");
+
+my @classes=(); # the classes a host belongs to
+
+# initialize ldap
+setup();
+my $ldap = Net::LDAP->new("$ldapuri") or die "$@";
+my $mesg = $ldap->bind;
+
+# create class hooks debconf disk_config package_config scripts files
+my @dirs= qw/class hooks debconf disk_config package_config scripts files/;
+foreach (@dirs) {
+ -d "$outdir/$_" || mkpath "$outdir/$_"
+ || warn "WARNING: Can't create subdir $outdir/$_ $!\n";
+}
+
+@classes= get_classes($mac);
+prt_scripts();
+prt_package_list();
+prt_debconf();
+prt_templates();
+prt_var();
+prt_hooks();
+prt_disk_config();
+
+# create sources list
+if (!$hostname) {
+ -d "${outdir}/files/etc/apt/sources.list"
+ || mkpath "${outdir}/files/etc/apt/sources.list";
+ copy ("${outdir}/tmp/apt-sources.list",
+ "${outdir}/files/etc/apt/sources.list/$hostname") ;
+}
+
+$mesg = $ldap->unbind; # take down session
+exit 0;
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub setup
+{
+ # Read LDAP
+ open (LDAPCONF,"${ldapdir}")
+ || usage("Can't open LDAP configuration$!\n");
+ my @content=<LDAPCONF>;
+ close(LDAPCONF);
+
+ # Scan LDAP config
+ foreach my $line (@content) {
+ $line =~ /^\s*(#|$)/ && next;
+ chomp($line);
+
+ if ($line =~ /^BASE\s+(.*)$/) {
+ $base= $1;
+ next;
+ }
+ if ($line =~ m#^URI\s+ldaps?://([^/:]+).*$#) {
+ $ldapuri= $1;
+ next;
+ }
+ }
+}
+
+sub usage
+{
+ (@_) && print STDERR "\n@_\n\n";
+
+ print STDERR << "EOF";
+usage: $0 [-hv] [-c config] [-d outdir] <MAC>
+
+-h : this (help) message
+-c : LDAP config file (default: ${ldapdir})
+-d : output dir (default: ${outdir})
+-v : be verbose
+EOF
+ exit -1;
+}
+#-----------------------------------------------------------------------------------
+
+sub write_file {
+
+ my @opts = @_;
+ my $len = scalar @_;
+ ($len < 2) && return;
+
+ my $filename = shift;
+ my $data = shift;
+
+ open (SCRIPT,">${filename}") || warn "Can't create ${filename}. $!\n";
+ print SCRIPT $data;
+ close(SCRIPT);
+
+ ($opts[2] ne "") && chmod oct($opts[2]),${filename};
+ ($opts[3] ne "") && chown_files(${filename}, $opts[3]);
+}
+
+#-----------------------------------------------------------------------------------
+
+sub chown_files
+{
+ my @owner = split('.',@_[1]);
+ my $filename = @_[0];
+ my ($uid,$gid);
+ $uid = getpwnam(@owner[0]);
+ $gid = getgrnam(@owner[1]);
+
+ chown $uid, $gid, $filename;
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub get_classes {
+
+ # return list of FAI classes defined for host
+ my $mac = shift;
+ my (@classes,$mesg,$entry);
+
+ $mesg = $ldap->search(
+ base => "ou=systems,$base",
+ filter => "(&(macAddress=$mac)(objectClass=gotoWorkstation))",
+ attrs => [ 'FAIclass', 'cn']);
+ $mesg->code && die $mesg->error;
+ # normally, only one value should be returned
+ if ($mesg->count != 1) {
+ die "LDAP search for client failed. ".$mesg->count." entries have been returned\n";
+ }
+
+ # this assigns the last value to @classes
+ $entry= ($mesg->entries)[0];
+ @classes= split /\s+/,$entry->get_value('FAIclass');
+
+ # get hostname
+ my $hname= $entry->get_value('cn');
+ my $dn= $entry->dn;
+ $hostname= $hname;
+
+ # Search for object groups containing this client
+ $mesg = $ldap->search(
+ base => "ou=groups,$base",
+ filter => "(&(objectClass=gosaGroupOfNames)(objectClass=FAIobject)(member=$dn))",
+ attrs => [ 'FAIclass' ]);
+ $mesg->code && die $mesg->error;
+ foreach my $m ($mesg->entries) {
+ push @classes, split /\s+/,$m->get_value('FAIclass');
+ }
+
+ # print all classes to the file with hostname
+ open (FAICLASS,">$outdir/class/$hname") || warn "Can't create $outdir/class/$hname. $!\n";
+ my @newclasses;
+ foreach my $class (@classes) {
+
+ # We need to walk through the list of classes and watch out for
+ # a profile which is named like the class. Replace the profile
+ # name by the names of the included classes.
+ $mesg = $ldap->search(
+ base => "ou=systems,$base",
+ filter => "(&(objectClass=FAIprofile)(cn=$class))",
+ attrs => [ 'FAIclass' ]);
+ $mesg->code && die $mesg->error;
+
+ if ($mesg->count > 0){
+ foreach my $m ($mesg->entries) {
+ foreach my $tc (split /\s+/,$m->get_value('FAIclass')){
+ print FAICLASS "$tc\n";
+ push @newclasses, $tc;
+ }
+ }
+ } else {
+ print FAICLASS "$class\n";
+ push @newclasses, $class;
+ }
+ }
+ close(FAICLASS);
+ print "Host $hname belongs to FAI classes: ",join ' ',@newclasses,"\n" if $verbose;
+ return @newclasses;
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub get_variables {
+ # gets all variables defined for a class
+ # returns a list of lines in bourne shell syntax
+
+ my $class = shift;
+ my ($mesg,$var_base,$entry,$line,@vars);
+
+ $mesg = $ldap->search(
+ base => "$base",
+ filter => "(&(cn=$class)(objectClass=FAIvariable))",
+ attrs => [ 'cn']);
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ $entry=($mesg->entries)[0];
+ $var_base=$entry->dn;
+
+ $mesg = $ldap->search(
+ base => "$var_base",
+ filter => "(objectClass=FAIvariableEntry)",
+ attrs => ['cn', 'FAIvariableContent']);
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+
+ foreach $entry ($mesg->entries) {
+ $line= sprintf "%s=\'%s\'\n", $entry->get_value('cn'),
+ $entry->get_value('FAIvariableContent');
+ push @vars,$line;
+ }
+ return @vars;
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub prt_var {
+
+ my (@lines, $hname);
+
+ foreach my $class (@classes) {
+ @lines = get_variables($class);
+ next until @lines; # do not create .var file if no variables are defined
+ open (FAIVAR,">$outdir/class/${class}.var")
+ || warn "Can't create $outdir/class/$hname.var.$!\n";
+ print FAIVAR @lines;
+ close(FAIVAR);
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub get_disk_config {
+
+ my $class = shift;
+ my ($mesg,$entry,$line,@diskconfig,$partition_base,$dn,%diskline,$xxmesg);
+
+ # Search for partition schema for the specified class
+ $mesg = $ldap->search(
+ base => "$base",
+ filter => "(&(cn=$class)(objectClass=FAIpartitionTable))" );
+
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ $entry=($mesg->entries)[0];
+ $partition_base= $entry->dn;
+
+ # Search for disks
+ $mesg = $ldap->search(
+ base => "$partition_base",
+ filter => "(objectClass=FAIpartitionDisk)" );
+
+ return if ($mesg->code == 32); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ foreach $entry ($mesg->entries) {
+ my $logic_count= 4;
+ my $primary_count= 0;
+ my $dn=$entry->dn;
+ my $disk=$entry->get_value('cn');
+ my $part;
+ undef %diskline;
+ $diskline{0} = "disk_config $disk\n";
+ $xxmesg = $ldap->search(
+ base => "$dn",
+ filter => "objectClass=FAIpartitionEntry" );
+ $xxmesg->code && die $xxmesg->error;
+ foreach my $dl ($xxmesg->entries) {
+ if ($dl->get_value('FAIpartitionType') eq 'primary'){
+ $primary_count++;
+ } else {
+ $logic_count++;
+ }
+ if ($dl->get_value('FAIpartitionFlags') eq 'preserve'){
+ if ($dl->get_value('FAIpartitionType') eq 'primary'){
+ $part= 'preserve'.$primary_count;
+ } else {
+ $part= 'preserve'.$logic_count;
+ }
+ $line= sprintf "%-7s %-12s %-12s %-10s ; %s\n",
+ $dl->get_value('FAIpartitionType'),
+ $dl->get_value('FAImountPoint'),
+ $part,
+ $dl->get_value('FAImountOptions') eq ''
+ ? 'rw' : $dl->get_value('FAImountOptions'),
+ $dl->get_value('FAIfsOptions');
+ }
+ elsif ($dl->get_value('FAIfsType') eq 'swap'){
+ $line= sprintf "%-7s %-12s %-12s %-10s\n",
+ $dl->get_value('FAIpartitionType'),
+ $dl->get_value('FAImountPoint'),
+ $dl->get_value('FAIpartitionSize'),
+ $dl->get_value('FAImountOptions') eq ''
+ ? 'rw' : $dl->get_value('FAImountOptions');
+ }
+ else {
+ $line= sprintf "%-7s %-12s %-12s %-10s ; %s %s\n",
+ $dl->get_value('FAIpartitionType'),
+ $dl->get_value('FAImountPoint'),
+ $dl->get_value('FAIpartitionSize'),
+ $dl->get_value('FAImountOptions') eq ''
+ ? 'rw' : $dl->get_value('FAImountOptions'),
+ $dl->get_value('FAIfsOptions'),
+ $dl->get_value('FAIfsType');
+ }
+
+ $diskline{$dl->get_value('FAIpartitionNr')}=$line;
+ }
+ foreach my $l (sort {$a <=> $b} keys %diskline) {
+ push @diskconfig, $diskline{$l};
+ }
+ }
+ return @diskconfig;
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub prt_disk_config {
+
+ # create one disk_config file
+
+ my ($class,@lines);
+
+ foreach $class (reverse @classes) {
+ @lines=get_disk_config($class);
+ next until @lines; # skip if nothing is defined for this class
+
+ print "Generating partition layout for class '${class}'\n." if $verbose;
+ open (FAIVAR,">${outdir}/disk_config/${class}")
+ || warn "Can't create $outdir/disk_config/$class. $!\n";
+ print FAIVAR join '',@lines;
+ close(FAIVAR);
+ last; # finish when one config file is created
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub get_packages {
+
+ # gets list of packages defined for a class
+
+ my $class = shift;
+ my ($mesg,$entry,$line,$method,%packlist);
+
+ -d "${outdir}/tmp" || mkpath "${outdir}/tmp"
+ || warn "Can't create ${outdir}/tmp. $!\n";
+ print "Generate sources.list for install\n" if $verbose;
+ open (SOURCES,">>${outdir}/tmp/apt-sources.list")
+ || warn "Can't create ${outdir}/tmp/apt-sources.list. $!\n";
+
+ $mesg = $ldap->search(
+ base => "$base",
+ filter => "(&(cn=$class)(objectClass=FAIpackageList))" ,
+ attrs => [ 'FAIpackage', 'FAIinstallMethod',
+ 'FAIdebianMirror', 'FAIdebianRelease', 'FAIdebianSection']);
+
+ $mesg->code && die $mesg->error;
+ # should also return only one value
+
+ undef %packlist;
+ foreach $entry ($mesg->entries) {
+ $method=$entry->get_value('FAIinstallMethod');
+ push @{$packlist{$method}}, $entry->get_value('FAIpackage');
+
+ print SOURCES "deb ".$entry->get_value('FAIdebianMirror')." ".$entry->get_value('FAIdebianRelease')." ";
+ my $section;
+ foreach $section ($entry->get_value('FAIdebianSection')){
+ print SOURCES "$section ";
+ }
+ print SOURCES "\n";
+ }
+
+ close (SOURCES);
+
+ # return a ref to the hash of arrays (key of the hash is the method),
+ # the value is the array of package names for this method
+ return \%packlist;
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub prt_package_list {
+
+ my (@lines,$plist,$method,$value);
+
+ foreach my $class (@classes) {
+ $plist=get_packages($class);
+ # test if hash contains any keys or values
+ unless (keys %{$plist}) {
+ next;
+ }
+
+ print "Generate package list for class '$class'.\n" if $verbose;
+ open (PACKAGES,">$outdir/package_config/$class")
+ || warn "Can't create $outdir/package_config/$class. $!\n";
+ while (($method, $value) = each %{$plist}) {
+ print PACKAGES "PACKAGES $method\n";
+ print PACKAGES join "\n",@{$value};
+ print PACKAGES "\n";
+ }
+ close(PACKAGES);
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub get_templates {
+
+ # get list of template-files defined for a class
+ my $class = shift;
+ my ($mesg,$entry,$str,$pfad,$name,$owner,$mode,$template_base,@template);
+
+ $mesg = $ldap->search(
+ base => "$base",
+ filter => "(&(cn=$class)(objectClass=FAItemplate))",
+ attrs => ['cn']);
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ $entry=($mesg->entries)[0];
+ $template_base=$entry->dn;
+
+ $mesg = $ldap->search(
+ base => "$template_base",
+ filter => "(objectClass=FAItemplateEntry)",
+ attrs => ['FAItemplateFile', 'FAItemplatePath', 'FAIowner', 'FAImode' ,'cn']);
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ foreach $entry ($mesg->entries) {
+ $name = $entry->get_value('cn');
+ $owner = $entry->get_value('FAIowner');
+ $owner = $entry->get_value('FAImode');
+ $pfad = $entry->get_value('FAItemplatePath');
+ chomp($pfad);
+ -d "${outdir}/files/${pfad}" || mkpath "${outdir}/files/${pfad}"
+ || warn "WARNING: Can't create subdir ${outdir}/files/${pfad} !$\n";
+ print "Generate template '$pfad' ($name) for class '$class'.\n" if $verbose;
+ write_file( "${outdir}/files/${pfad}/${class}",
+ $entry->get_value('FAItemplateFile'),$entry->get_value('FAImode'),$entry->get_value('FAIowner'));
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub prt_templates {
+ my ($class);
+
+ foreach $class (reverse @classes) {
+ get_templates($class);
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub get_debconf {
+
+ # gets list of packages defined for a class
+
+ my $class = shift;
+ my ($mesg,$entry,$str,$debconf_base,@debconf);
+
+ $mesg = $ldap->search(
+ base => "$base",
+ filter => "(&(cn=$class)(objectClass=FAIpackageList))",
+ attrs => ['cn']);
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ $entry=($mesg->entries)[0];
+ $debconf_base=$entry->dn;
+
+ $mesg = $ldap->search(
+ base => "$debconf_base",
+ filter => "(objectClass=FAIdebconfInfo)" ,
+ attrs => [ 'FAIpackage', 'FAIvariable',
+ 'FAIvariableType','FAIvariableContent']);
+ $mesg->code && die $mesg->error;
+
+ # undef @debconf;
+ foreach $entry ($mesg->entries) {
+ $str = sprintf "%s %s %s %s\n",
+ $entry->get_value('FAIpackage'),
+ $entry->get_value('FAIvariable'),
+ $entry->get_value('FAIvariableType'),
+ $entry->get_value('FAIvariableContent');
+ push @debconf, $str;
+ }
+ return @debconf;
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub prt_debconf {
+
+ my @lines;
+ my $class;
+
+ foreach $class (@classes) {
+ @lines = get_debconf($class);
+ next until @lines;
+ print "Generate DebConf for class '$class'.\n" if $verbose;
+ open (DEBCONF,">${outdir}/debconf/${class}") || warn "Can't create $outdir/debconf/$class. $!\n";
+ print DEBCONF @lines;
+ close(DEBCONF);
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub prt_scripts {
+ my ($class,@lines);
+
+ foreach $class (@classes) {
+ get_scripts($class);
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub get_scripts {
+
+ # gets list of packages defined for a class
+
+ my $class = shift;
+ my ($mesg,$entry,$str,$script_base,$prio,$name,$script);
+
+ $mesg = $ldap->search(
+ base => "$base",
+ filter => "(&(cn=$class)(objectClass=FAIscript))",
+ attrs => ['cn']);
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ $entry=($mesg->entries)[0];
+ $script_base= $entry->dn;
+
+ $mesg = $ldap->search(
+ base => "$script_base",
+ filter => "(objectClass=FAIscriptEntry)",
+ attrs => ['FAIpriority', 'FAIscript', 'cn']);
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ foreach $entry ($mesg->entries) {
+ $name = $entry->get_value('cn');
+ $prio = $entry->get_value('FAIpriority');
+ $script= sprintf('%02d-%s', $prio, $name);
+
+ -d "$outdir/scripts/$class" || mkpath "$outdir/scripts/$class" ||
+ warn "WARNING: Can't create subdir $outdir/scripts/$class !$\n";
+
+ write_file("${outdir}/scripts/${class}/${script}",
+ $entry->get_value('FAIscript'), "0700");
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub prt_hooks {
+ my ($class,@lines);
+
+ foreach $class (reverse @classes) {
+ get_hooks($class);
+ }
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+sub get_hooks {
+
+ # gets list of packages defined for a class
+
+ my $class = shift;
+ my ($mesg,$entry,$str,$hook_base,$prio,$task,$hook,$name);
+
+ $mesg = $ldap->search(
+ base => "$base",
+ filter => "(&(cn=$class)(objectClass=FAIhook))",
+ attrs => ['cn']);
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ $entry=($mesg->entries)[0];
+ $hook_base= $entry->dn;
+
+ $mesg = $ldap->search(
+ base => "$hook_base",
+ filter => "(objectClass=FAIhookEntry)",
+ attrs => ['FAItask', 'FAIscript', 'cn']);
+ return if ($mesg->count() == 0); # skip if no such object exists
+ $mesg->code && die $mesg->error;
+
+ foreach $entry ($mesg->entries) {
+ $name = $entry->get_value('cn');
+ $task = $entry->get_value('FAItask');
+ $prio = $entry->get_value('FAIpriority');
+ $hook = sprintf('%s.%s', ${task}, ${class});
+
+ write_file("${outdir}/hooks/${hook}",
+ $entry->get_value('FAIscript'), "0700");
+ }
+}
+
+# vim:ts=2:sw=2:expandtab:shiftwidth=2:syntax:paste
diff --git a/contrib/fai/goto-fai/secret b/contrib/fai/goto-fai/secret
--- /dev/null
@@ -0,0 +1 @@
+your secret terminal-admin password