#!/bin/bash # # /sbin/mkinstall - System Installer - version 1.9.1 - 2003-08-02 # This file is part of the Formilux project : http://formilux.ant-computing.com/ # # Copyright (C) 2001-2003 Benoit Dolez & Willy Tarreau # mailto: benoit@ant-computing.com,willy@ant-computing.com # # This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt ) cdlist=( ) names=( ) sizes=( ) parts=( ) # this utility uses a few temporary files : # # /tmp/fsmnt : # device=/dev/hda, /dev/sda1... # space=exactly one space # mount_mount=/home, /var, /, ..., mbr, cdrom, swap, # /tmp/fsid : # /tmp/fstype : # /tmp/fslist : # /tmp/fssize : # /tmp/sourcepkg : symlink to the source packages directory # give it a number suffixed with a k,M,G,T, and it will return it reduced to # the nearest power of 1024 suffixed with k,M,G or T humansize() { local pow val local -a suff=( "" k M G T P ) case "${1##[0-9]*}" in k) pow=1;; M) pow=2;; G) pow=3;; T) pow=4;; P) pow=5;; *) pow=0;; esac val=${1%%[a-zA-Z]*} # we don't return values lower than 10 when possible while [ $val -ge 10240 ]; do ((pow++)) ((val/=1024)) done REPLY=$val${suff[$pow]} echo -n $REPLY } detect_cdrom() { cdlist=($(grep -i '^drive name:' /proc/sys/dev/cdrom/info |cut -f2 -d:)) CDROMS="${cdlist[*]}" } detect_disks() { local i j major minor size name rest names=( ) sizes=( ) parts=( ) rm -f /tmp/partitions tail +3 /proc/partitions | sort -k4.1 >/tmp/partitions while read major minor size name rest; do if ((i >= 0)); then names[i]=$name sizes[i]=$size parts[i]=1 fi ((i++)) done < /tmp/partitions i=0 while ((i < ${#names[@]})); do if [ -n "${names[i]}" ]; then j=0 while ((j < ${#names[@]})); do if [ $i -ne $j -a -n "${names[j]}" -a -z "${names[j]##${names[i]}*}" ]; then names[j]="" ((parts[i]+=${parts[j]})) fi ((j++)) done fi ((i++)) done i=0 j=0 while ((i < ${#names[@]})); do if [ -n "${names[i]}" -a "${cdlist[*]##${names[i]}}" = "${cdlist[*]}" ]; then names[j]=${names[i]} sizes[j]=${sizes[i]} ((parts[j]=${parts[i]}-1)) ((j++)) fi if ((i >= j)); then unset names[i] parts[i] sizes[i] names=("${names[@]}") parts=("${parts[@]}") sizes=("${sizes[@]}") else ((i++)) fi done # now we have the list of the hard disks : # names[] contains their name in /dev # sizes[] contains their size in blocks (1 kB) # parts[] contains their number of partitions } # This function collects some information in /proc and other places. # It should be called ASAP. function init { #umount /mnt/cdrom >/dev/null 2>&1 # to avoid stupid recursive copying ! detect_cdrom detect_disks mkdir -p $ROOTDIR >/dev/null 2>&1 } # displays the main menu # if an arg is passed, it will be used as the name entry of the default action. # it returns the name of the entry in REPLY # returns 0 if OK, 1 if Cancel/Exit. function menu_main { REPLY=$(dialog --title " Formilux Installation Utility " --no-cancel --no-shadow ${1:+--default-item $1 }\ --menu "Installation Menu\n\n Press / to select an item.\n Press to move between [OK] and [Cancel].\n Press to confirm your choice." 24 80 14 \ "PART" "Configure Partitions and File Systems" \ "SOURCE" "Select Packages Source" \ "PKG" "Select which Packages to Install" \ "CONFIG" "Build Configuration" \ "SAVE" "Save Current Configuration" \ "LILO" "Run LILO" \ "UNMOUNT" "Unmount all File Systems" \ "SHELL" "Get Access to a Shell" \ "EXIT" "Exit this Utility" 2>&1 | grep -v EXIT) [ -n "$REPLY" ] } # presents a list of hard disks and lets the user choose one. # the default one can be passed in $1 # returns 0 if OK, 1 if Cancel/Exit. function menu_harddisk { local -a args=( ) local i=0 local model while ((i < ${#names[@]})); do model='unknown model' [ -e "/proc/ide/${names[i]}/model" ] && model=$(/ to select an item.\n Press to move between [OK] and [Cancel].\n Press to confirm your choice." 24 80 12 "${args[@]}" "EXIT" "Exit this menu" 2>&1 |grep -v EXIT) [ -n "$REPLY" ] } # presents a list of hard disks partitions and lets the user choose one. # the disk is passed in $1 # the default one can be passed in $2 # returns 0 if OK, 1 if Cancel/Exit. function menu_partition { local -a args=( ) local dev=$1 local disk=${1##/dev/} local def=$2 local mnt local device size id syst rest for device in $(grep "^$dev" /tmp/fslist 2>/dev/null); do size=$(grep "^$device " /tmp/fssize 2>/dev/null |cut -f2 -d' ') mnt=$(grep "^$device " /tmp/fsmnt 2>/dev/null |cut -f2 -d' ') id=$(grep "^$device " /tmp/fsid 2>/dev/null |cut -f2 -d' ') syst=$(grep "^$device " /tmp/fsid 2>/dev/null |cut -f3 -d' ') type=$(grep "^$device " /tmp/fstype 2>/dev/null |cut -f2 -d' ') if [ -z "$mnt" ]; then def=${def:-${device##/dev/}} mnt="not assigned" else mnt="assigned to $mnt" fi if [ -z "$type" ]; then def=${def:-${device##/dev/}} type="not formated" else type="type $type" fi args=("${args[@]}" "${device##/dev/}" "$(humansize ${size}k)B, Id 0x$id($syst), $type, $mnt") done def=${def:-EXIT} args=("${args[@]}" "CLEAR" "Clear ALL partitions on this disk" "FDISK" "Run fdisk on this disk") REPLY=$(dialog --title " Formilux Installation Utility " --no-shadow ${def:+--default-item $def} --menu "\nSelect a Partition\n\n Press / to select an item.\n Press to move between [OK] and [Cancel].\n Press to confirm your choice." 24 80 12 "${args[@]}" "EXIT" "Exit this menu" 2>&1 |grep -v EXIT) [ -n "$REPLY" ] } # reads the partition table on a disk and updates the associated files : # /tmp/fslist, /tmp/fssize, /tmp/fsid, /tmp/fsmnt, /tmp/fstype # the disk device is passed in $1 (/dev/xxx). There's no return code. function disk_read_part { local dev=$1 local disk=${1##/dev/} local device begin end cyl size id syst rest file rm -f /tmp/sfdisk.${disk//\//.} for file in fslist fssize fsid; do grep -v "^$dev" /tmp/$file 2>/dev/null >/tmp/${file}-; mv /tmp/${file}- /tmp/$file done for file in fsmnt fstype; do grep "^$dev" /tmp/$file 2>/dev/null >/tmp/$file.${disk//\//.} grep -v "^$dev" /tmp/$file 2>/dev/null >/tmp/${file}-; mv /tmp/${file}- /tmp/$file done sfdisk -l $dev | tr '*' ' ' | grep '^/dev/' >/tmp/sfdisk.${disk//\//.} while read device begin end cyl size id syst rest; do # let's ignore empty and extended partitions [ "$id" = "0" -o "$id" = "5" ] && continue size=${size%+} echo "$device" >> /tmp/fslist echo "$device $size" >> /tmp/fssize echo "$device $id $syst" >> /tmp/fsid if [ "$id" != "82" ] || grep -q "^$device " /tmp/fsmnt.${disk//\//.} && ! grep -q "^$device swap" /tmp/fsmnt.${disk//\//.} ; then grep "^$device " /tmp/fsmnt.${disk//\//.} >> /tmp/fsmnt grep "^$device " /tmp/fstype.${disk//\//.} >> /tmp/fstype else echo "$device swap" >> /tmp/fsmnt # we want to keep a trace of the format status of the swap partition # instead of assuming it has already been formated grep "^$device " /tmp/fstype.${disk//\//.} >> /tmp/fstype #echo "$device swap" >> /tmp/fstype fi done < /tmp/sfdisk.${disk//\//.} rm -f /tmp/sfdisk.${disk//\//.} } # presents a list of possible actions for a partition : # - change its mount point # - format it # the partition is passed in $1 # if a default choice should be proposed, its name must be in $2 # returns 0 if OK, 1 if Cancel/Exit. function menu_setupfs { local -a args=( ) local dev=$1 local def size type strext2s strext2l strext3 strreiser local mnt def=$2 mnt=$(grep "^$dev " /tmp/fsmnt 2>/dev/null |cut -f2 -d' ') [ -z "$mnt" ] && { mnt="not assigned" ; def=${def:-"MNT"}; } type=$(grep "^$dev " /tmp/fstype 2>/dev/null |cut -f2 -d' ') [ -z "$type" ] && type="not formated" size=$[ ($(grep "^$dev " /tmp/fssize 2>/dev/null | cut -f2 -d' ')+0) / 1024 ] args=("MNT" "Change the mount point ($mnt)") if [ "$mnt" = "swap" ]; then args=("${args[@]}" "SWAP" "* mkswap $dev (format as swap)") args=("${args[@]}" "SWAPC" " mkswap -c $dev (format and check)") def=${def:-SWAP} else strext2s="mke2fs -b 1024 -m 1 -s 1 $dev (format as small Ext2)" strext2l="mke2fs -b 4096 -s 1 $dev (format as large Ext2)" strext3="mke2fs -b 4096 -s 1 -j $dev (format as Ext3)" strreiser="mkreiserfs -h r5 $dev (format as ReiserFS)" if [ $size -lt 64 ]; then strext2s="* $strext2s" strext2l=" $strext2l" strext3=" $strext3" strreiser=" $strreiser" def=${def:-EXT2S} else strext2s=" $strext2s" strext2l=" $strext2l" strext3="* $strext3" strreiser=" $strreiser" def=${def:-EXT3} fi args=("${args[@]}" "EXT2S" "$strext2s" "EXT2L" "$strext2l" "EXT3" "$strext3" "REISER" "$strreiser" ) fi args=("${args[@]}" "SHELL" "Get Access to a Shell") REPLY=$(dialog --title " Formilux Installation Utility " --no-shadow ${def:+--default-item $def} --menu "\nFormat and Mount Point\n\nChoose a mount point for this partition, then select a format command to format it and set its type. The '*' indicates the recommended format.\n\n Press / to select an item.\n Press to move between [OK] and [Cancel].\n Press to confirm your choice." 24 80 8 "${args[@]}" "EXIT" "Exit this menu" 2>&1 |grep -v EXIT) [ -n "$REPLY" ] } # lets the user change a mount point for a partition. # the partition is passed in $1 # returns 0 if something changed, else 1. function menu_mount_point { local mnt dev type id name dev=$1 mnt=$(grep "^$dev " /tmp/fsmnt 2>/dev/null |cut -f2 -d' ') id=$(grep "^$dev " /tmp/fsid 2>/dev/null |cut -f2 -d' ') name=$(grep "^$dev " /tmp/fsid 2>/dev/null |cut -f3 -d' ') type=$(grep "^$dev " /tmp/fstype 2>/dev/null |cut -f2 -d' ') REPLY=$mnt [ -z "$REPLY" -a "$id" = "82" ] && REPLY="swap" [ -z "$REPLY" ] && ! grep -q " /boot$" /tmp/fsmnt && REPLY="/boot" [ -z "$REPLY" ] && ! grep -q " /$" /tmp/fsmnt && REPLY="/" [ -z "$REPLY" ] && ! grep -q " /var$" /tmp/fsmnt && REPLY="/var" [ -z "$REPLY" ] && ! grep -q " /home$" /tmp/fsmnt && REPLY="/home" REPLY=$(dialog --title " Formilux Installation Utility " --no-shadow --inputbox "Enter the mount point for partition $dev\n${id:+Partition Id=$id($name)}${type:+${id:+, }Formated as $type}\nEnter 'swap' to force it to become swap\n\n Press to move between [OK] and [Cancel].\n Press to confirm your choice." 12 60 $REPLY 2>&1 || echo $mnt) if [ "$REPLY" != "$mnt" ]; then (grep -v "^$dev " /tmp/fsmnt 2>/dev/null; echo "$dev $REPLY") >/tmp/fsmnt- mv /tmp/fsmnt- /tmp/fsmnt return 0 else return 1 fi } # lets the user change the package directory # the entry is checked to be a valid directory # returns 0 if something changed, else 1. function menu_pkg_dir { local old old=$(readlink /var/flx-pkg 2>/dev/null) REPLY=$old while : ; do REPLY=$(dialog --title " Formilux Installation Utility " --no-shadow --inputbox "Enter the new packages directory\nCurrently set to '$old'\n\n Press to move between [OK] and [Cancel].\n Press to confirm your choice." 12 60 $REPLY 2>&1 || echo $old) if [ "$REPLY" != "$old" ]; then if [ -d "$REPLY/." ]; then PKGDIR=$REPLY rm -f /var/flx-pkg ln -sf $REPLY /var/flx-pkg return 0 else dialog --title " Formilux Installation Utility " --msgbox "'$REPLY' is not a valid directory. Please try again, or press [Cancel].\n" 8 60 fi else # cancel or no changes return 1 fi done } # ask the user about the desired source of packages for the installation function menu_select_source { local -a args=( ) args=("CDROM" "CD-ROM" "DISK" "Hard disk or USB storage device" "NFS" "Remove file-system over NFS" "DIR" "Pre-mounted directory") REPLY=$(dialog --title " Formilux Installation Utility " --no-shadow --menu "\nSource Packages Selection\n\nChoose from which medium the source packages will be fetched.\n\n Press / to select an item.\n Press to move between [OK] and [Cancel].\n Press to confirm your choice." 24 80 8 "${args[@]}" "EXIT" "Exit this menu" 2>&1 |grep -v EXIT) [ -n "$REPLY" ] } # ask the user about the desired source cdrom # returns 0 if the CD could be mounted, 1 otherwise. function menu_select_cdrom { local -a args=( ) local cdrom umount -l /mnt/cdrom >/dev/null 2>&1 rm -f /dev/cdrom rm -f /var/flx-pkg PKGDIR= case ${#cdlist[@]} in 0) dialog --title " Formilux Installation Utility " --msgbox "No CD-ROM device was detected on this system. Please load manually any appropriate module or choose another source medium." 12 60 ; rm -f /var/flx-pkg return 1 ;; 1) ln -sf ${cdlist[0]} /dev/cdrom if mount /mnt/cdrom >/dev/null 2>&1 ; then PKGDIR=/mnt/cdrom/pkg ln -s $PKGDIR /var/flx-pkg dialog --title " Formilux Installation Utility " --msgbox "/dev/${cdlist[0]} has been selected as the only CD-ROM device, and mounted successfully.\n" 8 60 return 0 else dialog --title " Formilux Installation Utility " --msgbox "/dev/${cdlist[0]} has been selected as the only CD-ROM device, but could not be mounted. Please insert a valid CD-ROM and try again.\n" 8 60 return 1 fi ;; esac args=("AUTO" "Automatically find which drive contains a CD") for cdrom in "${cdlist[@]}"; do if [ -e "/proc/ide/$cdrom/model" ]; then args=("${args[@]}" "$cdrom" "$(cat /proc/ide/$cdrom/model)") elif [ -z "${cdrom##sr*}" -o -z "${cdrom##scd*}" ]; then args=("${args[@]}" "$cdrom" "SCSI CD-ROM") else args=("${args[@]}" "$cdrom" "Unknown CD-ROM model") fi done cdrom="${args[0]}" while [ -z "$PKGDIR" ]; do rm -f /dev/cdrom REPLY=$(dialog --title " Formilux Installation Utility " --no-shadow --default-item "$cdrom" --menu "\nCD-ROM\n\nSelect the CD-ROM drive which contains the Formilux CD-ROM you want to use for the installation.\n\n Press / to select an item.\n Press to move between [OK] and [Cancel].\n Press to confirm your choice." 24 80 8 "${args[@]}" "EXIT" "Exit this menu" 2>&1 |grep -v EXIT) cdrom=$REPLY case "$REPLY" in "") return 1 ;; AUTO) findcdrom if [ ! -e /dev/cdrom ]; then dialog --title " Formilux Installation Utility " --msgbox "No drive containing a valid CD-ROM was found. Please insert a valid CD-ROM and try again.\n" 8 60 continue fi ;; *) ln -sf $REPLY /dev/cdrom ;; esac if mount /mnt/cdrom >/dev/null 2>&1; then PKGDIR=/mnt/cdrom/pkg dialog --title " Formilux Installation Utility " --msgbox "/dev/$(readlink /dev/cdrom) has been selected as the new CD-ROM device, and mounted successfully.\n" 8 60 return 0 else dialog --title " Formilux Installation Utility " --msgbox "/dev/$(readlink /dev/cdrom) has been selected as the new CD-ROM device, but could not be mounted. Please insert a valid CD-ROM and try again.\n" 8 60 fi done return 1 } # ask the user a question to which he can reply by "yes" or "no". # A simple message is passed in $1 # if $2 is NOT EMPTY, the default response will be NO. # returns 0 if No, 1 if Yes function menu_yesno { dialog --title " Formilux Installation Utility " --no-shadow ${2:+--defaultno} --yesno "$1" 12 65 } # user interface functions function ask { echo -n "$1 [$2] : "; read if [ "$REPLY" = "" ]; then REPLY=$2; fi } function yesno { echo -n "$1 [$2] : "; read ; REPLY=`echo $REPLY | cut -c1` if [ "$REPLY" = "" ]; then REPLY=$2; fi if [ "$REPLY" = o -o "$REPLY" = y -o "$REPLY" = Y ]; then REPLY="y" fi } # function check_directories { if [ ! -d $ROOTDIR/etc/. ] ; then if [ -d $ROOTDIR/boot/etc/. ] ; then ln -s boot/etc $ROOTDIR/etc else echo "Can't find 'etc' directory neither in '/' nor in '/boot'" return 1 fi fi [ -d $ROOTDIR/var/. ] || mkdir $ROOTDIR/var [ -d $ROOTDIR/var/run ] || mkdir $ROOTDIR/var/run [ -d $ROOTDIR/var/spool ] || mkdir $ROOTDIR/var/spool [ -d $ROOTDIR/var/cache ] || mkdir $ROOTDIR/var/cache if [ ! -d $ROOTDIR/var/log ] ; then mkdir $ROOTDIR/var/log chown root:log $ROOTDIR/var/log chmod 2750 $ROOTDIR/var/log fi [ -d $ROOTDIR/var/adm/. ] || ln -s log $ROOTDIR/var/adm if [ ! -d $ROOTDIR/var/tmp ] ; then mkdir $ROOTDIR/var/tmp ; chmod 1777 $ROOTDIR/var/tmp ; fi # /tmp should exist, either as a dir or a link. if [ ! -e $ROOTDIR/tmp ] ; then mkdir $ROOTDIR/tmp ; chmod 1777 $ROOTDIR/tmp ; fi return 0 } # this function lists all hard drives found, but hides CDROMs function list_disks { echo "${names[@]}" #for i in `tail +3 /proc/partitions | awk '{print $4}' | grep '\([a-zA-Z]$\)\|\(c[0-9]*d[0-9]*$\)'`; do # if ! echo $CDROMS | grep -qw $i; then # echo $i # fi #done } # mounts all the new file-systems, and creates the mount points when needed function mount_new_fs { local -a mplist=($(sort -k2.1 /tmp/fsmnt 2>/dev/null|cut -f2 -d' ') ) local fs mp type rm -f /tmp/fstab echo "/proc /proc proc defaults 0 0" >> /tmp/fstab echo "#/dev /dev tmpfs size=0,nr_inodes=4096,remount,nosuid 0 0" >> /tmp/fstab echo "/dev/pts /dev/pts devpts defaults 0 0" >> /tmp/fstab echo "/dev/cdrom /mnt/cdrom iso9660 defaults,noauto,ro,users,exec 0 0" >> /tmp/fstab for mp in "${mplist[@]}"; do fs=$(grep " $mp\$" /tmp/fsmnt 2>/dev/null|cut -f1 -d' ') type=$(grep "^$fs " /tmp/fstype 2>/dev/null|cut -f2 -d' ') if [ "$mp" != "swap" ]; then mkdir -p -m 0755 $ROOTDIR$mp 2>/dev/null mount -t $type $fs $ROOTDIR$mp fi if [ "$mp" = "/" ]; then echo "#$fs $mp $type defaults,ro 1 1" >> /tmp/fstab echo "/dev/root $mp $type defaults,ro 1 1" >> /tmp/fstab mkdir -p -m 0755 $ROOTDIR/dev $ROOTDIR/proc $ROOTDIR/etc mount -t proc proc $ROOTDIR/proc # may be needed for compressed files elif [ "$mp" = "/boot" ]; then echo "$fs $mp $type defaults,ro 1 2" >> /tmp/fstab elif [ "$mp" = "swap" ]; then echo "$fs $mp $type defaults 0 0" >> /tmp/fstab else echo "$fs $mp $type defaults 1 2" >> /tmp/fstab fi done echo "/var/empty /var/empty tmpfs size=0,nr_inodes=1,ro,mode=0100,nosuid,nodev 0 0" >> /tmp/fstab } # unmounts all the new file-systems function unmount_new_fs { local -a mplist=($(sort -rk 2.1 /proc/mounts 2>/dev/null | cut -f2 -d' ' | grep "^$ROOTDIR") ) local fs mp type for mp in "${mplist[@]}"; do if [ "$mp" != "swap" ]; then umount $mp >/dev/null 2>&1 fi done } function setup_part { if [ -e /tmp/devmap -a -e /tmp/fstab ]; then echo "Filesystems are currently configured this way :" for i in `cut -f1 -d' ' /tmp/devmap`; do grep "^$i[ ]" /tmp/fstab | awk '{print $1 " => " $2 }'; done echo "-- end of list --" yesno "Do you want to change something (y/n) ?" "n" [ "$REPLY" = "y" ] || return 0 cp /tmp/fstab /tmp/fstab- cp /tmp/devmap /tmp/devmap- else touch /tmp/fstab- /tmp/devmap- fi # clean temporary files rm -rf /tmp/temp.$$ /tmp/fstab /tmp/devmap # unmount previously mounted file-systems for part in $(grep " $ROOTDIR" /proc/mounts|awk '{print $2}'|sort -r); do umount $part; done echo "/proc /proc proc defaults 0 0" >> /tmp/fstab echo "#/dev /dev tmpfs size=0,nr_inodes=4096,remount 0 0" >> /tmp/fstab echo "/dev/pts /dev/pts devpts defaults 0 0" >> /tmp/fstab echo "/dev/cdrom /mnt/cdrom iso9660 defaults,noauto,ro,users 0 0" >> /tmp/fstab echo "/dev/$(readlink /dev/cdrom) /dev/cdrom" >> /tmp/devmap (grep -v ' CDROM$' /tmp/mounts 2>/dev/null; echo "/dev/$(readlink /dev/cdrom) CDROM") >/tmp/mounts- && mv /tmp/mounts- /tmp/mounts # scan all disk # for disk in $(list_disks); do REPLY=${names[0]} while menu_harddisk $REPLY; do disk=${REPLY##/dev/} # look for all detected partitions # for spart in `sfdisk -l /dev/$disk 2>/dev/null | grep "^/" |tr '*' ' '| cut -f3- -d'/' | awk '{print $1 ":" $6 }'` ; do REPLY= while { disk_read_part /dev/$disk ; menu_partition /dev/$disk $REPLY; } do [ -z "$REPLY" ] && break if [ "$REPLY" = "CLEAR" ] ; then if menu_yesno "Warning !\n\nThis will erase the partition table for /dev/$disk.\nAll data will be lost.\n\nDo you still want to proceed ?" N; then dd if=/dev/zero of=/dev/$disk bs=1024 count=1 > /dev/null 2>&1 (echo o ; echo w ) | fdisk /dev/$disk > /dev/null 2>&1 fi REPLY=FDISK continue elif [ "$REPLY" = "FDISK" ]; then fdisk /dev/$disk REPLY= continue else echo "menu format/mount pour $REPLY" fi # partition name part=`echo $spart|cut -f1 -d:` set -- `echo $spart | tr ':' ' '` set -- $* `fdisk -s /dev/$1` `sfdisk -l /dev/$disk 2>/dev/null | grep "/dev/$1 " | cut -c15-` # hide mounted partitions part=/dev/$part if grep -q "$part " /proc/mounts > /dev/null ; then continue ; fi # hide empty or extended partitions if [ $2 = 0 -o $2 = 5 ] ; then continue ; fi # partition size in Mega Bytes size=$[ $3 / 1024] # partition type in human readable form type=$2 shift 8 htype=$* # redo while not a good value askagain=y unset mountpoint while [ "$askagain" = "y" ] ; do askagain=n echo echo "Partition : $part ($htype, ${size} MB)" # non linux partition if [ $type != 82 -a $type != 83 -a $type != 8e -a $type != fd ] ; then yesno "$part isn't a standard linux partition, would you like an entry in /etc/fstab (y/n)?" "n" if [ "$REPLY" = "n" ] ; then continue ; fi fstype=noauto else fstype=auto fi # getting mount point if [ $type = 82 ] ; then mountpoint=swap else mountpoint=$(grep "^$part[ ]" /tmp/fstab- | awk '{print $2 }') fi ask " Choose a mount point (swap,/,/boot,/var,...) or [Enter] for none" "$mountpoint" # remove useless leading and trailing slashes mountpoint=$(echo $REPLY|sed 's@^\([/]*\)\(/.*\)$@\2@'|sed 's@^\(.*[^/]\)\([/]*\)$@\1@') if [ -z "$mountpoint" ] ; then break ; fi case "$mountpoint" in /) echo "$part /dev/root" >> /tmp/devmap ;; /boot) echo "$part /dev/boot" >> /tmp/devmap ;; swap) echo "$part /dev/swap" >> /tmp/devmap ; echo "$part swap swap defaults 0 0" >> /tmp/fstab;; *) echo "$part /dev/fs/$(echo ${mountpoint#/} |tr '/' '.')" >> /tmp/devmap ;; esac case "$mountpoint" in swap) (grep -v "^$part " /tmp/mounts 2>/dev/null; echo "$part SWAP") >/tmp/mounts- && mv /tmp/mounts- /tmp/mounts;; *) (grep -v "^$part " /tmp/mounts 2>/dev/null; echo "$part $mountpoint") >/tmp/mounts- && mv /tmp/mounts- /tmp/mounts;; esac formatcmd='' # format linux partitions if [ $type = 82 -o $type = 83 -o $type = 8e -o $type = fd ] ; then # tell how to format echo " 0: -- DO NOT format this partition (default) --" ; ch=0 if [ "$mountpoint" = "swap" ] ; then ch1="mkswap $part" ; echo " >1: $ch1" ch2="mkswap -c $part" ; echo " 2: $ch2 (with check)" elif [ "`echo $mountpoint|cut -c1`" = "/" ] ; then ch1="mke2fs -b 1024 -m 1 -s 1 $part" if [ "$size" -lt 64 ]; then echo " >1: $ch1 (small ext2)" else echo " 1: $ch1 (small ext2)" fi ch2="mke2fs -b 4096 -s 1 $part" ; echo " 2: $ch2 (large ext2)" ch3="mke2fs -b 4096 -s 1 -j $part" if [ "$size" -ge 64 ]; then echo " >3: $ch3 (ext3)" else echo " 3: $ch3 (ext3)" fi ch4="mkreiserfs -h r5 $part" ; echo " 4: $ch4 (reiserfs)" fi ask " Select a format method or enter the complete command" "$ch" case $REPLY in 0) formatcmd='' ;; [1-9]) formatcmd=`eval echo '\$ch'$REPLY` ;; *) formatcmd=$REPLY ;; esac fi done # execute format if [ "$formatcmd" ] ; then echo -n "Doing: '$formatcmd': " eval "echo y | $formatcmd" > /tmp/error.$$ 2>&1 if [ "$?" = "0" ] ; then echo "done." else echo "failed." echo "--------------------------------------------------------" echo "$formatcmd said:" sed -e "s/^/>> /" /tmp/error.$$ echo "----------- Filesystem will not be mounted -------------" mountpoint="" fi fi if [ "`echo $mountpoint|cut -c1`" = "/" ] ; then echo "$mountpoint -t $fstype $part" >> /tmp/temp.$$ fi done done # now we will mount all the filesystems we have just created, and add them to fstab sort /tmp/temp.$$ | while read ; do set -- $REPLY mp=$1 ; shift if [ ! -d $ROOTDIR$mp ] ; then mkdir -p $ROOTDIR$mp ; echo "Creating directory $mp" ; fi if [ $2 != noauto ] ; then echo -n "Mounting $mp ($3): " mount -n $* $ROOTDIR$mp > /dev/null 2>&1 if [ "$?" = "0" ] ; then echo "done." ; else echo "failed." echo "##failed## $3 $mp $2 defaults 1 1" >> /tmp/fstab fi else echo "#$3 $1 auto defaults 0 0" >> /tmp/fstab fi done mount | grep '^[ ]*/' | grep "$ROOTDIR[/ ]" | sed "s@$ROOTDIR[/]*@/@" | \ awk '{ printf "%s\t%s\t%s\tdefaults%s\t1 %s\n",$1,$3,$5,($3=="/" || $3=="/boot")?",ro":"",($3=="/")?"1":"2" }' >> /tmp/fstab #grep '^/' /proc/swaps | awk '{ print $1 "\tswap \tswap \tdefault 0 0"}' >> /tmp/fstab mkdir -p -m 0755 $ROOTDIR/dev $ROOTDIR/proc $ROOTDIR/etc $ROOTDIR/mnt/cdrom mount -t proc proc $ROOTDIR/proc # may be needed for compressed files ### sed -e "s,^#L.*cdrom\$,ln ` readlink /dev/cdrom` /dev/cdrom," < /.preinit > $ROOTDIR/.preinit rm -f /tmp/temp.$$ return 0 } function setup_keyboard { sed -n '/^service keyboard/,/^ *$/p' < /etc/config.rc } function setup_mouse { sed -n '/^service mouse/,/^ *$/p' < /etc/config.rc } function setup_network { echo "# hostname formilux" echo "# interface eth0" echo "# ip address 10.101.20.4/16" echo "# ip dhcp" echo "# service network" } # (re)build config.rc, startup.rc, fstab, devmap, lilo.conf function setup_config { local MNT="$1" local MPWD=$PWD local TMP=/tmp/newconf if [ ! -w /tmp ] ; then echo "Directory /tmp not writable"; exit 1 fi mkdir -p $TMP >/dev/null 2>&1 if [ "$MNT" = "" ] ; then MNT="$ROOTDIR"; fi # copy startup.rc and config.rc rm -f $TMP/config.rc $TMP/startup.rc if [ "$UPDATE_ONLY" != "y" -o ! -e $MNT/etc/config.rc ]; then echo >> $TMP/config.rc echo "# service syslogd" >> $TMP/config.rc echo >> $TMP/config.rc setup_network >> $TMP/config.rc echo >> $TMP/config.rc setup_keyboard >> $TMP/config.rc setup_mouse >> $TMP/config.rc chmod 644 $TMP/config.rc fi if [ "$UPDATE_ONLY" != "y" -o ! -e $MNT/etc/startup.rc ]; then echo "#!/bin/sh" >> $TMP/startup.rc echo "echo -n \"Default configuration ... \" " >> $TMP/startup.rc echo "/sbin/init.d/sysprofiles /etc/config.rc" >> $TMP/startup.rc chmod 755 $TMP/startup.rc fi # copy fstab cp /tmp/fstab $TMP/fstab # copy devmap BOOTDEV=${BOOTDEV:-`echo $ROOTDEV | sed 's/[0-9]\+$//'`} ask "Choose device on which LILO will be installed " $BOOTDEV BOOTDEV=$REPLY grep -v '/dev/\(mbr\|cdrom\)$' /tmp/devmap > $TMP/devmap 2>/dev/null echo "$BOOTDEV /dev/mbr" >> $TMP/devmap echo "/dev/$(readlink /dev/cdrom) /dev/cdrom" >> $TMP/devmap # build a new lilo.conf cd $MNT KERNVER=`ls boot/*/bzImage | tail -1 | cut -f2 -d/` KERNLBL=`echo $KERNVER | tr -d '.-'` cat > $TMP/lilo.conf <> $TMP/lilo.conf echo " label = l`echo $bootimg | cut -f2 -d/ | tr -d '.-'`" >> $TMP/lilo.conf echo " append = \"root=$ROOTDEV\"" >> $TMP/lilo.conf echo " read-only" >> $TMP/lilo.conf done if [ `grep "label =" $TMP/lilo.conf | wc -l` = 0 ]; then echo echo "WARNING!!! no kernel was found in $MNT/boot !!!" echo "You must install a kernel and edit $TMP/lilo.conf or your system will never boot." echo sleep 1 fi # copy /.preinit if [ -e $MNT/.preinit -a "$UPDATE_ONLY" = "y" ]; then cp $MNT/.preinit $TMP/.preinit else cp /.preinit $TMP/.preinit fi # 1st complicated part : merge old and new fstab. # Method: # - mount points only in old fstab are kept as-is # - mount points in both with same types only have their dev updated # - mount points in both with diff types are fully updated # - mount points only in new fstab are merged if [ "$UPDATE_ONLY" = "y" -a -e $MNT/etc/fstab ]; then rm -f $TMP/fstab while read; do set -- $REPLY if ! grep -q "^[^ ]\+[ ]\+${2}[ ]" /tmp/fstab; then # not found echo "$REPLY" >> $TMP/fstab elif ! grep -q "^[^ ]\+[ ]\+${2}[ ]\+${3}[ ]" /tmp/fstab; then # not found with the same type echo "##old##$REPLY" >> $TMP/fstab grep "^[^ ]\+[ ]\+${2}[ ]" /tmp/fstab >> $TMP/fstab else # found with the same type. We may have to update the device dev=`grep "^[^# ]\+[ ]\+${2}[ ]" /tmp/fstab|head -1|awk '{print $1}'` if [ "$dev" -a "$dev" != "$1" ]; then echo "##old##$REPLY" >> $TMP/fstab echo "$dev $2 $3 $4 $5 $6" >> $TMP/fstab # keep options else echo "$REPLY" >> $TMP/fstab # was commented or the same fi fi done < $MNT/etc/fstab # add new entries while read; do set -- $REPLY if ! grep -q "^[^ ]\+[ ]\+${2}[ ]" $TMP/fstab; then echo "$REPLY" >> $TMP/fstab fi done < /tmp/fstab fi # try to update lilo.conf if [ -e $MNT/etc/lilo.conf -a "$UPDATE_ONLY" = "y" ]; then rm -f $TMP/lilo.conf if grep -q "^image.*$KERNVER" $MNT/etc/lilo.conf; then # the latest kernel is referenced. We can use this conf. (echo "boot = $BOOTDEV" ; grep -v "^boot[ ]*=[ ]*$BOOTDEV" $MNT/etc/lilo.conf | sed 's/^\(boot[ ]*=\)/##old##\1/') > $TMP/lilo.conf else # the latest kernel is missing from lilo.conf. (echo "boot = $BOOTDEV" ; grep -v "^boot[ ]*=[ ]*$BOOTDEV" $MNT/etc/lilo.conf | sed 's/^\(boot[ ]*=\)/##old##\1/') | sed -e 's:^\(image.*=[^/]*/boot/\)\([^/]*\)\(/.*\)$:\1'$KERNVER'\3:' > $TMP/lilo.conf fi fi # now, we may have to update .preinit to create aliased entries. # we remove all references to devices that have been updated grep -v "^[#]*\(ln\|L\).*[ ]\+\($(echo `cut -f2 -d' ' $TMP/devmap`|sed 's@ @\\|@g')\)" $TMP/.preinit > $TMP/.preinit- grep -v ' /dev/fs/' $TMP/devmap | sed 's@^/dev/@ln @' >> $TMP/.preinit- if grep -q ' /dev/fs' $TMP/devmap; then if ! grep -q "^\(md\|M\)[ ]\+/dev/fs" $TMP/.preinit-; then echo "md /dev/fs 755" >> $TMP/.preinit- fi grep ' /dev/fs/' $TMP/devmap | sed 's@^/dev@ln ..@' >> $TMP/.preinit- fi mv $TMP/.preinit- $TMP/.preinit ; chmod 711 $TMP/.preinit rm -f $TMP/passwd if [ "$UPDATE_ONLY" != "y" -o ! -e $MNT/etc/passwd ]; then sed -e 's@/home/admin@/root@' < /etc/passwd |grep -v '^\(squid:\|pdnsd:\|flx:\|install:\)' > $TMP/passwd chmod 644 $TMP/passwd fi # if /var is on its own filesystem, /tmp must be a true filesystem too. if grep -q ' \(/dev/fs/var\|/dev/fs/var\.tmp\)$' $TMP/devmap; then if ! grep -q "^[^ ]\+[ ]\+/tmp[ ]" $TMP/fstab; then echo "/tmp /tmp tmpfs defaults,nosuid,nodev 0 0" >> $TMP/fstab fi fi cd $MPWD return 0 } function apply_config { local MNT=$1 local TMP=/tmp/newconf [ -e $TMP/.preinit ] && (rm -f $MNT/.preinit ; cp -p $TMP/.preinit $MNT) [ -e $TMP/passwd ] && (rm -f $MNT/etc/passwd ; cp -p $TMP/passwd $MNT/etc) [ -e $TMP/lilo.conf ] && (rm -f $MNT/etc/lilo.conf ; cp -p $TMP/lilo.conf $MNT/etc) [ -e $TMP/fstab ] && (rm -f $MNT/etc/fstab ; cp -p $TMP/fstab $MNT/etc) [ -e $TMP/config.rc ] && (rm -f $MNT/etc/config.rc ; cp -p $TMP/config.rc $MNT/etc) [ -e $TMP/startup.rc ] && (rm -f $MNT/etc/startup.rc ; cp -p $TMP/startup.rc $MNT/etc) # replace /tmp with a directory if needed if grep -q "^[^ ]\+[ ]\+/tmp[ ]" $TMP/fstab; then if [ -L $MNT/tmp ]; then rm -f $MNT/tmp && mkdir -m 1777 $MNT/tmp >/dev/null 2>&1; fi fi return 0 } function do_lilo { if [ -e $ROOTDIR/dev -a -e $ROOTDIR/.preinit -a -e $ROOTDIR/etc/lilo.conf ]; then chroot $ROOTDIR /.preinit rebuild chroot $ROOTDIR /sbin/lilo || lilo -r $ROOTDIR umount $ROOTDIR/dev # remove what .preinit has installed else echo "LILO has NOT been run because it needs /dev, /.preinit, and /etc/lilo.conf" fi return 0 } # main ROOTDIR=/var/mount PKGDIR=/home/pkg SHELLDIR=/ init if [ $0 = "mkdisk" ] ; then setup_part && exit 0 ; exit 1 ; elif [ $0 = "mkconfig" ] ; then setup_config $1 && exit 0 ; exit 1 ; elif [ $0 = "doconfig" ] ; then apply_config $1 && exit 0 ; exit 1 ; fi end=0 while [ $# -ge 1 -a "$end" -ne 1 ] ; do case $1 in --disk) setup_part;; --config) setup_config $2; shift;; --apply) apply_config $2; shift;; --) end=1;; *) end=1;; esac if [ "$end" -eq 1 ] ; then break ; fi shift done action="PART" while [ -n "$action" ] ; do ROOTDEV=$(mount | grep " on $ROOTDIR " | cut -f1 -d' ') # echo # echo "Possible actions are :" # echo "1: Run fdisk" # echo "2: Setup filesystems" # echo "3: Install packages" # echo "4: Build running config" # echo "5: Save built config for next reboot" # echo "6: Run lilo" # echo "7: Unmount all" # echo "s: Shell" # echo "q: Quit" # # ask "Select an action (1..7/s/q)" "$action" menu_main $action [ -z "$REPLY" ] && break if [ "$REPLY" = "SHELL" ] ; then (cd $SHELLDIR; echo -n "Current directory : "; pwd; bash -i); REPLY=$action; continue; fi case $REPLY in PART) # unmount previously mounted file-systems #for part in $(grep " $ROOTDIR" /proc/mounts|awk '{print $2}'|sort -r); do umount $part; done unmount_new_fs detect_disks REPLY=${names[0]} while menu_harddisk $REPLY; do disk=${REPLY##/dev/} #sfdisk -l /dev/$disk #yesno "Clear partition table for '/dev/$disk' (y/n)?" "n" REPLY= while { disk_read_part /dev/$disk ; menu_partition /dev/$disk $REPLY; } do part=$REPLY [ -z "$REPLY" ] && break if [ "$REPLY" = "CLEAR" ] ; then if menu_yesno "Warning !\n\nThis will erase the partition table for /dev/$disk.\nAll data will be lost.\n\nDo you still want to proceed ?" N; then dd if=/dev/zero of=/dev/$disk bs=1024 count=1 > /dev/null 2>&1 (echo o ; echo w ) | fdisk /dev/$disk > /dev/null 2>&1 fi REPLY=FDISK elif [ "$REPLY" = "FDISK" ]; then fdisk /dev/$disk REPLY= else part=$REPLY REPLY= while menu_setupfs /dev/$part $REPLY; do case "$REPLY" in SHELL) (cd $SHELLDIR; echo -n "Current directory : "; pwd; bash -i) (grep -v "^/dev/$part " /tmp/fstype 2>/dev/null; echo "/dev/$part auto") >/tmp/fstype- mv /tmp/fstype- /tmp/fstype # goes automatically to default format REPLY= ;; MNT) menu_mount_point /dev/$part # goes automatically to default format REPLY= ;; SWAP) mkswap /dev/$part (grep -v "^/dev/$part " /tmp/fstype 2>/dev/null; echo "/dev/$part swap") >/tmp/fstype- mv /tmp/fstype- /tmp/fstype REPLY=EXIT ;; SWAPC) mkswap -c /dev/$part (grep -v "^/dev/$part " /tmp/fstype 2>/dev/null; echo "/dev/$part swap") >/tmp/fstype- mv /tmp/fstype- /tmp/fstype REPLY=EXIT ;; EXT2S) mke2fs -b 1024 -m 1 -s 1 /dev/$part (grep -v "^/dev/$part " /tmp/fstype 2>/dev/null; echo "/dev/$part ext2") >/tmp/fstype- mv /tmp/fstype- /tmp/fstype REPLY=EXIT ;; EXT2L) mke2fs -b 4096 -s 1 /dev/$part (grep -v "^/dev/$part " /tmp/fstype 2>/dev/null; echo "/dev/$part ext2") >/tmp/fstype- mv /tmp/fstype- /tmp/fstype REPLY=EXIT ;; EXT3) mke2fs -b 4096 -s 1 -j /dev/$part (grep -v "^/dev/$part " /tmp/fstype 2>/dev/null; echo "/dev/$part ext3") >/tmp/fstype- mv /tmp/fstype- /tmp/fstype REPLY=EXIT ;; REISER) mkreiserfs -h r5 /dev/$part (grep -v "^/dev/$part " /tmp/fstype 2>/dev/null; echo "/dev/$part reiserfs") >/tmp/fstype- mv /tmp/fstype- /tmp/fstype REPLY=EXIT ;; esac # this is done to exit right after an mkfs [ "$REPLY" = "EXIT" ] && break; done REPLY= fi done # things might have changed ! detect_disks REPLY=/dev/$disk done # we now have to mount all these file systems mount_new_fs SHELLDIR=/ action=SOURCE ;; SOURCE) action=SOURCE while menu_select_source; do case "$REPLY" in CDROM) menu_select_cdrom && break; ;; DISK) menu_select_disk ;; NFS) menu_select_nfs ;; DIR) menu_select_dir ;; esac done PKGDIR=$(readlink /var/flx-pkg 2>/dev/null) [ -d "/var/flx-pkg/." ] && action=PKG ;; PKG) cd / if [ "$ROOTDEV" != "" ] ; then #ask "Packages directory, or files pattern ($PKGDIR, $PKGDIR/*.lst, *.prf, *.tgz)"$'\n'" " $PKGDIR ; PKGDIR="$REPLY" #if [ -d "$PKGDIR" ]; then # list=`cd $PKGDIR && ls *.prf *.lst *.tgz 2>/dev/null` #else # list=`basename "$PKGDIR"` # PKGDIR=`dirname "$PKGDIR"` # list=$(cd $PKGDIR && echo $list) #fi menu_pkg_dir list=( ); idx=0 for pack in $(shopt -s nullglob ; cd $PKGDIR && echo *.{prf,tgz}); do list[idx++]=$pack list[idx++]="" if [ -z "${pack##[0-9][0-9][0-9]_*}" ]; then # pre-selects every numbered package list[idx++]="on" else list[idx++]="off" fi done list=( $(dialog --title " Formilux Installation Utility " --no-shadow \ --checklist "Packages Selection\n\n Press to select/deselect a package.\n Press / to select an item.\n Press to move between [OK] and [Cancel].\n Press to install your selection." 24 80 12 "${list[@]}" 2>&1) ) # dialog returns quoted words eval list=( "${list[@]}" ) [ ${#list[@]} -gt 0 ] || break for pack in "${list[@]}" ; do case "$pack" in *tgz) [ -d "$ROOTDIR" ] || mkdir -p -m 0755 $ROOTDIR [ -d "$ROOTDIR/etc/formilux" ] || { mkdir -p -m 0750 $ROOTDIR/etc/formilux; chgrp adm $ROOTDIR/etc/formilux; } echo "### begin $pack ###" >> $ROOTDIR/etc/formilux/install.log tar zpvxf $PKGDIR/$pack -C $ROOTDIR >> $ROOTDIR/etc/formilux/install.log echo "### end $pack ###" >> $ROOTDIR/etc/formilux/install.log ;; *prf) [ -d "$ROOTDIR/etc/formilux" ] || { mkdir -p -m 0750 $ROOTDIR/etc/formilux; chgrp adm $ROOTDIR/etc/formilux; } echo "### begin $pack ###" >> $ROOTDIR/etc/formilux/install.log rm -f /tmp/${pack##*/}.log flxextract -R $ROOTDIR -p $PKGDIR -i $PKGDIR/$pack -l /tmp/${pack##*/}.log cat /tmp/${pack##*/}.log >> $ROOTDIR/etc/formilux/install.log echo "### end $pack ###" >> $ROOTDIR/etc/formilux/install.log ;; esac done check_directories || exit 1 SHELLDIR=/ action=CONFIG else action=PART fi ;; CONFIG) check_directories || exit 1 if [ "$UPDATE_ONLY" != "n" -a "$UPDATE_ONLY" != "y" ]; then echo "Existing files can be REPLACED or UPDATED." yesno "Do you prefer to UPDATE existing files (y/n) ?" "y" UPDATE_ONLY="$REPLY" fi setup_config $ROOTDIR echo "done." echo "New files have been written to /tmp/newconf/" echo "You can check them now by starting a shell." SHELLDIR=/tmp/newconf (cd $SHELLDIR ; ls -lart) action=SAVE ;; SAVE) echo "Saving config (.preinit, startup.rc, config.rc, fstab, lilo.conf, passwd)" apply_config $ROOTDIR echo "Saving config ... done." echo "Updating dynamic files (/etc/formilux/sig.dat, /etc/ld.so.cache) ... " ldconfig -r $ROOTDIR > /dev/null 2>&1 for SYSTEMMAP in `echo $ROOTDIR/boot/System.map-*`; do KERNVER=${SYSTEMMAP#$ROOTDIR/boot/System.map-} chroot $ROOTDIR depmod -a -F /boot/System.map-$KERNVER $KERNVER done echo "Signing the filesystem... (this may take a while)" cd $ROOTDIR ; signfs -x `mount|grep -v ' type \(tmpfs\|ramfs\)'|grep "^/.* $ROOTDIR "| \ sed "s@^.*$ROOTDIR\([^ ]*\) .*@.\1@"` > /etc/formilux/sig.dat echo "Updating dynamic files ... done." SHELLDIR=/ action=LILO ;; LILO) do_lilo SHELLDIR=/ action=UNMOUNT ;; UNMOUNT) cd / unmount_new_fs umount -l /mnt/cdrom >/dev/null 2>&1 SHELLDIR=/ action=EXIT ;; *) ;; esac done