+ negative, do not use "int", but use "unsigned".
+
+- Use "char" only for actual characters. Use "uint8_t" or "int8_t"
+ when you actually mean a byte-sized signed or unsigned
+ integers. When referring to a generic byte, we generally prefer the
+ unsigned variant "uint8_t". Do not use types based on "short". They
+ *never* make sense. Use ints, longs, long longs, all in
+ unsigned+signed fashion, and the fixed size types
+ uint8_t/uint16_t/uint32_t/uint64_t/int8_t/int16_t/int32_t and so on,
+ as well as size_t, but nothing else. Do not use kernel types like
+ u32 and so on, leave that to the kernel.
+
+- Public API calls (i.e. functions exported by our shared libraries)
+ must be marked "_public_" and need to be prefixed with "sd_". No
+ other functions should be prefixed like that.
+
+- In public API calls, you *must* validate all your input arguments for
+ programming error with assert_return() and return a sensible return
+ code. In all other calls, it is recommended to check for programming
+ errors with a more brutal assert(). We are more forgiving to public
+ users then for ourselves! Note that assert() and assert_return()
+ really only should be used for detecting programming errors, not for
+ runtime errors. assert() and assert_return() by usage of _likely_()
+ inform the compiler that he should not expect these checks to fail,
+ and they inform fellow programmers about the expected validity and
+ range of parameters.
+
+- Never use strtol(), atoi() and similar calls. Use safe_atoli(),
+ safe_atou32() and suchlike instead. They are much nicer to use in
+ most cases and correctly check for parsing errors.
+
+- For every function you add, think about whether it is a "logging"
+ function or a "non-logging" function. "Logging" functions do logging
+ on their own, "non-logging" function never log on their own and
+ expect their callers to log. All functions in "library" code,
+ i.e. in src/shared/ and suchlike must be "non-logging". Every time a
+ "logging" function calls a "non-logging" function, it should log
+ about the resulting errors. If a "logging" function calls another
+ "logging" function, then it should not generate log messages, so
+ that log messages are not generated twice for the same errors.
+
+- Avoid static variables, except for caches and very few other
+ cases. Think about thread-safety! While most of our code is never
+ used in threaded environments, at least the library code should make
+ sure it works correctly in them. Instead of doing a lot of locking
+ for that, we tend to prefer using TLS to do per-thread caching (which
+ only works for small, fixed-size cache objects), or we disable
+ caching for any thread that is not the main thread. Use
+ is_main_thread() to detect whether the calling thread is the main
+ thread.
+
+- Command line option parsing:
+ - Do not print full help() on error, be specific about the error.
+ - Do not print messages to stdout on error.
+ - Do not POSIX_ME_HARDER unless necessary, i.e. avoid "+" in option string.
+
+- Do not write functions that clobber call-by-reference variables on
+ failure. Use temporary variables for these cases and change the
+ passed in variables only on success.
+
+- When you allocate a file descriptor, it should be made O_CLOEXEC
+ right from the beginning, as none of our files should leak to forked
+ binaries by default. Hence, whenever you open a file, O_CLOEXEC must
+ be specified, right from the beginning. This also applies to
+ sockets. Effectively this means that all invocations to:
+
+ a) open() must get O_CLOEXEC passed
+ b) socket() and socketpair() must get SOCK_CLOEXEC passed
+ c) recvmsg() must get MSG_CMSG_CLOEXEC set
+ d) F_DUPFD_CLOEXEC should be used instead of F_DUPFD, and so on
+
+- We never use the POSIX version of basename() (which glibc defines it in
+ libgen.h), only the GNU version (which glibc defines in string.h).
+ The only reason to include libgen.h is because dirname()
+ is needed. Everytime you need that please immediately undefine
+ basename(), and add a comment about it, so that no code ever ends up
+ using the POSIX version!
+
+- Use the bool type for booleans, not integers. One exception: in public
+ headers (i.e those in src/systemd/sd-*.h) use integers after all, as "bool"
+ is C99 and in our public APIs we try to stick to C89 (with a few extension).
+
+- When you invoke certain calls like unlink(), or mkdir_p() and you
+ know it is safe to ignore the error it might return (because a later
+ call would detect the failure anyway, or because the error is in an
+ error path and you thus couldn't do anything about it anyway), then
+ make this clear by casting the invocation explicitly to (void). Code
+ checks like Coverity understand that, and will not complain about
+ ignored error codes. Hence, please use this:
+
+ (void) unlink("/foo/bar/baz");
+
+ instead of just this:
+
+ unlink("/foo/bar/baz");
+
+- Don't invoke exit(), ever. It is not replacement for proper error
+ handling. Please escalate errors up your call chain, and use normal
+ "return" to exit from the main function of a process. If you
+ fork()ed off a child process, please use _exit() instead of exit(),
+ so that the exit handlers are not run.
+
+- Please never use dup(). Use fcntl(fd, F_DUPFD_CLOEXEC, 3)
+ instead. For two reason: first, you want O_CLOEXEC set on the new fd
+ (see above). Second, dup() will happily duplicate your fd as 0, 1,
+ 2, i.e. stdin, stdout, stderr, should those fds be closed. Given the
+ special semantics of those fds, it's probably a good idea to avoid
+ them. F_DUPFD_CLOEXEC with "3" as parameter avoids them.
+
+- When you define a destructor or unref() call for an object, please
+ accept a NULL object and simply treat this as NOP. This is similar
+ to how libc free() works, which accepts NULL pointers and becomes a
+ NOP for them. By following this scheme a lot of if checks can be
+ removed before invoking your destructor, which makes the code
+ substantially more readable and robust.
+
+- Related to this: when you define a destructor or unref() call for an
+ object, please make it return the same type it takes and always
+ return NULL from it. This allows writing code like this:
+
+ p = foobar_unref(p);
+
+ which will always work regardless if p is initialized or not, and
+ guarantees that p is NULL afterwards, all in just one line.
+
+- Use alloca(), but never forget that it is not OK to invoke alloca()
+ within a loop or within function call parameters. alloca() memory is
+ released at the end of a function, and not at the end of a {}
+ block. Thus, if you invoke it in a loop, you keep increasing the
+ stack pointer without ever releasing memory again. (VLAs have better
+ behaviour in this case, so consider using them as an alternative.)
+ Regarding not using alloca() within function parameters, see the
+ BUGS section of the alloca(3) man page.
+
+- Use memzero() or even better zero() instead of memset(..., 0, ...)
+
+- Instead of using memzero()/memset() to initialize structs allocated
+ on the stack, please try to use c99 structure initializers. It's
+ short, prettier and actually even faster at execution. Hence:
+
+ struct foobar t = {
+ .foo = 7,
+ .bar = "bazz",
+ };
+
+ instead of:
+
+ struct foobar t;
+ zero(t);
+ t.foo = 7;
+ t.bar = "bazz";
+
+- When returning a return code from main(), please preferably use
+ EXIT_FAILURE and EXIT_SUCCESS as defined by libc.
+
+- The order in which header files are included doesn't matter too
+ much. systemd-internal headers must not rely on an include order, so
+ it is safe to include them in any order possible.
+ However, to not clutter global includes, and to make sure internal
+ definitions will not affect global headers, please always include the
+ headers of external components first (these are all headers enclosed
+ in <>), followed by our own exported headers (usually everything
+ that's prefixed by "sd-"), and then followed by internal headers.
+ Furthermore, in all three groups, order all includes alphabetically
+ so duplicate includes can easily be detected.
+
+- To implement an endless loop, use "for (;;)" rather than "while
+ (1)". The latter is a bit ugly anyway, since you probably really
+ meant "while (true)"... To avoid the discussion what the right
+ always-true expression for an infinite while() loop is our
+ recommendation is to simply write it without any such expression by
+ using "for (;;)".
+
+- Never use the "off_t" type, and particularly avoid it in public
+ APIs. It's really weirdly defined, as it usually is 64bit and we
+ don't support it any other way, but it could in theory also be
+ 32bit. Which one it is depends on a compiler switch chosen by the
+ compiled program, which hence corrupts APIs using it unless they can
+ also follow the program's choice. Moreover, in systemd we should
+ parse values the same way on all architectures and cannot expose
+ off_t values over D-Bus. To avoid any confusion regarding conversion
+ and ABIs, always use simply uint64_t directly.
+
+- Commit message subject lines should be prefixed with an appropriate
+ component name of some kind. For example "journal: ", "nspawn: " and
+ so on.
+
+- Do not use "Signed-Off-By:" in your commit messages. That's a kernel
+ thing we don't do in the systemd project.
+
+- Avoid leaving long-running child processes around, i.e. fork()s that
+ are not followed quickly by an execv() in the child. Resource
+ management is unclear in this case, and memory CoW will result in
+ unexpected penalties in the parent much much later on.
+
+- Don't block execution for arbitrary amounts of time using usleep()
+ or a similar call, unless you really know what you do. Just "giving
+ something some time", or so is a lazy excuse. Always wait for the
+ proper event, instead of doing time-based poll loops.
+
+- To determine the length of a constant string "foo", don't bother
+ with sizeof("foo")-1, please use strlen("foo") directly. gcc knows
+ strlen() anyway and turns it into a constant expression if possible.
+
+- If you want to concatenate two or more strings, consider using
+ strjoin() rather than asprintf(), as the latter is a lot
+ slower. This matters particularly in inner loops.
+
+- Please avoid using global variables as much as you can. And if you
+ do use them make sure they are static at least, instead of
+ exported. Especially in library-like code it is important to avoid
+ global variables. Why are global variables bad? They usually hinder
+ generic reusability of code (since they break in threaded programs,
+ and usually would require locking there), and as the code using them
+ has side-effects make programs intransparent. That said, there are
+ many cases where they explicitly make a lot of sense, and are OK to
+ use. For example, the log level and target in log.c is stored in a
+ global variable, and that's OK and probably expected by most. Also
+ in many cases we cache data in global variables. If you add more
+ caches like this, please be careful however, and think about
+ threading. Only use static variables if you are sure that
+ thread-safety doesn't matter in your case. Alternatively consider
+ using TLS, which is pretty easy to use with gcc's "thread_local"
+ concept. It's also OK to store data that is inherently global in
+ global variables, for example data parsed from command lines, see
+ below.
+
+- If you parse a command line, and want to store the parsed parameters
+ in global variables, please consider prefixing their names with
+ "arg_". We have been following this naming rule in most of our
+ tools, and we should continue to do so, as it makes it easy to
+ identify command line parameter variables, and makes it clear why it
+ is OK that they are global variables.