Why does bash link to ncurses?
If you run bash
as:
LD_DEBUG=bindings bash
on a GNU system, and grep for bash.*tinfo
in that output, you'll see something like:
797: binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `UP'
797: binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `PC'
797: binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `BC'
797: binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `tgetent'
797: binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `tgetstr'
797: binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `tgetflag'
You can confirm from the output of nm -D /bin/bash
that bash
is using those symbols from tinfo.
Bringing the man page for any of those symbols clarifies what they're for:
$ man tgetent
NAME
PC, UP, BC, ospeed, tgetent, tgetflag, tgetnum, tgetstr, tgoto, tputs -
direct curses interface to the terminfo capability database
Basically, bash
, more likely its readline
(libreadline is statically linked in) editor, uses those to query the terminfo database to find out about terminal capabilities so it can run its line editor properly (sending the right escape sequences and identify key presses correctly) on any terminal.
As to why readline is statically linked into bash
, you have to bear in mind that readline
is developed alongside bash
by the same person and is included in the source of bash
.
It is possible to build bash
to be linked with the system's installed libreadline
, but only if that one is of a compatible version, and that's not the default. You need to call the configure
script at compilation time with --with-installed-readline
.
bash
is a termcap application via readline
, like screen
and some other programs. On most Linux-based systems (aside from Slackware), you're likely to see ncurses as underlying implementation of termcap.
The manual page for tgetent
(named curs_termcap because that's the way it was done in SVr4...) says:
These routines are included as a conversion aid for programs that use the termcap library. Their parameters are the same and the routines are emulated using the terminfo database. Thus, they can only be used to query the capabilities of entries for which a terminfo entry has been compiled.
That is, if the calling program does not look closely at the data returned, and uses the conventional termcap interface for reading the terminal description and writing data to the screen, it works just like the original termcap.
Most termcap applications don't look that closely (xterm is a rare exception — see FAQ). So bash
works with ncurses.
However, the termcap library is smaller than ncurses. Quite a while ago that mattered, and since 1997 ncurses has had a configure option --with-termlib
which makes it build the termcap- and terminfo-specific parts as a library separate from the functions needed in the higher-level curses library. A few years passed, and some of the Linux-based distributions incorporated that into their packages.
Since bash
doesn't use any of the curses functions (libncurses, etc.), it's reasonable to link only against the libtinfo
.
readline
is the termcap-specific part of bash
(actually when I first encountered bash
, its termcap parts were hardcoded, even though the official source used termcap — perhaps to save a few more bytes). When bash
is built with the bundled readline
, you will not see readline
as a separate library because there would be no point in making that bundled readline
install as a (possibly conflicting) shared library. But (depending on your system), you may see libtinfo
because ncurses is built one way or the other (split or not) — not both.