annotate killrpath.c @ 2:7bf4a164d5bb default tip

fix bug: long_options have to be zero terminated
author Peter Meerwald <p.meerwald@bct-electronic.com>
date Fri, 20 Jul 2012 11:28:30 +0200
parents bbbfb3f97919
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
1 /*
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
2 Taken from another list:
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
3
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
4 _Changing_ is a little tricky, but the attached program strips rpaths
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
5 from executables (I find it essential for debugging the binutils).
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
6 It's endian-dependent, if you want this for x86 you can just change
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
7 the occurrences of 'MSB' to 'LSB' and compile (I should really fix
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
8 that).
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
9
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
10 --
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
11 Geoffrey Keating <geoffk@ozemail.com.au>
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
12 */
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
13
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
14 #ifdef HAVE_CONFIG_H
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
15 # include "config.h"
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
16 #endif
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
17
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
18 #include <stdio.h>
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
19 #include <unistd.h>
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
20 #include <fcntl.h>
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
21 #include <elf.h>
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
22 #if defined(HAVE_LINK_H)
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
23 # include <link.h>
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
24 #endif /* HAVE_LINK_H */
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
25 #include <stdlib.h>
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
26 #include "protos.h"
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
27 #include <string.h>
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
28
1
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
29 static int
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
30 killrpath32(int fd, Elf32_Ehdr *ehdr) {
0
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
31 int i;
1
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
32 Elf32_Phdr phdr;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
33 Elf32_Dyn *dyns;
0
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
34 int dynpos;
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
35
1
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
36 if (0 != elf32_find_dynamic_section(fd, ehdr, &phdr))
0
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
37 {
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
38 perror("found no dynamic section");
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
39 return 1;
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
40 }
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
41
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
42 dyns = malloc(phdr.p_memsz);
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
43 if (dyns == NULL)
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
44 {
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
45 perror ("allocating memory for dynamic section");
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
46 return 1;
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
47 }
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
48 memset(dyns, 0, phdr.p_memsz);
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
49 if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
50 || read(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
51 {
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
52 perror ("reading dynamic section");
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
53 return 1;
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
54 }
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
55
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
56 dynpos = 0;
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
57 for (i = 0; dyns[i].d_tag != DT_NULL; i++)
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
58 {
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
59 dyns[dynpos] = dyns[i];
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
60 if ( ! elf_dynpath_tag(dyns[i].d_tag) )
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
61 dynpos++;
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
62 }
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
63 for (; dynpos < i; dynpos++)
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
64 dyns[dynpos].d_tag = DT_NULL;
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
65
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
66 if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
67 || write(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
68 {
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
69 perror ("writing dynamic section");
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
70 return 1;
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
71 }
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
72
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
73 elf_close(fd);
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
74
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
75 return 0;
b8f7423e385c import 0.13
Peter Meerwald <pmeerw@pmeerw.net>
parents:
diff changeset
76 }
1
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
77
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
78 static int
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
79 killrpath64(int fd, Elf64_Ehdr *ehdr) {
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
80 int i;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
81 Elf64_Phdr phdr;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
82 Elf64_Dyn *dyns;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
83 int dynpos;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
84
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
85 if (0 != elf64_find_dynamic_section(fd, ehdr, &phdr))
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
86 {
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
87 perror("found no dynamic section");
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
88 return 1;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
89 }
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
90
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
91 dyns = malloc(phdr.p_memsz);
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
92 if (dyns == NULL)
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
93 {
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
94 perror ("allocating memory for dynamic section");
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
95 return 1;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
96 }
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
97 memset(dyns, 0, phdr.p_memsz);
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
98 if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
99 || read(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
100 {
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
101 perror ("reading dynamic section");
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
102 return 1;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
103 }
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
104
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
105 dynpos = 0;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
106 for (i = 0; dyns[i].d_tag != DT_NULL; i++)
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
107 {
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
108 dyns[dynpos] = dyns[i];
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
109 if ( ! elf_dynpath_tag(dyns[i].d_tag) )
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
110 dynpos++;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
111 }
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
112 for (; dynpos < i; dynpos++)
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
113 dyns[dynpos].d_tag = DT_NULL;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
114
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
115 if (lseek(fd, phdr.p_offset, SEEK_SET) == -1
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
116 || write(fd, dyns, phdr.p_filesz) != (int)phdr.p_filesz)
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
117 {
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
118 perror ("writing dynamic section");
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
119 return 1;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
120 }
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
121
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
122 elf_close(fd);
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
123
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
124 return 0;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
125 }
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
126
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
127 /* Reads an ELF file, nukes all the RPATH entries. */
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
128
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
129 int
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
130 killrpath(const char *filename)
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
131 {
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
132 int fd;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
133 Elf32_Ehdr ehdr32;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
134 Elf64_Ehdr ehdr64;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
135
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
136 fd = elf32_open(filename, O_RDWR, &ehdr32);
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
137 if (fd >= 0)
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
138 {
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
139 return killrpath32(fd, &ehdr32);
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
140 }
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
141
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
142 fd = elf64_open(filename, O_RDWR, &ehdr64);
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
143 if (fd >= 0)
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
144 {
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
145 return killrpath64(fd, &ehdr64);
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
146 }
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
147
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
148 perror ("elf_open");
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
149 return 1;
bbbfb3f97919 implement 32 and 64 bit support
Peter Meerwald <p.meerwald@bct-electronic.com>
parents: 0
diff changeset
150 }

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.