#!/usr/bin/perl # You will need to get swim at http://www.sourceforge.net/projects/avd my $home = "$ENV{HOME}/.gbootroot"; my $home_yard = "$home/yard"; my $template_dir = "$home_yard/templates/"; my $home_yard_replacements = "$home_yard/Replacements"; my $nodename = `uname -n`; chomp $nodename; my $debian_yard = "Debian-$nodename.yard"; my $status = "/var/lib/dpkg/status"; my $info = "/var/lib/dpkg/info"; # You need file-rc, and you may add other extra stuff. These packages were # chosen for woody, so you may need something different. Check dependencies, # ofcourse, if you add stuff. my @extra_packages = qw(file-rc swim nvi sysklogd klogd netbase tcpd net-tools portmap netkit-ping netkit-inetd ifupdown less perl perl-modules); # And tests will be ran here for file-rc and swim # swim has to have its databases made. # Options: to include or remove docs /usr/share/{doc,man,info} # and other stuff which creates fluff. system "swim --search \"Priority: required\" > /dev/null 2>&1"; my $swim_packages = "swim -qS|"; my $swim_list = "swim -qSl|"; $, = " "; my $extra_files = "swim -ql @extra_packages|"; $, = ""; # All the packages open(SWIM,$swim_packages) or die "Couldn't open $!\n"; my @required_packages = ; chomp @required_packages; close(SWIM); push(@required_packages,@extra_packages); # All the files open(SWIM,$swim_list) or die "Couldn't open $!\n"; my @required_files = ; chomp @required_files; close(SWIM); open(SWIM,$extra_files) or die "Couldn't open $!\n"; my @extra_files = ; chomp @extra_files; close(SWIM); push(@required_files,@extra_files); ## Template Creation open(DEBIAN,">$template_dir/$debian_yard") or die "Couldn't open $!\n"; open(FILERC,"/etc/runlevel.conf") or die "No runlevel.conf: $!\n"; @filerc = ; close(FILERC); print DEBIAN stuff(); my @file_rc; foreach (@required_files) { if (-e && !-d) { if ($ARGV[0] eq "doc") { print DEBIAN "$_\n"; } else { if (! m,/usr/share/info|/usr/share/man|/usr/share/doc,) { print DEBIAN "$_\n"; } } if (m,/etc/init\.d,) { foreach my $filerc (@filerc) { push(@file_rc,$filerc) if $filerc =~ /$_/; } } } } print DEBIAN "\n# Scripts associated with packages found in info/*\n"; print DEBIAN status_info(); close(DEBIAN); # This creates a tweaked runlevel.conf which is easier then trying to figure # out which symlinks to use in /etc/rc?d. open(MY_FILERC,">$home_yard_replacements/etc/runlevel.conf") or die "Couldn't open $home_yard_replacements/etc/runlevel.conf: $!\n"; my @sortedrc = map { $_->[1] } sort { $a->[0] <=> $b->[0] } map { [ (split(/\s/,$_))[0], $_ ] } @file_rc; print MY_FILERC @sortedrc; close(MY_FILERC); # This creates a status file for use by dpkg and swim. # Although swim could be used to do this, it is more effecient just to # parse the status file. But because this is a good exercise for # using this script to create a status file found from packages on a system # which doesn't actually have a status file .. here would be the order # needed when using swim to query: # # Package, Status, Priority, Section, Installed-Size, Maintainer, Source, # Version, Replaces, Provides, Depends, Pre-Depends, Recommends, Suggests, # Conflicts, Conffiles, Description. # # Conffiles would have to be handled both before and after Root Filesystem # creation so that their md5sums could be accounted for in status. # # And this finds all the scripts associated with a package in info/*. sub status_info { $/ = ""; open(STATUS,"$status") or die "Can't find /var/lib/dpkg/status: $!\n"; home_builder("$home_yard_replacements/var/lib/dpkg"); open(NEW_STATUS,">$home_yard_replacements/var/lib/dpkg/status") or die "Couldn't open $home_yard_replacements/var/lib/dpkg/status: $!\n"; while () { # keep the order $stat = $_; my $stat2 = (split(/\n/,$stat))[0]; # might as well foreach my $rp (@required_packages) { $rp = (split(/_/,$rp))[0]; # Deal with names with + $rp =~ s/\+/\\+/g if $rp !~ /\\+/g; if ($stat2 =~ /^Package: $rp$/) { print NEW_STATUS $stat; } } } close(NEW_STATUS); close(STATUS); $/ = "\n"; my @info; foreach my $rp (@required_packages) { $rp = (split(/_/,$rp))[0]; # Get rid of the escape from the previous invocation. $rp =~ s/\\//g if $rp =~ /\\+/g; # Figure out info/* .. this covers it for now. if (-f "$info/$rp.preinst") { push(@info,"$info/$rp.preinst\n"); } if (-f "$info/$rp.postinst") { push(@info,"$info/$rp.postinst\n"); } if (-f "$info/$rp.prerm") { push(@info,"$info/$rp.prerm\n"); } if (-f "$info/$rp.postrm") { push(@info,"$info/$rp.postrm\n"); } if (-f "$info/$rp.list") { push(@info,"$info/$rp.list\n"); } if (-f "$info/$rp.shlibs") { push(@info,"$info/$rp.shlibs\n"); } if (-f "$info/$rp.conffiles") { push(@info,"$info/$rp.conffiles\n"); } if (-f "$info/$rp.md5sums") { push(@info,"$info/$rp.md5sums\n"); } if (-f "$info/$rp.config") { push(@info,"$info/$rp.config\n"); } } return @info; } # end sub status_info sub stuff { $stuff = << "STUFF"; # This template creates a complete Debian system which is more streamlined # than the base.tgz used for normal installations. Once everything is made, # you can use user-mode-linux to tweak the system, as well as apt. # Make-debian generates all the information you need, you will need swim and # file-rc installed, and you will have to be running a Debian system to make # this template. Make-debian ditches info, man, and doc files by default, # use the "doc" option to make documentation. # Characteristics: user: root passwd: root # user: user passwd: user # Uses devfs. # Alternatives aren't working so you will have to use the real name like # nvi for vi and w.procps for w. Not all libs are associated with packages # but that isn't a big deal. # IMPORTANT NOTE: Things slow down noticeably when the buffer gets too big in # the verbosity box so consider closing it with the slider for faster # generation. Look at /tmp/verbose instead. # Todays Quote: Creating a root filesystem is all about stuff. # The STUFF NEEDED in order for init to work. /etc/runlevel.conf <= Replacements/etc/runlevel.conf # made by make_debian /etc/init.d/rc /etc/init.d/rcS /etc/inittab <= Replacements/etc/inittab.debian # specific to devfs /etc/default/rcS # Stuff needed to return init to its state prior to installing file-rc. /etc/init.d/rc.links /etc/init.d/rcS.links /usr/sbin/update-rc.d.links # Login stuff /etc/securetty <= Replacements/etc/securetty.debian # devfs needs this /root/.bashrc <= Replacements/root/.bashrc.debian /root/.profile <= Replacements/root/.profile.debian /home/user/.bashrc <= Replacements/home/user/.bashrc.debian /home/user/.bash_profile <= Replacements/home/user/.bash_profile.debian /etc/hostname <= Replacements/etc/hostname /etc/motd <= Replacements/etc/motd # Important stuff .. you will need to edit the login files if you add packages # which require other users/groups. The default fstab mounts /dev/ubd/0. #/etc/fstab <= Replacements/etc/fstab.new # Made from Yard Box menu /etc/fstab <= Replacements/etc/fstab.debian # devfs specific /etc/passwd <= Replacements/etc/passwd.debian /etc/passwd- <= Replacements/etc/passwd-debian /etc/group <= Replacements/etc/group.debian /etc/group- <= Replacements/etc/group-debian /etc/shadow <= Replacements/etc/shadow.debian # The stuff required by dpkg. /var/lib/dpkg/diversions <= Replacements/var/lib/dpkg/diversions /var/lib/dpkg/cmethopt /var/lib/dpkg/lock /var/lib/dpkg/status <= Replacements/var/lib/dpkg/status /var/lib/dpkg/methods/disk /var/lib/dpkg/methods/floppy /var/lib/dpkg/methods/mnt /var/lib/dpkg/info /var/lib/dpkg/updates /var/lib/dpkg/alternatives # Devices - optional stuff which can be picked up by devfsd. /dev/MAKEDEV # a link /dev/mem /dev/kmem /dev/null /dev/zero /dev/ram* /dev/console /dev/tty[0-9] /dev/hd[abcd]* /dev/ttyS[0-9] /dev/fd0* /dev/sd* #/dev/cdrom #/dev/modem /dev/pts* /dev/ptmx /dev/initctl /dev/urandom /dev/ubd0 <= Replacements/dev/ubd0 # Empty directories with no stuff. /mnt /proc /tmp /var/tmp /var/run /var/lock /var/log ## ALL the REQUIRED files generated by make-debian. ## This is stuff from the required packages, so some files may be ## removed, or some files can be replaced with stuff from say .. busybox. STUFF return $stuff; } # end sub stuff sub home_builder { my ($home_builder) = @_; if (!-d $home_builder) { if (-e $home_builder) { print "ERROR: A file exists where $home_builder should be.\n"; } else { my @directory_parts = split(m,/,,$home_builder); my $placement = "/"; for (1 .. $#directory_parts) { $_ == 1 ? ($placement = "/$directory_parts[$_]") : ($placement = $placement . "/" . $directory_parts[$_]); -d $placement or mkdir $placement; } } } } # end home_builder