General guidelines:
===================
- If there's an upper-case macro that wraps a function, use the macro
if possible. These use macro magic to add safety.
- If there's a *_a() macro that wraps an API, use the macro if
possible. These use countof() to add bounds safety.
- x*() functions wrap a function of the same name without the 'x'.
These wrappers exit on error instead of returning NULL.
They simplify program code. Avoid them in library code.
- strn*() functions are forbidden for use with strings. Consider strn
a mnemonic for [[gnu::nonstring]]. We use them with utmp(5) members
(almost) exclusively.
Don't use some libc functions without Really Good Reasons:
==========================================================
<stdio.h>
asprintf(3)
Use aprintf(3) instead.
It is difficult to handle errors after asprintf(3).
Also, it makes it more difficult for static analyzers to check
that memory is later free(3)d appropriately.
<string.h>
snprintf(3)
Use stprintf() or seprintf() instead.
It is difficult to check for truncation after snprintf(3).
strcmp(3)
Use streq(3) instead.
The return value of strcmp(3) is confusing.
strcmp(3) would be legitimate for sorting strings.
strncmp(3)
Use strneq_a(), or strpfx(), or else,
depending on what you want.
The return value of strncmp(3) is confusing,
and it is unclear the purpose of its use when you read it.
strcasecmp(3)
Use strcaseeq() instead.
strncat(3)
Use strndup(3) or strndupa(3) instead.
strncat(3) is legitimate for catenating a prefix of a string
after an existing string.
strlcpy(3)
Use strtcpy() instead.
strlcpy(3) is vulnerable to DoS.
Also, it is difficult to check for truncation after strlcpy(3).
strlcat(3)
Use strtcat() or stpecpy() instead.
strlcat(3) is vulnerable to DoS.
Also, it is difficult to check for truncation after strlcat(3).
Specific guidelines:
====================
Under lib/string/ we provide a set of functions to manipulate
strings, separated in subdirectories by utility type. In this
section, we provide a broad overview.
ctype/ - Character classification and conversion functions
isascii.h
The functions defined in this file
return true
if the character
belongs to the category specified in the function name.
strchrisascii.h
The functions defined in this file
return true
if the string has any characters that
belong to the category specified in the function name.
strisascii.h
The functions defined in this file
return true
if all of the characters of the string
belong to the category specified in the function name.
The behavior is undefined is the string is an empty string.
strtoascii.h
The functions defined in this file
translate all characters in a string.
memset/ - Memory zeroing
memzero()
Synonym of explicit_bzero(3).
memzero_a()
Like memzero(), but takes an array.
strzero()
Like memzero(), but takes a string.
strchr/ - Character search and counting
strchrcnt()
Count the number of occurrences of a given character in a string.
strchrscnt()
Count the number of occurrences of several characters.
strnul(3)
Return a pointer to the terminating null byte.
strstr/ - String search
s/
stppfx() // Current name: strprefix()
Return a pointer to the end of the prefix,
or NULL if not found.
stpsfx() // Unimplemented
Return a pointer to the beginning of the suffix,
or NULL if not found.
strcmp/ - String comparison
s/
streq(3)
Return true if the strings are equal.
strpfx() // Unimplemented
Return true if the string starts with a prefix.
strsfx() // Unimplemented
Return true if the string ends with a suffix.
strcaseeq()
Like streq(3), but ignore upper-/lower-case.
strcasepfx() // Unimplemented
Like strpfx(), but ignore upper-/lower-case.
strcasesfx() // Unimplemented
Like strsfx(), but ignore upper-/lower-case.
n/
strneq()
Return true if a [[gnu::nonstring]] is equal to a string.
strneq_a()
Like strneq(), but takes an array.
strnpfx() // Unimplemented
Return true if a [[gnu::nonstring]] starts with a prefix.
STRNPFX() // Unimplemented
Like strnpfx(), but takes an array.
strdup/ - Memory duplication
s/
strndupa(3)
Create a new string (in stack) from a [[gnu::nonstring]].
strndupa_a()
Like strndupa(3), but takes an array.
strndup_a()
Like strndup(3), but takes an array.
m/
memdup() // Unimplemented
Duplicate an object. Returns a pointer to the dup.
memdup_T()
Like memdup(), but with type-safety checks.
strcpy/ - String copying
n/
strncpy_a()
Like strncpy(3), but takes an array.
Use it *exclusively* for copying from a string into a utmp(5)
member.
strncpytail()
Like strncpy(), but when truncating, the tail of the string is
kept instead of the beginning. This is useful for ut_id.
STRNCPYTAIL()
Like strncpytail, but takes an array.
strncat_a() // To be removed
Do NOT use. I'll remove it soon.
s/
strtcpy()
Copy from a string into another string with truncation.
This is what the Linux kernel calls strscpy().
If you need more than one call to form a string,
use stpecpy() instead.
strtcpy_a()
Like strtcpy(), but takes an array.
strtcat() // Unimplemented
Catenate a string after an existing string, with truncation.
Rarely useful. Consider using stpecpy() instead.
STRTCAT() // Unimplemented
Like strtcat(), but takes an array.
stpecpy()
Similar to strtcpy(), but takes a pointer to the end instead of
a size. This makes it safer for chaining several calls.
m/
MEMCPY()
Like memcpy(3), but takes two arrays.
sprintf/ - Formatted string creation
aprintf(3)
sprintf(3) variant that allocates.
It has better interface than asprintf(3).
stprintf()
snprintf(3) wrapper that reports truncation with -1.
If you need more than one call to form a string,
use seprintf() instead.
If the size is 0, the behavior is undefined; currently, we
abort(3).
stprintf_a()
Like stprintf(), but takes an array.
seprintf()
Similar to stprintf(), but takes a pointer to the end instead of
a size. This makes it safer for chaining several calls.
strspn/ - String span searching
Naming conventions:
- 'r': rear (search from the end).
- 'c': complement (negate the second argument).
- 'stp': return a pointer instead of a length.
stpspn()
Like strspn(3), but return a pointer instead of an offset.
It is useful for skipping leading white space.
strrspn_()
Return the length of a trailing span consisting only of
characters in 'accept'.
It is useful for determining if a string ends with characters
in "accept".
stprspn()
Like strrspn(), but return a pointer instead of a length.
It is useful for removing trailing white space.
strrcspn()
Use stprcspn() instead.
Return the length of a trailing span consisting only of
characters not in 'reject'.
It is useful for determining if a string ends with characters
not in "reject".
stprcspn()
Like strrcspn(), but return a pointer instead of a length.
This is rarely useful. It was useful for implementing
basename().
strsep/ - String separation
stpsep()
Similar to strsep(3), but swap the input pointer with the return
value. It writes a null byte at the first delimiter found, and
returns a pointer to one past that null byte. If no delimiters
are found, it returns NULL.
It is very useful after fgets(3), for removing the '\n', while
checking for its presence. In some cases, it's also useful as
a replacement for strsep(3) with a more convenient calling
convention, but this depends on the surrounding code.
strsep2arr()
Loop around strsep(3) to fill an array of buffers with all
the delimited strings that have been split.
Useful when the number of delimiter-separated fields is known.
strsep2arr_a()
Like strsep2arr(), but take an array, and simplify error checks.
strsep2ls()
Similar to strsep2arr(), but terminate the list with a null
pointer.
Useful when the number of delimiter-separated fields is unknown.
strsep2ls_a()
Like strsep2ls(), but take an array.
astrsep2ls()
Variant of strsep2ls() that allocates the array of strings.
(But the strings themselves are not duplicated.)
strftime.h
strftime_a()
Like strftime(3), but takes an array.