Thursday, June 5, 2008

MacOSX and stdin,stdout,stderr

I am in the process of porting a friends software to MacOSX. Don't ask what it does yet, all will be revealed soon. The code compiles quite happily on Solaris and Linux, but fails with the following error on MacOSX...

Why?

dbFile.c: In function ‘_setLogfile’:
dbFile.c:243: error: invalid lvalue in assignment
dbFile.c:244: error: invalid lvalue in assignment
dbFile.c: In function ‘fieldFillGen’:

I know what the problem is -
Seems on MacOSX 10.4 and below:
stdin, stdout, and stderr are addresses of a FILE rather than a FILE*
On MacOSX 10.5 they are FILE*

So depending on the OS version you are targeting will determine whether the code compiles or not. The issue goes back to the way FreeBSD originally implemented this in stdio.h which is the base for MacOSX, and it looks like it finally became "correct" i.e. portable and adhering to other implementations in MacOSX 10.5
A quick look at /usr/include/stdio.h confirms this...
the FILE* appears within the ifdef for _DARWIN_UNIX_03

__BEGIN_DECLS
#if __DARWIN_UNIX03
extern FILE *__stdinp;
extern FILE *__stdoutp;
extern FILE *__stderrp;
#else /* !__DARWIN_UNIX03 */
extern FILE __sF[];
#endif /* __DARWIN_UNIX03 */
__END_DECLS


So I need to come up with a simple workaround for what was originally valid code on other operating systems:

stderr = wk;
stdout = wk;

the following seems to work:

dup2(wk->_file ,STDERR_FILENO);
dup2(wk->_file ,STDOUT_FILENO);

No comments: