Die wichtigste Sache, die du machen solltest, ist mit anderen zu kommunizieren. Frage die anderen Leute auf ports@openbsd.org, ob sie am selben Port 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, den Port 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 einem erfolgreichen Port und einem Port, der 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 den Port aus (submit). Erzeuge einen ,gzipped tarball' des Port-Verzeichnisses. Du kannst diesen entweder auf einen öffentlichen FTP- oder HTTP-Server legen und die Addresse an ports@openbsd.org mailen, oder den Port ,mime encoded' an die selbe Adresse schicken. Wähle einfach eine Methode aus.
/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. Ports, die ein
bestimmtes Boot-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 die Makefile eingefügt wird. Wenn du einen Port von einem
anderen System importierst, stelle sicher, dass du auch ihren
Tag in der 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 gefixed 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 im rsync-Port 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 natürlich die
erforderliche Magie zum Schreiben von Daemonen 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-Port 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-Manualseite 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. Manualseiten 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
zur 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 Manualseite 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.
/* ,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 dein Port ein
GNU-configure benutzt, füge einfach die Zeile
CONFIGURE_ARGS += ${CONFIGURE_SHARED} in die
Makefile ein.
bsd.port.mk zwingend zu benötigen, da die Leute
sowieso ihren Ports-Tree 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 einer 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 Manualseite aufgeführt werden.