Unfortunately, not only are the approaches described above somewhat error prone, they are also not usually very efficient.
The first workaround using strcspn() is conceptually simple, and we might naively assume that the performance of strcspn() would be similar to that of strchr().
In fact, it's not. This is hardly surprising, since the second argument to strcspn() is another string, rather than a single value.
If we discard strcspn() as an almost drop-in replacement for strchrnul(), due to strcspn() not being particularly good for performance, the other obvious workaround is the combination of strchr() and strlen().
This apparently more complicated approach has more potential, especially if the length of the string is already known and we can avoid the call to strlen().
But in reality, the 'C' implementation of strchr() on OpenBSD is still a simple byte by byte comparison.
Potential performance compared with a native 'C' implementation of strchrnul() is further constrained by the very difference between the two functions. Whereas strchrnul() returns the same value, (a pointer to the current search position in the string), regardless of whether it finds the requested character or the NUL terminator, strchr() has two separate conditionals to evaluate, with a different result being returned for each one.
Knowing all this, we can presume that even an unoptimised 'C' implementation of strchrnul() will likely slightly outperform either of the two alternative approaches already mentioned.