Die wichtigste Sache, die du machen solltest, ist mit anderen zu kommunizieren. Frage die anderen Leute auf ports@openbsd.org, ob sie an derselben Portierung arbeiten. Teile es dem ursprünglichen Programmierer mit, inklusive der Probleme, wenn du welche findest. Wenn die Lizenzbedingungen nicht korrekt sind, sag es ihm. Wenn du große Schwierigkeiten hattest, die Portierung zum Laufen zu kriegen, teile ihm mit, was verbessert werden könnte. Wenn sie nur auf Linux entwickeln und den Rest der Unix-Welt ignorieren, versuche, ihre Sichtweise etwas zu erweitern.
KOMMUNIKATION macht den Unterschied zwischen einer erfolgreichen Portierung und einer Portierung, die langsam von allen alleine gelassen und nicht mehr benutzt wird, aus.
Sieh dir zuerst die Portierungsinformationen auf dieser Seite an. Dann überprüfe all die gelinkten Dokumente, insbesondere die OpenBSD-Porting-Checkliste.
Teste, teste nochmal und schlussendlich teste nochmals!
OpenBSD unterstützt Updates nun vollständig. Dies bedeutet, dass ein paar Sonderfälle berücksichtigt werden müssen.
Liefere die Portierung aus (submit). Erzeuge einen ,gzipped tarball' des Verzeichnisses der Portierung. Du kannst diesen entweder auf einen öffentlichen FTP- oder HTTP-Server legen und die Adresse an ports@openbsd.org mailen oder ,mime encoded' an die selbe Adresse schicken. Wähle einfach eine Methode aus.
Neue Software zu portieren nimmt Zeit in Anspruch. Schwerer ist es allerdings, diese danach weiterhin zu verwalten. Es ist schon in Ordnung, wenn du Software portierst und die Verwaltung Anderen überlässt. Es ist ebenfalls in Ordnung, wenn du Anderen bei der Aktualisierung und Verwaltung anderer Portierungen hilfst, so lange du mit ihnen in Verbindung bleibst, damit nicht die gleiche Arbeit mehrmals gemacht wird.
In der OpenBSD-Kultur zählt »MAINTAINERship« (auf
Deutsch Betreuung) nicht als Statussymbol sondern als Verantwortung.
Wir verwenden CVS und die Kommentare werden verwendet, um die Person
zu vermerken, die die Arbeit gemacht hat. Ein
Portierungs-MAINTAINER ist jemand anderes: eine Person,
die sich der Funktionalität der Portierungs verpflichtet fühlt und bereit
ist, Zeit zu investieren, um diese so gut es geht bereitzustellen.
/usr/local/etc/rc.d./usr/local wird dank NFS oftmals von verschiedenen
Maschinen benutzt. Aus diesem Grund können
Konfigurationsdateien, die spezifisch für eine bestimmte
Maschine sind, auch nicht in /usr/local abgelegt
werden, /etc ist die zentrale Lagerstätte für
individuelle Maschinen-Konfigurationsdateien.
Außerdem ist es eine OpenBSD-Richtlinie, niemals Dateien unter
/etc automatisch upzudaten. Portierungen, die ein
bestimmtes Systemstart-Setup benötigen, sollten den Administrator
anweisen, was zu tun ist, anstatt blind Dateien zu
installieren.
-lcrypt.libc.
/usr/ports/infrastructure/db/user.list für
genaue Details.
$OpenBSD$-CVS-Tag
in das Makefile eingefügt wird. Wenn du eine Portierung von einem
anderen System importierst, stelle sicher, dass du auch ihren
Tag in dem Makefile belässt.
strcat/strcpy/strcmp/sprintf. Im Allgemeinen sollte
sprintf durch snprintf ersetzt werden.
/tmp mit symbolischen Links auf strategischere
Dateien setzen, wie etwa /etc/master.passwd.
fopen als auch
freopen
eine neue Datei oder öffnen eine bereits
existierende zum Schreiben. Ein Angreifer könnte einen
symbolischen Link von /etc/master.passwd auf
/tmp/addrpool_dump setzen. Sofort wenn du ihn
öffnest ist deine Passwortdatei verraten. Ja, sogar mit einem
unlink direkt davor. Du kannst nur die Anzahl der
Möglichkeiten verringern. Benutze stattdessen
open mit O_CREAT|O_EXCL und
fdopen.
mktemp-Funktion. Beachte die Warnungen des
,bsd linker's bei ihrer Benutzung.
Die müssen gefixt werden. Das ist nicht ganz
so einfach wie s/mktemp/mkstemp/g. mktemp(3) genauer an, um weitere Informationen
zu erhalten.
Korrekter Code, der mkstemp benutzt, schließt den
Source zu ed oder mail ein.
Eine seltenes Beispiel an Code, der mktemp korrekt
benutzt, kann in der rsync-Portierung gefunden werden.
startx-Problem. Als setuid-Programm konntest du
startx mit jeder Datei als Skript starten. Wenn die Datei kein
sauberes Shellskript war, folgte eine Fehlermeldung zusammen mit
der ersten Zeile der betreffenden Datei, ohne weitere Überprüfung
der Rechte. Ziemlich einfach die erste Zeile der
shadow-passwd-Datei zu erhalten, besonders wenn man bedenkt, dass
die erste Zeile meist den root-Eintrag enthält.
Öffne nicht deine Datei, um dann ein fstat auf den
,open descriptor' zu machen, um zu überprüfen, ob du sie hättest
öffnen können müssen (oder der Angreifer wird mit /dev/rst0
spielen und dein Band zurückspulen) - öffne es mit korrekt
gesetzter uid/gid/grouplist.
popen und
system ein.
Benutze stattdessen fork, pipe und
execve.
/dev/fd/0 benutzen.
inetd zu überlassen und nur die relevanten Einträge
in inetd.conf zu machen. Du musst selbstverständlich
die erforderliche Magie zum Schreiben von Daemons kennen, um das
zu erreichen. Man könnte sagen, dass du keinerlei Chancen hast,
ein gutes setuid-Programm zu schreiben, wenn du nicht weißt, wie
man das macht.
xkobo-Portierung für ein Beispiel einer solchen Änderung.
PATH ein (benutze niemals
system mit einem unqualifizierten Namen, vermeide
execvp), es betrifft aber auch solche feinen Dinge
wie locale, timezone, termcap, und so weiter. Sei vorsichtig mit
,transitivity': Auch wenn du alle Vorsichtsmaßregeln triffst,
machen das Programme, die du aufrufst, noch lange nicht.
Benutze niemals system in
privilegierten Programmen, baue eine saubere Kommandozeile,
eine kontrollierte Umgebung und rufe execve direkt
auf. Die perlsec-Handbuchseite ist ein gutes Tutorium
über solche Probleme.
issetugid kümmert sich um dieses Problem
vom Standpunkt eines-Bibliotheks-Autors aus. Versuche nicht
Bibliotheken zu portieren, bis du diesen Punkt wirklich
absolut verstanden hast.
__OpenBSD__ sollte sparsam benutzt werden, wenn
überhaupt. Konstruktionen, die wie
#if defined(__NetBSD__) || defined(__FreeBSD__)
aussehen, sind oft unpassend. Füge nicht blindlings
__OpenBSD__ hinzu. Versuche stattdessen
herauszufinden, was vor sich geht und welche Funktionalität
tatsächlich gebraucht wird. Handbuchseiten sind oftmals hilfreich,
da sie historische Kommentare enthalten und darstellen, wann eine
spezielle Funktionalität in OpenBSD eingefügt wurde. Den
numerischen Wert von BSD gegen bekannte
Versionen/Zahlen zu prüfen ist meistens der richtige Weg. Der
NetBSD
pkgsrc guide
enthält noch weitere Informationen.
BSD zu definieren ist eine schlechte Idee. Versuche
sys/param.h einzubinden. Das definiert nicht nur
BSD, sondern gibt auch einen sauberen Wert.
Das richtige Codefragment sollte etwa so aussehen:
#if (defined(__unix__) || defined(unix)) && !defined(USG)
#include <sys/param.h>
#endif
tcgetattr funktioniert, als zu
erfahren, ob man gerade auf 4.3 BSD oder später oder etwa
SystemVR4 arbeitet. Diese Art von Test trifft einfach nicht den
Punkt. Ein sinnvoller Weg wäre zum Beispiel auf ein bestimmtes
System zu testen, eine Runde von HAVE_TCGETATTR zu
definieren und dann mit dem nächsten System weiterzumachen.
Diese Technik trennt die Funktionalitätstests von denen auf
spezielle Betriebssysteme. In großer Eile kann ein anderer
Portierer das ganze Set an -DHAVE_XXX-Definitionen
zum Makefile hinzufügen. Man könnte das auch selber schreiben
oder im configure-Skript testen und es dann automatisch
hinzufügen. Als negatives Beispiel, dem man _nicht_ folgen
sollte, kann der nethack-3.2.2-Source dienen: er nimmt jede
Menge Dinge basierend auf dem Systemtyp an. Die meisten dieser
Annahmen sind veraltet und haben nichts mehr mit der Realität zu
tun: POSIX sind nützlicher als alte
BSD-versus-SystemV-Unterschiede, da einige traditionelle
BSD-Funktionen jetzt nur noch durch
Kompatibilitäts-Bibliotheken unterstützt werden.
#define POSIX_C_SOURCE im
ganzen Projekt einsetzt, nicht nur wenn dir danach ist.
unistd.h, fcntl.h oder
termios.h. Die Handbuchseite zeigt regelmäßig wo die
,prototypes' zu finden sind. Du könntest noch eine Runde
HAVE_XXX-Makros benötigen, um die richtige Datei zu
beschaffen. Mach dir keine Sorgen darum , dass du eine Datei
zweimal 'includen' könntest, include Dateien haben Aufpasser, die
solchen Unfug verhindern.unsigned long anstelle von size_t)
benutzen, oder einen const-Status falsch verstehen.
Außerdem sind einige Compiler, so wie auch OpenBSDs gcc,
in der Lage, bessere Arbeit mit sehr oft verwendeten Funktionen
wie strlen zu leisten, wenn man die richtigen
header-Dateien einbindet.
implicit declaration of function foo()
bedeutet, dass ein Funktionsprototyp nicht vorhanden ist.
Das bedeutet, dass der Compiler annimmt, dass der Typ
des Rückgabewert Integer ist.
Gibt die Funktion eigentlich einen Pointer zurück,
wird dieser auf 64-Bit-Systemen abgeschnitten, was
üblicherweiße zu einem Segmentation-Fault führt.
/* ,prototype'-Teil */
#ifdef USE_OWN_GCVT
char *foo_gcvt(double number, size_t ndigit, char *buf);
#else
/* die richtige Datei einbinden */
#include <stdlib.h>
/* use system function */
#define foo_gcvt gcvt
#endif
/* ,definition'-Teil */
#ifdef USE_OWN_GCVT
char *foo_gcvt(double number, size_t ndigit, char *buf)
{
/* proper definition */
}
/* typische Verwendung */
s = foo_gcvt(n, 15, b);
bsd.port.mk setzen den
Installer-Pfad. Sie sorgen insbesondere dafür, dass
/usr/bin und /bin vor
/usr/local/bin und /usr/X11R6/bin
durchsucht werden.
${NO_SHARED_LIBS} auf YES gesetzt ist (Vorsicht: es
kann nur nach der Einbindung von bsd.port.mk
definiert werden). Wenn deine Portierung ein
GNU-configure benutzt, füge einfach die Zeile
CONFIGURE_ARGS += ${CONFIGURE_SHARED} in das
Makefile ein.
bsd.port.mk zwingend zu benötigen, da die Leute
sowieso ihren Portierungsbaum mitsamt bsd.port.mk
updaten sollten. NEED_VERSION ist von nun an hinfällig.
update-plist, um Paketlisten zu generieren
und zu aktualisieren, anstatt diese Dinge per Hand zu erledigen.
Du kannst die unerwünschten Zeilen auskommentieren.
update-plist kann die meisten Dateitypen alleine
erkennen und die meisten zusätzlichen ,annotations' korrekt
kopieren.
USE_SYSTRACE=Yes in /etc/mk.conf
ein, um fehlfunktionierende Skripte, Makefiles etc. zu
entdecken.
curses.h/libcurses/libtermlib die
,neuen curses'. Ändere:ncurses.h ==> curses.h_USE_OLD_CURSES_ verfügbar
und zwar vor dem Einbinden von curses.h (für
gewöhnlich in einem Makefile) und dem Linken mit
-locurses.
sgtty zur neuen
POSIX-tcgetattr-Familie umgestellt. Vermeide den
alten Stil in neuem Code. Es kann Code geben, der
tcgetattr als Synonym für das ältere
sgtty definiert, aber das ist auf OpenBSD höchstens
eine kurzfristige Methode.
Der xterm-Quelltext ist ein sehr gutes Beispiel,
wie man es nicht machen sollte. Versuche deine
Systemfunktionalität richtig hinzubekommen: Du
willst ja einen Typen, der den Status deines Terminals behält
(möglicher typedef), du willst eine Funktion, die den momentanen
Status herausfindet, und eine Funktion, die den neuen Status
setzt. Funktionen, die diesen Status modifizieren sind
schwieriger als es den Anschein hat, da sie dazu tendieren, von
System zu System unterschiedlich zu sein. Vergiss auch
nicht, dass du Fälle behandeln musst, bei denen du gar nicht an
einem Terminal angeschlossen bist, und in denen du ,signals'
behandeln musst: nicht nur das Beenden, sondern auch
(SIGTSTP) im Hintergrund. Du solltest das Terminal
immer in einem sauberen Zustand belassen. Mach die Tests unter
einer alten Shell, wie etwa sh, die das Terminal nicht gleich in
allen Fällen zurücksetzt, nachdem das Programm beendet wurde.
TERMCAP-Variable zu übersteuern
und sie dadurch zu sauberem Arbeiten zu bringen.
sigaction, um spezifische Semantiken zu
bekommen, zusammen mit anderen Systemaufrufen, die in der
entsprechenden Handbuchseite aufgeführt werden.