Subject: lib/29944: Cursor keys are not recognized after running a subshell
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <michael@moria.de>
List: netbsd-bugs
Date: 04/11/2005 11:04:00
>Number:         29944
>Category:       lib
>Synopsis:       Cursor keys are not recognized after running a subshell
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Apr 11 11:04:00 +0000 2005
>Originator:     Michael Haardt
>Release:        2.0
>Organization:
>Environment:
NetBSD galadriel 2.0_STABLE NetBSD 2.0_STABLE (GALADRIEL) #0: Sat Apr  2 01:18:51 CEST 2005  root@galadriel.moria.de:/usr/obj/sys/arch/sparc64/compile/GALADRIEL sparc64

>Description:
The sequence of the first typed cursor key is not recognized.  Further typed keys are.  After running the shell, getch() returns -1 until a key is typed.  Cursor keys will never be recognized at this point.
>How-To-Repeat:
This code is ripped out of an editor.  The editor works fine on Linux with ncurses and an executable compiled with NetBSD 1.6 still works fine under 2.0, but when built new under 2.0, it shows the problem.

/* gcc -Wall main.c -lcurses */

#include <sys/wait.h>
#include <curses.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

static void keys(void)
{
  int ch;
  static int n=0;

  do
  {
    switch ((ch=getch()))
    {
      case KEY_UP: printw("%d: key up\n",n++); break;
      case KEY_DOWN: printw("%d: key down\n",n++); break;
      case KEY_LEFT: printw("%d: key left\n",n++); break;
      case KEY_RIGHT: printw("%d: key right\n",n++); break;
      default: printw("%d: %d\n",n++,ch); break;
    }
    refresh();
  } while (ch!='q');
}

int main(int argc, char *argv[])
{
  pid_t pid;
  struct sigaction interrupt;

  initscr();
  noecho();
  raw();
  nonl();
  scrollok(stdscr,TRUE);
  keypad(stdscr,TRUE);
  keys();
  interrupt.sa_flags=0;
  sigemptyset(&interrupt.sa_mask);
  interrupt.sa_handler=SIG_IGN;
  sigaction(SIGINT,&interrupt,(struct sigaction *)0);
  sigaction(SIGQUIT,&interrupt,(struct sigaction *)0);
  switch (pid=fork())
  {
    case -1: exit(255);
    case 0:
    {
      move(LINES-1,0);
      refresh();
      reset_shell_mode();
      write(1,"\n",1);
      interrupt.sa_handler=SIG_DFL;
      sigaction(SIGINT,&interrupt,(struct sigaction *)0);
      sigaction(SIGQUIT,&interrupt,(struct sigaction *)0);
      execlp("/bin/sh","sh",(const char*)0);
      exit(127);
      break;
    }
    default:
    {
      pid_t r;
      int status;

      while ((r=wait(&status))!=-1 && r!=pid);
      reset_prog_mode();
      interrupt.sa_handler=SIG_DFL;
      sigaction(SIGINT,&interrupt,(struct sigaction *)0);
      sigaction(SIGQUIT,&interrupt,(struct sigaction *)0);
      touchwin(curscr);
      wrefresh(curscr);
    }
  }
  keys();
  scrl(1);
  refresh();
  echo();
  noraw();
  endwin();
  return 0;
}

Type up, left, right, down, q, exit the shell, then type up and q.  The output is:

0: 27
1: 91
2: 65
3: key left
4: key right
5: key down
6: 113
michael@galadriel; ./a.out

$ exit

7: -1
8: -1
9: -1
10: -1
11: -1
[more deleted]102: -1
103: -1
104: 27
105: 91
106: 65
107: 113


>Fix: