Najważniejszą rzeczą do zrobienia jest komunikacja. Zapytaj ludzi na ports@openbsd.org, czy ktoś nie pracuje już nad tym portem. Poinformuj o tym oryginalnego autora, włączając informacje, o problemach, które mogłeś znaleźć. Jeśli informacja o licencji wydaje się niewłaściwa, powiedz mu o tym. Jeśli musiałeś pokonywać złożone problemy, aby zbudować port, powiedz mu, co może poprawić. Jeśli są zainteresowani jedynie programowaniem na Linuksa i nie interesują się resztą świata Uniksa, postaraj się zmienić ich zdanie.
KOMUNIKACJA odróżnia udany port, od portu, który będzie wkrótce porzucony przez wszystkich.
Przede wszystkim, zapoznaj się z informacjami na temat portowania na tej stronie. Następnie zobacz dokumenty nawiązujące do tego tematu, zwłaszcza Listę rzeczy do sprawdzenia podczas portowania na OpenBSD.
Testuj, ponownie testuj, i jeszcze raz testuj!
Obecnie OpenBSD w pełni wspiera aktualizacje. Oznacza to, że kilka spraw musi zostać wykonanych w koncie.
Przedstaw port. Stwórz paczkę "gzipped tarball" katalogu portu. Możesz wtedy umieścić go na publicznym serwerze FTP lub HTTP, wysyłając adres paczki na ports@openbsd.org lub wysyłając ją w załączniku na ten sam adres. Wybierz metode, która Ci najbardziej odpowiada.
/usr/local/etc/rc.d./usr/local jest często współdzielone przez kilka maszyn
poprzez NFS. Z tego powodu, pliki konfiguracyjne, które są specyficzne
dla danej maszyny nie mogą być przechowywane w /usr/local,
/etc jest centralnym repozytorium zależnych od indywidualnej
maszyny plików konfiguracyjnych. Ponadto, zgodnie z polityką OpenBSD,
pliki w /etc nie są nigdy uaktualniane automatycznie.
Porty, które wymagają jakichś specyficznych ustawień do odpalenia
powinny uprzedzić o tym administratora, aby wykonał je samodzielnie,
zamiast ślepo instalować pliki.
-lcrypt.libc.
/usr/ports/infrastructure/db/user.list.
$OpenBSD$ do
Makefile. Jeśli importujesz port z innego systemu, upewnij się o
pozostawieniu także ich taga w Makefile.
strcat/strcpy/strcmp/sprintf.
Ogólnie, sprintf powinno być zastąpione przez
snprintf.
/tmp na
symboliczne dowiązania dla bardziej znaczących plików, takich jak
/etc/master.passwd.
fopen i freopen
tworzą nowy plik lub otwierają już istniejący do
zapisu. Atakujący może utworzyć symboliczne dowiązanie z
/etc/master.passwd do /tmp/addrpool_dump. W
momencie, gdy go otworzysz, twój plik z hasłami jest wydany. Tak, nawet
mimo unlink tuż przed operacją. Zmniejsza to jedynie nieco
szanse. Używaj zamiast tego open z flagą
O_CREAT|O_EXCL i fdopen.
mktemp.
Zwróć uwagę na ostrzeżenia konsolidatora (linker) bsd, na temat jej
użycia. Musi to być naprawione.
Nie jest to kwestia jedynie s/mktemp/mkstemp/g. mktemp(3).
Popraw kod używając mkstemp, dotyczy to źródeł między innymi
ed czy mail.
Rzadkim wypadkiem jest kod prawidłowo korzystający z mktemp;
można spotkać się z tym w porcie rsync.
startx.
Jako program uprzywilejowany (setuid), mógłbyś wywołać startx z jakimkolwiek
plikiem, jako skryptem. Jeśli plik ten nie był poprawnym plikiem skryptu
powłoki, wypisany zostałby komunikat o błędzie składni razem z pierwszą
linią niepoprawnego pliku i bez jakichkolwiek dalszych sprawdzeń uprawnień.
Dość poręczne, aby pobrać pierwszą linie zaszyfrowanego pliku haseł,
a który często zaczyna się od wpisu dla użytkownika root. Nie otwieraj
swojego pliku, a następnie używaj fstat na otwartym
deskryptorze, aby sprawdzić, czy rzeczywiście powinieneś być zdolnym
do jego otwarcia (albo atakujący przy pomocy /dev/rst0 przewinie go)
-- otwieraj go tylko dla właściwych uid/gid/zestawów grup.
popen i system. Używaj zamiast tego
fork, pipe i execve.
/dev/fd/0.
inetd
i po prostu dodać odpowiednie wpisy w inetd.conf.
Musisz znać sztukę pisania demonów (daemons), aby to osiągnąć w inny
sposób. Można powiedzieć, że nie powinieneś pisać programów
uprzywilejowanych (setuid), jeśli nie wiesz jak to robić.
xkobo dla przykładu takiej zmiany.
PATH (nigdy nie używaj
system z nie pełną ścieżką, unikaj execvp),
ale i bardziej subtelnych rzeczy jak twoje locale, timezone, termcap,
i tak dalej.
Wystrzegaj się pośredniości: nawet, jeśli rozważasz wszystkie założenia,
programy wywoływane bezpośrednio nie muszą tego koniecznie wymagać.
Nigdy nie używaj funkcji system w
uprzywilejowanych programach, zbuduj swoją linię poleceń, kontrolowane
środowisko pracy, i wywołaj bezpośrednio execve.
Strona podręcznika man perlsec jest dobrym przewodnikiem
na temat takich problemów.
issetugid w OpenBSD. Nie próbuj przenosić (to
port) bibliotek, jeśli nie rozumiesz całkowicie natury problemu.
__OpenBSD__ powinno być używane oszczędnie, jeśli w ogóle.
Konstrukcje, które wyglądają jak ta
#if defined(__NetBSD__) || defined(__FreeBSD__)
są często niewłaściwe. Nie dodawaj na ślepo __OpenBSD__
do nich. Zamiast tego, postaraj się zrozumieć co się dzieje i jaka właściwie
funkcja jest wymagana. Strony podręcznika man są często pomocne,
ponieważ zawierają wiele historycznych komentarzy, łącznie z informacją,
kiedy konkretna funkcja została wprowadzona w BSD.
Porównywanie numerycznej wartości BSD ze znanymi
wydaniami jest często właściwą drogą. Zobacz
przewodnik do NetBSD pkgsrc
w celu uzyskania większej ilości informacji.
BSD jest złym pomysłem. Postaraj się dołączyć sys/param.h.
Definiuje on nie tylko BSD, ale i nadaje mu właściwą wartość.
Właściwy fragment kody powinien powinien wyglądać jak:
#if (defined(__unix__) || defined(unix)) && !defined(USG)
#include <sys/param.h>
#endif
tcgetattr
po prostu działa, bez rozróżnienia, czy jest ona wywoływana na BSD 4.3
lub późniejszym, czy SystemVR4. Tego typu testy wprowadzają tylko
wątpliwości. Właściwą drogą jest natomiast sprawdzanie, czy konkretny
system definiuje HAVE_TCGETATTR, a następnie przejście do
następnego systemu. Technika ta oddziela testowanie funkcji dla
specyficznego systemu operacyjnego. W pośpiechu, inna osoba portująca
może po prostu dodać cały zestaw definicji -DHAVE_XXX do
pliku Makefile. Można także napisać lub dodać skrypt "configure", aby
sprawdzać tą funkcje i dodawać ją automatycznie. Jako negatywny przykład
przeglądnij źródła nethack 3.2.2: zakłada się tam ładowanie rzeczy na
podstawie typu systemu operacyjnego. Większość tych założeń jest
przestarzała i nie odzwierciedla rzeczywistości: funkcje POSIX są
bardziej przydatne niż stare BSD vs. SystemV rozróżnienia, albowiem
obecnie niektóre tradycyjne funkcje bsd są wspierane jedynie poprzez
biblioteki kompatybilności.
#define POSIX_C_SOURCE
w całym projekcie, a nie kiedy ci się podoba.
unistd.h, fcntl.h lub
termios.h.
Odpowiednia strona podręcznika systemowego man określa, gdzie dany
prototyp może być odnaleziony.
Możesz potrzebować kolejnych makr HAVE_XXX, aby otrzymać
właściwy plik. Nie martw się włączaniem tego samego pliku dwukrotnie,
pliki nagłówkowe mają blokady zapobiegające takim wypadkom.unsigned long zamiast size_t), lub mają
jakiś zły status const. Poza tym, niektóre kompilatory,
jak własne gcc OpenBSD, mogą znacznie lepiej wykonywać swoją prace
na wielu często spotykanych funkcjach, jak np strlen,
jeśli załączysz odpowiednie pliki nagłówkowe.
/* czesc prototypowa */
#ifdef USE_OWN_GCVT
char *foo_gcvt(double number, size_t ndigit, char *buf);
#else
/* zalacz odpowiedni plik */
#include <stdlib.h>
/* uzyj funkcji systemowej */
#define foo_gcvt gcvt
#endif
/* czesc definiujaca */
#ifdef USE_OWN_GCVT
char *foo_gcvt(double number, size_t ndigit, char *buf)
{
/* wlasciwa definicja */
}
/* typowe uzycie */
s = foo_gcvt(n, 15, b);
bsd.port.mk ustalają ścieżki (path) instalacji.
Zwłaszcza ustalają, że /usr/bin i
/bin są przeszukiwane przed
/usr/local/bin i /usr/X11R6/bin.
${NO_SHARED_LIBS} ma wartość 'yes' (uwaga, może to być
zdefiniowane jedynie po załączeniu bsd.port.mk). Jeśli
twój port ma GNU configure, po prostu dodaj linie
CONFIGURE_ARGS += ${CONFIGURE_SHARED} do pliku Makefile.
bsd.port.mk, albowiem użytkownicy powinni uaktualniać
całe swoje drzewo portów, włączając bsd.port.mk.
NEED_VERSION jest obecnie przeżytkiem.
update-plist przy generacji i aktualizacji list
zawartości paczki zamiast wykonywać te czynności ręcznie.
Możesz zakomentować niechciane linie.
update-plist potrafi wykryć większość typów plików oraz dołączyć
dodatkowe wpisy poprawnie.
USE_SYSTRACE=Yes na końcu /etc/mk.conf aby
bezpośrednio zmienić zachowanie skryptów, plików makefiles, itp.
curses.h/libcurses/libtermlib są
``nowym curses''. Zmień:ncurses.h ==> curses.h_USE_OLD_CURSES_
przed załączeniem curses.h (zwykle w pliku Makefile) oraz
konsolidowaniu (linking) z -locurses.
sgtty do nowszej (POSIX) rodziny tcgetattr.
Unikaj starego stylu w nowym kodzie. Część kodów może definiować
tcgetattr jako synonim starszego sgtty,
lecz jest to w najlepszym wypadku prowizorka na OpenBSD.
Kod źródłowy xterm jest dobrym przykładem, czego nie należy
robić. Postaraj się uzyskać funkcjonalność systemu poprawnie: chcesz
typu, który zapamiętuje stan twojego terminala (dopuszczalne typedef),
chcesz funkcji, która przywraca zapamiętany stan, oraz funkcje,
która ustawia nowy stan.
Funkcje, które modyfikują ten stan są trudniejsze, albowiem mają
skłonność do zróżnicowania w zależności od systemu. Poza tym, nie
zapominaj, że będziesz musiał poradzić sobie z przypadkami, kiedy
nie jesteś podłączony do terminala, oraz o przechwytywaniu sygnałów
(to handle signals): nie tylko zakończenia, ale także przejścia
w tło (SIGTSTP). Powinieneś zawsze przywracać terminal
do pierwotnego stanu. Przeprowadź testy na starej powłoce,
jak sh, która nie resetuje w żaden sposób terminala po zakończeniu
pracy programu.
TERMCAP i uzyskać pożądane działanie.
sigaction aby zapewnić specyficzną
sematykę, razem z pozostałymi wywołaniami systemowymi (system calls)
opisanymi w odpowiednich stronach podręcznika man.