X-Spam-Check-By: sourceware.org Date: Mon, 30 Jan 2006 10:50:13 -0500 From: Bob Rossi To: cygwin AT cygwin DOT com Cc: Chet Ramey Subject: Re: readline-5.1 && CGDB Message-ID: <20060130155013.GA13751@brasko.net> Mail-Followup-To: cygwin AT cygwin DOT com, Chet Ramey References: <20060127220812 DOT GA6931 AT brasko DOT net> <43DAA063 DOT 7070305 AT byu DOT net> <20060129041953 DOT GB30565 AT brasko DOT net> <43DE1EA1 DOT 9090506 AT byu DOT net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="xHFwDpU9dbj6ez1V" Content-Disposition: inline In-Reply-To: <43DE1EA1.9090506@byu.net> User-Agent: Mutt/1.5.9i X-IsSubscribed: yes Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com --xHFwDpU9dbj6ez1V Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Jan 30, 2006 at 07:11:45AM -0700, Eric Blake wrote: > According to Bob Rossi on 1/28/2006 9:19 PM: > > On Linux, something totally different happens. When I initialize > > readline, it eventually calls tgetent, which happens to set LINES and > > COLS to the correct size of the terminal. On cygwin this doesn't happen. > > The call readline makes to tgetent leaves LINES and COLS alone. Then, > > in Cygwin when I get to initscr, LINES and COLS is set to 25x80, unless > > I set the LINES and COLUMNS environment variables before the call to > > initscr. > > http://www.die.net/doc/linux/man/man3/tgetent.3.html does not document > that tgetent() messes with the environment, but if that is the case, you > may be onto something. Perhaps it really is something cygwin1.dll needs > to patch to be more similar to linux. I've finally produced a small test case like you asked me too. It did take some time, but it should certainly help discover the problem. I've attached the program. Basically, you can run the program like './main' and that will have readline operate on stdout, or you can run it like './main use_pty' and that will have readline operate on a PTY that I have created. Besides the code that opens the PTY, there is only the main function, and a function that modifies the readline library. If you run with the use_pty option, then ncurses thinks the terminal size is 25x80 after the call to rl_reset_terminal. Here's the output: [bar AT bar-nt ~/cvs/cgdb/builddir/tmp] $ ./main.exe use_pty before rline_initialize LINES=0 COLS=0 before rl_callback LINES=0 COLS=0 after rl_callback LINES=75 COLS=85 before rl_reset_terminal LINES=75 COLS=85 after rl_reset_terminal LINES=25 COLS=80 after rline_initialize LINES=25 COLS=80 before initscr LINES=25 COLS=80 after initscr LINES=25 COLS=80 However, if you run without that option, then ncurses thinks the terminal size is the correct terminal size. Here's the output: [bar AT bar-nt ~/cvs/cgdb/builddir/tmp] $ ./main before rline_initialize LINES=0 COLS=0 before rl_callback LINES=0 COLS=0 (tgdb) after rl_callback LINES=75 COLS=85 before rl_reset_terminal LINES=75 COLS=85 after rl_reset_terminal LINES=75 COLS=85 after rline_initialize LINES=75 COLS=85 before initscr LINES=75 COLS=85 after initscr LINES=75 COLS=85 I've tracked down the code in readline to the line that manipulates the LINES/COLS curses variables when initialize readline with a PTY. (This same code does not modify the LINES/COLS variable when readline is initialized with stdout). The code is in terminal.c:_rl_init_terminal_io line 420 for me. It looks like tgetent_ret = tgetent (term_buffer, term); where term is the string "dumb". What I can't understand is, why would tgetent act differently when I initialize readline with a created PTY, instead of stdout? Thanks, Bob Rossi --xHFwDpU9dbj6ez1V Content-Type: text/x-csrc; charset=us-ascii Content-Disposition: attachment; filename="main.c" #include #include #include #include #include #include /***************************************************************************** **************************** PTY CODE *************************************** ****************************************************************************/ #define SLAVE_SIZE 64 static size_t strlcpy_local(char *dst, const char *src, size_t size) { const char *s = src; char *d = dst; size_t n = size; if (n) while (--n && (*d++ = *s++)) {} if (n == 0) { if (size) *d = '\0'; while (*s++) {} } return s - src - 1; } int pty_open( int *masterfd, int *slavefd, char *slavename, size_t slavenamesize, const struct termios *slave_termios, const struct winsize *slave_winsize) { char *name; if (!masterfd || !slavefd || !slavename || slavenamesize < 64) return -1; if ((*masterfd = open("/dev/ptmx", 2 | 0x8000)) == -1) return -1; if (grantpt(*masterfd) == -1) { close(*masterfd); return -1; } if (unlockpt(*masterfd) == -1) { close(*masterfd); return -1; } if (!(name = ptsname(*masterfd))) { close(*masterfd); return -1; } if (strlcpy_local(slavename, name, slavenamesize) >= slavenamesize) { close(*masterfd); return -1; } if ((*slavefd = open(slavename, 2 | 0x8000)) == -1) { close(*masterfd); return -1; } if (slave_termios && tcsetattr(*slavefd, 2, slave_termios) == -1) { close(*masterfd); close(*slavefd); return -1; } if (slave_winsize && ioctl(*slavefd, (('T' << 8) | 2), slave_winsize) == -1) { close(*masterfd); close(*slavefd); return -1; } return 0; } struct pty_pair { int masterfd; int slavefd; char slavename[SLAVE_SIZE]; }; typedef struct pty_pair *pty_pair_ptr; pty_pair_ptr pty_pair_create (void) { int val; static char local_slavename[SLAVE_SIZE]; pty_pair_ptr ptr = (pty_pair_ptr)malloc (sizeof (struct pty_pair)); if (!ptr) return NULL; ptr->masterfd = -1; ptr->slavefd = -1; ptr->slavename[0] = 0; val = pty_open (&(ptr->masterfd), &(ptr->slavefd), local_slavename, SLAVE_SIZE, NULL, NULL); if (val == -1) return NULL; strncpy(ptr->slavename, local_slavename, SLAVE_SIZE); return ptr; } /***************************************************************************** **************************** APPLICATION CODE ******************************* ****************************************************************************/ void command (char *b) {} typedef void command_cb (char *); int rline_initialize (int slavefd, command_cb *command) { FILE *input, *output; input = fdopen (slavefd, "r"); if (!input) return -1; output = fdopen (slavefd, "w"); if (!output) return -1; rl_instream = input; rl_outstream = output; /* Tell readline what the prompt is if it needs to put it back */ fprintf (stderr, "\tbefore rl_callback LINES=%d COLS=%d\n", LINES, COLS); rl_callback_handler_install("(tgdb) ", command); fprintf (stderr, "\tafter rl_callback LINES=%d COLS=%d\n\n", LINES, COLS); /* Set the terminal type to dumb so the output of readline can be * understood by tgdb */ fprintf (stderr, "\tbefore rl_reset_terminal LINES=%d COLS=%d\n", LINES, COLS); if (rl_reset_terminal ("dumb") == -1) return -1; fprintf (stderr, "\tafter rl_reset_terminal LINES=%d COLS=%d\n\n", LINES, COLS); return 0; } int main (int argc, char **argv) { #if 0 int c; read(0, &c, 1); #endif pty_pair_ptr pty_pair; pty_pair = pty_pair_create (); if (!pty_pair) return -1; fprintf (stderr, "before rline_initialize LINES=%d COLS=%d\n\n", LINES, COLS); /** * If you initialize readline with stdout, everything appears to be fine. * However, if you initialize readline with a created slave PTY, the LINES * COLS are incorrect after the call to rl_reset_terminal. */ if (argc == 2 && strcmp (argv[1], "use_pty") == 0) rline_initialize (pty_pair->slavefd, command); else rline_initialize (0, command); fprintf (stderr, "after rline_initialize LINES=%d COLS=%d\n\n", LINES, COLS); fprintf (stderr, "before initscr LINES=%d COLS=%d\n", LINES, COLS); initscr (); fprintf (stderr, "after initscr LINES=%d COLS=%d\n", LINES, COLS); endwin (); return 0; } --xHFwDpU9dbj6ez1V Content-Type: text/plain; charset=us-ascii -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ --xHFwDpU9dbj6ez1V--