nimble-code / Cobra

An interactive (fast) static source code analyzer
139 stars 31 forks source link

interactive session does not show any keystrokes for re-compiled version on alpine linux #33

Closed yilmazdurmaz closed 2 years ago

yilmazdurmaz commented 2 years ago

Hi there,

I try Cobra on an Alpine Linux on Docker and installing gcc, musl-dev, byacc, and make are enough to compile it (or at least there is no compilation errors).

However something is seemingly missing and I could not get the interactive session to show anything I write (not even the colons are there). If I blindly write without any typo or copy-paste a command, it has no problem working. It is just that the curser sits still on the left-most side and does not move for any key stroke until enter key pressed.

Also, this problem is not happening on an Ubuntu container.

I tried to check the source code and libraries installed on Ubuntu and Alpine. Unfortunately, I failed to isolate the problem. I also tried to understand source code and failed in that too.

It might be solved by a few additional library installation, or might be purely dependent on how Alpine linux is made. In the latter case, clearly there is nothing to solve the issue.

Is there anything you can think of?

PS: The reason I try to work on Alpine is its small docker image size to work on while on Windows. And by the way, precompiled linux binaries do not work in Alpine.

nimble-code-Cobra-issue

nimble-code commented 2 years ago

it means that the raw settings don't work the same. it's this part of the code that turns off echo'ing in cobra_main() (file cobra_lib.c): { tcgetattr(STDIN_FILENO, &n_tio); // disable canonical mode and local echo n_tio.c_lflag &= (~ICANON & ~ECHO); // pass along SIGINT n_tio.c_lflag |= (ISIG); tcsetattr(STDIN_FILENO, TCSANOW, &n_tio); signal(SIGINT, ihandler); } not sure what would be missing on Alpine Linux?

yilmazdurmaz commented 2 years ago

Alright, from the code part you gave, I found out you have a -g flag to use. I can see my keystrokes and commands,

but now I hit another smaller problem.

My original problem is happening because somewhere gui is not set and this flag apparently sets it in cobra_prep.c at line 1216:

case 'g': gui = 1;

But then program uses another output style defined in cobra_lib.c at line 3565:

if (gui)
{  printf("Ready: \n");
         fflush(stdout);
         if (!fgets(buf, sizeof(buf), stdin))
         {  break;
         }
} else

and then output becomes a bit off :

shell# cobra -g src/cobra.h
1 core, 1 files, 1000 tokens
Ready:
F
  src/cobra.h
Ready:
match int
41 matches
Ready:
q       
shell# 

If you don't have a specific reason for that I think changing it to printf(": "); will make equal output. Currently I made this change to my compilation.

Besides this, I searched all files for gui term, yet I couldn't figure out when and where it is set, let alone how it is even set for compilation in Ubuntu but not set in Alpine compilation.

nimble-code commented 2 years ago

right, the -g (gui) flag isn't meant to be used for command-line use: it's for interacting with a GUI written in ttcl/tk....

yilmazdurmaz commented 2 years ago

@nimble-code

I find a use case example on gnu.org that has the same problem (https://www.gnu.org/software/libc/manual/html_node/Noncanon-Example.html)

And then removed all terminal-related parts, and left with only a loop of reading a character and then writing on the screen. I was actually surprised that the problem was with putchar.

I have found a post about putchar in this stackoverflow post: getch-and-putchar-not-working-without-return

In essence it says:

stdout stream is line buffered ... program is getting the individual characters .. but the output stream is buffering them

proposed solution gives error because of the -std=c99 flag, so I followed keywords in the source code and came up with this solution, replacing fileno(stdout) with STDOUT_FILENO

In cobra_lib.c, before entering the key read loop at line 3591, adding the following line helps to solve the issue in Alpine linux.

    if ( isatty( STDOUT_FILENO ) )  setbuf( stdout, NULL );

As usual, I am not sure if this breaks anything else. Can you please check this and add the fix if suitable?

nimble-code commented 2 years ago

I checked it on my system, and it does seem to work (i.e., not break anything). for now I'll add it into the code in an ifdef ALPINE part, but it can probably be the default. thanks for figuring this out!

ifdef ALPINE

// looks safe to use by default as well
// avoids an issue on alpine linux
if (!gui
&& isatty(STDOUT_FILENO))
{   setbuf(stdout, NULL);
}

endif