Extended Slackware

Przygotowywanie pakietów binarnych dla Slackware

Data dodania: Fri, 07 Oct 2005 21:49:29 +0200

Autor: dozzie

Wstęp

Artykuł pojawił się najpierw jako propozycja do FAQ na Forum Slackware, gdzie po paru uwagach został nieco rozbudowany. Artykuł, który czytasz, zawiera tą samą treść, co tam zamieszczony.

Dlaczego slackbuildy?

Niektórzy z was mogą się zastanawiać, po co tracić czas na pisanie slackbuildów, kiedy można użyć checkinstall? Ja znam dwa powody. Po pierwsze, z doświadczenia wiem, że pakiet zrobiony przez checkinstalla należy z reguły jeszcze poprawić (a to uprawnienia, a to pliki konfiguracyjne). Po drugie, pakiet zbudowany za pomocą slackbuilda znacznie łatwiej uaktualnić, gdy wyjdzie nowa wersja programu -- nie trzeba sobie przypominać, z jakimi opcjami był kompilowany, najczęściej wystarczy zmienić jeden numerek na początku slackbuilda i przebudować pakiet.

Struktura wewnętrzna pakietu .tgz

Aby napisać dobrego slackbuilda, najpierw należy dobrze poznać strukturę pakietów Slackware. Zajrzyjmy do przeciętnego pakietu:

[dozzie@hans ap]$ tar tzf ash-0.4.0-i386-1.tgz 
./
bin/
bin/ash
usr/
usr/doc/
usr/doc/ash-0.4.0/
usr/doc/ash-0.4.0/TOUR
usr/man/
usr/man/man1/
usr/man/man1/ash.1.gz
install/
install/doinst.sh
install/slack-desc
[dozzie@hans ap]$ 

Jak widać, to jest proste archiwum tar skompresowane gzipem. Instalacja takiego pakietu z grubsza rzecz biorąc polega na rozpakowaniu go w /. Archiwum ma dość dokładnie określony schemat nazwy: <nazwa-programu>-<wersja>-<arch>-<kompilacja>.tgz. <nazwa-programu> może zawierać dowolną ilość myślników, ale pozostałe pola już nie mogą ich zawierać. <arch> to architektura, pod którą jest kompilowany pakiet (z grubsza odpowiada opcji -march=<arch> podawanej w CFLAGS kompilatorowi). <kompilacja> to kolejny numer pakietu, istniejący po to, aby móc wprowadzić poprawki do pakietu bez zmiany numeru wersji.

W pakiecie znajduje się dodatkowy katalog, który nie występuje w normalnym drzewie katalogów: install. W nim trzymane są dwa pliki. slack-desc zawiera opis pakietu (tekst, który pojawia się przy instalacji). Zostanie omówiony nieco dalej. doinst.sh to skrypt, który jest uruchamiany tuż po zainstalowaniu pakietu. Jego zadania omówię w dalszej części, bo to jest bardzo istotna część dobrego pakietu. Oba pliki i katalog są usuwane zaraz po zainstalowaniu pakietu (doinst.sh jest przenoszony do var/log/scripts).

W dobrym pakiecie wszystkie pliki należą do root:root, z wyjątkiem katalogów bin, sbin, usr/bin, usr/sbin i usr/X11R6/bin, w które razem z zawartymi w nich plikami należą do root:bin. Należy również pamiętać o stosownych uprawnieniach: zwykłe pliki (dokumentacja, manuale itd.) mają mieć prawa 644, katalogi i pliki wykonywalne -- 755. (To oczywiście niewielkie uproszczenie, bo nie biorę pod uwagę specjalnych przypadków, takich jak pliki suidowane (pakiet shadow, sudo) i katalogi znajdujące się w var/lib przeznaczone specjalnie dla daemonów.)

Pakiet Slackware nie może zawierać żadnych plików instalujących się w usr/local, wszystkie manuale (umieszczone w stosownym podkatalogu usr/man) powinny być skompresowane gzipem, pliki wykonywalne i biblioteki dzielone powinny być oczyszczone z symboli debuggowych (odstrippowane), a dokumentacja dostarczona z programem (pliki README, INSTALL, FAQ i tym podobne z katalogu ze źródłami) powinny się znaleźć w usr/doc/nazwa-programu.

Pakiet powinien pociągać za sobą jak najmniej zależności od innych pakietów. Nie znaczy to, żeby od razu kompilować wszystko jako -static. Chodzi o to, żeby nie rozdrabniać nadmiernie pakietów (Slackware nie doczekał się porządnego [IMHO] narzędzia do śledzenia zależności). Sprowadza się to do tego, że jeśli jakiejś biblioteki wymaga tylko jeden pakiet, to niech zawiera ją od razu (przykładem jest tcpdump z dystrybucji, zawierający jednocześnie libpcap).

