ioctl(TIOCGETP/TIOCSETP) troubles

John Tytgat John.Tytgat at
Tue Dec 30 09:04:38 PST 2003

Currently the getpass() function in UnixLib does not work properly, i.e. it
displays the characters you're typing.  This can be traced back to
__ttyioctl(TIOCGETP) call which doesn't fill in gtty->sg_ospeed (instead
it fills in gtty->sg_ispeed twice) and this makes tcsetattr() fail when
it loops over the __bsd_speeds array (BTW, the end-loop detection is
wrong there but that doesn't matter for this discussion).

Fixing this, makes getpass() work again.  A CVS update is in the pipeline.

However, there is IMHO another problem which I don't know if (and how) this
needs fixing.  The __ttyioctl(TIOCGETP) call transfers term->__ispeed value
into gtty->sg_ispeed.  Note that the type of term->__ispeed is 'speed_t'
(or 'long int') and the type of gtty->sg_ispeed is 'char'.  My understanding
is that in both variables the used is supposed to fill in the 'B' #defines
specified in termios.h :

/* Input and output baud rates.  */
#define	B0	0		/* Hang up.  */
#define	B50	50		/* 50 baud.  */
#define	B75	75		/* 75 baud.  */
#define	B110	110		/* 110 baud.  */
#define	B134	134		/* 134.5 baud.  */
#define	B150	150		/* 150 baud.  */
#define	B200	200		/* 200 baud.  */
#define	B300	300		/* 300 baud.  */
#define	B600	600		/* 600 baud.  */
#define	B1200	1200		/* 1200 baud.  */
#define	B1800	1800		/* 1800 baud.  */
#define	B2400	2400		/* 2400 baud.  */
#define	B4800	4800		/* 4800 baud.  */
#define	B9600	9600		/* 9600 baud.  */
#define	B19200	19200		/* 19200 baud.  */
#define	B38400	38400		/* 38400 baud.  */

#define B7200   7200
#define B14400  14400
#define B28800  28800
#define B57600  57600
#define B76800  76800
#define B115200 115200
#define B230400 230400
#define	EXTA	19200
#define	EXTB	38400

I don't think I need to say that this gives trouble when assigning these B
values to a 'char' type variable.

BTW, the current baud value is set to 38400 which is in hex 0x9600 so
the gtty->sg_ispeed (and gtty->sg_ospeed too after the above mentioned
fix) becomes 0 which would mean 'Hang up' so more or less by accident
the tcgetattr() and tcsetattr() work.

The story isn't finished yet : it looks like this was somewhat forseen in
the past and there is a mapping from 'char' values to read baud values in
tcgetattr() and tcsetattr().

So the questions are:

1. I suppose this needs fixing, right ?

2. If so, I see two obvious ways to fix this but I don't know which one
   is preferred :
   a. Either change the type of sg_ispeed and sg_ospeed to 'speed_t' but
      as this makes the sgttyb struct bigger and this struct gets used in
      ioctl(), so I'm not sure if this is a good solution.  It is also
      incompatible with the sgttyb struct in TCPIPLibs (see below).

   b. Another possibility for a fix would be that a similar mapping between
      real baud values and 'char' compatible baud speed indications like done
      in tcgetattr() & tcsetattr(), is also done in __ttyioctl(TIOCGETP /
      TIOCSETP).  [Aside: why not (re)using convert_baud_rate() in
      unix/tty.c for this ?]
      This would mean that the above mentioned #define B values need to be
      changed as well.
3. Other possibilities to fix this ?

Out of curiosity, I looked at the TCPIPLibs headers of the Norcroft C
distribution.  In sys/termios.h I see the same #define B values defined
(with the 2nd block only defined when _POSIX_SOURCE is defined).  However
in its sys/ttydef.h I see:


#ifndef _SYS_TTYDEV_H_
#define	_SYS_TTYDEV_H_

#ifdef USE_OLD_TTY
#define B0	0
#define B50	1
#define B75	2
#define B110	3
#define B134	4
#define B150	5
#define B200	6
#define B300	7
#define B600	8
#define B1200	9
#define	B1800	10
#define B2400	11
#define B4800	12
#define B9600	13
#define EXTA	14
#define EXTB	15
#define B57600  16
#define B115200 17
#endif /* USE_OLD_TTY */

#endif /* !_SYS_TTYDEV_H_ */

Which is more or less the 2nd proposal for fixing this (but this header
is marked as "compatability header" so shouldn't act as an example ?).
Note that the TCPIPLibs distribution has the same sgttyb struct as UnixLib
does (i.e. still the 'char' type for sg_ispeed and sg_ospeed).

Any suggestions on this please ?

John Tytgat, in his comfy chair at home                                 BASS
John.Tytgat at                             ARM powered, RISC OS driven

More information about the gcc mailing list