Porting to OS/2: Case #21 setmode()

setmode() is used to change the text/binary mode of a file handle. By the way, these modes exists on DOS-like OSes such as OS/2, Windows and DOS. Whereas, UNIX-like OSes such as Linux don't distinguish these modes. They treats all the file handles as a binary mode.

In addition, they uses pipes actively via standard handles such as stdin, stdout and stderr. By the way, on OS/2, they are opened in a text mode by default. So it is general to call setmode() in order to change standard handles to a binary mode at the beginning. Because -Zbin-files does not affect on standard handles.

This is a good strategy. However, standard handles are used to input from keyboard and to output to a screen, too. As a result, if you change standard handles to binary mode when they are not connected to pipes, then you would encounter unexpected behaviors.

For example, if you output two lines, "Hello," and "World", then you expect like this.

Hello,
World

Instead, howver, you'll see like this.

Hello,
      World

Why does this problem occur ? Because '\n' is not translated to '\r\n' in binary mode.

We should use binary mode for compatiblity with UNIX-like OSes. However, this may cause a problem when not connected to pipes.

If so, it would be fine to change standard handles to binary mode if and only if they are connected to pipes, reversely.

Is it possible to determine if standard handles are connected to pipes ? Yes, of course. You can use isatty() funciton. It returns non-zero value if given handle refers to a character device, that is, a standard input(keyboard) or a standard output(screen). Otherwise it returns 0. That is, file or pipe.

After all, if return value of isatty() is 0, then change standard handles to binary mode, otherwise change to text mode. By the way, text mode is default, there is no need to change to text mode.

Here are the codes.

1
2
    if( !isatty( fileno( stdin ))) setmode( fileno( stdin ), O_BINARY );
    if( !isatty( fileno( stdout ))) setmode( fileno( stdout ), O_BINARY );


If you place the above codes at the beginning of main(), so-called stair problems will not occur.

However, setmode() is called in any other place, the above codes do not help. Here are the more general codes replacing setmode() of kLIBC.

1
2
3
4
5
6
7
8
9
10
int _std_setmode( int handle, int mode );

int setmode( int handle, int mode )
{
    /* set a console to O_TEXT unconditionally */
    if( isatty( handle ))
        mode = O_TEXT;

    return _std_setmode( handle, mode );
}


Complete sources are available in below link.


댓글

이 블로그의 인기 게시물

토렌트: < 왕좌의 게임 > 시즌 1 ~ 시즌 8 완결편 마그넷

토렌트: < 스타워즈 > Ep.1 ~ Ep.6 마그넷

토렌트: NGC < 코스모스 > 우리말 더빙 전편(1편~13편) 마그넷