Hi Christian,

sorry for the delay caused by holidays.

Christian Weisgerber wrote on Thu, Aug 07, 2008 at 03:53:00PM +0000:
> Ingo Schwarze <[EMAIL PROTECTED]> wrote:

>> What i do not yet understand is why xterm has -oxtabs
>> by default but the terminfo(5) database has no OTpt for it.
>> Isn't that inconsistent?

> I don't follow.  Our ttys default to oxtabs.

Ok, i see.

> xterm has nothing to do with it.

Well, if you start an xterm in X, either directly
from /etc/X11/xdm/Xsession or from a window manager,
for example fvwm, stty -a tells you -oxtabs.

After digging through the code, i found the reason why xterms
have -oxtabs in /usr/xenocara/app/xterm/main.c revision 1.8.
So xterm does have at least a bit to do with it.

Very much abridged (uh - all those #ifdefs),
this is what xterm/main.c says:

  static TERMIO_STRUCT d_tio;

  int
  main(int argc, char *argv[]ENVP_ARG)
  {
    d_tio.c_oflag = OPOST | ONLCR;  /* note the absence of OXTABS */
  }

  static int
  spawnXTerm(XtermWidget xw)
  {
    ttyfd = open("/dev/tty", O_RDWR);
    if (ttyfd < 0) {
      tio = d_tio;
    } else {
      if ((rc = ttyGetAttr(ttyfd, &tio)) == -1)  /* =tcgetattr */
        tio = d_tio;
    }
    get_pty(&screen->respond, XDisplayString(screen->display));  /* =openpty */
    /* now some code to tweak tio, but not OXTABS */
    ttySetAttr(ttyfd, &tio);  /* =tcsetattr */
  }

The crucial point is that xterm sets up its terminal IO struct
to be fed to tcsetattr before initializing the pty, so the tty
defaults get lost.

The usual call chain when starting an xterm in X is

  init -> rc -> xdm -> xsession -> fvwm -> xterm

None of these have a controlling tty, so the open call on /dev/tty
fails and the xterm ends up with xterm defaults (i.e. -oxtabs),
not with tty defaults (i.e. +oxtabs).

Now is this a bug?
Shouldn't the xterm use the settings of the pty it is running on?
I'm not really sure what to think.
At least, the lack of +oxtabs is what confused the original poster.

The patch below fixes the behaviour of the xterm, in the sense
that it now uses the defaults of its shiny new pty.  Of course
this is not intended for commit, i'm well aware that xterm
comes from upstream, and even if this were indeed slightly buggy, 
probably it would need to be fixed differently, but the patch
demonstrates the effect.

That's also why i left a bit of debugging in the patch, proving
that -oxtabs indeed stems from the lack of a controlling tty:
When you start an xterm from the window manager,
 - you always get ttyfd = -1,
 - without the patch, you get -oxtabs
 - with the patch, you get +oxtabs
When you start an xterm from another xterm,
 - you always get ttyfd > 0,
 - without the patch, you inherit
   whatever oxtabs setting the old xterm happens to have
 - with the patch, you get +oxtabs

> The pt flag is obsolete.  Its lack doesn't bother
> curses(3), which still sets -oxtabs in cbreak mode.

Enough code digging for tonight; i shall try to understand
that part of your answer later.

Yours,
  Ingo


Index: main.c
===================================================================
RCS file: /cvs/xenocara/app/xterm/main.c,v
retrieving revision 1.8
diff -u -p -r1.8 main.c
--- main.c      25 Aug 2008 18:05:57 -0000      1.8
+++ main.c      25 Aug 2008 23:09:38 -0000
@@ -456,6 +456,9 @@ static int pty_search(int *pty);
 #endif
 #endif /* ! VMS */
 
+#include <syslog.h>
+char logstr[128];
+
 static int get_pty(int *pty, char *from);
 static void resize_termcap(XtermWidget xw, char *newtc);
 static void set_owner(char *device, uid_t uid, gid_t gid, mode_t mode);
@@ -3085,6 +3088,8 @@ spawnXTerm(XtermWidget xw)
        alarm(2);               /* alarm(1) might return too soon */
        if (!sigsetjmp(env, 1)) {
            ttyfd = open("/dev/tty", O_RDWR);
+           (void) snprintf(logstr, sizeof(logstr), "ttyfd = %d", ttyfd);
+           syslog(LOG_INFO, logstr);
            alarm(0);
            tty_got_hung = False;
        } else {
@@ -3204,6 +3209,9 @@ spawnXTerm(XtermWidget xw)
        if (get_pty(&screen->respond, XDisplayString(screen->display))) {
            SysError(ERROR_PTYS);
        }
+#ifdef TERMIO_STRUCT
+       (void) ttyGetAttr(screen->respond, &tio);
+#endif /* TERMIO_STRUCT */
 #if OPT_INITIAL_ERASE
        if (resource.ptyInitialErase) {
 #ifdef TERMIO_STRUCT

Reply via email to