[Toybox] FreeBSD porting, removing bashisms

Rob Landley rob at landley.net
Tue Mar 29 22:21:16 PDT 2016


On 03/29/2016 07:37 PM, Ed Maste wrote:
> On 29 March 2016 at 23:54, Rob Landley <rob at landley.net> wrote:
>>
>> There are also a number of places where we know what the Linux
>> information is, and use that. For example, in ifconfig:
>>
>>       // Is this an SIOCSI entry?
>>       if ((off|0xff) == 0x89ff) {
> 
> Yes, I suspect tools like ifconfig and ps would need completely
> separate implementations for non-Linux systems, but I believe many of
> the will have no portability troubles. At first I'd be happy to just
> avoid building the Linux-specific ones.

I expect at least a third, probably more like half of the commands will
have some sort of profound linuxism. (Just _glancing_ I see acpi, chcon,
eject, fallocate, fsfreeze, hwclock, insmod, losetup, lsattr, lspci,
lsusb, mix, nbd_client, nsenter, pivot_root, reboot, rfkill, sysctl,
taskset...)

>> Why is expecting /usr/bin/env to be at a specific absolute path less
>> constraining than expecting bash to be at a specific absolute path?
>>
>> I've never understood that one...
> 
> Because /usr/bin/env is universally available on relevant UNIX-like
> systems (POSIX requires it), and /bin/bash is not.

Posix requires "batch", "compress", and "pax" too, none of which are
currently on my system. (There's a lot of other stuff in the standard it
expects ala qdel, sccs, ed, fort77, uucp. And stuff like cpio and cc
that the standard _dropped_ but which linux requires. And then show me
the posix spec for "init" or "mount"...)

But ok, let's assume it does expect it there. Where does it say it
should be in /usr/bin instead of in /bin? Why is expecting THAT to be at
a specific location ok, but not expecting bash to be at a specific
location (next to /bin/sh) to avoid having to launch two binaries to
interpret one file?

>>> Another error shows up in a few spots due to conflicts between a
>>> couple of toybox functions and libc:
>>>
>>> ./lib/lib.h:204:7: error: conflicting types for 'strnstr'
>>> char *strnstr(char *line, char *str);
>>> ./lib/lib.h:289:7: error: conflicting types for 'basename_r'
>>> char *basename_r(char *name);
>>
>> In neither case did you say what the conflicting definition was. What
>> header they came from, how they're defining those prototypes...
> 
> strnstr is:
> /usr/include/string.h:char      *strnstr(const char *, const char *,
> size_t) __pure;
> It originated in FreeBSD,

I'd never heard of it, I just combined "strnchr" and "strstr" in the
obvious way. Apparently what I'm missing is const, which toybox
functions never have. (Some global read-only arrays have it, that's
about it, one of the links in http://landley.net/toybox/cleanup.html
explains why.)

> but it hasn't been adopted widely elsewhere
> as I thought (OS X has it though). It examines not more than the given
> number of characters in the search string.

Apparently what I decided it was obvious for it to do and what you
decided it was obvious for it to do didn't match.

(I was also using strlcpy() back under dos back before I ever heard of
openbsd, although I don't remember if the l stood for "length" or
"landley". :)

Then again the WORST such name clash was way back when I wrote a BBS
that had a DOS direct screen write function that updated the buffer at
0xb8000000 directly, using a function called "throw()". Switching from
borland C++ 1.0 to borland C++ 2.0 made that program very unhappy...

> basename_r is:
> /usr/include/libgen.h:char      *basename_r(const char *, char *);
> Where a buffer is passed in to store the result.

In my case it's just "do not modify the string this points to, ever".
(Which means it doesn't remove trailing slashes and weird things like
that.) basename, read only.

> I see bionic
> implements a similar basename_r but they sensibly pass a size_t for
> the buffer length as well; FreeBSD just requires that the provided
> buffer is at least MAXPATHLEN bytes.

in lib/portability.h:

// glibc was handled above; for 32-bit bionic we need to avoid a collision
// with toybox's basename_r so we can't include <libgen.h> even though that
// would give us a POSIX basename(3).
#if defined(__BIONIC__)
char *basename(char *path);
char *dirname(char *path);
#endif

I suppose I should probably rename this sucker basename_readonly if
random systems are going to pollute the namespace with nonstandard
functions like that when you include standard headers. (Of course
guessing what they'll add is predicting the future, but now that two
libc's have done it...)

>> That said, we have lib/portability.c and lib/portability.h to paper over
>> that sort of issue.
> 
> Thanks, I'll see what's being done for other systems already.

Rob

 1459315276.0


More information about the Toybox mailing list