From 6f42e3fab7c24d8b4b35576d4d9ccede53ed1ed1 Mon Sep 17 00:00:00 2001
From: joakim_tosteberg <joakim_tosteberg@ed781fb6-379c-401f-938c-123af3e31ac0>
Date: Tue, 2 Dec 2008 18:38:52 +0000
Subject: [PATCH] Import of some manifest files, lasmot enough to bring an
 ubuntu machine up to speed, but needs some more things and some cleaning.

git-svn-id: file:///lysator/puppet/trunk@2 ed781fb6-379c-401f-938c-123af3e31ac0
---
 Files/Makefile                              |   6 +
 Files/auto.master.erb                       |   3 +
 Files/common-account                        |  10 +
 Files/common-auth                           |  14 +
 Files/common-password                       |  10 +
 Files/common-session                        |  11 +
 Files/cups-printers.conf-client             |   0
 Files/hosts.erb                             |  17 +
 Files/interfaces-Debian.erb                 |  14 +
 Files/krb5.conf                             |  24 +
 Files/nrpe.cfg                              |  28 ++
 Files/nsswitch.conf-limited                 |  20 +
 Files/nsswitch.conf-user                    |  20 +
 Files/ntp.conf-client                       |  18 +
 Files/puppet-Makefile.erb                   |  67 +++
 Files/puppetrun-rcinit.erb                  |  39 ++
 Files/resolv.conf                           |   3 +
 Files/root-.bash_logout                     |   2 +
 Files/root-.bash_profile                    |  28 ++
 Files/root-.bashrc                          |  48 ++
 Files/root-.cvsrc                           |   4 +
 Files/root-.emacs                           |  86 ++++
 Files/ssmtp.conf.erb                        |  21 +
 Files/syslogd.conf                          |  72 +++
 Files/xorg.conf-furfur.erb                  |   1 +
 Files/xorg.conf-ubuntu.erb                  |  33 ++
 Files/yp.conf                               |   2 +
 Lib/facter/environ.rb                       |   9 +
 Lib/puppet/parser/functions/regexp_quote.rb |   9 +
 Lib/puppet/parser/functions/sprintf.rb      |   9 +
 Lib/puppet/parser/functions/strftime.rb     |  12 +
 Lib/puppet/type/delete_lines.rb             | 125 +++++
 Lib/puppet/type/ensure_line.rb              | 233 +++++++++
 Lib/puppet/type/regexp_replace_lines.rb     | 157 ++++++
 Lib/puppet/type/replace_sections.rb         | 127 +++++
 Lib/ruby/nsc_utils.rb                       | 185 +++++++
 Makefile                                    |  85 ++++
 README                                      | 134 +++++
 SITE.pp                                     |  60 +++
 autofs.pp                                   |  24 +
 environment.pp                              | 142 ++++++
 kerberos.pp                                 |  55 +++
 mail.pp                                     |  15 +
 network.pp                                  |  60 +++
 nis.pp                                      |  73 +++
 nrpe.pp                                     |  36 ++
 osfixes-debian.pp                           |  18 +
 osfixes-fedora.pp                           | 182 +++++++
 osfixes.pp                                  |  27 ++
 printing.pp                                 |  46 ++
 puppet.pp                                   |  78 +++
 rootuser.pp                                 |  25 +
 syslog.pp                                   |  33 ++
 time.pp                                     |  58 +++
 util.pp                                     | 510 ++++++++++++++++++++
 55 files changed, 3128 insertions(+)
 create mode 100644 Files/Makefile
 create mode 100644 Files/auto.master.erb
 create mode 100644 Files/common-account
 create mode 100644 Files/common-auth
 create mode 100644 Files/common-password
 create mode 100644 Files/common-session
 create mode 100644 Files/cups-printers.conf-client
 create mode 100644 Files/hosts.erb
 create mode 100644 Files/interfaces-Debian.erb
 create mode 100644 Files/krb5.conf
 create mode 100644 Files/nrpe.cfg
 create mode 100644 Files/nsswitch.conf-limited
 create mode 100644 Files/nsswitch.conf-user
 create mode 100644 Files/ntp.conf-client
 create mode 100644 Files/puppet-Makefile.erb
 create mode 100644 Files/puppetrun-rcinit.erb
 create mode 100644 Files/resolv.conf
 create mode 100644 Files/root-.bash_logout
 create mode 100644 Files/root-.bash_profile
 create mode 100644 Files/root-.bashrc
 create mode 100644 Files/root-.cvsrc
 create mode 100644 Files/root-.emacs
 create mode 100644 Files/ssmtp.conf.erb
 create mode 100644 Files/syslogd.conf
 create mode 120000 Files/xorg.conf-furfur.erb
 create mode 100644 Files/xorg.conf-ubuntu.erb
 create mode 100644 Files/yp.conf
 create mode 100644 Lib/facter/environ.rb
 create mode 100644 Lib/puppet/parser/functions/regexp_quote.rb
 create mode 100644 Lib/puppet/parser/functions/sprintf.rb
 create mode 100644 Lib/puppet/parser/functions/strftime.rb
 create mode 100644 Lib/puppet/type/delete_lines.rb
 create mode 100644 Lib/puppet/type/ensure_line.rb
 create mode 100644 Lib/puppet/type/regexp_replace_lines.rb
 create mode 100644 Lib/puppet/type/replace_sections.rb
 create mode 100644 Lib/ruby/nsc_utils.rb
 create mode 100644 Makefile
 create mode 100644 README
 create mode 100644 SITE.pp
 create mode 100644 autofs.pp
 create mode 100644 environment.pp
 create mode 100644 kerberos.pp
 create mode 100644 mail.pp
 create mode 100644 network.pp
 create mode 100644 nis.pp
 create mode 100644 nrpe.pp
 create mode 100644 osfixes-debian.pp
 create mode 100644 osfixes-fedora.pp
 create mode 100644 osfixes.pp
 create mode 100644 printing.pp
 create mode 100644 puppet.pp
 create mode 100644 rootuser.pp
 create mode 100644 syslog.pp
 create mode 100644 time.pp
 create mode 100644 util.pp

