0

I am currently working on a complete shell built in C.

I want to implement a bash history and navigation using arrows keys through my double linked list but I am having some troubles with TermCaps and properly setting up read() function.

Here is how I set up my terminal :

static int      set_terminal_mode(t_shell *shell, const int mode)
 {
   char          *term_name;

   if (mode == 0)
     {
       if ((term_name = getenv("TERM")) == NULL)
         return (-1);
       ioctl(0, TCGETS, &shell->term);
       shell->term.c_lflag &= ~ICANON;
       shell->term.c_cc[VMIN] = 1;
       shell->term.c_cc[VTIME] = 0;                                         
       ioctl(0, TCGETS, &shell->term_save);
       ioctl(0, TCSETS, &shell->term);
     }
   if (mode == 1)
     ioctl(0, TCSETS, &shell->term_save);
   return (0);
 }

I can catch when left or right key is pressed and then I use \r to erase the line (which doesn't really work) but the main problem is that I cannot use the return key anymore (only display ^?) How can I fix this?

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
rak007
  • 973
  • 12
  • 26

1 Answers1

0

This line

       shell->term.c_lflag &= ~ICANON;

turns off canonical mode, which according to POSIX does several things including turning off the line-buffering, which includes special treatment of carriage return:

In non-canonical mode input processing, input bytes are not assembled into lines, and erase and kill processing shall not occur.

and

CR
Special character on input, which is recognized if the ICANON flag is set; it is the carriage-return character. When ICANON and ICRNL are set and IGNCR is not set, this character shall be translated into an NL, and shall have the same effect as an NL character.

If you want to read single bytes (for cursor-keys), you'll have to handle single-byte control characters such as carriage return (CR) and line-feed (referred to as NL or newline).

By the way, your example seems to have the saved/modified settings reversed: The call

     ioctl(0, TCSETS, &shell->term_save);

uses terminal settings saved in

       ioctl(0, TCGETS, &shell->term_save);

which is after you have already modified the terminal settings.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105