Dobrą praktyką jest zmiana nazwy wszystkich plików konfiguracyjnych z katalogu etc z plik.conf na plik.conf.new. Prawidłowa nazwa jest przywracana w skrypcie doinst.sh, jeśli plik konfiguracyjny jeszcze nie istnieje. To zachowanie pozwala uniknąć przypadkowego nadpisania konfiguracji przy aktualizacji pakietu.

Z czysto technicznego punktu widzenia w pakiecie jako archiwum nie mogą się znaleźć dowiązania symboliczne. Te są tworzone przez skrypt doinst.sh. My jednak będziemy posługiwać się poleceniem makepkg, więc nie musimy się tym martwić. Jednak trzeba zadbać o to, żeby wszystkie symlinki wskazywały na pliki ścieżkami względnymi, bowiem ktoś może instalować pakiet w innym katalogu niż /.

Przygotowanie slackbuilda

Slackbuild jest prostym skryptem powłoki o nazwie nazwa-programu.SlackBuild. Jego działanie można podzielić na etapy: przygotowania i przeprowadzenia kompilacji, zainstalowania plików wynikowych w osobnym katalogu, poprawienia ewentualnej fuszerki instalatora i kompresowania manuali, i wreszcie utworzenia pakietu.

Z uwagi na to, że tworzony pakiet nie powinien mieszać w uprawnieniach systemu, na którym będzie instalowany, slackbuild musi być uruchamiany przez użytkownika root. Większość slackbuildów zakłada, że są uruchamiane w katalogu, w którym znajdują się wszystkie źródła, patche i inne pliki potrzebne do kompilacji programu, tak więc zwykle wywołuje się je poleceniem # ./nazwa-programu.SlackBuild. Pozwolę sobie wstawić szkielet slackbuilda, którego sam używam:

#!/bin/bash
# XXX: change "template" to whatever are you compiling

# template got from http://template.sourceforge.net/

set -e

# Set initial variables:
CWD=`pwd`
if [ "$TMP" = "" ]; then
  TMP=/tmp
fi

PKGNAME=template
VERSION=1.0.0
ARCH=i486
BUILD=1x

export CFLAGS="-O2 -march=i486 -mcpu=i686"

# XXX: prepare directories and unpack sources

PKG=$TMP/package-$PKGNAME
rm -rf $PKG

if [ ! -d $TMP ]; then
  mkdir -p $TMP # location to build the source
fi
if [ ! -d $PKG ]; then
  mkdir -p $PKG # place for the package to be built
fi

cd $TMP
rm -rf $PKGNAME-$VERSION

tar xjvf $CWD/$PKGNAME-$VERSION.tar.bz2
cd $PKGNAME-$VERSION

chown -R root:root .

# XXX: compile

./configure --prefix=/usr
make
# XXX: before uncommenting line below check if it is appropriate way to
# install program
#make install DESTDIR=$PKG

# XXX: end compile

# Strip binaries:
( cd $PKG
  find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | \
    xargs strip --strip-unneeded 2> /dev/null
  find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | \
    xargs strip --strip-unneeded 2> /dev/null
)

# set ownership of /usr/bin scripts
find $PKG/bin $PKG/usr/X11R6/bin $PKG/usr/bin -perm 755 -print0 | \
  xargs -0 chown root:bin

find $PKG/usr/X11R6/man $PKG/usr/man -type f -not -name '*.gz' -print0 | \
  xargs -0 gzip

mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc

# Build the package:
cd $PKG
makepkg -l y -c n $TMP/$PKGNAME-$VERSION-$ARCH-$BUILD.tgz

# Clean up the extra stuff:
if [ "$1" = "--cleanup" ]; then
  rm -rf $TMP/$PKGNAME-$VERSION
  rm -rf $PKG
fi

Czas na krótkie omówienie zasad działania. Komentarz z początku skryptu o pochodzeniu programu bywa przydatny, gdy chcemy sprawdzić, czy program nie ma nowszej wersji. Nie wszystko przecież dostępne jest na http://sourceforge.net/.

set -e powoduje przerwanie pracy skryptu, gdy którekolwiek polecenie zakończy się z niezerowym kodem błędu. Poza oczywistym przerwaniem działania skryptu zaraz za nieudaną kompilacją pozwala to uniknąć na przykład niekontrolowanej zmiany praw w katalogu, w którym budujemy pakiet (w moim przypadku w /tmp).

