I am working on embedded system using C
and linux
. User can connect to the device via SSH or a console serial cable. He can do this through PuTTY o
TIOCGWINSZ is the way to go. Your device in question has to announce its size, otherwise this just can't work. Take xterm as an example:
device —— ttyS driver —— ttyS0 devnode —— screen/minicom
xterm —— pty devnode —— pty driver —— pts devnode —— bash
xterm does ioctl(TIOCSWINSZ) the first time it is spawned to let the tty driver know the window size. bash and programs spawned from it can then inquire it. If you resize the xterm window, it will tell the tty driver the new size, and xterm also emits SIGWINCH to its child process (bash in this case) to notify it of the size change.
None of this happens with devices (such as yours) that have no idea what they are connected to in the first place. Neither does the tty driver know what is connected to it. (Nor does it usually care.) xterm can tell the driver the size, because it can issue an ioctl, but ioctls are not transported via serial for example. What it would in theory take is a specialized kernel driver that knows how to communicate size changes with your particular device (perhaps a protocol on top of serial so that no rewrite of a core component is needed).
Note that the connected device may not even have a concept of a fixed region—e.g. a printer could be considered to have practically infinitely many lines.
ncurses just assumes 80x24 if it sees 0x0, because the programmer defined it that way. That size may not be correct, and in practice usually is not because people can resize their windows (even if they can't, like on tty1, they can still use stuff like screen(1) and shrink the size to something less than 80x24).
I use this code to print a bunch of equals signs as a divider. Works on most boxes/terms I've tried. Not sure what devices you are talking about. Worth a try I guess ;-)
#include <termios.h>
#include <sys/ioctl.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
struct winsize ws;
ioctl(0, TIOCGWINSZ, &ws);
int i=0;
for(;i<10*ws.ws_col;++i) printf("=");
printf("\n");
return 0;
}
A serial line does not have a way to negotiate the size of the terminal. Running a real xterm et.al. over a TTY/PTY device pair uses the TIOCSWINSZ
/TIOCGWINSZ
ioctl()
pair to pass this information.
Traditionally, this information was kept in termcap
or terminfo
about the real physical piece-of-glass-with-phosphor-coating terminals such as a DEC VT220. This is a static fixed database of values known ahead of time, which was correct around the time that a "terminal" literally was this fixed piece of hardware, but doesn't work so well in modern times of terminals being just some piece of program that draws to a framebuffer or similar.
I'd suggest the best method would be to try TIOCGWINSZ
, if that fails use terminfo
's tgetnum("co")
, and if that fails just presume 80x24.