Hi Alex, Alejandro Colomar (man-pages) wrote on Sun, Mar 20, 2022 at 09:34:47PM +0100: > I have ready some code to extract source code from EXAMPLES in man-pages. Frankly, i don't see the point at all. Manual Pages are not HOWTO documents that mindless users are supposed to copy from verbatim without understanding what they see. Instead, the are supposed to be read with your brain switched on and the reader is supposed to *apply* what they learnt, not copy it. > .\" SRC BEGIN (program_name.c) Ugly as hell. I would very strongly object to have anything like that added to any manual pages i maintain. When people add comments in order to convey syntax and semantics to a machine, that is a sure sign that the design of whatever it is intended to achieve was totally botched. > The next step will be to add targets to lint and compile the produced > files, to check their correctness. If any code snippet from an EXAMPLES section does compile, i would argue that it is severely ill-designed as it obviously contains lots of needless fluff that distracts from the point the example is actually trying to demonstrate. It ought to be stripped down to what really matters, to become shorter, more readable, and more to the point. Here are a few EXAMPLES sections (in formatted form for readability) that demonstate how EXAMPLES sections should look like: EXAMPLES /* from chroot(2) */ The following example changes the root directory to newroot, sets the current directory to the new root, and drops some setuid privileges. There may be other privileges which need to be dropped as well. #include <err.h> #include <unistd.h> if (chroot(newroot) != 0 || chdir("/") != 0) err(1, "%s", newroot); setresuid(getuid(), getuid(), getuid()); EXAMPLES /* from write(2) */ A typical loop allowing partial writes looks like this: const char *buf; size_t bsz, off; ssize_t nw; int d; for (off = 0; off < bsz; off += nw) if ((nw = write(d, buf + off, bsz - off)) == 0 || nw == -1) err(1, "write"); EXAMPLES /* from BIO_s_fd(3) */ This is a file descriptor BIO version of "Hello World": BIO *out; out = BIO_new_fd(fileno(stdout), BIO_NOCLOSE); BIO_printf(out, "Hello World\n"); BIO_free(out); EXAMPLES /* from MB_CUR_MAX(3) */ Size a buffer in a portable way to hold one single multibyte character: char buf[MB_LEN_MAX]; wchar_t wchar; /* input value */ if (wctomb(buf, wchar) == -1) /* error */ Switch between code handling the ascii(7) and UTF-8 character encodings in an OpenBSD-specific way (not portable): if (MB_CUR_MAX == 1) { /* Code to handle ASCII-encoded single-byte strings. */ } else { /* Code to handle UTF-8-encoded multibyte strings. */ } EXAMPLES /* from malloc(3) */ If malloc() must be used with multiplication, be sure to test for overflow: size_t num, size; ... /* Check for size_t overflow */ if (size && num > SIZE_MAX / size) errc(1, EOVERFLOW, "overflow"); if ((p = malloc(num * size)) == NULL) err(1, NULL); The above test is not sufficient in all cases. For example, multiplying ints requires a different set of checks: int num, size; ... /* Avoid invalid requests */ if (size < 0 || num < 0) errc(1, EOVERFLOW, "overflow"); /* Check for signed int overflow */ if (size && num > INT_MAX / size) errc(1, EOVERFLOW, "overflow"); if ((p = malloc(num * size)) == NULL) err(1, NULL); Assuming the implementation checks for integer overflow as OpenBSD does, it is much easier to use calloc(), reallocarray(), or recallocarray(). The above examples could be simplified to: if ((p = reallocarray(NULL, num, size)) == NULL) err(1, NULL); or at the cost of initialization: if ((p = calloc(num, size)) == NULL) err(1, NULL); Yours, Ingo