Reassigning VINTR Keystrokes

Craig Thomas thomas@cs.queensu.ca
Fri Jun 29 09:15:00 GMT 2001


Hello all,

Before I begin asking for help with a problem I've been having, I just wanted to let everyone know that Cygwin has been an amazing tool 
in helping port a large linguistic analysis tool (45,000+ lines) from a Solaris system to Windows 98. The software was developed 
orginally using a PDP-11 in machine code and eventually was re-written in C around 1980. In the mid 90's the linguistic portion of the 
code became substantially more robust and the idea was to port the code over to a DOS/Windows based machine. Traditionally porting this 
software to a PC has meant rewriting most of the modules involved with I/O. Thanks to Cygwin, the changes to code were extremely minimal 
with only cosmetic changes needed. Hats off to all the developers and users who have made this software a powerful development tool.

Now on to the problem at hand. The problem I'm currently having is remapping the key which generates a VINTR signal from CTRL-C to 
something else. Under a Solaris system, the code looks something like this:

/* Global variables */
struct termios oldintrps, newintrps;


/********************************************************/
/*                  I N I T E R M                       */
/********************************************************/
/*                                                      */
/* This procedure modifies the various protocols which  */
/* control communications between UNIX and the terminal */
/* Existing protocols are preserved to allow them to be */
/* restored on exit.                                    */
/*                                                      */
/********************************************************/

initerm()
{
     extern struct termios oldintrps, newintrps;

     char * tempstring;

     cbreak();
     noecho();
     nonl();
     intrflush(stdscr,FALSE);
     keypad(stdscr,FALSE);

     /* make two copies of the structure containing the communications
     attributes, one to change, the other for subsequent restoration */
     tcgetattr(TERMOUT1, &oldintrps);
     tcgetattr(TERMOUT1, &newintrps);

     /* The VINTR key below is change from ^C to ^_ */
     newintrps.c_cc[VINTR] = '\037'; 
     newintrps.c_cc[VQUIT] = 0;
     newintrps.c_cc[VSTART] = 0;    
     newintrps.c_cc[VSTOP] = 0;
     newintrps.c_cc[VEOL] = 0;
     newintrps.c_cc[VSUSP] = '\001';
     #ifndef WIN95
         newintrps.c_cc[VDSUSP] = 0;
     #endif
     newintrps.c_cc[VREPRINT] = 0;
     newintrps.c_cc[VDISCARD] = 0;
     newintrps.c_cc[VWERASE] = 0;
     newintrps.c_cc[VLNEXT] = 0;

     /* install the modified attributes */
     tcsetattr(TERMOUT1, TCSANOW, &newintrps);
}

As you can see, the VINTR key is changed from CTRL-C to CTRL-_ instead. In our program, we want the keypress CTRL-_ to generate a SIGINT 
which is handled by our SIGINT handler. CTRL-C we just want to treat as normal input (ie. generate character #3). The following code is 
what handles input to our program:

int ivigetc(void)
{
    return( (progstate == ACTIVE) ? getc( iviinput ) : getchar() );
}

Under Cygwin, I wrote a small program to test remapping the CTRL-C key, one that could be ported back to solaris, the program is as 
follows:

(thomas@minstrel:~/vinci_source/temp)[22]$ cat inttest.c
/* I N C L U D E S ********************/

#ifdef CYGWIN
  #include <ncurses.h>
  #include <ncurses/term.h>
#else
  #include <curses.h>
  #include <term.h>
#endif

#include <termios.h>
#include <signal.h>
#include <stdio.h>

/* D E F I N E S **********************/

#define TERMOUT1 1

/* G L O B A L S **********************/
struct termios oldintrps, newintrps;

/* S U B R O U T I N E S **************/
void initerm( void )
{
  /* Grab copies of the current communications attributes */
  tcgetattr( TERMOUT1, &oldintrps );
  tcgetattr( TERMOUT1, &newintrps );

  /* Remap VINTR key from ^C to ^_ */
  newintrps.c_cc[VINTR] = '\037';

  /* Install the modified attributes */
  tcsetattr( TERMOUT1, TCSANOW, &newintrps );
}

/**************************************/

void restoreterm( void )
{
  /* Restore our old interrupt handler */
  tcsetattr( TERMOUT1, TCSANOW, &oldintrps );
}

/**************************************/

void inthandler( int unused )
{
  /* Print a message to the effect that an interrupt occurred. A
     bad thing to do in an interrupt handler, but we just want to
     demonstrate that the handler was entered */
  printf( "The SIGINT signal has been generated.\n" );
}

/* M A I N   P R O G R A M ************/
int main( void )
{
  /* -- VARIABLE DECLARATION -- */
  char c;  /* Used to store input from the keyboard */
  struct termios currentintrps; /* Used to store the current interrupts */

  /* Initalize the new keyboard mappings */
  initerm();

  /* Install the SIGINT interrupt handler */
  signal( SIGINT, inthandler );

  /* Print our character settings */
  tcgetattr( TERMOUT1, &currentintrps );
  printf( "Current VINTR key: %d\n", currentintrps.c_cc[VINTR] );

  /* Loop and output the keystrokes the user entered */
  while( c != 'q' )
  {
    printf( "=> " );
    /* Get a character from the keyboard */
    c = getchar();
    /* Tell the user what key they pressed */
    printf( "\nCharacter #%d was pressed\n", c );
  }

  /* Restore the old terminal settings */
  restoreterm();

  /* Print the value of the settings */
  tcgetattr( TERMOUT1, &currentintrps );
  printf( "Current VINTR key: %d\n", currentintrps.c_cc[VINTR] );
}

I compiled under cygwin B20 by doing a "gcc -DCYGWIN inttest.c -lncurses" and ran it. Output was as follows (the CTRL-C in brackets 
means that I typed the CTRL-C key):

--------
Current VINTR key: 31
=> g

Character #103 was pressed
=>
Character #10 was pressed
=> (CTRL-C)The SIGINT signal has been generated.

Character #-1 was pressed
=> q

Character #113 was pressed
Current VINTR key: 3
-------

I then compiled under Solaris by doing a "cc inttest.c -lcurses" and ran it. Output was as follows:

-------
Current VINTR key: 31
=> g

Character #103 was pressed
=> 
Character #10 was pressed
=> ^C

Character #3 was pressed
=> 
Character #10 was pressed
=> ^_The SIGINT signal has been generated.

Character #-1 was pressed
=> q

Character #113 was pressed
Current VINTR key: 3
-------

As you can see here, the CTRL-C key still generates a SIGINT signal under Cygwin even though we remapped the key. I appologize for the 
length of the message, but I wanted to include test cases here. I also appologize if this issue has already been addressed. I've been 
searching for about 2 days now on the mailing list archives and have seen some talk of CTRL-C SIGINT handling but have had no luck in 
finding any specific code or fixes. Anyone have any thoughts on this? Any input would be greatly appreciated!

Thanks,
Craig

-------------------------
Craig Thomas
thomas@cs.queensu.ca
7cmt@qlink.queensu.ca
-------------------------


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/



More information about the Cygwin mailing list