Once it hits the fan, the only rational choice is to sweep it up, package it, and sell it as fertilizer. | |
anonymous |
This document tries to cover multiple platforms through conditional compilation. There is a configure.pl that determines the host type and sets up a config.sh containing environment variable definitions. There also are equivalent config.csh, config.h, config.mak, config.sed, and config.xml. The Makefile then uses individual sub-directories for each platform. The name of these directories (and some other platform specific values) is retrieved through environment variables. The directory structure is not without meaning.
src/ is for source code, i.e. text files written and maintained by humans.
pre/i386-redhat7.3-linux/ is directory src/ pre-processed with config.sed. In pre/ all program names are absolute. Magic numbers and platform specific constants are verbatim.
tmp/i386-redhat7.3-linux/ is the only place to hold binaries, i.e. executables and .o files.
out/i386-redhat7.3-linux/ is for the output of executables, hex dumps, disassembly listings, text processing.
The files in src/ are obfuscated with obscene amounts of variable references like ${TEVWH_ELF_BASE} or even ${TEVWH_PATH_LS}. I admit that using variables instead of plain program names makes shell scripts harder to read. But this is necessary to maintain a minimum level of reproducibility on SunOS. Anyway, directory pre/ makes that 8048000 and /bin/ls, so you will probably never encounter this syntax nightmare. An almost complete list of used variables is given below.
Table 1. Variables prefixed with TEVWH_
Variable name | Value on this platform | Variable name | Value on this platform |
---|---|---|---|
ARCH | i386 | ASM_COMMENT | ; |
ASM_FLAVOR | set disassembly-flavor intel | ASM_RETURN | \(ret\|hlt\) |
ASM_STYLE | intel | BYTE_ORDER | L |
CFLAGS | -O1 -I out/i386-redhat7.3-linux -D NDEBUG | ELF_ADDR_SIZE | 32 |
ELF_ALIGN | 0x1000 | ELF_BASE | 0x8048000 |
ELF_EHDR | Elf32_Ehdr | ELF_MAGIC | 0x8048001 |
ELF_PHDR | Elf32_Phdr | ELF_SHDR | Elf32_Shdr |
HOSTTYPE | Linux/i386 | OS_CODE | i386-redhat7.3-linux |
OS_NAME | Red Hat Linux release 7.3 (Valhalla) | OS_PKG_SYS | rpm |
OS_VENDOR | redhat | OS_VERSION | 7.3 |
OUT | out/i386-redhat7.3-linux | OUT_XML | out/i386-redhat7.3-linux/xml |
PAGESIZE | 0x1000 | PRE | pre/i386-redhat7.3-linux |
PROC_EXE | /proc/self/exe | PROC_MEM | /proc/self/mem |
TMP | tmp/i386-redhat7.3-linux | UNAME | Linux |
Note that hexadecimal shell variables actually miss the leading 0x to simplify calculations with bc. These values are also available to C code through corresponding #define statements after #include <config.h>. Values are not quoted, but hexadecimal values are correctly prefixed by 0x.
Table 2. Variables prefixed with TEVWH_PATH_
Variable name | Value on this platform | Variable name | Value on this platform |
---|---|---|---|
BC | /usr/bin/bc | CC | /usr/bin/gcc |
CHMOD | /bin/chmod | COL | /usr/bin/col |
CSH | /bin/tcsh | CUT | /usr/bin/cut |
DD | /bin/dd | DU | /usr/bin/du |
ECHO | /bin/echo | EXPAND | /usr/bin/expand |
FILE | /usr/bin/file | FIND | /usr/bin/find |
GDB | /usr/bin/gdb | GREP | /bin/grep |
HEAD | /usr/bin/head | HEXDUMP | /usr/bin/hexdump |
KILL | /bin/kill | LD | /usr/bin/ld |
LDD | /usr/bin/ldd | LS | /bin/ls |
MAKE | /usr/bin/make | MAN | /usr/bin/man |
MT | /bin/mt | NASM | /usr/bin/nasm |
NDISASM | /usr/bin/ndisasm | NICE | /bin/nice |
NM | /usr/bin/nm | OBJDUMP | /usr/bin/objdump |
OD | /usr/bin/od | PERL | /usr/bin/perl |
READELF | /usr/bin/readelf | RPM | /bin/rpm |
SED | /bin/sed | SH | /bin/sh |
SORT | /bin/sort | STRACE | /usr/bin/strace |
STRINGS | /usr/bin/strings | STRIP | /usr/bin/strip |
TAIL | /usr/bin/tail | TEE | /usr/bin/tee |
TR | /usr/bin/tr | UNIQ | /usr/bin/uniq |
WHICH | /usr/bin/which | XARGS | /usr/bin/xargs |
XXD | /usr/bin/xxd |
One of the lesser known features of package management is self-reflection. How do we determine the package owning a file if we have the canonical path name?
Red Hat Linux release 7.3 (Valhalla) uses rpm for package management. It maintains an extensive database in /var/lib/rpm/ in binary form. Query operations are quite fast, but disk space usage is rather high.
Source: pre/i386-redhat7.3-linux/packages/rpm/du.sh
#!/bin/sh
/usr/bin/file /var/lib/rpm/*
/usr/bin/du -s /var/lib/rpm |
Output: out/i386-redhat7.3-linux/packages/du
/var/lib/rpm/Basenames: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Conflictname: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Dirnames: Berkeley DB (Btree, version 8, native byte-order)
/var/lib/rpm/Filemd5s: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Group: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Installtid: Berkeley DB (Btree, version 8, native byte-order)
/var/lib/rpm/Name: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Packages: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Providename: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Provideversion: Berkeley DB (Btree, version 8, native byte-order)
/var/lib/rpm/Requirename: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Requireversion: Berkeley DB (Btree, version 8, native byte-order)
/var/lib/rpm/Sha1header: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Sigmd5: Berkeley DB (Hash, version 7, native byte-order)
/var/lib/rpm/Triggername: Berkeley DB (Hash, version 7, native byte-order)
23926 /var/lib/rpm |
The query is straightforward:
Source: pre/i386-redhat7.3-linux/packages/rpm/simple.sh
#!/bin/sh
/bin/rpm -qf $( /usr/bin/which perl ) |
Output: out/i386-redhat7.3-linux/packages/simple
perl-5.6.1-34.99.6 |
Output format is customizable. A list of available tag names is output by rpm --querytags.
Source: pre/i386-redhat7.3-linux/packages/rpm/custom.sh
#!/bin/sh
/bin/rpm -q -f $( /usr/bin/which perl ) \
--qf 'name=%{name}\nversion=%{version}\nrelease=%{release}\n' |
Output: out/i386-redhat7.3-linux/packages/rpm/custom
name=perl
version=5.6.1
release=34.99.6 |
Option -a of man returns all matching entries, not just the lowest section. This behavior is identical between platforms.
Command: pre/i386-redhat7.3-linux/packages/man-all/Linux.sh
#!/bin/sh
/usr/bin/man -a -w kill |
Output: out/i386-redhat7.3-linux/packages/man-all
/usr/share/man/man1/kill.1.gz
/usr/share/man/man2/kill.2.gz |
Requesting a specific section requires option -s section on SunOS, while Linux prefers a plain section.
Command: pre/i386-redhat7.3-linux/packages/man-section/Linux.sh
#!/bin/sh
/usr/bin/man -w 2 kill |
Output: out/i386-redhat7.3-linux/packages/man-section
/usr/share/man/man2/kill.2.gz |
This chapter is not about checking the integrity of package files. See Intrusion detection systems for a general introduction.
rpm(1) lets you verify everything or complete packages. A package can be specified indirectly through a file owned by it, though.
Command: pre/i386-redhat7.3-linux/packages/rpm/verify.sh
#!/bin/sh
/bin/rpm -qf /etc/profile
/bin/rpm --verify bash
/bin/echo status=$?
/bin/rpm --verify -f /etc/profile
/bin/echo status=$? |
Output: out/i386-redhat7.3-linux/packages/verify
setup-2.5.12-1
status=0
S.5....T c /etc/csh.cshrc
S.5....T c /etc/printcap
..?..... c /etc/securetty
status=1 |
A quick fix to lower the noise is to ignore all files flagged as " c ". Take the following as inspiration for a cron-based script.
Command: pre/i386-redhat7.3-linux/packages/rpm/verify-all.sh
#!/bin/sh
/bin/nice -n 19 /bin/rpm --verify --all \
| /bin/grep -v '........ c' |
With option -p package_file you can verify against the checksums included in a package file, e.g. on the installation CD.