Na podstawie zmiennych PKGNAME i VERSION zwykle jest ustalana nazwa tarballa zawierającego źródła. Zwykle to zmiana właśnie tutaj, przy VERSION, wystarcza do zbudowania nowszej wersji pakietu.

Dalej mamy upewnienie się, że istnieją katalogi docelowe i że katalog, w którym znajdą się pliki później wejdące w skład pakietu jest pusty. Następnie czyścimy katalog na rozpakowane źródła, aby poprzednie kompilacje nie wpływały w żaden sposób na obecną budowę pakietu.

Teraz pora na ostatnie poprawki przed kompilacją: poprawiamy właściciela i grupę plików źródłowych (widywałem źródła należące do użytkownika o UID==574). Tutaj też jest miejsce, w którym można zaaplikować ewentualne patche i poprawiać znane nam błędy w makefiles. Pamiętaj: w slackbuildzie do poprawiania skryptów kompilacji i instalacji możesz używać dowolnych narzędzi, na przykład Perla. W końcu to twoja maszyna ma budować pakiet (oczywiście nie przesadzaj, bo chyba nie będziesz zmuszać kogoś chcącego przekompilować pakiet do instalacji Ruby'ego i kompilatora Haskella, których nie ma w Slackware?).

Doszliśmy szczęśliwie do momentu, w którym podajemy wszystkie znane nam opcje do ./configure. Jak wspominałem w sekcji o strukturze pakietów, program powinien się zainstalować w /usr, względnie w /usr/X11R6 albo /opt/kde (przynajmniej w typowych sytuacjach), w związku z czym podanie --prefix=... jest konieczne. Pozostałych opcji wskazujących katalogi (--bindir, --datadir, --mandir i innych) nie musimy podawać, dzięki strukturze katalogów w Slackware. Inne opcje kompilacji, jak wszystkie --enable-... i --with-... możemy znaleźć czytając $ ./configure --help | less i pliki README i INSTALL. Uwaga: przejrzyj instrukcje instalacji zawarte w tych plikach, nawet jeśli wydaje ci się, że wiesz jak skompilować program. Zdarzają się tam opisy naprawdę ciekawych opcji.

Po konfiguracji źródeł następuje etap kompilacji, załatwiany zwykle przez pojedyncze make. Jeśli kompilacja się nie powiedzie, set -e z początku skryptu nie pozwoli przejść nad błędem do porządku dziennego.

Teraz następuje część, która bywa najtrudniejsza: umieścimy wszystkie pliki wynikowe w odpowiednich dla nich miejscach w katalogu $PKG. Zwykle wystarcza # make install DESTDIR=$PKG, ale niestety nie zawsze, dlatego najpierw musimy sprawdzić, czy to wystarczy. Wydajmy polecenie $ make -n install DESTDIR=/blabla | less -S. Teraz trzeba przejrzeć wynik szukając ścieżki /blabla. Jeśli pojawia się w miejscach innych niż przekazanie DESTDIR kolejnemu make, to możemy na tym etapie zakończyć szukanie sposobu instalacji (przynajmniej tak wynika z moich doświadczeń). Jeśli podanie parametru DESTDIR nie przynosi rezultatów, to można jeszcze spróbować wykonać ten sam zabieg z INSTALL_ROOT=$PKG, ewentualnie z prefix=$PKG/usr. Jeśli i te dwa nie dadzą pożądanych wyników (tj. zmiany katalogu bazowego, w którym zainstaluje się program), zostaje przejrzeć pliki Makefile (tu niestety już nie mogę poradzić nic bardziej konkretnego). W ostateczności, jeśli nie instaluje się zbyt dużo plików, możemy wstawić jawne kopiowanie plików do katalogów docelowych w $PKG uzyskane przy $ make -n install. Powtarzam, w ostateczności. Tak nieestetyczna instalacja zabija uniwersalność slackbuilda przywiązując go do układu plików w tej konkretnej wersji programu. Uwaga: katalog, w którym program ma się zainstalować, powinien być podany jako ścieżka bezwzględna, czyli zaczepiona w /. make install zwykle wchodzi w podkatalogi, a nie przewiduje obsługi ścieżki względnej, przez co program nie instaluje się poprawnie.

Teraz już mamy przed sobą same proste czynności. Najpierw wykonujemy polecenie strip na wszystkich znalezionych plikach wykonywalnych i bibliotekach dzielonych, potem poprawiamy uprawnienia katalogów */*bin i zawartych w nich plików i kompresujemy nieskompresowane jeszcze strony manuala.

Zostało jeszcze tylko umieścić opis pakietu w stosownym miejscu i utworzyć pakiet, po czym, być może, posprzątać po kompilacji (uważaj, gdzie tworzysz pakiet, żeby go przypadkiem nie usunąć przy --cleanup).

Metadane w pakietach

Zaczniemy od pliku install/slack-desc. Istotne są jedynie linijki zaczynające się od <nazwa-pakietu>: (<nazwa-pakietu> to ten sam symbol co w schemacie nazewnictwa pakietów, czyli wszystko do trzeciego od końca myślnika). Takich linii powinno być jedenaście, bo tyle wyświetla pkgtool. Opis powinien być łamany na 71 kolumnie, licząc od dwukropka. W praktyce oznacza to łamanie opisu na 70 kolumnie, bo warto doliczyć jedną spację marginesu z lewej strony. Przykład pliku slack-desc (pochodzi z pakietu ash):

# HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description.  Line
# up the first '|' above the ':' following the base package name, and the '|'
# on the right side marks the last column you can put a character in.  You must
# make exactly 11 lines for the formatting to be correct.  It's also
# customary to leave one space after the ':'.

   |-----handy-ruler------------------------------------------------------|
ash: ash (Kenneth Almquist's ash shell)
ash:
ash: A lightweight (92K) Bourne compatible shell.  Great for machines with
ash: low memory, but does not provide all the extras of shells like bash,
ash: tcsh, and zsh.  Runs most shell scripts compatible with the Bourne
ash: shell.  Note that under Linux, most scripts seem to use at least some
ash: bash-specific syntax.  The Slackware setup scripts are a notable
ash: exception, since ash is the shell used on the install disks.  NetBSD
ash: uses ash as its /bin/sh.
ash:
ash:

Dobry opis zwykle można znaleźć w pliku README w katalogu ze źródłami albo na stronie domowej programu.

Do omówienia został mi plik install/doinst.sh. Wszystkie polecenia w tym pliku powinny operować na ścieżkach względnych. Dlaczego? Ponieważ ktoś może chcieć instalować pakiet w innym katalogu niż /, na przykład przygotowując środowisko dla chroot czy User-mode Linux (z tego samego powodu wszystkie symlinki powinny wskazywać na pliki ścieżkami względnymi). Każde polecenie może zakładać, że znajduje się w katalogu, w którym pakiet jest instalowany (czyli zwykle w katalogu /).

Jeśli pakiet zawiera jakieś pliki konfiguracyjne, to wypada w tym miejscu sprawdzić, czy już nie istnieją wcześniejsze pliki konfiguracyjne. W przypadku, gdy nowy plik konfiguracyjny jest identyczny z tym już istniejącym, można spokojnie usunąć kopię. Ja zwykle stosuję taką konstrukcję (przykład pochodzi z pakietu sudo):

#!/bin/sh

config() {
  if [ ! -e ${1%.new} ]; then
    mv $1 ${1%.new}
  elif diff $1 ${1%.new} > /dev/null 2>&1; then
    rm -f "$1"
  fi
}

config etc/sudoers.new

Skrypt install/doinst.sh jest również odpowiednim miejscem do założenia nowych użytkowników i grup, o ile takie zabiegi są potrzebne.

Case study: nettools

Ten punkt będzie długi. Omówimy w nim niemal krok po kroku, jak przygotować dobrego slackbuilda nawet mimo "niestandardowej" metody instalacji programu, jak również jak tworzyć pakiety zawierające więcej niż jeden program.

Budowanie pakietu nettools zaczniemy od sporządzenia szkieletu skryptu budującego.

#!/bin/sh

set -e

# mtr got from http://www.bitwizard.nl/mtr/
# hping2 got from http://www.hping.org/
# sendip got from http://www.earth.li/projectpurple/progs/sendip.html
# ngrep got from http://ngrep.sourceforge.net/
# p0f got from http://lcamtuf.coredump.cx/p0f/p0f.shtml
# fping got from http://www.fping.com/
# xprobe2 got from http://www.sys-security.com/html/projects/X.html

# Set initial variables:
CWD=`pwd`
if [ "$TMP" = "" ]; then
  TMP=/tmp
fi
PKGNAME=nettools
VERSION=1.2
ARCH=i486
BUILD=2x

export LDFLAGS="-s" CFLAGS="-O2 -march=i486 -mcpu=i686"

PKG=$TMP/package-$PKGNAME
rm -rf $PKG

if [ ! -d $TMP ]; then
  mkdir -p $TMP # location to build the source
fi
if [ ! -d $PKG ]; then
  mkdir -p $PKG # place for the package to be built
fi

rm -rf $TMP/$PKGNAME-$VERSION
mkdir -p $TMP/$PKGNAME-$VERSION


#----------------------------------------------------------------------------
#----------------------------------------------------------------------------

find $PKG/usr/man/man? -type f -not -name '*.gz' -print0 | xargs -0 gzip
find $PKG/usr/*bin -perm 755 -print0 | xargs -0 chown :bin

# Strip binaries:
( cd $PKG
  find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | \
    xargs strip --strip-unneeded 2> /dev/null
  find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | \
    xargs strip --strip-unneeded 2> /dev/null
)

mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc

# Build the package:
cd $PKG
makepkg -l y -c n $TMP/$PKGNAME-$VERSION-$ARCH-$BUILD.tgz

# Clean up the extra stuff:
if [ "$1" = "--cleanup" ]; then
  rm -rf $TMP/$PKGNAME-$VERSION
  rm -rf $PKG
fi

Jak widać, niewiele się różni od szkieletu podanego przeze mnie wcześniej. Zwróćmy uwagę na przygotowanie katalogu $TMP/$PKGNAME-$VERSION, a nie tylko $TMP. Programów, które znajdą się w pakiecie, będzie nieco więcej, więc nie chcielibyśmy za bardzo śmiecić w $TMP.

Pora teraz na dodanie pierwszego programu: będzie nim mtr. Slackbuilda zmienimy w dwóch miejscach.

PKGNAME=nettools
VERSION=1.2
ARCH=i486
BUILD=2x

MTR=mtr
MTRVER=0.69
export LDFLAGS="-s" CFLAGS="-O2 -march=i486 -mcpu=i686"

BUILD_MTR=yes

Tuż pod informacjami o samym pakiecie zwykle dodaje się informacje o programach, które wejdą w jego skład, bo łatwo go wtedy przebudować, gdy pojawi się nowa wersja programu (no i nie trzeba szukać po całym slackbuildzie, gdzie ten numerek jest ustawiany). Wyprzedzę nieco drugą poprawkę i powiem, że przy pisaniu jednego slackbuilda dla wielu programów warto oznaczyć, które części mają zostać zbudowane. Do tego będzie mi służyć zmienna $BUILD_MTR. Dzięki temu będę mógł pominąć niepotrzebny etap budowania mtr przy pisaniu fragmentu dla pozostałych programów.

rm -rf $TMP/$PKGNAME-$VERSION
mkdir -p $TMP/$PKGNAME-$VERSION

#----------------------------------------------------------------------------
# mtr
#

if [ "$BUILD_MTR" = yes ]; then

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$MTR-$MTRVER.tar.gz
  cd $MTR-$MTRVER
  ./configure --prefix=/usr --with-gtk=/dev/null
  # mtr 0.67 has a bit broken makefile
  make
  # make install
  mkdir -p $PKG/usr/bin $PKG/usr/man/man8 $PKG/usr/doc/$MTR-$MTRVER
  cp mtr $PKG/usr/bin
  chown :bin $PKG/usr/bin/mtr
  chmod 4711 $PKG/usr/bin/mtr
  cp *.8 $PKG/usr/man/man8
  cp AUTHORS ChangeLog COPYING FORMATS INSTALL NEWS README SECURITY TODO \
     $PKG/usr/doc/$MTR-$MTRVER

fi

#----------------------------------------------------------------------------
#----------------------------------------------------------------------------

Procedura instalacji mtr, zgodnie z tym, co już mówiłem, jest otoczona przez ifa.

Najpierw rozpakowujemy źródła do $TMP/$PKGNAME-$VERSION, zwykłe ./configure z opcjami (tu akurat chciałem się pozbyć zależności od GTK+, więc postąpiłem zgodnie z instrukcją z pliku README), potem make. Zamiast make install zastosowałem bezpośrednie kopiowanie plików w odpowiednie miejsca. DESTDIR=$PKG nie działa w tym przypadku (za to zadziała prefix=$PKG/usr), instalacja umieszcza polecenie mtr w usr/sbin (my chcemy mieć je w usr/bin) i w ogóle nie przejmuje się plikami README, INSTALL i innymi, w związku z czym jedyne, co by było odpowiednie, to skopiowanie manuala w stosowne miejsce.

Z uwag dodatkowych: chown i chmod wstawiłem tutaj nie bez powodu. W dalszej części skryptu znajduje się linijka zmieniająca przynależność do grupy wszystkim plikom z usr/*bin, o ile te pliki mają prawa 755. Ja chcę mtr udostępnić wszystkim użytkownikom, stąd nadanie bitu SUID. Jednak zgodnie z zasadami budowy pakietów, wszystkie pliki w usr/bin powinny należeć do grupy bin, o ile przynależność pliku do określonej grupy jest nieistotna (na przykład plik nie ma ustawionego prawa SGID). Kolejność wykonania chown i chmod również nie jest przypadkowa: po zmianie przynależności pliku prawa SUID i SGID są pod Linuksem resetowane.

Pora na kolejny program. Na początku skryptu dodajmy linijki z informacjami o hping3:

MTR=mtr
MTRVER=0.69
HPING=hping
HPINGVER=3-alpha-2
HPINGDIR=hping$HPINGVER
export LDFLAGS="-s" CFLAGS="-O2 -march=i486 -mcpu=i686"

BUILD_MTR=yes
BUILD_HPING=yes

hping jest spakowany nie do końca zgodnie z powszechnie przyjętą konwencją, stąd podaję jawnie, jak się nazywa katalog w archiwum ze źródłami.

Pod sekcją budującą mtr dodajmy teraz procedurę budowania hping:

#----------------------------------------------------------------------------
# hping3
#

if [ "$BUILD_HPING" = yes ]; then

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$HPING$HPINGVER.tar.gz
  cd $HPINGDIR
  perl -pi -e 'BEGIN{@ARGV = grep -f, @ARGV} s{net/bpf\.h}{pcap-bpf.h}' *
  # if you don't want to have Tcl scripting enabled then try using
  # `./configure --no-tcl'
  ./configure
  make
  # make install
  mkdir -p $PKG/usr/sbin $PKG/usr/man/man8 $PKG/usr/doc/$HPING-$HPINGVER
  cp hping3 $PKG/usr/sbin
  cp -R AUTHORS BUGS CHANGES COPYING INSTALL KNOWN-BUGS NEWS README TODO RFCs \
     $PKG/usr/doc/$HPING-$HPINGVER
  cd docs
  cp APD.txt API.txt AS-BACKDOOR HPING2-HOWTO.txt HPING2-IS-OPEN \
     hping2rc.example HPING3.txt MORE-FUN-WITH-IPID SPOOFED_SCAN.txt \
     $PKG/usr/doc/$HPING-$HPINGVER
  cp *.8 $PKG/usr/man/man8

fi

Przede wszystkim trzeba poprawić dyrektywy #include, ponieważ w libpcap 0.8.3 nagłówkek net/bpf.h nosi nazwę pcap-bpf.h. To nam załatwia wywołanie Perla. Mógłbym użyć tu for FILE in *; do test -f $FILE || continue; sed -i 's|net/bpf\.h|pcap-bpf.h|' $FILE; done, ale wywołanie Perla uznałem za zgrabniejsze. Mógłbym również użyć standardowego patcha uzyskanego poleceniem diff -u ..., ale nie widzę sensu stosować tego wyjścia do takiej drobnej poprawki.

Instalacja hping3 nie jest w pełni standardowa, przy czym tutaj w ogóle nie działają zabiegi ze zmianą DESTDIR, prefix czy czegokolwiek (rzut okiem do makefile wyjaśni, dlaczego). Niestety musimy wszystko pokopiować ręcznie.

Czas na sendip. Dodajmy w stosownych miejscach

SENDIP=sendip
SENDIPVER=2.5
BUILD_SENDIP=yes
#----------------------------------------------------------------------------
# sendip
#

if [ "$BUILD_SENDIP" = yes ]; then

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$SENDIP-$SENDIPVER.tar.gz
  cd $SENDIP-$SENDIPVER
  make PREFIX=/usr
  mkdir -p $PKG/usr/man/man1
  make install PREFIX=$PKG/usr
  mv $PKG/usr/share/man/man1/* $PKG/usr/man/man1
  rm -rf $PKG/usr/share/man
  rmdir $PKG/usr/share
  cp contrib/wake.sh $PKG/usr/bin
  mkdir -p $PKG/usr/doc/$SENDIP-$SENDIPVER
  cp CHANGES LICENSE README TODO $PKG/usr/doc/$SENDIP-$SENDIPVER

fi

Instalacja sendip na szczęście przebiega prawie całkowicie standardowo, może z wyjątkiem braku etapu ./configure.

Instalacja ngrep, fping/fping6 i xprobe2 nie różni się praktycznie niczym od sendip. Jedynie p0f się nieco różni, poza tym trzeba mu zaaplikować taką samą poprawkę z net/bpf.h, jak przy hping3, ale to już nie wnosi nic nowego.

Podsumowując, pełny slackbuild będzie wyglądał następująco:

#!/bin/sh

set -e

# mtr got from http://www.bitwizard.nl/mtr/
# hping2 got from http://www.hping.org/
# sendip got from http://www.earth.li/projectpurple/progs/sendip.html
# ngrep got from http://ngrep.sourceforge.net/
# p0f got from http://lcamtuf.coredump.cx/p0f/p0f.shtml
# fping got from http://www.fping.com/
# xprobe2 got from http://www.sys-security.com/html/projects/X.html

# Set initial variables:
CWD=`pwd`
if [ "$TMP" = "" ]; then
  TMP=/tmp
fi
PKGNAME=nettools
VERSION=1.2
ARCH=i486
BUILD=2x

MTR=mtr
MTRVER=0.69
HPING=hping
HPINGVER=3-alpha-2
HPINGDIR=hping$HPINGVER
SENDIP=sendip
SENDIPVER=2.5
NGREP=ngrep
NGREPVER=1.44-1
NGREPDIR=ngrep-1.44
POF=p0f
POFVER=2.0.5
FPING=fping
FPINGVER=2.4b2
FPINGNAME=fping-2.4b2_to
FPING6NAME=fping-2.4b2_to-ipv6
XPROBE=xprobe2
XPROBEVER=0.2.2
export LDFLAGS="-s" CFLAGS="-O2 -march=i486 -mcpu=i686"

BUILD_MTR=yes
BUILD_HPING=yes
BUILD_SENDIP=yes
BUILD_NGREP=yes
BUILD_POF=yes
BUILD_FPING=yes
BUILD_XPROBE=yes

PKG=$TMP/package-$PKGNAME
rm -rf $PKG

if [ ! -d $TMP ]; then
  mkdir -p $TMP # location to build the source
fi
if [ ! -d $PKG ]; then
  mkdir -p $PKG # place for the package to be built
fi

rm -rf $TMP/$PKGNAME-$VERSION
mkdir -p $TMP/$PKGNAME-$VERSION

#----------------------------------------------------------------------------
# mtr
#
if [ "$BUILD_MTR" = yes ]; then

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$MTR-$MTRVER.tar.gz
  cd $MTR-$MTRVER
  ./configure --prefix=/usr --with-gtk=/dev/null
  make
  # make install
  mkdir -p $PKG/usr/bin $PKG/usr/man/man8 $PKG/usr/doc/$MTR-$MTRVER
  cp mtr $PKG/usr/bin
  chown :bin $PKG/usr/bin/mtr
  chmod 4711 $PKG/usr/bin/mtr
  cp *.8 $PKG/usr/man/man8
  cp AUTHORS ChangeLog COPYING FORMATS INSTALL NEWS README SECURITY TODO
$PKG/usr/doc/$MTR-$MTRVER

fi

#----------------------------------------------------------------------------
# hping3
#

if [ "$BUILD_HPING" = yes ]; then

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$HPING$HPINGVER.tar.gz
  cd $HPINGDIR
  perl -pi -e 'BEGIN{@ARGV = grep -f, @ARGV} s{net/bpf\.h}{pcap-bpf.h}' *
  # if you don't want to have Tcl scripting enabled then try using
  # `./configure --no-tcl'
  ./configure
  make
  # make install
  mkdir -p $PKG/usr/sbin $PKG/usr/man/man8 $PKG/usr/doc/$HPING-$HPINGVER
  cp hping3 $PKG/usr/sbin
  cp -R AUTHORS BUGS CHANGES COPYING INSTALL KNOWN-BUGS NEWS README TODO RFCs \
     $PKG/usr/doc/$HPING-$HPINGVER
  cd docs
  cp APD.txt API.txt AS-BACKDOOR HPING2-HOWTO.txt HPING2-IS-OPEN \
     hping2rc.example HPING3.txt MORE-FUN-WITH-IPID SPOOFED_SCAN.txt \
     $PKG/usr/doc/$HPING-$HPINGVER
  cp *.8 $PKG/usr/man/man8

fi

#----------------------------------------------------------------------------
# sendip
#

if [ "$BUILD_SENDIP" = yes ]; then

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$SENDIP-$SENDIPVER.tar.gz
  cd $SENDIP-$SENDIPVER
  make PREFIX=/usr
  mkdir -p $PKG/usr/man/man1
  make install PREFIX=$PKG/usr
  mv $PKG/usr/share/man/man1/* $PKG/usr/man/man1
  rm -rf $PKG/usr/share/man
  rmdir $PKG/usr/share
  cp contrib/wake.sh $PKG/usr/bin
  mkdir -p $PKG/usr/doc/$SENDIP-$SENDIPVER
  cp CHANGES LICENSE README TODO $PKG/usr/doc/$SENDIP-$SENDIPVER

fi

#----------------------------------------------------------------------------
# ngrep
#

if [ "$BUILD_NGREP" = yes ]; then

  cd $TMP/$PKGNAME-$VERSION
  tar xjvf $CWD/$NGREP-$NGREPVER.tar.bz2
  cd $NGREPDIR
  # PCRE provided with ngrep is much slower than GNU regexes (at least the
  # author claims that)
  ./configure \
    --prefix=/usr \
  #  --enable-pcre
  make
  # make install
  mkdir -p $PKG/usr/sbin $PKG/usr/man/man8 $PKG/usr/doc/$NGREP-$NGREPVER
  cp ngrep $PKG/usr/sbin
  cp *.8 $PKG/usr/man/man8
  rm -rf doc/CVS
  cp doc/* LICENSE.txt $PKG/usr/doc/$NGREP-$NGREPVER

fi

#----------------------------------------------------------------------------
# p0f
#

if [ "$BUILD_POF" = yes ]; then

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$POF-$POFVER.tgz
  cd $POF
  perl -pi -e 'BEGIN{@ARGV = grep -f, @ARGV} s{net/bpf\.h}{pcap-bpf.h}' *
  ./Build
  make
  # make install
  mkdir -p $PKG/usr/sbin $PKG/usr/man/man1 $PKG/etc/p0f \
           $PKG/usr/doc/$POF-$POFVER
  cp p0f p0frep $PKG/usr/sbin
  cp *.1 $PKG/usr/man/man1
  cp p0f.fp p0fa.fp p0fr.fp p0fo.fp $PKG/etc/p0f
  cp -R doc/* test $PKG/usr/doc/$POF-$POFVER

fi

#----------------------------------------------------------------------------
# fping
#

if [ "$BUILD_FPING" = yes ]; then

  mkdir -p $PKG/usr/sbin $PKG/usr/man/man8 $PKG/usr/doc/$FPING-$FPINGVER

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$FPINGNAME.tar.gz
  cd $FPINGNAME
  ./configure --prefix=/usr
  make
  cp fping $PKG/usr/sbin/fping

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$FPING6NAME.tar.gz
  cd $FPING6NAME
  ./configure --prefix=/usr
  make
  cp fping $PKG/usr/sbin/fping6

  cp ChangeLog COPYING INSTALL README $PKG/usr/doc/$FPING-$FPINGVER
  chmod 644 $PKG/usr/doc/$FPING-$FPINGVER/*
  cp *.8 $PKG/usr/man/man8
  ln -s fping.8.gz $PKG/usr/man/man8/fping6.8.gz

fi

#----------------------------------------------------------------------------
# xprobe2
#

if [ "$BUILD_XPROBE" = yes ]; then

  cd $TMP/$PKGNAME-$VERSION
  tar xzvf $CWD/$XPROBE-$XPROBEVER.tar.gz
  cd $XPROBE-$XPROBEVER
  (unset LDFLAGS CFLAGS CXXFLAGS; ./configure --prefix=/usr --sysconfdir=/etc)
  make
  make install DESTDIR=$PKG
  mkdir -p $PKG/usr/doc
  chmod 644 docs/*
  cp -R docs $PKG/usr/doc/$XPROBE-$XPROBEVER

fi

#----------------------------------------------------------------------------
#----------------------------------------------------------------------------

find $PKG/usr/man/man? -type f -not -name '*.gz' -print0 | xargs -0 gzip
find $PKG/usr/*bin -perm 755 -print0 | xargs -0 chown :bin

# Strip binaries:
( cd $PKG
  find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | \
    xargs strip --strip-unneeded 2> /dev/null
  find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | \
    xargs strip --strip-unneeded 2> /dev/null
)

mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc

# Build the package:
cd $PKG
makepkg -l y -c n $TMP/$PKGNAME-$VERSION-$ARCH-$BUILD.tgz

# Clean up the extra stuff:
if [ "$1" = "--cleanup" ]; then
  rm -rf $TMP/$PKGNAME-$VERSION
  rm -rf $PKG
fi

Zostało jeszcze tylko wymyślić dobry opis do pliku slack-desc i już możemy zbudować pakiet nettools.

Engine by Dozzie. Awful design by Dozzie.