The most important thing to do is to communicate. Ask people on ports@openbsd.org if they are working on the same port. Tell the original software author about it, including problems you may find. If licensing information appears incorrect tell him. If you had to jump through loops to make the port build, tell him what he can fix. If they are only developing on Linux and feel like ignoring the rest of the Unix world, try to make them change their view.
COMMUNICATION makes the difference between a successful port and a port that will slowly be abandoned by everyone.
First look at the porting information on this page. Then check out the referenced documents, especially the OpenBSD porting checklist.
Test, then re-test, and finally test again!
OpenBSD now fully supports updates. This means that quite a few issues must be taken into account.
Submit the port. Create a gzipped tarball of the port directory. You can then either place it on a public FTP or HTTP server, sending its address to ports@openbsd.org or send the port mime encoded to the same address. Pick whichever method works best for you.
Porting some new software takes time. Maintaining it over time is harder. It is quite okay to port software, and let other people handle it afterwards. It is also okay to help other people update and maintain other ports, as long as you communicate to avoid doing the same things twice.
In the OpenBSD culture, MAINTAINERship is not a status item,
but a responsibility. We have CVS and comments to give credit to the
person who did the work. A port MAINTAINER is something else:
a person who assumes responsibility for the working of the port, and is
willing to spend some time ensuring it works as best as can be.
/usr/local/etc/rc.d./usr/local is often shared between several machines
thanks to NFS. For this reason, configuration files that are specific
to a given machine can't be stored under /usr/local,
/etc is the central repository for per machine
configuration files. Moreover, OpenBSD policy is to never update
files under /etc automatically. Ports that need some
specific boot setup should advise the administrator about what to do
instead of blindly installing files.
-lcrypt.libc.
/usr/ports/infrastructure/db/user.list for details.
$OpenBSD$ CVS tag to
the Makefile. If importing a port from another system be sure to
leave their tag in the Makefile, too.
strcat/strcpy/strcmp/sprintf. In general,
sprintf should be replaced with snprintf.
/tmp with symbolic links to more strategic files, such as
/etc/master.passwd.
fopen and freopen
create a new file or open an existing file for
writing. An attacker may create a symbolic link from
/etc/master.passwd to /tmp/addrpool_dump. The
instant you open it, your password file is hosed. Yes, even with
an unlink right before. You only narrow the window
of opportunity. Use open with
O_CREAT|O_EXCL and fdopen instead.
mktemp
function. Heed the warnings of the bsd linker about its uses.
These must be fixed.
This is not quite as simple as s/mktemp/mkstemp/g. mktemp(3) for more information.
Correct code using mkstemp includes the source to
ed or mail.
A rare instance of code that uses mktemp correctly
can be found in the rsync port.
startx problem. As a setuid program,
you could launch startx with any file as a script. If the file was not
a valid shell script, a syntax error message would follow, along with the
first line of the offending file, without any further permission check.
Pretty handy to grab the first line of a shadow passwd file, considering
these often start with root entry. Do not open your file, and then do
an fstat on the open descriptor to check if you should have
been able to open it (or the attacker will play with /dev/rst0 and rewind
your tape) -- open it with the correct uid/gid/grouplist set.
popen and
system.
Use fork, pipe and execve instead.
/dev/fd/0.
inetd
control and just add the relevant entries to inetd.conf.
You must know the appropriate magic for writing daemons to achieve that.
It could be argued that you have no business writing setuid programs
if you don't know how to do that.
xkobo port for an instance of such a change.
PATH (never use system with an
unqualified name, avoid execvp), but also more subtle
items such as your locale, timezone, termcap, and so on.
Be aware of transitivity: even though you're taking full precautions,
programs you call directly won't necessarily. Never
use system in privileged programs, build your command
line, a controlled environment, and call execve directly.
The perlsec man page is a good tutorial on such problems.
issetugid addresses this problem, from the
library writer point of view. Don't try to port libraries unless you
understand this issue thoroughly.
__OpenBSD__ should be used sparingly, if at all.
Constructs that look like
#if defined(__NetBSD__) || defined(__FreeBSD__)
are often inappropriate. Don't add blindly __OpenBSD__
to it. Instead, try to figure out what's going on, and what actual
feature is needed. Manual pages are often useful, as they include
historic comments, stating when a particular feature was incorporated
into BSD. Checking the numeric value of BSD against known
releases is often the right way. See
The NetBSD pkgsrc guide
for more information.
BSD is a bad idea. Try to include sys/param.h.
This not only defines BSD, it also gives it a proper value.
The right code fragment should look like:
#if (defined(__unix__) || defined(unix)) && !defined(USG)
#include <sys/param.h>
#endif
tcgetattr works than whether
you're running under BSD 4.3 or later, or SystemVR4. These kind of
tests just confuse the issue. The way to go about it is, for instance,
to test for one particular system, set up a slew of
HAVE_TCGETATTR defines, then proceed to the next system.
This technique separates features tests from specific OSes.
In a hurry, another porter can just add the whole set of
-DHAVE_XXX defines to the Makefile. One may also write
or add to a configure script to check for that feature and add it
automatically. As an example not to follow, check nethack 3.2.2
source: it assumes loads of things based on the system type. Most
of these assumptions are obsolete and no longer reflect reality:
POSIX functions are more useful than older BSD versus SystemV
differences, to the point that some traditional bsd functions are
now only supported through compatibility libraries.
#define POSIX_C_SOURCE
throughout the whole project, not when you feel like it.
unistd.h, fcntl.h or
termios.h.
The man page frequently states where the prototype can be found.
You might need another slew of HAVE_XXX macros to
procure the right file. Don't worry about including the same file
twice, include files have guards that prevent all kinds of nastiness.unsigned long instead of
size_t), or get some const status wrong.
Also, some compilers, such as OpenBSD's own gcc,
are able to do a better job with some very frequent functions such as
strlen if you include the right header file.
/* prototype part */
#ifdef USE_OWN_GCVT
char *foo_gcvt(double number, size_t ndigit, char *buf);
#else
/* include correct file */
#include <stdlib.h>
/* use system function */
#define foo_gcvt gcvt
#endif
/* definition part */
#ifdef USE_OWN_GCVT
char *foo_gcvt(double number, size_t ndigit, char *buf)
{
/* proper definition */
}
/* typical use */
s = foo_gcvt(n, 15, b);
bsd.port.mk set the installers
path. Specifically, they set /usr/bin and
/bin to be searched before
/usr/local/bin and /usr/X11R6/bin.
${NO_SHARED_LIBS} is set to yes (beware, it can be defined
only after inclusion of bsd.port.mk). If your port has
a GNU configure simply add the line
CONFIGURE_ARGS += ${CONFIGURE_SHARED} to the Makefile.
bsd.port.mk, as people are supposed to update their
whole ports tree, including bsd.port.mk.
NEED_VERSION is now obsolete.
update-plist to generate and update
packing-lists instead of doing things manually.
You can comment unwanted lines out.
update-plist can detect most file types and copy most
extra annotations correctly.
USE_SYSTRACE=Yes to /etc/mk.conf to
detect misbehaving scripts, makefiles, etc.
curses.h/libcurses/libtermlib are the
``new curses''. Change:ncurses.h ==> curses.h_USE_OLD_CURSES_
before including curses.h (usually in a Makefile) and
linking with -locurses.
sgtty to the newer POSIX tcgetattr family.
Avoid the older style in new code. Some code may define
tcgetattr to be a synonym for the older
sgtty, but this is at best a stopgap measure on OpenBSD.
The xterm source code is a very good example of
what not to do. Try to get your system functionality right: you
want a type that remembers the state of your terminal
(possible typedef), you want a function that extracts the current
state, and a function that sets the new state.
Functions that modify this state are more difficult, as they tend
to vary depending upon the system. Also, don't forget that you will
have to handle cases where you are not connected to a terminal,
and that you need to handle signals: not only termination, but
also background (SIGTSTP). You should always leave
the terminal in a sane state. Do your tests under an older shell,
such as sh, which does not reset the terminal in any way at
program's termination.
TERMCAP variable and get it to work properly.
sigaction to ensure a specific semantics, along
with other system calls referenced in the corresponding manpage.