12

I think I've noticed this before but never thought about it much; now I'm curious.

> ldd /bin/bash
        linux-vdso.so.1 =>  (0x00007fff2f781000)
        libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f0fdd9a9000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f0fdd7a5000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f0fdd3e6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0fddbf6000)

Libtinfo is part of ncurses. This is a fedora system, but it is the same on ubuntu, and I notice on raspbian (a debian variant) it also links to libncurses itself.

What's the reason for this? I thought everything bash did could be done with libreadline (which curiously, it does not link to). Is this simply a substitute for that?

goldilocks
  • 86,451
  • 30
  • 200
  • 258
  • It's part of ncurses? The package description (*shared low-level terminfo library for terminal handling*) doesn't say anything (http://packages.ubuntu.com/trusty/libtinfo5), and it sounds reasonable for a shell to have. Maybe needed for values of `TERM`? Ah, never mind - I see the source package is `ncurses`. – muru Sep 16 '15 at 18:42
  • `zsh` also link to libtinfo, too – cuonglm Sep 17 '15 at 02:04

2 Answers2

18

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.

dhag
  • 15,440
  • 4
  • 54
  • 65
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
3

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.

Thomas Dickey
  • 75,040
  • 9
  • 171
  • 268