diff --git a/Files/Makefile b/Files/Makefile
new file mode 100644
index 00000000..466d472e
--- /dev/null
+++ b/Files/Makefile
@@ -0,0 +1,6 @@
+default:
+	@true
+
+.PHONY: clean
+clean:
+	@true
diff --git a/Files/auto.master.erb b/Files/auto.master.erb
new file mode 100644
index 00000000..703d5bc4
--- /dev/null
+++ b/Files/auto.master.erb
@@ -0,0 +1,3 @@
+/home	yp:auto_home	nosuid,nodev
+/mp	yp:auto_lysator	nosuid,nodev
+/pkg	yp:auto_pkg	nosuid,nodev
diff --git a/Files/common-account b/Files/common-account
new file mode 100644
index 00000000..cc9518ad
--- /dev/null
+++ b/Files/common-account
@@ -0,0 +1,10 @@
+#
+# /etc/pam.d/common-account - authorization settings common to all services
+#
+# This file is included from other service-specific PAM config files,
+# and should contain a list of the authorization modules that define
+# the central access policy for use on the system.  The default is to
+# only deny service to users whose accounts are expired in /etc/shadow.
+
+account	sufficient	pam_krb5.so minimum_uid=100
+account	sufficient	pam_unix.so
diff --git a/Files/common-auth b/Files/common-auth
new file mode 100644
index 00000000..cc30d3fb
--- /dev/null
+++ b/Files/common-auth
@@ -0,0 +1,14 @@
+#
+# /etc/pam.d/common-auth - authentication settings common to all services
+#
+# This file is included from other service-specific PAM config files,
+# and should contain a list of the authentication modules that define
+# the central authentication scheme for use on the system
+# (e.g., /etc/shadow, LDAP, Kerberos, etc.).  The default is to use the
+# traditional Unix authentication mechanisms.
+
+auth	required	pam_env.so
+auth	required	pam_group.so
+auth	sufficient	pam_unix.so likeauth nullok
+auth	sufficient	pam_krb5.so use_first_pass minimum_uid=100
+auth	required	pam_deny.so
diff --git a/Files/common-password b/Files/common-password
new file mode 100644
index 00000000..63ded773
--- /dev/null
+++ b/Files/common-password
@@ -0,0 +1,10 @@
+#
+# /etc/pam.d/common-password - password-related modules common to all services
+#
+# This file is included from other service-specific PAM config files,
+# and should contain a list of modules that define the services to be
+# used to change user passwords.  The default is pam_unix.
+
+password sufficient	pam_krb5.so minimum_uid=100
+password sufficient	pam_unix.so nullok md5 shadow use_authtok
+password required	pam_deny.so
diff --git a/Files/common-session b/Files/common-session
new file mode 100644
index 00000000..e4f1ee34
--- /dev/null
+++ b/Files/common-session
@@ -0,0 +1,11 @@
+#
+# /etc/pam.d/common-session - session-related modules common to all services
+#
+# This file is included from other service-specific PAM config files,
+# and should contain a list of modules that define tasks to be performed
+# at the start and end of sessions of *any* kind (both interactive and
+# non-interactive).
+
+session	required	pam_limits.so
+session	required	pam_krb5.so minimum_uid=100
+session	sufficient	pam_unix.so
diff --git a/Files/cups-printers.conf-client b/Files/cups-printers.conf-client
new file mode 100644
index 00000000..e69de29b
diff --git a/Files/hosts.erb b/Files/hosts.erb
new file mode 100644
index 00000000..027267af
--- /dev/null
+++ b/Files/hosts.erb
@@ -0,0 +1,17 @@
+#
+# /etc/hosts: static lookup table for host names
+#
+
+#<ip-address>	<hostname.domain.org>	<hostname>
+127.0.0.1		localhost.localdomain	localhost
+<%= ipaddress %>	<%= fqdn %>	<%= hostname %>	
+2001:6b0:17:f0a0::<%= ipaddress.split('.')[3].to_i().to_s(16) %>	 <%= fqdn %>     <%= hostname %>
+
+130.236.254.1	liunet-gw.lysator.liu.se	liunet-gw
+130.236.254.2	ns-master.lysator.liu.se	ns-master
+130.236.254.4	ns-slave.lysator.liu.se		ns-slave
+130.236.254.25	hoover.lysator.liu.se		hoover loghost
+130.236.254.125	as-master.lysator.liu.se	as-master
+130.236.254.126	as-slave.lysator.liu.se		as-slave
+
+# End of file
diff --git a/Files/interfaces-Debian.erb b/Files/interfaces-Debian.erb
new file mode 100644
index 00000000..eb21f496
--- /dev/null
+++ b/Files/interfaces-Debian.erb
@@ -0,0 +1,14 @@
+auto lo
+iface lo inet loopback
+
+auto eth0
+iface eth0 inet static
+	address <%= ipaddress %>
+	netmask 255.255.255.0
+	network	130.236.254.0
+	broadcast 130.236.254.255
+	gateway	130.236.254.1
+
+iface eth0 inet6 static
+	address 2001:6b0:17:f0a0::<%= ipaddress.split('.')[3].to_i().to_s(16) %>
+	netmask 64
diff --git a/Files/krb5.conf b/Files/krb5.conf
new file mode 100644
index 00000000..4acf5a91
--- /dev/null
+++ b/Files/krb5.conf
@@ -0,0 +1,24 @@
+# $HeadURL: file:///lysator/root/cfengine2/trunk/files/linux/krb5.conf $
+# $Id: krb5.conf 47 2008-09-02 13:48:31Z creideiki $
+#
+# /etc/krb5.conf, configuration file for MIT Kerberos.
+#
+
+[libdefaults]
+        default_realm = LYSATOR.LIU.SE
+
+[realms]
+        LYSATOR.LIU.SE = {
+                kdc = as-master.lysator.liu.se
+                kdc = as-slave.lysator.liu.se
+                admin_server = as-master.lysator.liu.se
+        }
+
+[domain_realm]
+        .lysator.liu.se = LYSATOR.LIU.SE
+
+[appdefaults]
+        kinit = {
+                renewable = true
+                forwardable = true
+        }
diff --git a/Files/nrpe.cfg b/Files/nrpe.cfg
new file mode 100644
index 00000000..75e049a9
--- /dev/null
+++ b/Files/nrpe.cfg
@@ -0,0 +1,28 @@
+# This file is centrally managed.  Do not edit.  Source:
+# svn+ssh://lsvn.lysator.liu.se/svnroot/nagios-plugins/trunk/nagios-plugins
+
+pid_file=/var/run/nrpe.pid
+server_port=5666
+nrpe_user=nagios
+nrpe_group=nagios
+dont_blame_nrpe=0
+debug=0
+command_timeout=60
+connection_timeout=300
+
+# OS-specific commands added by the lysator-nagios-plugins framework.
+include=/opt/nrpe/etc/nrpe-os.cfg
+
+# OS-and-site-specific commands, also from the lysator-nagios-plugins
+# framework.
+include=/opt/nrpe/etc/nrpe-os-site.cfg
+
+# Commands derived automatically from the current host configuration
+# the the lysator-nagios-plugins framework.
+include=/opt/nrpe/etc/nrpe-host-auto.cfg
+
+# Extra commands added manually by the host administrator.  This file
+# will not be overwritten by the next install of
+# lysator-nagios-plugins, so this is the proper place to adde
+# host-specific check commands.
+include=/opt/nrpe/etc/nrpe-host-manual.cfg
diff --git a/Files/nsswitch.conf-limited b/Files/nsswitch.conf-limited
new file mode 100644
index 00000000..d53fdfa4
--- /dev/null
+++ b/Files/nsswitch.conf-limited
@@ -0,0 +1,20 @@
+# /etc/nsswitch.conf
+#
+# Example configuration of GNU Name Service Switch functionality.
+# If you have the `glibc-doc-reference' and `info' packages installed, try:
+# `info libc "Name Service Switch"' for information about this file.
+
+passwd:         compat
+group:          compat
+shadow:         compat
+
+hosts:          files dns
+networks:       files
+
+protocols:      db files
+services:       db files
+ethers:         db files
+rpc:            db files
+
+automount:	files nis
+netgroup:       nis
diff --git a/Files/nsswitch.conf-user b/Files/nsswitch.conf-user
new file mode 100644
index 00000000..9583c424
--- /dev/null
+++ b/Files/nsswitch.conf-user
@@ -0,0 +1,20 @@
+# /etc/nsswitch.conf
+#
+# Example configuration of GNU Name Service Switch functionality.
+# If you have the `glibc-doc-reference' and `info' packages installed, try:
+# `info libc "Name Service Switch"' for information about this file.
+
+passwd:         nis files
+group:          nis files
+shadow:         files
+
+hosts:          files dns
+networks:       files
+
+protocols:      db files
+services:       db files
+ethers:         db files
+rpc:            db files
+
+automount:	files nis
+netgroup:       nis
diff --git a/Files/ntp.conf-client b/Files/ntp.conf-client
new file mode 100644
index 00000000..09a6ef85
--- /dev/null
+++ b/Files/ntp.conf-client
@@ -0,0 +1,18 @@
+# NOTES:
+#  - you should only have to update the server line below
+#  - if you start getting lines like 'restrict' and 'fudge'
+#    and you didnt add them, AND you run dhcpcd on your
+#    network interfaces, be sure to add '-Y -N' to the
+#    dhcpcd_ethX variables in /etc/conf.d/net
+
+# Name of the servers ntpd should sync with
+# Please respect the access policy as stated by the responsible person.
+#server		ntp.example.tld		iburst
+
+server ntp1.lysator.liu.se iburst
+server ntp2.lysator.liu.se iburst
+server ntp3.lysator.liu.se iburst
+
+# you should not need to modify the following paths
+logfile		/var/log/ntp.log
+driftfile	/var/lib/ntp/ntp.drift
diff --git a/Files/puppet-Makefile.erb b/Files/puppet-Makefile.erb
new file mode 100644
index 00000000..d395bf40
--- /dev/null
+++ b/Files/puppet-Makefile.erb
@@ -0,0 +1,67 @@
+CVSUSER		= bellman
+CVSHOST		= kjell.nsc.liu.se
+CVSDIR		= /net/storage/home/bellman/CvsRoot
+CVSROOT		= :ext:${CVSUSER}@${CVSHOST}:${CVSDIR}
+export CVS_RSH	= ssh
+CVSMODULE	= playpuppet
+
+CONFIGHOME	= /home/bellman/puppet
+PKGTREE		= /sw/packages/extra
+DISTHOSTS	= calle.nsc.liu.se
+PDISTHOSTS	:=$(shell echo ${DISTHOSTS} | tr ' ' ,)
+SKARP		= SKARP
+
+RM_R	= ${RM} -r
+MV	= mv -vi
+COPY_R	= cp -a
+MAKEFLAGS = --no-print-directory
+
+
+default:
+	@echo ""
+	@echo "There is no default target!"  >&2
+	@echo "You might want to do \`\`${MAKE} skarp''"  >&2
+	@echo ""
+	@exit 64
+
+
+skarp: ${SKARP}/CVS
+	cd ${SKARP} && chmod -R +w .
+	[ "x${NOCLEAN}" = "xtrue" ] || { cd ${SKARP} && ${MAKE} clean; }
+	cd ${SKARP} && cvs -q update -C -d .
+	cd ${SKARP} && ${MAKE}
+	cd ${SKARP} && find . -name '.#*.*.*' -exec ${RM} '{}' \;
+	cd ${SKARP} && chmod -R a-w .
+
+xskarp:
+	${MAKE} skarp NOCLEAN=true
+
+%/CVS:
+	@${MAKE} checkout TARGET=$(@D)
+
+checkout:
+	@[ -n "${TARGET}" ] || (echo "Variable TARGET not set" >&2; exit 64)
+	(cvs -q -d"${CVSROOT}" checkout -d "${TARGET}" "${CVSMODULE}")
+
+pdist:
+	@echo
+	@echo -e '\tNOTE!  This does not remove old files from target hosts!'
+	@echo
+	pdsh -w root@${PDISTHOSTS} mkdir -pv "${CONFIGHOME}" #"${PKGTREE}"
+	pdcp -w root@${PDISTHOSTS} -rp "${CONFIGHOME}/" "${CONFIGHOME}"
+	@#pdcp -w root@${PDISTHOSTS} -rp "${PKGTREE}" "${PKGTREE}"
+
+rdist:
+	@for host in ${DISTHOSTS}; do \
+	    echo; echo "-----  $$host  -----"; echo; \
+	    ( \
+		set -x; \
+		rsync -essh -avR --delete --delete-excluded \
+				--exclude CVS/ --exclude src/ \
+			"${CONFIGHOME}"/[A-Z][A-Z0-9]* \
+			"${CFEBINTREE}" \
+			"${PKGTREE}" \
+			"root@$$host:/"; \
+	    ); \
+	    echo; \
+	done
diff --git a/Files/puppetrun-rcinit.erb b/Files/puppetrun-rcinit.erb
new file mode 100644
index 00000000..210d9b4e
--- /dev/null
+++ b/Files/puppetrun-rcinit.erb
@@ -0,0 +1,39 @@
+#!/bin/bash
+# chkconfig: 345 65 0
+# description: Run Puppet at boot.
+
+# Check that we're a priviledged user
+[ `id -u` = 0 ] || exit 0
+
+PUPPETDIR='<%= puphome %>'
+
+. /etc/init.d/functions
+
+set -u -e
+
+
+function start()
+{
+    echo "Configuring machine using Puppet from $PUPPETDIR"
+    action "" make -C "$PUPPETDIR" -s install
+}
+
+
+# See how we were called.
+case "$1" in
+    start|restart|reload|force-reload)
+	start
+	;;
+    stop)
+	exit 0
+	;;
+    status)
+	exit 3
+	;;
+    try-restart|condrestart)
+	exit 3
+	;;
+    *)
+	echo $"Usage: $0 {start|stop}"
+	exit 2
+esac
diff --git a/Files/resolv.conf b/Files/resolv.conf
new file mode 100644
index 00000000..24415311
--- /dev/null
+++ b/Files/resolv.conf
@@ -0,0 +1,3 @@
+nameserver 130.236.254.2
+nameserver 130.236.254.4
+search lysator.liu.se
diff --git a/Files/root-.bash_logout b/Files/root-.bash_logout
new file mode 100644
index 00000000..af7c6fd8
--- /dev/null
+++ b/Files/root-.bash_logout
@@ -0,0 +1,2 @@
+# ~/.bash_logout
+
diff --git a/Files/root-.bash_profile b/Files/root-.bash_profile
new file mode 100644
index 00000000..a99681bb
--- /dev/null
+++ b/Files/root-.bash_profile
@@ -0,0 +1,28 @@
+# .bash_profile
+
+stty sane
+
+if [ -r ~/.bashrc ]; then
+    . ~/.bashrc
+fi
+
+# User specific environment and startup programs
+
+case $TERM in
+    linux)
+	case $(tty) in
+	    # RedHat 8 default uses a font without bold, so hold off on bold
+	    /dev/tty[1])	bg=black fg=green  bold=off	;;
+	    /dev/tty[2])	bg=black fg=red	   bold=off	;;
+	    /dev/tty[3])	bg=black fg=blue   bold=off	;;
+	    /dev/tty[4])	bg=black fg=yellow bold=off	;;
+	    /dev/tty[56])	bg=black fg=white  bold=off	;;
+	esac
+	if [ -n "${fg:-}" ]; then
+	    setterm -background $bg -foreground $fg -bold $bold -store
+	fi
+	;;
+esac
+
+export	LESS="-i -X -z-2"
+export	EDITOR="vi"
diff --git a/Files/root-.bashrc b/Files/root-.bashrc
new file mode 100644
index 00000000..264cd738
--- /dev/null
+++ b/Files/root-.bashrc
@@ -0,0 +1,48 @@
+# .bashrc
+
+# Ugly hack
+if [ "${LOGNAME:-}" != "root" -a -n "${DISPLAY:-}" -a -z "${XAUTHORITY}" ];
+then
+    export XAUTHORITY=`eval "echo ~$LOGNAME"`/.Xauthority
+fi
+
+alias ls='ls -F'
+alias ty=less
+alias psg='ps waux | egrep'
+alias j='jobs -l'
+alias hi=history
+
+alias rm='rm -i'
+alias cp='cp -i'
+alias mv='mv -i'
+
+set +o interactive-comments
+set -o notify
+auto_resume=
+no_exit_on_failed_exec=
+HISTCONTROL=ignoredups; history_control=$HISTCONTROL
+
+PS1='[\u@\h \W]\$ '
+if [ "$TERM" = "linux" ]; then
+    _k='\[\033[00;30m\]'		# blacK
+    _e='\[\033[01;30m\]'		# grEy
+    _r='\[\033[00;31m\]'		# Red
+    _r1='\[\033[01;31m\]'		# Light Red
+    _g='\[\033[00;32m\]'		# Green
+    _g1='\[\033[01;32m\]'		# Light Green
+    _o='\[\033[00;33m\]'		# Orange
+    _y='\[\033[01;33m\]'		# Yellow
+    _b='\[\033[00;34m\]'		# Blue
+    _b1='\[\033[01;34m\]'		# Light Blue
+    _m='\[\033[00;35m\]'		# Magenta
+    _m1='\[\033[01;35m\]'		# Light Magenta
+    _c='\[\033[00;36m\]'		# Cyan
+    _c1='\[\033[01;36m\]'		# Light Cyan
+    _w0='\[\033[00;37m\]'		# Off-white
+    _w='\[\033[01;37m\]'		# White
+    _n='\[\033[00m\]'			# Normal
+    _B='\[\033[01m\]'			# Bold
+
+#    PS1="$_r[$_y\\u$_r@$_y\\h$_r $_w\\W$_r]$_c\\\$$_n "
+    unset _k _e _r _r1 _g _g1 _o _y _b _b1 _m _m1 _c _c1 _w0 _w _n _B
+fi
diff --git a/Files/root-.cvsrc b/Files/root-.cvsrc
new file mode 100644
index 00000000..72e713cb
--- /dev/null
+++ b/Files/root-.cvsrc
@@ -0,0 +1,4 @@
+cvs -q
+#diff -U5
+update -d -P
+checkout -P
diff --git a/Files/root-.emacs b/Files/root-.emacs
new file mode 100644
index 00000000..c36b059f
--- /dev/null
+++ b/Files/root-.emacs
@@ -0,0 +1,86 @@
+;;;  ==================================================================
+;;;  Mina alldeles egna inst�llningar f�r Emacs
+
+(require 'iso-transl)
+;;(require 'jka-compr)
+(require 'complete)
+(if (>= emacs-major-version 20) 
+    (partial-completion-mode +1)
+  (setq PC-meta-flag t))
+(define-key	minibuffer-local-completion-map
+		"\M-?" 'minibuffer-completion-help)
+(define-key	minibuffer-local-must-match-map
+		"\M-?" 'minibuffer-completion-help)
+(define-key	emacs-lisp-mode-map
+		"\M-\t" 'PC-lisp-complete-symbol)
+(define-key	lisp-interaction-mode-map
+		"\M-\t" 'PC-lisp-complete-symbol)
+
+(load "uniquify" 'noerr 'nomsg)
+(setq uniquify-buffer-name-style 'post-forward-angle-brackets)
+
+
+;;;  ==================================================================
+;;;  Lite diverse saker som jag vill ha inst�llt.
+
+(let ((mode (current-input-mode)))
+  (rplaca (cdr (cdr mode)) '8bit)
+  (apply 'set-input-mode mode))
+(setq next-line-add-newlines nil)
+(setq inhibit-startup-message t)	; Inget dumt startupmeddelande
+(put 'eval-expression 'disabled nil)	; Jo, jag *vill* k�ra elisp
+(put 'narrow-to-region 'disabled nil)	; Klart att jag vet vad jag g�r!
+(put 'narrow-to-page 'disabled nil)
+(setq enable-recursive-minibuffers t)	; Varf�r inte?
+(setq visible-bell nil)
+(setq window-min-height 1)		; Inga dumma begr�nsningar
+(setq backup-by-copying-when-linked t)
+(setq search-slow-speed 2400)
+(setq diff-switches "-u")
+
+(setq Man-notify-method 'friendly)
+
+(menu-bar-mode -1)			; Menyer h�r hemma i restauranger!
+(mapcar (function (lambda (mode)	; Bort med blinkande mark�r och
+		    (if (fboundp mode)  ; eventuella knappar.
+			(apply mode '(-1)))))
+	'(blink-cursor-mode tool-bar-mode))
+
+;;;  Dessutom vill jag se vilken maskin jag k�r p�.  En del moder f�rst�r
+;;;  tyv�rr den informationen.  Info och Dired �r ett par syndare...
+(setq-default mode-line-buffer-identification
+	      (list (concat (if (= (user-uid) 0) "Root (@) " "")
+			    (capitalize ((lambda (x)
+					   (substring x 0
+						      (string-match "\\." x)))
+					 (or (getenv "HOSTNAME")
+ 					     (system-name))))
+			    ": %17b")))
+
+(setq auto-save-list-file-prefix nil)	; Inga .saves-filer, tack.
+
+(setq Info-mode-hook
+       (lambda ()
+	 (define-key Info-mode-map " " 'scroll-up)
+	 (define-key Info-mode-map "\C-?" 'scroll-down)))
+
+
+
+;;;  ==================================================================
+;;;  Lite diverse tangentbindningar
+
+(global-set-key "\C-x\C-o"		; Jag skriver j�mt fel...
+		(lambda (arg) (interactive "p") (other-window (- arg))))
+(global-set-key	"\r"		'newline-and-indent) ; S� h�r ska RET och
+(global-set-key	"\n"		'newline)	     ; LFD sitta...
+(global-set-key "\C-cg"		'goto-line)
+(global-set-key "\C-xv"		'scroll-other-window-down)
+(global-set-key "\M-&"		'query-replace-regexp)
+(global-set-key "\M- "		'fixup-whitespace)
+(global-set-key "\C-x\C-q"	'toggle-read-only)
+(global-set-key "\C-xV"		vc-prefix-map)
+(global-set-key [home]		'beginning-of-line)
+(global-set-key [end]		'end-of-line)
+(global-set-key [insert]	'yank)
+(global-set-key [f18]		'yank)
+(setq mouse-yank-at-point t)
diff --git a/Files/ssmtp.conf.erb b/Files/ssmtp.conf.erb
new file mode 100644
index 00000000..2527ac6f
--- /dev/null
+++ b/Files/ssmtp.conf.erb
@@ -0,0 +1,21 @@
+#
+# Config file for sSMTP sendmail
+#
+# The person who gets all mail for userids < 1000
+# Make this empty to disable rewriting.
+root=root+<%= hostname %>
+
+# The place where the mail goes. The actual machine name is required no 
+# MX records are consulted. Commonly mailhosts are named mail.domain.com
+mailhub=mail
+
+# Where will the mail seem to come from?
+rewriteDomain=lysator.liu.se
+
+# The full hostname
+hostname=<%= fqdn %>
+
+# Are users allowed to set their own From: address?
+# YES - Allow the user to specify their own From: address
+# NO - Use the system generated From: address
+FromLineOverride=YES
diff --git a/Files/syslogd.conf b/Files/syslogd.conf
new file mode 100644
index 00000000..44d51ebc
--- /dev/null
+++ b/Files/syslogd.conf
@@ -0,0 +1,72 @@
+#  /etc/syslog.conf	Configuration file for syslogd.
+#
+#			For more information see syslog.conf(5)
+#			manpage.
+
+#
+# First some standard logfiles.  Log by facility.
+#
+
+auth,authpriv.*			/var/log/auth.log
+*.*;auth,authpriv.none		-/var/log/syslog
+#cron.*				/var/log/cron.log
+daemon.*			-/var/log/daemon.log
+kern.*				-/var/log/kern.log
+lpr.*				-/var/log/lpr.log
+mail.*				-/var/log/mail.log
+user.*				-/var/log/user.log
+
+#
+# Logging for the mail system.  Split it up so that
+# it is easy to write scripts to parse these files.
+#
+mail.info			-/var/log/mail.info
+mail.warning			-/var/log/mail.warn
+mail.err			/var/log/mail.err
+
+# Logging for INN news system
+#
+news.crit			/var/log/news/news.crit
+news.err			/var/log/news/news.err
+news.notice			-/var/log/news/news.notice
+
+#
+# Some `catch-all' logfiles.
+#
+*.=debug;\
+	auth,authpriv.none;\
+	news.none;mail.none	-/var/log/debug
+*.=info;*.=notice;*.=warning;\
+	auth,authpriv.none;\
+	cron,daemon.none;\
+	mail,news.none		-/var/log/messages
+
+#
+# Emergencies are sent to everybody logged in.
+#
+*.emerg				*
+
+#
+# I like to have messages displayed on the console, but only on a virtual
+# console I usually leave idle.
+#
+#daemon,mail.*;\
+#	news.=crit;news.=err;news.=notice;\
+#	*.=debug;*.=info;\
+#	*.=notice;*.=warning	/dev/tty8
+
+# The named pipe /dev/xconsole is for the `xconsole' utility.  To use it,
+# you must invoke `xconsole' with the `-file' option:
+# 
+#    $ xconsole -file /dev/xconsole [...]
+#
+# NOTE: adjust the list below, or you'll go crazy if you have a reasonably
+#      busy site..
+#
+daemon.*;mail.*;\
+	news.err;\
+	*.=debug;*.=info;\
+	*.=notice;*.=warning	|/dev/xconsole
+
+*.*	@loghost
+
diff --git a/Files/xorg.conf-furfur.erb b/Files/xorg.conf-furfur.erb
new file mode 120000
index 00000000..3eb48301
--- /dev/null
+++ b/Files/xorg.conf-furfur.erb
@@ -0,0 +1 @@
+xorg.conf-ubuntu.erb
\ No newline at end of file
diff --git a/Files/xorg.conf-ubuntu.erb b/Files/xorg.conf-ubuntu.erb
new file mode 100644
index 00000000..07efa5a2
--- /dev/null
+++ b/Files/xorg.conf-ubuntu.erb
@@ -0,0 +1,33 @@
+# xorg.conf (X.Org X Window System server configuration file)
+#
+# This file was generated by dexconf, the Debian X Configuration tool, using
+# values from the debconf database.
+#
+# Edit this file with caution, and see the xorg.conf manual page.
+# (Type "man xorg.conf" at the shell prompt.)
+#
+# This file is automatically updated on xserver-xorg package upgrades *only*
+# if it has not been modified since the last upgrade of the xserver-xorg
+# package.
+#
+# Note that some configuration settings that could be done previously
+# in this file, now are automatically configured by the server and settings
+# here are ignored.
+#
+# If you have edited this file but would like it to be automatically updated
+# again, run the following command:
+#   sudo dpkg-reconfigure -phigh xserver-xorg
+
+Section "Device"
+	Identifier	"Configured Video Device"
+EndSection
+
+Section "Monitor"
+	Identifier	"Configured Monitor"
+EndSection
+
+Section "Screen"
+	Identifier	"Default Screen"
+	Monitor		"Configured Monitor"
+	Device		"Configured Video Device"
+EndSection
diff --git a/Files/yp.conf b/Files/yp.conf
new file mode 100644
index 00000000..ccaeb49a
--- /dev/null
+++ b/Files/yp.conf
@@ -0,0 +1,2 @@
+domain lysator server ns-master.lysator.liu.se
+domain lysator server ns-slave.lysator.liu.se
diff --git a/Lib/facter/environ.rb b/Lib/facter/environ.rb
new file mode 100644
index 00000000..bb188cb7
--- /dev/null
+++ b/Lib/facter/environ.rb
@@ -0,0 +1,9 @@
+# Note!  The variable names will be turned into lowercase by Puppet...
+
+ENV.each_pair do |var,value|
+    Facter.add("env_"+var) do
+        setcode do
+            value
+        end
+    end
+end
diff --git a/Lib/puppet/parser/functions/regexp_quote.rb b/Lib/puppet/parser/functions/regexp_quote.rb
new file mode 100644
index 00000000..5614ef93
--- /dev/null
+++ b/Lib/puppet/parser/functions/regexp_quote.rb
@@ -0,0 +1,9 @@
+module Puppet::Parser::Functions
+    newfunction(:regexp_quote, :type => :rvalue) do |args|
+	if args.length != 1
+	    self.fail("regexp_quote(): wrong number of arguments" +
+		      " (#{args.length} for 1)")
+	end
+	return Regexp.quote(args[0])
+    end
+end
diff --git a/Lib/puppet/parser/functions/sprintf.rb b/Lib/puppet/parser/functions/sprintf.rb
new file mode 100644
index 00000000..0a50761f
--- /dev/null
+++ b/Lib/puppet/parser/functions/sprintf.rb
@@ -0,0 +1,9 @@
+module Puppet::Parser::Functions
+    newfunction(:sprintf, :type => :rvalue) do |args|
+	if args.length < 1
+	    self.fail('sprintf(): Too few arguments (missing format string)')
+	end
+	fmt = args.shift()
+	return sprintf(fmt, *args)
+    end
+end
diff --git a/Lib/puppet/parser/functions/strftime.rb b/Lib/puppet/parser/functions/strftime.rb
new file mode 100644
index 00000000..f576e594
--- /dev/null
+++ b/Lib/puppet/parser/functions/strftime.rb
@@ -0,0 +1,12 @@
+module Puppet::Parser::Functions
+    newfunction(:strftime, :type => :rvalue) do |args|
+	if args.length < 1
+	    self.fail("strftime(): Missing format string parameter")
+	end
+	fmt = args.shift()
+	if args.length == 0
+	    return Time.now().strftime(fmt)
+	end
+	self.fail("strftime(): Too many arguments")
+    end
+end
diff --git a/Lib/puppet/type/delete_lines.rb b/Lib/puppet/type/delete_lines.rb
new file mode 100644
index 00000000..3b3888c1
--- /dev/null
+++ b/Lib/puppet/type/delete_lines.rb
@@ -0,0 +1,125 @@
+require 'nsc_utils'
+
+
+Puppet::Type.newtype(:delete_lines) do
+
+    @doc = "Delete lines matching regexp :pattern in the file :file.
+
+	    Parameters are the same as for the regexp_replace_lines type
+	    (except, of course, that there is no :replacement parameter).
+	   "
+
+    newparam(:name) do
+	desc "Name/title"
+    end
+
+    newparam(:file) do
+	desc "The file to edit"
+    end
+
+    newparam(:group_start) do
+	desc "Regexp specifying lines that start groups.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:group_end) do
+	desc "Regexp specifying lines that ends groups.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:start) do
+	desc "Only delete lines after ones matching this regexp.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:end) do
+	desc "Stop deleting when reaching a line matching this regexp.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:pattern) do
+	desc "Delete lines looking like this regexp (implicitly anchored at
+	      the beginning and end of the line).
+	     "
+
+	validate do |value|
+	    if not value  or  value == ""
+		self.fail "Parameter 'pattern' must not be the empty string"
+	    end
+	end
+    end
+
+    newparam(:skip) do
+	desc "Don't delete lines looking like this regexp (implicitly
+	      anchored at the beginning and end of the line).
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newproperty(:ensure) do
+	desc "
+	     "
+	newvalue(:deleted)
+	defaultto :deleted
+
+	def retrieve
+	    @to_kill = []
+	    @saves = {}
+	    NSC_Utils::on_section_lines(self.resource, @saves) do |l,i|
+		@to_kill.push(i)
+	    end
+
+	    if @to_kill.length > 0
+		patsource = @saves[:pattern].source
+		return self.value == patsource ? false : patsource
+	    else
+		@saves = nil
+		return self.value
+	    end
+	end
+
+	def sync
+	    lines = @saves[:lines]
+	    for i in @to_kill
+		##puts "--DEBUG: #{i+1}: <#{lines[i].chomp}>"
+		lines[i] = nil
+	    end
+	    lines.delete(nil)
+	    fp = File.new(self.resource[:file], 'w')
+	    fp.write(lines.join(""))
+	    fp.close()
+	    @saves = nil
+	    # FIXME: I have no idea what we *should* return here, but at
+	    # least this makes Puppet report that something has been done.
+	    # FIXME: It would be nice if we could convince Puppet to save
+	    # the old version of the file in the filebucket.
+	    return :true
+	end
+    end
+
+end
+
diff --git a/Lib/puppet/type/ensure_line.rb b/Lib/puppet/type/ensure_line.rb
new file mode 100644
index 00000000..8b9dcdc1
--- /dev/null
+++ b/Lib/puppet/type/ensure_line.rb
@@ -0,0 +1,233 @@
+require 'nsc_utils'
+
+
+Puppet::Type.newtype(:ensure_line) do
+
+    @doc = "Make sure the line :line exists in the file :file.
+
+            If it does not already exist, the first line matching the
+            regexp :pattern will be replace by :line.
+
+            If no match against :pattern can be found either, :line is
+            inserted after or before the first line matching :where,
+            depending on if :addhow is set to 'append' (default) or
+            'prepend'.
+
+            If no line matches :where either, or if :where is not set,
+            :line is placed first or last in the file, depending on the
+            value of :addhow.
+
+	    FIXME!
+	    There are more parameters, but I don't have the energy to
+	    document them right now.
+
+            All regexps (:pattern, :sufficient, :start, :end and :where)
+	    are implicitly anchored at the beginning of the line, i.e, as
+	    if they always began with ^.
+
+            NOTE: the parameter names are not very pretty, and may change
+            in the future when I can think of better names.
+	   "
+
+    newparam(:name) do
+	desc "Name/title"
+    end
+
+    newparam(:file) do
+	desc "The file to edit"
+    end
+
+    newparam(:start) do
+	desc "Ensure line exist whithin section(s) beginning with this regexp.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:end) do
+	desc "Ensure line exist whithin section(s) ended with this regexp.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newproperty(:line) do
+	desc "How the wanted line should look"
+
+	validate do |value|
+	    if value == ""
+		self.fail "Parameter 'line' must not be the empty string"
+	    end
+	end
+
+	def retrieve
+	    resources = self.resource
+	    section_start, include_section_start =
+		NSC_Utils::boundary(resources, :start)
+	    section_end, include_section_end =
+		NSC_Utils::boundary(resources, :end)
+
+	    wanted_line = self.value
+	    searchpattern = self.resource[:pattern]
+	    if searchpattern
+		searchpattern = Regexp.new('^' + self.resource[:pattern])
+	    end
+	    sufficient = self.resource[:sufficient]
+	    if sufficient
+		sufficient = Regexp.new('^' + sufficient)
+	    end
+	    wherepattern = self.resource[:where]
+	    if wherepattern
+		wherepattern = Regexp.new('^' + wherepattern)
+	    end
+	    addhow = self.resource[:addhow]
+
+	    @lines = File.readlines(self.resource[:file])
+	    sections = NSC_Utils::extract_sections(
+		    NSC_Utils::enumerate(@lines),
+		    section_start, true,
+		    section_end, true,
+		    true)
+
+
+	    case self.resource[:section]
+	    when :first
+		sections = sections[0,1]
+	    when :last
+		sections = sections[-1,1] or []
+	    when :all
+		sections = sections
+	    end
+
+	    if @lines.length == 0
+		sections = [["", 0]]
+		include_section_start = include_section_end = false
+	    end
+
+	    @to_replace = []
+	    @to_add = []
+	    for sect in sections
+		found = rpos = ipos = false
+		firstline = sect[0][1]
+		lastline = sect[-1][1]
+		if not include_section_start
+		    sect = sect[1..-1] or []
+		end
+		if not include_section_end
+		    sect = sect[0..-2]
+		end
+		for l,i in sect
+		    l = l.chomp
+		    if l == wanted_line
+			found = i
+		    elsif sufficient and sufficient.match(l)
+			found = i
+		    elsif searchpattern and searchpattern.match(l)
+			rpos = i
+		    elsif not ipos and wherepattern and wherepattern.match(l)
+			ipos = i
+		    end
+		end
+
+		if found
+		    0
+		elsif rpos
+		    @to_replace.push(rpos)
+		elsif ipos
+		    if addhow == :prepend
+			@to_add.push(ipos)
+		    else
+			@to_add.push(ipos + 1)
+		    end
+		elsif addhow == :prepend
+		    @to_add.push(firstline + (include_section_start ? 0 : 1))
+		elsif addhow == :append
+		    @to_add.push(lastline + (include_section_end ? 1 : 0))
+		else
+		    self.fail('Internal error')
+		end
+	    end
+
+	    ##puts "--DEBUG: to_add     = [#{@to_add.join(', ')}]"
+	    ##puts "--DEBUG: to_replace = [#{@to_replace.join(', ')}]"
+	    if @to_replace.length > 0
+		return @lines[@to_replace[0]].chomp
+	    elsif @to_add.length > 0
+		return wanted_line == "" ? false : ""
+	    else
+		@lines = nil
+		return wanted_line
+	    end
+	end
+
+	def sync
+	    line = self.value + "\n"
+	    for i in @to_replace
+		@lines[i] = line
+	    end
+	    for i in @to_add.reverse
+		@lines.insert(i, line)
+	    end
+	    fp = File.new(self.resource[:file], "w")
+	    fp.write(@lines.join(""))
+	    fp.close()
+	    @lines = nil
+
+	    # FIXME: I have no idea what we *should* return here, but at
+	    # least this makes Puppet report that something has been done.
+	    # FIXME: It would be nice if we could convince Puppet to save
+	    # the old version of the file in the filebucket.
+	    return :true
+	end
+    end
+
+    newparam(:pattern) do
+	desc "Replace lines looking like this regexp.
+	      If not set, an exact match against :line is done.
+	     "
+	defaultto false
+    end
+
+    newparam(:sufficient) do
+	desc "Lines matching this regexp are sufficiently close to the target,
+	      and thus the line will be deemed to exist.
+
+	      If not set, an exact match against :line is required.
+	     "
+	defaultto false
+    end
+
+    newparam(:section) do
+	desc "Which section(s) to ensure the line's presence in.
+	      Allowed values are 'first', 'last', and 'all'.  Other
+	      sections are not touched.
+
+	      This parameter is meaningless if :start or :end is not set,
+	      as there will then only be one section.
+	     "
+	newvalues(:first, :last, :all)
+	defaultto :first
+    end
+
+    newparam(:where) do
+	desc "If set, and no existing line matches :pattern, place the new
+	      line after or before (according to :addhow) the first line
+	      matching this regexp.  If not set, or if no line matches
+	      :where, :line is added at the end of the file if :addhow is
+	      append, or at the beginning of the file if :addhow is prepend.
+	     "
+	defaultto false
+    end
+
+    newparam(:addhow) do
+	desc "Whether to append or prepend a new line."
+	newvalues(:append, :prepend)
+	defaultto :append
+    end
+end
diff --git a/Lib/puppet/type/regexp_replace_lines.rb b/Lib/puppet/type/regexp_replace_lines.rb
new file mode 100644
index 00000000..4103ee46
--- /dev/null
+++ b/Lib/puppet/type/regexp_replace_lines.rb
@@ -0,0 +1,157 @@
+require 'nsc_utils'
+
+
+Puppet::Type.newtype(:regexp_replace_lines) do
+
+    @doc = "Replace lines in the file :file matching regexp :pattern with
+	    :replacement, unless they also match the regexp :skip. The
+	    pattern is implicitly anchored at the start and end of the line.
+	    The replacement text can use the standard Ruby regexp replacement
+	    back-references.
+
+	    Only lines within sections delimited by the patterns :start
+	    and :end are eligible for replacement.  Sections must in turn
+	    lie within \"groups\" that are delimited by the patterns
+	    :group_start and :group_end.  These patterns are anchored at
+	    the start of the line.
+
+	    An open section will be canceled if the surrounding group ends,
+	    and similarly an open group will be canceled if end of file is
+	    reached.  However, if the end patterns are not set, the sections
+	    and groups extend to the end of the group and file, respectively.
+	    Similarly, if the start patterns are not set, sections and
+	    groups begin at the start of the group and file, respectively.
+
+	    By default, the lines that mark the start and end of sections
+	    are not part of the sections themselves, and the lines that
+	    mark the start and end of groups are not part of the groups
+	    themselves.	 However, if the delimiter patterns start with a
+	    plus sign (+), the corresponding lines will be counted as being
+	    part of the sections or groups.
+
+	    Note that the replacement must be idempotent.  It is an error
+	    if the result of the replacement still matches :pattern.
+	   "
+
+    newparam(:name) do
+	desc "Name/title of action."
+    end
+
+    newparam(:file) do
+	desc "The file to edit"
+    end
+
+    newparam(:group_start) do
+	desc "Regexp specifying lines that start groups.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:group_end) do
+	desc "Regexp specifying lines that ends groups.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:start) do
+	desc "Only do replacements on lines after ones matching this regexp.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:end) do
+	desc "Stop replacing after reaching a line matching this regexp.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:pattern) do
+	desc "Replace lines looking like this regexp (implicitly anchored at
+	      the beginning and end of the line).
+	     "
+
+	validate do |value|
+	    if value == ""
+		self.fail "Parameter 'pattern' must not be the empty string"
+	    end
+	end
+    end
+
+    newparam(:skip) do
+	desc "Don't replace lines looking like this regexp (implicitly
+	      anchored at the beginning and end of the line).
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newproperty(:replacement) do
+	desc "What to replace the lines with.
+	      Standard Ruby backreferences can be used.
+	     "
+
+	def retrieve
+	    @to_replace = []
+	    @saves = {}
+	    NSC_Utils::on_section_lines(self.resource, @saves) do |l,i|
+		@to_replace.push(i)
+	    end
+
+	    if @to_replace.length > 0
+		patsource = @saves[:pattern].source
+		return self.value == patsource ? false : patsource
+	    else
+		@saves = nil
+		return self.value
+	    end
+	end
+
+	def sync
+	    lines = @saves[:lines]
+	    pattern = @saves[:pattern]
+	    skip = @saves[:skip]
+	    replacement = self.value
+	    for i in @to_replace
+		l = lines[i]
+		l2 = l.chomp
+		r = l2.sub(pattern, replacement)
+		##puts "--DEBUG: #{i+1}: <#{l2}> => <#{r}>"
+		if pattern.match(r) and not (skip and skip.match(r))
+		    msg = "Result of replacement still matches on line #{i+1}"
+		    self.fail(msg)
+		end
+		if l[-1,1] == "\n"
+		    r += "\n"
+		end
+		lines[i] = r
+	    end
+	    fp = File.new(self.resource[:file], 'w')
+	    fp.write(lines.join(""))
+	    fp.close()
+	    # FIXME: I have no idea what we *should* return here, but at
+	    # least this makes Puppet report that something has been done.
+	    # FIXME: It would be nice if we could convince Puppet to save
+	    # the old version of the file in the filebucket.
+	    return :true
+	end
+    end
+end
diff --git a/Lib/puppet/type/replace_sections.rb b/Lib/puppet/type/replace_sections.rb
new file mode 100644
index 00000000..d94c2d83
--- /dev/null
+++ b/Lib/puppet/type/replace_sections.rb
@@ -0,0 +1,127 @@
+require 'nsc_utils'
+
+
+Puppet::Type.newtype(:replace_sections) do
+
+    @doc = "Replace sections of lines in the file :file with :replacement.
+	    All the lines of the sections are replaced by the lines in
+	    :replacement; the old and the new section contents does not
+	    have to be the same number of lines.
+
+	    Sections are delimited by lines matching the regexps :start
+	    and :end.  By default, the delimiting lines are not part of
+	    the sections, but if the regexps start with a plus sign (+),
+	    they will be.
+
+	    Sections must be contained within groups that are delimited
+	    by lines matching the regexps :group_start and :group_end.
+	    See the documentation for regexp_replace_lines for further
+	    details about sections and groups.
+
+	    It is up to the caller to ensure that the replacements are
+	    idempotent.
+	   "
+
+    newparam(:name) do
+	desc "Name/title of action."
+    end
+
+    newparam(:file) do
+	desc "The file to edit"
+    end
+
+    newparam(:group_start) do
+	desc "Regexp specifying lines that start groups.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:group_end) do
+	desc "Regexp specifying lines that ends groups.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:start) do
+	desc "Only do replacements on lines after ones matching this regexp.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newparam(:end) do
+	desc "Stop replacing after reaching a line matching this regexp.
+	     "
+	defaultto false
+
+	munge do |value|
+	    return (value == "") ? false : value
+	end
+    end
+
+    newproperty(:replacement) do
+	desc "What to replace the lines with.
+	     "
+
+	def retrieve
+	    resources = self.resource
+	    @replacement = self.value
+	    if @replacement[-1,1] != "\n"
+		@replacement = @replacement + "\n"
+	    end
+
+	    @saves = {}
+	    @to_replace = []
+	    NSC_Utils::on_sections(resource, @saves) do |first, sect, last|
+		current = (sect.map {|l,i| l}).join('')
+		if current[-1,1] != "\n"
+		    current += "\n"
+		end
+		if current != @replacement
+		    @to_replace.push([first, last, current])
+		end
+	    end
+
+	    if @to_replace.length > 0
+		return @to_replace[0][2].chomp
+	    else
+		@saves = @replacement = @to_replace = nil
+		return self.value
+	    end
+	end
+
+	def sync
+	    lines = @saves[:lines]
+	    for s,e,old in @to_replace.reverse
+		##puts "--DEBUG: About to replace #{s}..#{e}"
+		if s == 0  and  e == -1
+		    lines.insert(0, @replacement)
+		else
+		    lines[s..e] = @replacement
+		end
+	    end
+
+	    fp = File.new(self.resource[:file], 'w')
+	    fp.write(lines.join(""))
+	    fp.close()
+
+	    @saves = @replacement = @to_replace = nil
+	    # FIXME: I have no idea what we *should* return here, but at
+	    # least this makes Puppet report that something has been done.
+	    # FIXME: It would be nice if we could convince Puppet to save
+	    # the old version of the file in the filebucket.
+	    return :true
+	end
+    end
+end
diff --git a/Lib/ruby/nsc_utils.rb b/Lib/ruby/nsc_utils.rb
new file mode 100644
index 00000000..cf5b81b0
--- /dev/null
+++ b/Lib/ruby/nsc_utils.rb
@@ -0,0 +1,185 @@
+module NSC_Utils
+
+    def boundary(resources, name)
+	include_boundary = 0
+	boundary = resources[name]
+	if boundary
+	    if boundary[0,1] == "+"
+		include_boundary = true
+		boundary = boundary[1..boundary.length]
+	    else
+		include_boundary = false
+	    end
+	    boundary = Regexp.new('^' + boundary)
+	end
+	return [boundary, include_boundary]
+    end
+    module_function :boundary
+
+
+    def enumerate(lines)
+	result = []
+	lines.each_with_index do |l,i|
+	    result.push([l,i])
+	end
+	return result
+    end
+    module_function :enumerate
+
+
+    def extract_sections(lines, startp, include_start, endp, include_end,
+			   cancel_unclosed)
+	include_start = (include_start ? 0 : 1)
+	extracted = [[]]
+	inside = startp ? false : -1
+	for l,i in lines
+	    cl = l.chomp
+	    if not inside  and  startp  and  startp.match(cl)
+		inside = i
+		extracted.push([])
+	    end
+	    if inside  and  i >= inside + include_start
+		extracted[-1].push([l,i])
+	    end
+	    if inside  and  endp  and  endp.match(cl)
+		if not include_end
+		    extracted[-1].pop()
+		end
+		inside = false
+	    end
+	end
+	if inside  and  endp  and  cancel_unclosed
+	    extracted.pop()
+	end
+	extracted.delete([])
+	return extracted
+    end
+    module_function :extract_sections
+
+
+    def on_sections(resources, saves)
+	group_start, include_group_start =
+	    NSC_Utils::boundary(resources, :group_start)
+	group_end, include_group_end =
+	    NSC_Utils::boundary(resources, :group_end)
+	section_start, include_section_start =
+	    NSC_Utils::boundary(resources, :start)
+	section_end, include_section_end =
+	    NSC_Utils::boundary(resources, :end)
+
+	saves[:lines] = File.readlines(resources[:file])
+	groups = NSC_Utils::extract_sections(
+		NSC_Utils::enumerate(saves[:lines]),
+		group_start, include_group_start,
+		group_end, include_group_end,
+		true)
+	for grp in groups
+	    sections = NSC_Utils::extract_sections(
+		    grp,
+		    section_start, true,
+		    section_end, true,
+		    true)
+	    for sect in sections
+		firstline = sect[0][1]
+		lastline = sect[-1][1]
+		if not include_section_start
+		    sect = sect[1..-1] or []
+		    firstline += 1
+		end
+		if not include_section_end
+		    sect = sect[0..-2]
+		    lastline -= 1
+		end
+		yield [firstline, sect, lastline]
+	    end
+	end
+    end
+    module_function :on_sections
+
+
+    # FIXME!
+    # This function is supposed to replace the on_section_lines() function
+    # below.  However, it is as of yet untested, so for the time being,
+    # the old implementation is the one we use.
+    def on_section_lines_2(resources, saves)
+	saves[:pattern] = Regexp.new('^' + resources[:pattern] + '$')
+	saves[:skip] = resources[:skip]
+	if saves[:skip]
+	    saves[:skip] = Regexp.new('^' + saves[:skip] + '$')
+	end
+	NSC_Utils::on_sections do |firstline, sect, lastline|
+	    for l,i in sect
+		cl = l.chomp
+		if saves[:pattern].match(cl)
+		    unless saves[:skip]  and  saves[:skip].match(cl)
+			yield [l,i]
+		    end
+		end
+	    end
+	end
+    end
+    module_function :on_section_lines_2
+
+
+    def on_section_lines(resources, saves)
+	group_start, include_group_start =
+	    NSC_Utils::boundary(resources, :group_start)
+	group_end, include_group_end =
+	    NSC_Utils::boundary(resources, :group_end)
+	section_start, include_section_start =
+	    NSC_Utils::boundary(resources, :start)
+	section_end, include_section_end =
+	    NSC_Utils::boundary(resources, :end)
+	saves[:pattern] = Regexp.new('^' + resources[:pattern] + '$')
+	saves[:skip] = resources[:skip]
+	if saves[:skip]
+	    saves[:skip] = Regexp.new('^' + saves[:skip] + '$')
+	end
+
+	saves[:lines] = File.readlines(resources[:file])
+	groups = NSC_Utils::extract_sections(
+		NSC_Utils::enumerate(saves[:lines]),
+		group_start, include_group_start,
+		group_end, include_group_end,
+		true)
+	for grp in groups
+	    sections = NSC_Utils::extract_sections(
+		    grp,
+		    section_start, include_section_start,
+		    section_end, include_section_end,
+		    true)
+	    for sect in sections
+		for l,i in sect
+		    cl = l.chomp
+		    if saves[:pattern].match(cl)
+			unless saves[:skip]  and  saves[:skip].match(cl)
+			    yield [l,i]
+			end
+		    end
+		end
+	    end
+	end
+    end
+    module_function :on_section_lines
+
+    if false
+    _l1 = [ 'foo', 'bar', 'gazonk', 'del',
+	   'apelsin', 'citron', 'fromage',
+	   'choklad', 'pudding',
+	  ]
+    _l2 = File.readlines('/tmp/trh/grub.conf')
+    _nl1 = enumerate(_l1)
+    _nl2 = enumerate(_l2)
+    _sp1 = /^bar|^citron/
+    _ep1 = /^del|^pudding/
+    _ep2 = /^del|^choklad/
+    _ep3 = /^del|^fromage/
+    _ep4 = /^del|^gurksallad/
+    _ep5 = /^gurksallad/
+    end
+
+    X = 17
+    Y = 23
+    Z = 69
+
+end
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..4c9d2a39
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,85 @@
+RM	= rm -vf
+
+export	PUPHOME	= $(shell pwd)
+export	RUBYLIB	= ${PUPHOME}/Lib/ruby
+# We can't rely on $PATH when Puppet is run from cron.  Specifically,
+# /sbin and /usr/sbin are missing.
+export	PATH	= /bin:/usr/bin:/sbin:/usr/sbin
+
+LOGDIR	  := /var/log/puppet
+export LOGDIR			# Needed by the log-puppetrun class
+NOW	  := $(shell /bin/date +'%Y %m %d--%H.%M.%S')
+MONTHDIR  := $(word 1,${NOW})-$(word 2,${NOW})
+TIMESTAMP := $(word 1,${NOW})-$(word 2,${NOW})-$(word 3,${NOW})
+SHORTHOST := $(shell /bin/uname -n | /bin/sed 's/[.].*//')
+LOGSUBDIR := ${LOGDIR}/${SHORTHOST}/${MONTHDIR}
+LOGFILE	  := ${LOGSUBDIR}/${TIMESTAMP}
+
+# Extra flags to give to Puppet
+PUPFLAGS=
+# Extra environment variables to give to Puppet
+PUPENV	=
+
+# Command to strip "uninteresting" messages from cron runs
+#STRIPMSG= egrep -v '^notice:|^info:|^debug:'
+STRIPMSG= cat
+PUPPET	= ${PUPENV} puppet --color=false ${PUPFLAGS} --libdir="${PUPHOME}/Lib" --factpath="${PUPHOME}/Lib/facter"
+
+
+default:
+	cd Files && ${MAKE}
+	@#cd sendmail && ${MAKE}
+
+# Note that this target does not install, or change, the cron job that
+# runs Puppet.
+run:
+	mkdir -p "${LOGSUBDIR}"
+	@echo "Source:  ${PUPHOME}"	>"${LOGFILE}"
+	@echo "Command: ${PUPPET}"	>>"${LOGFILE}"
+	@echo ""			>>"${LOGFILE}"
+	${PUPPET} --tags pkgrepo SITE.pp 2>&1 | tee -a "${LOGFILE}"
+	${PUPPET} SITE.pp 2>&1 | tee -a "${LOGFILE}"
+	@if [ `wc -l <"${LOGFILE}"` -le 3 ]; then \
+	    /bin/rm -f "${LOGFILE}" ; true ; \
+	else \
+	    fin=`date +'%Y-%m-%d  %H:%M:%S'`; \
+	    echo ""			>>"${LOGFILE}" ; \
+	    echo "Finished:  $$fin"	>>"${LOGFILE}" ; \
+	fi
+
+# This target, however, does install the cron job.
+install:
+	@${MAKE} run PUPENV="PUP_DOINSTALL=true ${PUPENV}"
+
+# Run from cron
+# This target also installs the cron job, but it only logs problems
+# to the "terminal".
+# Note: egrep will return 1 if nothing matches, which is perfectly normal
+# in this case, thus the "; true".  Unfortunately we lose the exit status
+# of the make command, but it shouldn't matter much here.
+cron:
+	@${MAKE} run PUPENV="PUP_DOINSTALL=true ${PUPENV}" | \
+	    (${STRIPMSG}; true)
+
+# The 'kickstart' target is used when we run Puppet from the %post kickstart
+# script, since we don't want to actually start the services then.
+kickstart:
+	@${MAKE} run PUPENV="PUP_DOINSTALL=true PUP_RUNDAEMONS=false ${PUPENV}"
+
+# Perform a "dryrun", i.e run without actually making any changes.
+dry:
+	@${MAKE} run PUPFLAGS="--noop ${PUPFLAGS}"
+
+test:
+	${PUPPET} test.pp
+
+
+clean:
+	${RM} .puppethome
+	cd Files && ${MAKE} clean
+	@#cd sendmail && ${MAKE} clean
+	${RM}  *..tmp *.BAK *~ \#.*
+
+
+
+.PHONY: default run install cron kickstart test clean
diff --git a/README b/README
new file mode 100644
index 00000000..f9ed36f9
--- /dev/null
+++ b/README
@@ -0,0 +1,134 @@
+This README file documents how these Puppet manifests are used.
+
+
+
+Unlike the "traditional" way of deploying Puppet, this doesn't
+use a central puppetmasterd with clients connecting to it using
+puppetd.  Instead, the manifests are supposed to be directly
+accessible in the file system on the clients, and the stand-alone
+puppet program is used.
+
+
+The manifests are under CVS revision control, in a central CVS
+repository.  To apply them on a machine, you check them out
+using something like:
+
+    [~]$ cd /config
+    [/config]$ cvs -d :ext:user@cvshost:repopath co -d TEST puppet
+    [/config]$ cd TEST
+
+and then run them using:
+
+    [/config/TEST]$ su
+    [/config/TEST]# make install
+
+This will run Puppet (twice, actually; more on that later).  The
+manifests will also install a cron job that runs Puppet from this
+directory (/config/TEST in this example) regularly.
+
+Other interesting targets in the Makefile are:
+
+- run	'make run' runs Puppet without installing the cron job
+	that runs Puppet.
+
+- dry	Similar to 'make run', but it also passes the --noop flag
+	to Puppet, so you can see what Puppet wants to do without
+	actually doing anything.  Useful when you aren't 100% sure
+	that your changes are correct. :-)
+
+- cron	This is the target that the cron job uses.  The difference
+	from 'make install' is that it can be configured to filter
+	out informational messages, so only error messages are
+	mailed to root.
+
+- kickstart
+	Similar to 'make install', but it will make sure all services
+	are stopped instead of running.  This is supposed to be used
+	when Puppet is run from inside RedHat kickstart, Solaris
+	jumpstart, or other similar situations.  It is not used by these
+	manifests, but it is used on some NSC clusters.
+
+
+Usually, you have the manifests checked out at least twice on
+every client, in different directories.  One such directory is
+slightly special; it is named SKARP (Swedish for "live", as in a
+live grenade), and is usually located under /config.  This is
+from where clients run normally, and you are not supposed to edit
+files directly there; it is kept read-only.
+
+When you want to change the manifests, you check them out in
+another directory (e.g, /config/TEST), and edit and test them
+there.  When you are satisfied, you check in your changes to CVS,
+and check them out under SKARP, using:
+
+    [/config]# make skarp
+    [/config]# cd SKARP
+    [/config/SKARP]# make install
+
+The Makefile in /config is installed automatically by the Puppet
+manifests.  The "skarp" target will check out the manifests from
+CVS into the SKARP subdirectory; it knows that SKARP is read-only,
+so you don't need to change permissions manually before or after
+checking out to SKARP.
+
+Note that it is important to run 'make install' from the SKARP
+subdirectory after checking out updated manifests there.
+Otherwise, the client might have its cron job pointing to a
+directory with broken or unmaintained manifests.  By running
+'make install', the cron job will be updated to point to the
+/config/SKARP directory.
+
+
+
+LOGGING
+=======
+
+The Makefile and Puppet manifests maintain logs of the Puppet
+runs, by default under /var/log/puppet/$HOSTNAME.  There will be
+one file named "puppetrun", which contain one line for each time
+Puppet is run, specifying:
+
+  - timestamp (date and time of day)
+  - operating system and OS version
+  - Puppet version
+  - directory from where the manifests where taken
+
+By doing a 'tail -n1' on this file, you can quickly see if Puppet
+is being run properly, and is running from the correct directory
+(i.e, SKARP).
+
+Logs of what Puppet actually did, including any error messages,
+are written in a separate file for each Puppet run.  They are
+kept in a subdirectory per month, and named after the date and
+time when Puppet ran.  Log files when nothing happened (no
+messages at all from Puppet, neither informational nor error
+messages) are however immediately deleted, so you only have the
+interesting logs around.
+
+
+
+THE PKGREPO TAG
+===============
+
+As mentioned above, the make targets will actually run Puppet
+twice, once with --tags pkgrepo, and once without.  In the
+manifests, resources that set up package repositories, set
+package build flags and so on, are tagged with the tag
+'pkgrepo'.  This is done because package repositories must be
+configured before we try to install any packages, and it is
+currently (as of Puppet 0.24.6) not possible to say that some
+resources must be implemented before *all* package resources.
+
+
+
+PUPPET EXTENSIONS
+=================
+
+There are a few custom resource types for editing lines in text
+files included here.  You can find them in the Lib/puppet/type
+subdirectory.  There are documentation strings in the source code
+for these that hopefully make their purpose understandable.
+
+There are also a couple of custom functions (which you can find
+in Lib/puppet/parser/functions), and a number of definitions (in
+util.pp) which makes use of the custom types.
diff --git a/SITE.pp b/SITE.pp
new file mode 100644
index 00000000..7d4c86b7
--- /dev/null
+++ b/SITE.pp
@@ -0,0 +1,60 @@
+$puphome  = $env_puphome
+$pupfiles = "$puphome/Files"
+
+# The normal location where we check out Puppet, and especially where
+# SKARP is located:
+$puptree  = "/config"
+# Where we log Puppet runs:
+$pup_logdir = $env_logdir
+
+$osdist = "${operatingsystem}-${lsbdistrelease}"
+
+# We set $running to stopped when Puppet is run during kickstart, and
+# use $running in every service definition when we would normally have
+# specified 'ensure => running', so services aren't started while the
+# machine is installing.
+$running = $env_pup_rundaemons ? { "false" => stopped, default => running, }
+
+
+import "util.pp"
+import "rootuser.pp"
+import "osfixes.pp"
+import "autofs.pp"
+import "printing.pp"
+import "time.pp"
+import "puppet.pp"
+import "environment.pp"
+import "nis.pp"
+import "network.pp"
+import "kerberos.pp"
+import "syslog.pp"
+import "mail.pp"
+import "nrpe.pp"
+
+
+node "furfur"
+{
+   $puptree = "/root/puppet"
+
+   include user-environment
+   include development-environment
+   include sysadm-environment
+   include workstation
+   include network
+   include kerberos
+   include syslog
+   include mail
+   include nrpe
+
+   include root-home
+   include osfixes
+   include log-puppetrun
+   include puppetmaster
+ #  include puppetify
+   include nis-client-user
+   include autofs
+   include printclient
+   include timeclient-static
+   include multimedia-station
+   
+}
diff --git a/autofs.pp b/autofs.pp
new file mode 100644
index 00000000..36ed5fa0
--- /dev/null
+++ b/autofs.pp
@@ -0,0 +1,24 @@
+class autofs
+{
+    package {
+	"autofs":
+	    ensure => installed,
+	    name => $operatingsystem? {
+		"Debian" => "autofs",
+	    };
+    }
+
+    file {
+	"/etc/auto.master":
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    require => Package["autofs"],
+	    content => template("$pupfiles/auto.master.erb");
+    }
+
+    service { 
+	"autofs": 
+	    enable => true, ensure => $running, 
+	    require => Package["autofs"], subscribe => File["/etc/auto.master"];
+    }
+}
diff --git a/environment.pp b/environment.pp
new file mode 100644
index 00000000..220e7b96
--- /dev/null
+++ b/environment.pp
@@ -0,0 +1,142 @@
+class user-environment::debian
+{
+    package {
+	[
+	  "emacs", "screen", "telnet"
+	]:
+	    ensure => installed;
+    }
+}
+
+class user-environment
+{
+    include "user-environment::$operatingsystem"
+}
+
+
+
+class development-environment::debian
+{
+    package {
+	[
+	  "build-essential", "subversion", "cvs", "git"
+	]:
+	    ensure => installed;
+    }
+}
+
+class development-environment
+{
+    include "development-environment::$operatingsystem"
+}
+
+
+
+class sysadm-environment::debian
+{
+    package {
+	[
+	  "pciutils", "usbutils",
+	  "sysstat", "strace", "lsof", "lshw",
+	  "traceroute"
+	]:
+	    ensure => installed;
+    }
+}
+
+class sysadm-environment
+{
+    include "sysadm-environment::$operatingsystem"
+}
+
+
+
+class x11-client::debian
+{
+    package {
+	[
+	  "xterm",
+	  "gv", "xpdf"
+	]:
+	    ensure => installed;
+    }
+}
+
+# X11 programs that are of "generic" use, and can be of use remotely
+# as well.  Very graphically intensive applications that will almost
+# certainly be used on machines with a local display do not belong
+# here.
+class x11-client
+{
+    include "x11-client::$operatingsystem"
+}
+
+
+
+class x11-server::debian
+{
+    package {
+	[
+	]:
+	    ensure => installed;
+    }
+}
+
+class x11-server
+{
+    include "x11-server::$operatingsystem"
+
+    file {
+	"/etc/X11/xorg.conf":
+	    content => template("$pupfiles/xorg.conf-${hostname}.erb"),
+	    owner => "root", group => "root", mode => 0444,
+	    require => Class["x11-server::$operatingsystem"];
+    }
+}
+
+
+
+class workstation::debian
+{
+    package {
+	[
+	]:
+	    ensure => installed;
+    }
+}
+
+class workstation
+{
+    include x11-server
+    include x11-client
+    include "workstation::$operatingsystem"
+}
+
+
+
+class audio-station::debian
+{
+#    package {
+#	[ 
+#	]:
+#	    ensure => installed;
+#    }
+}
+
+class audio-station
+{
+    include "audio-station::$operatingsystem"
+}
+
+
+
+class multimedia-station::debian
+{
+}
+
+class multimedia-station
+{
+    include workstation
+    include audio-station
+    include "multimedia-station::$operatingsystem"
+}
diff --git a/kerberos.pp b/kerberos.pp
new file mode 100644
index 00000000..303e0df8
--- /dev/null
+++ b/kerberos.pp
@@ -0,0 +1,55 @@
+class pam
+{
+    file {
+	"/etc/pam.d/common-auth":
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    source => "$pupfiles/common-auth";
+	 "/etc/pam.d/common-account":
+            ensure => file,
+            owner => "root", group => "root", mode => 644,
+            source => "$pupfiles/common-account";
+	 "/etc/pam.d/common-session":
+            ensure => file,
+            owner => "root", group => "root", mode => 644,
+            source => "$pupfiles/common-session";
+	 "/etc/pam.d/common-password":
+            ensure => file,
+            owner => "root", group => "root", mode => 644,
+            source => "$pupfiles/common-password";
+
+    }
+}
+
+class kerberos
+{
+    $krb5 = $operatingsystem ? {
+	"Debian" => "krb5-user",
+    }
+
+    $pam_krb5 = $operatingsystem ? {
+	"Debian" => "libpam-krb5"
+    }
+
+   $krb5_conf = $operatingsystem ? {
+	"Debian" => "/etc/krb5.conf",
+	default => "/etc/krb5/krb5.conf"
+   }
+
+    package {
+	[ $krb5, $pam_krb5 ]:
+	    ensure => installed,
+    }
+
+    file {
+	"/etc/krb5.conf":
+	    name => $krb5_conf,
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    require => Package[$krb5],
+	    source => "$pupfiles/krb5.conf";
+    }
+
+    include pam
+}
+
diff --git a/mail.pp b/mail.pp
new file mode 100644
index 00000000..0536470d
--- /dev/null
+++ b/mail.pp
@@ -0,0 +1,15 @@
+class mail
+{
+    package {
+	"ssmtp":
+	    ensure => installed;
+    }
+
+    file {
+	"/etc/ssmtp/ssmtp.conf":
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    require => Package["ssmtp"],
+	    content => template("$pupfiles/ssmtp.conf.erb");
+   }
+}
diff --git a/network.pp b/network.pp
new file mode 100644
index 00000000..de78da67
--- /dev/null
+++ b/network.pp
@@ -0,0 +1,60 @@
+class dns
+{
+    file {
+	"/etc/resolv.conf":
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    source => "$pupfiles/resolv.conf";
+    }
+}
+
+class hosts
+{
+    file {
+        "/etc/hosts":
+            ensure => file,
+            owner => "root", group => "root", mode => 644,
+            content => template("$pupfiles/hosts.erb");
+     }
+}
+
+class interfaces
+{
+    file {
+	"interfaces":
+	    name => $operatingsystem? {
+		"Debian" => "/etc/network/interfaces"
+	    },
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    content => template("$pupfiles/interfaces-${operatingsystem}.erb");
+    }
+}
+
+class ssh
+{
+    package {
+	"ssh":
+	    ensure => installed
+    }
+
+    service {
+	"ssh":
+	    enable => true, ensure => $running,
+	    require => Package["ssh"], subscribe => File["/etc/ssh/sshd_config"];
+    }
+
+    file {
+	"/etc/ssh/sshd_config":
+	    ensure => file,
+	    owner => "root", group => "root", mode => 600;
+    }
+}
+
+class network
+{
+    include interfaces
+    include hosts
+    include dns
+    include ssh
+}
diff --git a/nis.pp b/nis.pp
new file mode 100644
index 00000000..76348fd1
--- /dev/null
+++ b/nis.pp
@@ -0,0 +1,73 @@
+class nis-generic
+{
+    package {
+	 "nis":
+	    ensure => installed,
+	    name => $operatingsystem? {
+		"Debian" => "nis",
+	    };
+    }
+
+    file {
+	"/etc/defaultdomain":
+	   name => $operatingsystem? {
+	       "Debian" => "/etc/defaultdomain",
+            },
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    require => Package["nis"],
+	    content => "lysator"
+    }
+
+    service { 
+	"nis": 
+	    enable => true, ensure => $running, 
+	    pattern => "ypbind",
+	    require => Package["nis"], subscribe => File["/etc/defaultdomain"], subscribe => File["/etc/yp.conf"];
+    }
+}
+
+class nis-client-generic inherits nis-generic
+{
+    file {
+	"/etc/yp.conf":
+	    name => $operatingsystem? {
+		"Debian" => "/etc/yp.conf",
+	    },
+	    ensure => file,
+            owner => "root", group => "root", mode => 644,
+	    require => Package["nis"],
+	    source => "$pupfiles/yp.conf";
+    }
+}
+
+class nis-client-limited inherits nis-client-generic
+{
+    file {
+	"/etc/nsswitch.conf":
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    source => "$pupfiles/nsswitch.conf-limited",
+	    require => Package["nis"];
+    }
+
+    ensure_line {
+	passwd_root:
+	    file => "/etc/passwd",
+	    line => "+@root:x::::/roots:";
+	passwd_nouser:
+	    file => "/etc/passwd",
+	    line => "+:x:::::/bin/nologin";
+    }
+}
+
+class nis-client-user inherits nis-client-generic
+{
+    file {
+        "/etc/nsswitch.conf":
+            ensure => file,
+            owner => "root", group => "root", mode => 644,
+            source => "$pupfiles/nsswitch.conf-user",
+            require => Package["nis"];
+    }
+}
diff --git a/nrpe.pp b/nrpe.pp
new file mode 100644
index 00000000..ceedc1f2
--- /dev/null
+++ b/nrpe.pp
@@ -0,0 +1,36 @@
+class nrpe
+{
+    package {
+	"nagios-nrpe-plugin":
+	    ensure => installed,
+	    name => $operatingsystem? {
+		"Debian" => "nagios-nrpe-plugin",
+	    };
+	"nagios-nrpe-server":
+	    ensure => installed,
+	    name => $operatingsystem? {
+		"Debian" => "nagios-nrpe-server",
+	    };
+    }
+
+    file {
+	"/etc/nagios/nrpe.cfg":
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    require => Package["nagios-nrpe-server"],
+	    source => "$pupfiles/nrp.cfg";
+	"/opt/nrpe":
+	    ensure => directory,
+	    owner => "root", group => "root", mode => 644,
+	    require => Package["subversion"];
+    }
+
+    service { 
+	"nrpe": 
+	    name => "nagios-nrpe-server",
+	    enable => true, ensure => $running, 
+	    pattern => "nrpe",
+	    require => Package["nagios-nrpe-plugin"],
+	    require => Package["nagios-nrpe-server"];
+    }
+}
diff --git a/osfixes-debian.pp b/osfixes-debian.pp
new file mode 100644
index 00000000..c6d48ea8
--- /dev/null
+++ b/osfixes-debian.pp
@@ -0,0 +1,18 @@
+class debian-keep-os-updated
+{
+}
+
+class debian-no-networkmanager
+{
+    package {
+	[
+	    "network-manager", "gnome-network-manager"
+	]:
+	    ensure => absent;
+    }
+}
+
+class debian-fixes
+{
+    include debian-no-networkmanager
+}
diff --git a/osfixes-fedora.pp b/osfixes-fedora.pp
new file mode 100644
index 00000000..d1d97c93
--- /dev/null
+++ b/osfixes-fedora.pp
@@ -0,0 +1,182 @@
+class fedora-package-repositories
+{
+    yumrepo {
+	"nsc":
+	    descr => "NSC - Internal repository",
+	    baseurl => "http://spocto.nsc.liu.se/repo/el5/\$basearch/",
+	    enabled => 0;
+    }
+}
+
+class fedora-extra-packages
+{
+    package {
+	[ ]:
+	    ensure => installed;
+    }
+}
+
+class fedora-keep-os-updated
+{
+    service {
+	"yum-updatesd":
+	    enable => false, ensure => stopped;
+    }
+    if "" {
+	exec {
+	    "/usr/bin/yum -d 1 -e 0 -y update":
+		logoutput => true,
+		schedule => updates;
+	}
+    } else {
+	cron {
+	    update-os:
+		command => "sleep \$[\$RANDOM\\%1200]; yum -d 1 -e 0 -y update",
+		user    => "root",
+		month   => "1-12", monthday => "1-31", weekday => "0-7",
+		hour    => "3", minute => "33";
+	}
+    }
+}
+
+class fedora-no-wtmp-rotation
+{
+    comment_lines {
+	wtmp-logrotate:
+	    file => "/etc/logrotate.conf",
+	    start => "+/var/log/[wb]tmp", end => "+\\}",
+	    comment => "## ";
+    }
+}
+
+class fedora-verbose-text-boot
+{
+    regexp_replace_lines {
+	no_rhgb_boot:
+	    file => "/boot/grub/grub.conf",
+	    pattern => "([ \t]*kernel[ \t].*)[ \t]rhgb(|[ \t].*)",
+	    replacement => "\\1\\2";
+	no_quiet_boot:
+	    file => "/boot/grub/grub.conf",
+	    pattern => "([ \t]*kernel[ \t].*)[ \t]quiet(|[ \t].*)",
+	    replacement => "\\1\\2";
+	no_hidden_menu:
+	    file => "/boot/grub/grub.conf",
+	    pattern => "hiddenmenu",
+	    replacement => "#\\&";
+    }
+    ensure_line {
+	grub_timeout:
+	    file => "/boot/grub/grub.conf",
+	    line => "timeout=5",
+	    pattern => "timeout[ \t]*=",
+	    where => "title",
+	    addhow => prepend;
+    }
+}
+
+class fedora-thunderbird-junk
+{
+    tidy {
+	"/tmp/tmprules.dat":
+	    backup => false, age => "5m";
+	# Wildcards doesn't seem to be supported.
+	##--"/tmp/tmprules-*.dat":
+	##--    backup => false, age => "5m";
+    }
+    exec {
+	"/bin/rm -vf /tmp/tmprules-*.dat":
+	logoutput => false, onlyif => "/bin/ls /tmp/tmprules-*.dat";
+    }
+}
+
+class fedora-profile-aliases
+{
+    tidy {
+	"/etc/profile.d/colorls.sh":		age => "0";
+	"/etc/profile.d/colorls.csh":		age => "0";
+	"/etc/profile.d/vim.sh":		age => "0";
+	"/etc/profile.d/vim.csh":		age => "0";
+	"/etc/profile.d/which-2.sh":		age => "0";
+	# We can't kill lang.sh, since other parts of Fedora
+	# explicitly source it.  But the i18n-settings class
+	# at least makes it less harmful...
+	##--"/etc/profile.d/lang.sh":		age => "0";
+	##--"/etc/profile.d/lang.csh":		age => "0";
+	"/etc/profile.d/ccache.sh":		age => "0";
+	"/etc/profile.d/ccache.csh":		age => "0";
+	"/etc/profile.d/gnome-ssh-askpass.sh":	age => "0";
+	"/etc/profile.d/gnome-ssh-askpass.csh":	age => "0";
+    }
+}
+
+class fedora-i18n-settings
+{
+    comment_lines {
+	sysconfig_no_lang:
+	    file => "/etc/sysconfig/i18n",
+	    pattern => "LANG=.*";
+    }
+    ensure_line {
+	sysconfig_lc_ctype:
+	    file => "/etc/sysconfig/i18n",
+	    line => "LC_CTYPE=sv_SE.UTF-8",
+	    pattern => "LC_CTYPE=",
+	    where => ".*LANG=", addhow => append;
+    }
+}
+
+class fedora-selinux
+{
+    rh_sysconfig {
+	selinux-selinux:
+	    subsystem => "selinux",
+	    setting => "SELINUX", value => "disabled";
+	selinux-selinuxtype:
+	    subsystem => "selinux",
+	    setting => "SELINUXTYPE", value => "targeted";
+    }
+}
+
+class fedora-lvm
+{
+    ensure_line {
+	lvm_filter_devices:
+	    file => "/etc/lvm/lvm.conf",
+	    line => "    filter = [ \"r|/dev/cdrom|\", \"r|/dev/fd.*|\" ]",
+	    pattern => "[ \t]*filter[ \t]*=.*",
+	    where => "^devices";
+	lvm_filter_devices_comment:
+	    file => "/etc/lvm/lvm.conf",
+	    line => "    # Trying to do LVM on CDs or floppies is foolish.",
+	    where => "[ \t]*filter[ \t]*=.*",
+	    addhow => prepend,
+	    require => Ensure_line[lvm_filter_devices];
+    }
+}
+
+
+class fedora8-fixes
+{
+    include fedora-package-repositories
+    include fedora-extra-packages
+    include fedora-no-wtmp-rotation
+    include fedora-verbose-text-boot
+    include fedora-thunderbird-junk
+    include fedora-profile-aliases
+    include fedora-i18n-settings
+    include fedora-selinux
+    include fedora-lvm
+
+    file { "/dev/shm":
+	    ensure => "directory",
+	    owner => "root", group => "root", mode => 1777;
+    }
+    ensure_line {
+	boot_runlevel:
+	    file    => "/etc/inittab",
+	    line    => "id:3:initdefault:",
+	    pattern => "^id:.*",
+	    where   => "^$|^[^#].*$", addhow => prepend;
+    }
+}
diff --git a/osfixes.pp b/osfixes.pp
new file mode 100644
index 00000000..21d2465b
--- /dev/null
+++ b/osfixes.pp
@@ -0,0 +1,27 @@
+import "osfixes-debian.pp"
+
+schedule {
+    updates:
+	range => "3:00-5:00", period => daily, repeat => 1;
+}
+
+
+class keep-os-updated
+{
+    case $operatingsystem {
+	"Debian": {
+		include debian-keep-os-updated
+	}
+    }
+}
+
+
+class osfixes
+{
+    case $operatingsystem {
+	"Debian": {
+		include debian-fixes
+	}
+    }
+    include keep-os-updated
+}
diff --git a/printing.pp b/printing.pp
new file mode 100644
index 00000000..1d3c9ab5
--- /dev/null
+++ b/printing.pp
@@ -0,0 +1,46 @@
+class cups-printclient
+{
+    file {
+	"/etc/cups/printers.conf":
+		source => "$pupfiles/cups-printers.conf-client",
+		owner => root, group => lp,  mode => 0600;
+    }
+}
+
+class cups-printserver
+{
+    file {
+	"/etc/cups/printers.conf":
+		source => "$pupfiles/cups-printers.conf-server",
+		owner => root, group => lp,  mode => 0600;
+    }
+}
+
+class cups
+{
+    service {
+	cups:
+	    subscribe => File["/etc/cups/printers.conf"]
+    }
+}
+
+
+class printclient
+{
+    case $operatingsystem {
+	"Fedora": {
+		include cups
+		include cups-printclient
+	}
+    }
+}
+
+class printserver
+{
+    case $operatingsystem {
+	"Fedora": {
+		include cups
+		include cups-printserver
+	}
+    }
+}
diff --git a/puppet.pp b/puppet.pp
new file mode 100644
index 00000000..856cd015
--- /dev/null
+++ b/puppet.pp
@@ -0,0 +1,78 @@
+class puppetify
+{
+    $puppetpkg = $operatingsystem ? {
+	    "Debian" => "puppet",
+	    "Fedora" => "puppet",
+	    "CentOS" => "puppet",
+	    "Gentoo" => "app-admin/puppet"
+	}
+    package {
+	$puppetpkg:
+	    ensure => present;
+    }
+
+    if $env_pup_doinstall {
+	cron {
+	    run-puppet:
+		command => "sleep \$[\$RANDOM\\%300]; cd '$puphome' && make -s --no-print-directory cron",
+		user => "root",
+		month => "1-12", monthday => "1-31", weekday => "0-7",
+		hour => "*/4", minute => "7",
+		ensure => present;
+	}
+	file {
+	    "/etc/init.d/puppetrun":
+		ensure => file,
+		content => template("$pupfiles/puppetrun-rcinit.erb"),
+		owner => "root", group => "root", mode => 0555;
+	}
+	service {
+	    "puppetrun":
+		# We don't run this at boot, since it takes too long when
+		# don't have network (not uncommon on a portable).
+		# FIXME: This should be configurable per node.
+		enable => false,
+		ensure => stopped, hasstatus => true,
+		require => [ File["/etc/init.d/puppetrun"],
+			     Package[$puppetpkg] ];
+	    "puppet":
+		enable => false, ensure => stopped, hasstatus => true,
+		require => Package[$puppetpkg];
+	}
+    }
+}
+
+
+class puppetmaster
+{
+    file {
+	"$puptree/Makefile":
+	    ensure => file,
+	    content => template("$pupfiles/puppet-Makefile.erb"),
+	    owner => "root", group => "root", mode => 0444;
+    }
+}
+
+
+class log-puppetrun
+{
+    $runlogdir  = "$pup_logdir/${hostname}"
+    $runlogfile = "$runlogdir/puppetrun"
+    $timestamp  = strftime("%Y-%m-%d  %H:%M:%S")
+
+    file {
+	$runlogdir:
+	    ensure => directory, owner => root, group => root, mode => 0755;
+	$runlogfile:
+	    ensure => file, owner => root, group => root, mode => 0644,
+	    require => File[$runlogdir];
+    }
+    ensure_line {
+	log_puppetrun:
+	    file => $runlogfile,
+	    line => sprintf("%s\t%s\t%s\t%s",
+			    $timestamp, $osdist, $puppetversion, $puphome),
+	    require => File[$runlogfile],
+	    loglevel => info;
+    }
+}
diff --git a/rootuser.pp b/rootuser.pp
new file mode 100644
index 00000000..a52c66fa
--- /dev/null
+++ b/rootuser.pp
@@ -0,0 +1,25 @@
+$root_home = $operatingsystem ? {
+	solaris => "/",
+	default => "/root",
+}
+
+class root-home
+{
+    file {
+	"$root_home/.emacs":
+		source => "$pupfiles/root-.emacs",
+		owner => "root", group => "root", mode => 0644;
+	"$root_home/.bashrc":
+		source => "$pupfiles/root-.bashrc",
+		owner => "root", group => "root", mode => 0644;
+	"$root_home/.bash_profile":
+		source => "$pupfiles/root-.bash_profile",
+		owner => "root", group => "root", mode => 0644;
+	"$root_home/.bash_logout":
+		source => "$pupfiles/root-.bash_logout",
+		owner => "root", group => "root", mode => 0644;
+	"$root_home/.cvsrc":
+		source => "$pupfiles/root-.cvsrc",
+		owner => "root", group => "root", mode => 0644;
+    }
+}
diff --git a/syslog.pp b/syslog.pp
new file mode 100644
index 00000000..05bd1fb0
--- /dev/null
+++ b/syslog.pp
@@ -0,0 +1,33 @@
+class syslog
+{
+    $syslog_conf = $operatingsystem ? {
+	default => "/etc/syslog.conf"
+    }
+    
+    $syslog = $operatingsystem ? {
+	"Debian" => "sysklogd",
+	default => "syslogd"
+    }
+
+    file {
+	"/etc/syslog.conf":
+	    name => $syslog_conf,
+	    ensure => file,
+	    owner => "root", group => "root", mode => 644,
+	    source => "$pupfiles/syslogd.conf";
+    }
+
+    service { 
+	"$syslog": 
+	    enable => true, ensure => $running, 
+	    pattern => "syslog",
+	    subscribe => File["/etc/syslog.conf"];
+    }
+
+    cron {
+	"syslog_mark":
+    	    command => "/usr/bin/logger mark",
+	    user => root,
+	    minute => 43
+    }
+}
diff --git a/time.pp b/time.pp
new file mode 100644
index 00000000..dd75860d
--- /dev/null
+++ b/time.pp
@@ -0,0 +1,58 @@
+class ntp-generic
+{
+    package {
+	"ntp":
+	    ensure => installed,
+	    name => $operatingsystem ? {
+		"Debian"	=> "ntp",
+	    };
+    }
+    file {
+	"/var/lib/ntp":
+	    # Ntpd needs to be able to store /var/lib/ntp/drift.
+	    ensure => directory,
+	    owner => "ntp", group => "ntp", mode => 0755,
+	    require => Package["ntp"];
+    }
+    case $operatingsystem {
+	"Fedora", "CentOS": {
+	    rh_sysconfig {
+		ntpd_options:
+		    subsystem => "ntpd", setting => "OPTIONS",
+		    value => '"-g -u ntp:ntp -p /var/run/ntpd.pid"',
+		    require => Package["ntp"],
+		    notify => Service["ntp"];
+	    }
+	}
+	#"Ubuntu": {
+	#}
+    }
+    file {
+	"/etc/ntp.conf":
+	    name => "/etc/ntp.conf",
+	    owner => "root", group => "root", mode => 0444,
+	    require => Package["ntp"];
+    }
+    service {
+	"ntp":
+	    enable => true, ensure => $running,
+	    require => Package["ntp"], subscribe => File["/etc/ntp.conf"];
+    }
+}
+
+
+class timeserver inherits ntp-generic
+{
+    File["/etc/ntp.conf"] {
+	source => "$pupfiles/ntp.conf-server"
+    }
+}
+
+
+class timeclient-static inherits ntp-generic
+{
+    File["/etc/ntp.conf"] {
+	source => "$pupfiles/ntp.conf-client"
+    }
+}
+
diff --git a/util.pp b/util.pp
new file mode 100644
index 00000000..d5ef71ea
--- /dev/null
+++ b/util.pp
@@ -0,0 +1,510 @@
+# Comment out lines in the file $file matching the regexp $pattern.
+# The regexp is implicitly anchored at both ends of the line.
+# This is only done on matching lines within sections within groups;
+# see the regexp_replace_lines type for how sections and groups work.
+#
+# Commenting out is done by adding $comment (default "#") to the start
+# of the lines, and $comment_end to the end of the lines.
+
+define comment_lines($file, $pattern=".*", $comment="#", $comment_end="",
+       		     $group_start="", $group_end="", $start="", $end="")
+{
+    $quoted_comment = regexp_quote($comment)
+    $quoted_comment_end = regexp_quote($comment_end)
+
+    regexp_replace_lines {
+	"comment--$title--$file--$start--$end":
+	    file => $file,
+	    group_start => $group_start, group_end => $group_end,
+	    start => $start, end => $end,
+	    pattern => "${pattern}",
+	    skip => "${quoted_comment}${pattern}(${quoted_comment_end})?",
+	    replacement => "${comment}\\&${comment_end}";
+    }
+}
+
+
+
+define config_option($file, $option, $value, $ensure="present")
+{
+    case $ensure {
+	"present": {
+	    ensure_line {
+		"config_option--$file--$option":
+		    file    => $file,
+		    line    => "${option}=${value}",
+		    pattern => "^(#)?${option}[ \t]*=.*$";
+	    }
+	}
+	"absent": {
+	    # FIXME: This will create an out-commented line if none exists.
+	    ensure_line {
+		"config_option--$file--$option":
+		    file    => $file,
+		    line    => "#${option}=${value}",
+		    pattern => "^(#)?${option}[ \t]*=.*$";
+	    }
+	}
+	"purged": {
+	    delete_lines {
+		"config_option--$file--$option":
+		    file    => $file,
+		    pattern => "^(#)?${option}[ \t]*=.*$";
+	    }
+	}
+	default: {
+	    fail("Bad config_option parameter ensure: $ensure")
+	}
+    }
+}
+
+
+# Ensure that the variable $setting is set to $value for subsystem $subsystem.
+# If $service is set, that service is notified when the file is changed.
+#
+# Note that if you need spaces or other shell metacharacters in $value,
+# you need to quote it yourself.
+#
+# This definition is RedHat-specific, as it does its duty by editing
+# the /etc/sysconfig/$subsystem file.
+
+define rh_sysconfig($subsystem, $setting, $value, $ensure="present",
+		    $service="")
+{
+    config_option {
+	"rh_sysconfig--${subsystem}--${setting}":
+	    file   => "/etc/sysconfig/${subsystem}",
+	    option => $setting,
+	    value  => $value,
+	    ensure => $ensure,
+	    notify => $service ? { "" => [], default => Service[$service] };
+    }
+}
+
+
+
+# Configure settings in /etc/make.conf in Gentoo/Portage.
+# Parameters:
+# - $name	The name of the setting, e.g. CFLAGS, FEATURES or VIDEO_CARDS
+# - $value	The value of the setting.  The value will be surrounded
+#		by double quotes, but no other quoting of the value will
+#		be done.  Be careful to not have newlines in the value,
+#		since portage_makeconf won't be able to handle what it
+#		will write in the file.
+# - $ensure	'present' (default), 'absent' or 'purged'
+
+define portage_makeconf($value="", $ensure="present")
+{
+    config_option {
+	"portage_makeconf--$name":
+	    file   => "/etc/make.conf",
+	    option => $name,
+	    value  => "\"${value}\"",
+	    ensure => $ensure,
+	    tag    => "pkgrepo";
+    }
+}
+
+
+
+# Internal helper class for Gentoo/Portage.
+class portage_files__
+{
+    file {
+	"/etc/portage":
+	    ensure => directory,
+	    owner => "root", group => "root", mode => "0755";
+	[ "/etc/portage/package.use",
+	  "/etc/portage/package.keywords",
+	  "/etc/portage/package.mask",
+	  "/etc/portage/package.unmask"
+	]:
+	    ensure => file,
+	    owner => "root", group => "root", mode => "0444";
+    }
+}
+
+# Declare Portage USE flags for packages.
+# Parameters:
+# - $name	The package for which USE flags are set.
+#		The special name "GLOBAL" means set global use flags,
+#		i.e. set the USE variable in /etc/make.conf.
+# - $use	The USE flags to set.  When set to the empty string,
+#		the entire line for the package will be removed from
+#		/etc/portage/package.use.
+
+# Note: It might be tempting to add an automatic before => Package[$name],
+# but that would be a mistake.  Sometimes you want to set use flags for
+# packages that are only installed as dependencies for other packages,
+# not because you want that package for itself.  Having to add that
+# package to the Puppet manifests would be a nuisance, and wrong (it
+# would then appear in the Portage world file).
+#    Instead we tag the changes with 'pkgrepo', so it will be done in
+# the first run of Puppet from Make.
+
+define portage_useflags($use)
+{
+    case $name {
+	"GLOBAL": {
+	    portage_makeconf {
+		"USE": value => $use;
+	    }
+	}
+	default: {
+	    include portage_files__
+	    $quoted_package = regexp_quote($name)
+	    $quoted_use = regexp_quote($use)
+	    if $use {
+		ensure_line {
+		    "portage-useflags--$name":
+			file    => "/etc/portage/package.use",
+			line    => sprintf("%-24s\t%s", $name, $use),
+			pattern => "$quoted_package[ \t]+.*",
+			sufficient => "$quoted_package[ \t]+$quoted_use",
+			require => File["/etc/portage/package.use"],
+			tag	=> 'pkgrepo';
+		}
+	    } else {
+		delete_lines {
+		    "portage-useflags--$name":
+			file    => "/etc/portage/package.use",
+			pattern => "$quoted_package[ \t]+.*",
+			require => File["/etc/portage/package.use"],
+			tag	=> 'pkgrepo';
+		}
+	    }
+	}
+    }
+}
+
+
+
+# Declare Portage keyword for packages.
+# Parameters:
+# - $name	The package for which keyword is set.
+#		The special name "GLOBAL" means set global keyword,
+#		i.e. set the ACCEPT_KEYWORDS variable in /etc/make.conf.
+# - $keyword	The keyword to set.  When set to the empty string,
+#		the entire line for the package will be removed from
+#		/etc/portage/package.keywords.
+
+# Note: Don't add a before => Package[$name]; see the note for
+# portage_useflags for further explanation.
+
+define portage_keyword($keyword)
+{
+    case $name {
+	"GLOBAL": {
+	    portage_makeconf {
+		"ACCEPT_KEYWORDS": value => $keyword;
+	    }
+	}
+	default: {
+	    include portage_files__
+	    $quoted_package = regexp_quote($name)
+	    $quoted_keyword = regexp_quote($keyword)
+	    if $keyword {
+		ensure_line {
+		    "portage-keyword--$name":
+			file    => "/etc/portage/package.keywords",
+			line    => sprintf("%-24s\t%s", $name, $keyword),
+			pattern => "$quoted_package[ \t]+.*",
+			sufficient => "$quoted_package[ \t]+$quoted_keyword",
+			require => File["/etc/portage/package.keywords"],
+			tag	=> 'pkgrepo';
+		}
+	    } else {
+		delete_lines {
+		    "portage-keyword--$name":
+			file    => "/etc/portage/package.keywords",
+			pattern => "$quoted_package[ \t]+.*",
+			require => File["/etc/portage/package.keywords"],
+			tag	=> 'pkgrepo';
+		}
+	    }
+	}
+    }
+}
+
+
+
+# Set Gentoo config options, in /etc/conf.d.
+# Parameters:
+# - $subsystem	The subsystem for which an option is defined.  The option
+#		will be written to /etc/conf.d/$subsystem.
+# - $option	The name of the option to set.
+# - $value	The value of the option.  The value will be surrounded
+#		by double quotes, but no other quoting will be performed.
+# - $ensure	'present' (default), 'absent' or 'purged'.
+
+define gentoo_conf($subsystem, $option, $value, $ensure="present")
+{
+    config_option {
+	"gentoo--${subsystem}--${option}":
+	    file   => "/etc/conf.d/${subsystem}",
+	    option => $option,
+	    value  => "\"${value}\"",
+	    ensure => $ensure;
+    }
+}
+
+
+
+# Set options for a Xinetd service.
+# Assumes that the service definition is in a file in /etc/xinetd.d
+# with the same name as the service.
+
+define xinetd_srv_option($service, $option, $value)
+{
+    $qopt = regexp_quote($option)
+    $qval = regexp_quote($value)
+
+    ensure_line {
+	"xinetd--$service--$option":
+	    file	=> "/etc/xinetd.d/$service",
+	    line	=> sprintf("\t%-23s = %s", $option, $value),
+	    pattern	=> sprintf("[ \t]*%s[ \t]*=", $qopt),
+	    sufficient	=> sprintf("[ \t]*%s[ \t]*=[ \t]*%s[ \t]*$",
+				   $qopt, $qval),
+	    start	=> ".*\\{",
+	    end		=> "[ \t]*\\}",
+    }
+}
+
+
+
+# Create (or remove) a system accont, i.e one with a "low" uid.
+# The normal user type can't be instructed to create a system
+# account without hardcoding a uid, which we don't want to do.
+#
+# A group with the same name as the user will be created at the
+# same time.
+#
+# This implementation is RedHat specific.
+
+define rh_sysuser($comment="", $home="/", $shell="/sbin/nologin",
+		  $ensure="present")
+{
+    rh_sysgroup {
+	$name:
+	    ensure => $ensure;
+    }
+    case $ensure {
+	"present": {
+	    exec {
+		"sysuser--$name":
+		    command => "useradd -r -c '$comment' -M -d '$home' -s '$shell' -g '$name'  '$name'",
+		    unless  => "getent passwd '$name'",
+		    path    => "/sbin:/usr/sbin:/bin:/usr/bin",
+		    require => Rh_sysgroup[$name];
+	    }
+	}
+	"absent": {
+	    exec {
+		"sysuser--$name":
+		    command => "userdel -f '$name'",
+		    onlyif  => "getent passwd '$name'",
+		    path    => "/sbin:/usr/sbin:/bin:/usr/bin",
+		    before  => Rh_sysgroup[$name];
+	    }
+	}
+	default: {
+	    fail("Bad rh_sysuser parameter ensure: $ensure")
+	}
+    }
+    # These are here so we get auto-require from things that want
+    # user and/or group names, like the file type.
+    user {
+	"$name":
+	    ensure => $ensure,
+	    gid => $name, comment => $comment, home => $home, shell => $shell,
+	    require => Exec["sysuser--$name"]
+    }
+}
+
+
+define rh_sysgroup($ensure="present")
+{
+    case $ensure {
+	"present": {
+	    exec {
+		"sysgroup--$name":
+		    command => "groupadd -r '$name'",
+		    unless  => "getent group '$name'",
+		    path    => "/sbin:/usr/sbin:/bin:/usr/bin";
+	    }
+	}
+	"absent": {
+	    exec {
+		"sysgroup--$name":
+		    command => "groupdel '$name'",
+		    onlyif  => "getent group '$name'",
+		    path    => "/sbin:/usr/sbin:/bin:/usr/bin";
+	    }
+	}
+	default: {
+	    fail("Bad rh_sysgroup parameter ensure: $ensure")
+	}
+    }
+    # This is here so we get auto-require from things that want
+    # group names, like the file type.
+    group {
+	"$name":
+	    ensure => $ensure, require => Exec["sysgroup--$name"]
+    }
+}
+
+
+
+# Mirror a directory tree using rsync.
+#
+# The key in the file $sshkey must not be encrypted.
+#
+# For security, the remote host should have something like this as flags
+# in its .ssh/authorized_keys file for the key:
+#
+# command="/usr/bin/rsync --server -vlogDtprR --delete --delete-excluded . $dir"
+# no-pty
+# no-port-forwarding
+# no-agent-forwarding
+# no-X11-forwarding
+
+define rsync_mirror($source, $target,
+		    $sshkey="",
+		    $unless="", $onlyif="", $creates="",
+		    $month="1-12", $monthday="1-31", $weekday="0-7",
+		    $hour="", $minute="",
+		    $ensure="present"
+		   )
+{
+    if $sshkey {
+	$sshcmd = "ssh -i$sshkey"
+    } else {
+	$sshcmd = "ssh"
+    }
+    $rsynccmd = "rsync -aRqv --no-implied-dirs --delete --delete-excluded"
+    $command = "RSYNC_RSH=\"$sshcmd\"  $rsynccmd  '$source'  '$target'"
+
+    case $ensure {
+	"present": {
+	    exec {
+		"$rsynccmd '$source' '$target'":
+		    path => "/bin:/usr/bin",
+		    unless => $unless ? { "" => undef, default => $unless },
+		    onlyif => $onlyif ? { "" => undef, default => $onlyif },
+		    creates => $creates ? { "" => undef, default => $creates };
+	    }
+
+	    if $hour {
+		cron {
+		    "mirror--$title":
+			command => "PATH=/bin:/usr/bin;  $command",
+			user => "root",
+			month => $month, monthday => $monthday,
+			weekday => $weekday,
+			hour => $hour, minute => $minute;
+		}
+	    }
+	}
+	"absent": {
+	    tidy {
+		$target:
+		    recurse => true, rmdirs => true,
+		    size => 0,
+		    backup => false
+		    ;
+	    }
+	    cron {
+		"mirror--$title":
+		    command => "PATH=/bin:/usr/bin;  $command",
+		    ensure => absent;
+	    }
+	}
+	default: {
+	    fail("Bad rsync_mirror parameter ensure: $ensure")
+	}
+    }
+}
+
+
+
+# The interface type in Puppet 0.24.x is broken.  We thus define
+# our own version, although with a somewhat different API.
+
+define rh_interface($bootproto="static",
+		    $ipaddress="",
+		    $netmask="",
+		    $gateway="",
+		    $onboot="yes",
+		    $ensure="up",
+		    $persistent_dhcp="yes")
+{
+    file {
+	"/etc/sysconfig/network-scripts/ifcfg-$name":
+	    content => template("$pupfiles/rh-ifcfg.erb"),
+	    owner => "root", group => "root", mode => 0444,
+	    notify => Exec["rh_interface--ifconfig--$name/$ensure"];
+    }
+    case $ensure {
+	"up": {
+	    exec {
+		"rh_interface--ifconfig--$name/up":
+		    command => "/sbin/ifdown '$name' && /sbin/ifup '$name'",
+		    refreshonly => true,
+		    path => "/bin:/usr/bin:/sbin:/usr/sbin";
+	    }
+	}
+	"down": {
+	    exec {
+		"rh_interface--ifconfig--$name/down":
+		    command => "/sbin/ifdown '$name'",
+		    refreshonly => true,
+		    path => "/bin:/usr/bin:/sbin:/usr/sbin";
+	    }
+	}
+	default: {
+	    fail("Bad ensure parameter to rh_interface $title: $ensure")
+	}
+    }
+}
+
+
+
+# Define a sysctl setting.
+#
+# This sets the kernel's current value, as well as adding it to
+# /etc/sysctl.conf so it gets loaded immediately when booting.
+#
+# Setting $value to the empty string ("") will remove the setting
+# from /etc/sysctl.conf.  However, since there is no way to make
+# the running kernel revert to its default value, it will not take
+# effect until next boot.
+#
+# Note also that some sysctl parameters may require a restart of
+# the kernel subsystem to take effect (e.g, the NFS lock daemon).
+
+define sysctl($value)
+{
+    $qname = regexp_quote($name)
+
+    if $value {
+	ensure_line {
+	    "sysctl--$name":
+		file => "/etc/sysctl.conf",
+		line => "$name = $value",
+		pattern => "${qname}[ \t]*=.*";
+	}
+	exec {
+	    "sysctl-w-$name":
+		command => "sysctl -w $name=$value",
+		unless  => "[ \"`sysctl -n $name`\" = '$value' ]",
+		path => "/sbin:/bin:/usr/bin";
+	}
+    } else {
+	delete_lines {
+	    "sysctl--$name":
+		file => "/etc/sysctl.conf",
+		pattern => "${qname}[ \t]*=.*";
+	}
+    }
+}
-- 
GitLab