Why don't termcaps work before a `write` syscall?

124 Views Asked by At

Why is the output of this program not getting underlined

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  write(1, "Hello world!\n", 13);
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

but this is?

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  puts("Hello world!");
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

EDIT

The issue is, indeed, about buffer management! If I add fflush, the string is properly underlined

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  fflush(stdout);
  write(1, "Hello world!\n", 13);
  tputs(tgetstr("ue", NULL), 1, &putchar);
}
1

There are 1 best solutions below

0
On

The reason for the difference is that putchar and puts are buffered, while write is not. In this example

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  write(1, "Hello world!\n", 13);
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

the characters written by

write(1, "Hello world!\n", 13);

are likely to get to the screen first, because (unlike the tputs calls) they are written immediately. The characters written by the tputs calls are stored in a buffer (which generally is much larger than the strings returned from tgetstr), and since you provided no other way to flush the buffer, those are written by the runtime's cleanup as it exits.

Without an explicit return statement, the C standard guarantees that it has the same effect as calling exit (which does an fflush on each open file—including streams such as stdout).

While you could in principle construct a termcap which had extremely long strings, termcap descriptions are supposed to be limited to 1023 bytes (and even terminfo descriptions are generally limited to 4096 bytes), while the standard I/O buffer size is generally several times that limit, so you wouldn't see those tputs calls written out without a lot of work (i.e., changing the runtime...).