Bump GPLv2+ to GPLv3+ for some files, clarify BSD 2-clause. Everything else stays under GPLv3+. New Linking Exception exempts resulting executables from LGPLv3 section 4. Add CONTRIBUTORS file to keep track of licensing. Remove 'Copyright Red Hat Inc' comments. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
		
			
				
	
	
		
			352 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			352 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* termios.cc: termios for WIN32.
 | |
| 
 | |
|    Written by Doug Evans and Steve Chamberlain of Cygnus Support
 | |
|    dje@cygnus.com, sac@cygnus.com
 | |
| 
 | |
| This file is part of Cygwin.
 | |
| 
 | |
| This software is a copyrighted work licensed under the terms of the
 | |
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
 | |
| details. */
 | |
| 
 | |
| #include "winsup.h"
 | |
| #include "cygwin/version.h"
 | |
| #include <stdlib.h>
 | |
| #include "cygerrno.h"
 | |
| #include "security.h"
 | |
| #include "path.h"
 | |
| #include "fhandler.h"
 | |
| #include "dtable.h"
 | |
| #include "cygheap.h"
 | |
| #include "perprocess.h"
 | |
| #include "cygtls.h"
 | |
| 
 | |
| /* tcsendbreak: POSIX 7.2.2.1 */
 | |
| extern "C" int
 | |
| tcsendbreak (int fd, int duration)
 | |
| {
 | |
|   int res = -1;
 | |
| 
 | |
|   cygheap_fdget cfd (fd);
 | |
|   if (cfd < 0)
 | |
|     goto out;
 | |
| 
 | |
|   if (!cfd->is_tty ())
 | |
|     set_errno (ENOTTY);
 | |
|   else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
 | |
|     res = cfd->tcsendbreak (duration);
 | |
| 
 | |
| out:
 | |
|   syscall_printf ("%R = tcsendbreak(%d, %d)", res, fd, duration);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* tcdrain: POSIX 7.2.2.1 */
 | |
| extern "C" int
 | |
| tcdrain (int fd)
 | |
| {
 | |
|   pthread_testcancel ();
 | |
| 
 | |
|   int res = -1;
 | |
| 
 | |
|   termios_printf ("tcdrain");
 | |
| 
 | |
|   cygheap_fdget cfd (fd);
 | |
|   if (cfd < 0)
 | |
|     goto out;
 | |
| 
 | |
|   if (!cfd->is_tty ())
 | |
|     set_errno (ENOTTY);
 | |
|   else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
 | |
|     res = cfd->tcdrain ();
 | |
| 
 | |
| out:
 | |
|   syscall_printf ("%R = tcdrain(%d)", res, fd);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* tcflush: POSIX 7.2.2.1 */
 | |
| extern "C" int
 | |
| tcflush (int fd, int queue)
 | |
| {
 | |
|   int res = -1;
 | |
| 
 | |
|   cygheap_fdget cfd (fd);
 | |
|   if (cfd < 0)
 | |
|     goto out;
 | |
| 
 | |
|   if (!cfd->is_tty ())
 | |
|     set_errno (ENOTTY);
 | |
|   else if (queue != TCIFLUSH && queue != TCOFLUSH && queue != TCIOFLUSH)
 | |
|       set_errno (EINVAL);
 | |
|   else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
 | |
|     res = cfd->tcflush (queue);
 | |
| 
 | |
| out:
 | |
|   termios_printf ("%R = tcflush(%d, %d)", res, fd, queue);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* tcflow: POSIX 7.2.2.1 */
 | |
| extern "C" int
 | |
| tcflow (int fd, int action)
 | |
| {
 | |
|   int res = -1;
 | |
| 
 | |
|   cygheap_fdget cfd (fd);
 | |
|   if (cfd < 0)
 | |
|     goto out;
 | |
| 
 | |
|   if (!cfd->is_tty ())
 | |
|     set_errno (ENOTTY);
 | |
|   else if ((res = cfd->bg_check (-SIGTTOU)) > bg_eof)
 | |
|     res = cfd->tcflow (action);
 | |
| 
 | |
| out:
 | |
|   syscall_printf ("%R = tcflow(%d, %d)", res, fd, action);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* tcsetattr: POSIX96 7.2.1.1 */
 | |
| extern "C" int
 | |
| tcsetattr (int fd, int a, const struct termios *t)
 | |
| {
 | |
|   int res;
 | |
|   t = __tonew_termios (t);
 | |
|   int e = get_errno ();
 | |
| 
 | |
|   while (1)
 | |
|     {
 | |
|       res = -1;
 | |
|       cygheap_fdget cfd (fd);
 | |
|       if (cfd < 0)
 | |
| 	{
 | |
| 	  e = get_errno ();
 | |
| 	  break;
 | |
| 	}
 | |
| 
 | |
|       if (!cfd->is_tty ())
 | |
| 	{
 | |
| 	  e = ENOTTY;
 | |
| 	  break;
 | |
| 	}
 | |
| 
 | |
|       res = cfd->bg_check (-SIGTTOU);
 | |
| 
 | |
|       switch (res)
 | |
| 	{
 | |
| 	case bg_eof:
 | |
| 	  e = get_errno ();
 | |
| 	  break;
 | |
| 	case bg_ok:
 | |
| 	  if (cfd.isopen ())
 | |
| 	    res = cfd->tcsetattr (a, t);
 | |
| 	  e = get_errno ();
 | |
| 	  break;
 | |
| 	case bg_signalled:
 | |
| 	  if (_my_tls.call_signal_handler ())
 | |
| 	    continue;
 | |
| 	  res = -1;
 | |
| 	  /* fall through intentionally */
 | |
| 	default:
 | |
| 	  e = get_errno ();
 | |
| 	  break;
 | |
| 	}
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|   set_errno (e);
 | |
|   termios_printf ("iflag %y, oflag %y, cflag %y, lflag %y, VMIN %d, VTIME %d",
 | |
| 	t->c_iflag, t->c_oflag, t->c_cflag, t->c_lflag, t->c_cc[VMIN],
 | |
| 	t->c_cc[VTIME]);
 | |
|   termios_printf ("%R = tcsetattr(%d, %d, %p)", res, fd, a, t);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* tcgetattr: POSIX 7.2.1.1 */
 | |
| extern "C" int
 | |
| tcgetattr (int fd, struct termios *in_t)
 | |
| {
 | |
|   int res = -1;
 | |
|   struct termios *t = __makenew_termios (in_t);
 | |
| 
 | |
|   cygheap_fdget cfd (fd);
 | |
|   if (cfd < 0)
 | |
|     /* saw an error */;
 | |
|   else if (!cfd->is_tty ())
 | |
|     set_errno (ENOTTY);
 | |
|   else if ((res = cfd->tcgetattr (t)) == 0)
 | |
|     __toapp_termios (in_t, t);
 | |
| 
 | |
|   if (res)
 | |
|     termios_printf ("%R = tcgetattr(%d, %p)", res, fd, in_t);
 | |
|   else
 | |
|     termios_printf ("iflag %y, oflag %y, cflag %y, lflag %y, VMIN %d, VTIME %d",
 | |
| 	  t->c_iflag, t->c_oflag, t->c_cflag, t->c_lflag, t->c_cc[VMIN],
 | |
| 	  t->c_cc[VTIME]);
 | |
| 
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* tcgetpgrp: POSIX 7.2.3.1 */
 | |
| extern "C" int
 | |
| tcgetpgrp (int fd)
 | |
| {
 | |
|   int res;
 | |
| 
 | |
|   cygheap_fdget cfd (fd);
 | |
|   if (cfd < 0)
 | |
|     res = -1;
 | |
|   else
 | |
|     res = cfd->tcgetpgrp ();
 | |
| 
 | |
|   termios_printf ("%R = tcgetpgrp(%d)", res, fd);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| extern "C" pid_t
 | |
| tcgetsid (int fd)
 | |
| {
 | |
|   int res;
 | |
| 
 | |
|   cygheap_fdget cfd (fd);
 | |
|   if (cfd < 0)
 | |
|     res = -1;
 | |
|   else
 | |
|     res = cfd->tcgetsid ();
 | |
| 
 | |
|   termios_printf ("%R = tcgetsid(%d)", res, fd);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* tcsetpgrp: POSIX 7.2.4.1 */
 | |
| extern "C" int
 | |
| tcsetpgrp (int fd, pid_t pgid)
 | |
| {
 | |
|   int res = -1;
 | |
| 
 | |
|   cygheap_fdget cfd (fd);
 | |
|   if (cfd < 0)
 | |
|     /* saw an error */;
 | |
|   else if (!cfd->is_tty ())
 | |
|     set_errno (ENOTTY);
 | |
|   else
 | |
|     res = cfd->tcsetpgrp (pgid);
 | |
| 
 | |
|   termios_printf ("%R = tcsetpgrp(%d, %d)", res, fd, pgid);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* NIST PCTS requires not macro-only implementation */
 | |
| #undef cfgetospeed
 | |
| #undef cfgetispeed
 | |
| #undef cfsetospeed
 | |
| #undef cfsetispeed
 | |
| 
 | |
| /* cfgetospeed: POSIX96 7.1.3.1 */
 | |
| extern "C" speed_t
 | |
| cfgetospeed (const struct termios *tp)
 | |
| {
 | |
|   return __tonew_termios (tp)->c_ospeed;
 | |
| }
 | |
| 
 | |
| /* cfgetispeed: POSIX96 7.1.3.1 */
 | |
| extern "C" speed_t
 | |
| cfgetispeed (const struct termios *tp)
 | |
| {
 | |
|   return __tonew_termios (tp)->c_ispeed;
 | |
| }
 | |
| 
 | |
| static inline int
 | |
| setspeed (speed_t &set_speed, speed_t from_speed)
 | |
| {
 | |
|   int res;
 | |
|   switch (from_speed)
 | |
|     {
 | |
|     case B0:
 | |
|     case B50:
 | |
|     case B75:
 | |
|     case B110:
 | |
|     case B134:
 | |
|     case B150:
 | |
|     case B200:
 | |
|     case B300:
 | |
|     case B600:
 | |
|     case B1200:
 | |
|     case B1800:
 | |
|     case B2400:
 | |
|     case B4800:
 | |
|     case B9600:
 | |
|     case B19200:
 | |
|     case B38400:
 | |
|     case B57600:
 | |
|     case B115200:
 | |
|     case B128000:
 | |
|     case B230400:
 | |
|     case B256000:
 | |
|     case B460800:
 | |
|     case B500000:
 | |
|     case B576000:
 | |
|     case B921600:
 | |
|     case B1000000:
 | |
|     case B1152000:
 | |
|     case B1500000:
 | |
|     case B2000000:
 | |
|     case B2500000:
 | |
|     case B3000000:
 | |
|       set_speed = from_speed;
 | |
|       res = 0;
 | |
|       break;
 | |
|     default:
 | |
|       set_errno (EINVAL);
 | |
|       res = -1;
 | |
|       break;
 | |
|     }
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* cfsetospeed: POSIX96 7.1.3.1 */
 | |
| extern "C" int
 | |
| cfsetospeed (struct termios *in_tp, speed_t speed)
 | |
| {
 | |
|   struct termios *tp = __tonew_termios (in_tp);
 | |
|   int res = setspeed (tp->c_ospeed, speed);
 | |
|   __toapp_termios (in_tp, tp);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* cfsetispeed: POSIX96 7.1.3.1 */
 | |
| extern "C" int
 | |
| cfsetispeed (struct termios *in_tp, speed_t speed)
 | |
| {
 | |
|   struct termios *tp = __tonew_termios (in_tp);
 | |
|   int res = setspeed (tp->c_ispeed, speed);
 | |
|   __toapp_termios (in_tp, tp);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /* cfsetspeed: 4.4BSD */
 | |
| extern "C" int
 | |
| cfsetspeed (struct termios *in_tp, speed_t speed)
 | |
| {
 | |
|   struct termios *tp = __tonew_termios (in_tp);
 | |
|   int res;
 | |
|   /* errors come only from unsupported baud rates, so setspeed() would return
 | |
|      identical results in both calls */
 | |
|   if ((res = setspeed (tp->c_ospeed, speed)) == 0)
 | |
|     setspeed (tp->c_ispeed, speed);
 | |
|   __toapp_termios (in_tp, tp);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| extern "C" void
 | |
| cfmakeraw(struct termios *tp)
 | |
| {
 | |
|   tp->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
 | |
| 		 | INLCR | IGNCR | ICRNL | IXON);
 | |
|   tp->c_oflag &= ~OPOST;
 | |
|   tp->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
 | |
|   tp->c_cflag &= ~(CSIZE | PARENB);
 | |
|   tp->c_cflag |= CS8;
 | |
| }
 |