How do I port this program from conio to curses? - c

I wrote this simple program on Windows. Since Windows has conio, it worked just fine.
#include <stdio.h>
#include <conio.h>
int main()
{
char input;
for(;;)
{
if(kbhit())
{
input = getch();
printf("%c", input);
}
}
}
Now I want to port it to Linux, and curses/ncurses seems like the right way to do it. How would I accomplish the same using those libraries in place of conio?

#include <stdio.h>
#include <ncurses.h>
int main(int argc, char *argv)
{
char input;
initscr(); // entering ncurses mode
raw(); // CTRL-C and others do not generate signals
noecho(); // pressed symbols wont be printed to screen
cbreak(); // disable line buffering
while (1) {
erase();
mvprintw(1,0, "Enter symbol, please");
input = getch();
mvprintw(2,0, "You have entered %c", input);
getch(); // press any key to continue
}
endwin(); // leaving ncurses mode
return 0;
}
When building your program do not forget to link with ncurses lib (-L lncurses) flag to gcc
gcc -g -o sample sample.c -L lncurses
And here you can see kbhit() implementation for linux.

Related

Why isn't the system() command working for me?

I'm new to c, so I'm probably stupid.
Here is somewhat my code:
#include <stdio.h>
#include <stdlib.h>
int main() {
int input;
setvbuf(stdout, NULL, _IONBF, 0);
printf("Welcome to example");
printf("\n" "Select an option." "\n" "1. ex1" "\n" "2. ex2" "\n");
scanf("%d", &input);
if (input == 1) {
printf ("You selected ex1.");
system("echo 'testing.'");
}
else if (input == 2) {
printf ("You selected ex2.");
}
return 0;
}
If you're wondering, I'm running the exe in MSYS2 with ./a.exe
If I input 1, then it should execute the command echo. However, it does nothing.
How do I fix this?
Edit: Heres the output
You selected ex1.
And then the program ends.
It could be because system uses command prompt (I'm having issues with command prompt...), so how do I switch it to use MSYS2 as the system terminal?

How to get all currently available input with ncurses? [duplicate]

I have been looking for an equivalent to kbhit() and I have read several forums on this subject, and the majority seem to suggest using ncurses.
How should I go about checking if a key is pressed in C++ using ncurses?
The function getch() provided by ncurses reads a character from the window.
I would like to write a function that only checks if there is a key press and then I want to do getch().
You can use the nodelay() function to turn getch() into a non-blocking call, which returns ERR if no key-press is available. If a key-press is available, it is pulled from the input queue, but you can push it back onto the queue if you like with ungetch().
#include <ncurses.h>
#include <unistd.h> /* only for sleep() */
int kbhit(void)
{
int ch = getch();
if (ch != ERR) {
ungetch(ch);
return 1;
} else {
return 0;
}
}
int main(void)
{
initscr();
cbreak();
noecho();
nodelay(stdscr, TRUE);
scrollok(stdscr, TRUE);
while (1) {
if (kbhit()) {
printw("Key pressed! It was: %d\n", getch());
refresh();
} else {
printw("No key pressed yet...\n");
refresh();
sleep(1);
}
}
}

How to process KEY_HOME and KEY_END reliably under ncurses

I am struggling to have ncurses generate KEY_HOME or KEY_END events, instead the raw escape sequence is coming through as a sequence of characters.
The following simple C program illustrates the problem:
#define _XOPEN_SOURCE 700
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
void clean(void)
{
echo();
nl();
nocbreak();
endwin();
}
int main(int argc, char *argv[])
{
setvbuf(stderr, NULL, _IONBF, 0);
initscr();
cbreak();
nonl();
noecho();
atexit(clean);
keypad(stdscr, TRUE);
clear();
refresh();
int ch = getch();
if (ch == ERR)
errx(EXIT_FAILURE, "getch");
warnx("read: %x", ch);
halfdelay(1);
while((ch = getch()) != ERR)
{
warnx("read: %x", ch);
}
exit(EXIT_SUCCESS);
}
Compile with -lncurses, and redirect stderr to a log file.
When pressing HOME:
test: read: 1b
test: read: 5b
test: read: 31
test: read: 7e
When pressing UP
test: read: 103
How come HOME and END (and indeed F1 etc.) are not parsed by ncurses into KEY_HOME?
You probably have set TERM to a value which does not match the terminal's behavior. For instance, the linux terminal description has khome=\E[1~ (which corresponds to the example output), while xterm has khome=\E[OH. You can see this using
infocmp linux xterm | grep khome
If the terminal description does not match the actual behavior, ncurses will not match the incoming bytes, and will behave as shown.

How to do nonblocking input from stdin in C [duplicate]

This question already has answers here:
How to read terminal's input buffer immediately after keypress
(2 answers)
Closed 6 years ago.
I have follow situation I have an program make an set of operations on a file continuously and I want, when a specific key is pressed, to stop and do another set of operations.
For this I tryed use scanf of an character with
fcntl(0, F_SETFL, O_NONBLOCK);
and
while(feof(stdin))
but it doesn't work as expected.
I have searched and in some places someone says to use select but I can't find how to use it.
Anyone can advice me somehow?
my main function to provide more information:
int main(int argc, char *argv[])
{
if(argc>1){
char* password;
char* password2;
printf("Password? ");
password = get_password();
printf("Repita a password? ");
password2 = get_password();
if(strcmp(password,password2)!=0){
printf("Passwords diferentes!\n");
exit(1);
}
FILE *fptr;
fptr = fopen("./regist", "r");
if(fptr == NULL) //if file does not exist, create it
{
fptr = fopen("./regist", "w");
}
fclose(fptr);
if(find_username(argv[1])){
printf("Utilizador ja existe\n");
exit(1);
}
add_user_regist(argv[1],password);
printf("Utilizador %s adicionado.\n",argv[1]);
exit(0);
}
char readbuf[250];
/* Create the FIFO if it does not exist */
umask(0);
mknod(FIFO_FILE, S_IFIFO|0666, 0);
printf("Servidor iniciado.\nEm modo de espera de mensagens\n");
fcntl(0, F_SETFL, O_NONBLOCK);
while(1){
char c = getchar();
if(c=='q' || c=='Q')
exit(0);//by now only goes out
fp = fopen(FIFO_FILE, "r");
fgets(readbuf, 250, fp);
fclose(fp);
if(readbuf[0]=='U')
user_access(readbuf);
else if(readbuf[0]=='W')
who_online(readbuf);
else if(readbuf[0]=='R'){
char* tmp;
strtok(readbuf,":");
tmp = strtok(NULL,";");
remove_online(tmp);
printf("# %s fez logout\n",tmp);
}
else if(readbuf[0]=='F'){
process_msg(readbuf);
}
}
return(0);
}
Check out NCurses, the go-to library for any kind of advanced terminal software.
Among other things, it provides you with the tools to do "raw" terminal I/O -- using int getch( void ), made a non-blocking call via int nodelay( WINDOWS * win, bool bf ).
This blocks:
#include <ncurses.h>
int main()
{
initscr();
printw( "Press a key:\n" );
int c = getch();
endwin();
}
This doesn't (returning ERR if there is no input pending):
#include <ncurses.h>
int main()
{
initscr();
printw( "Press a key:\n" );
nodelay( stdscr, TRUE );
int c = getch();
endwin();
}
Note that NCurses comes with its own set of I/O functions, which you will have to use instead of the <stdio.h> ones (check the printw() above).
An alternative to termios/ncurses using GNU Readline:
#include <readline/readline.h>
#include <stdio.h>
static int func(int count, int key)
{
printf ("key pressed: %c\n", key); /* exec your function */
return 0;
}
int main(void)
{
char *line;
rl_bind_key('x', func); /* 'x' is the specific key */
line = readline ("> ");
printf("%s\n", line);
return 0;
}
Compile using -lreadline

Ctrl+D doesn't stop application from executing in command window

I've written a program to encrypt a given message by XOR. It works, but It doesn't end. Here is the code.(I have created 3 files):
encrypt.h :
void encrypt(char *message);
message_hider.c:
#include <stdio.h>
#include "encrypt.h"
int main() {
char msg[80];
while (fgets(msg, 80, stdin)){
encrypt(msg);
printf("%s", msg);
}
return 0;
}
encrypt.c :
#include "encrypt.h"
void encrypt(char *message) {
while (*message) {
*message++ ^= 0x1f;
}
}
As I mentioned above, It works. but I can't stop it. When I pressed Ctrl+D to stop it (in cmd) It encrypts it also.(I need this code stop after it encrypt a message). Please explain me about this case.
When I pressed Ctrl+D to stop it (in cmd)
If that's the cmd from Windows you probably want Ctrl+Z.
Ctrl-D is used for the console EOF on Unix systems.
Ctrl-Z is used for the console EOF on Windows systems.
isprint() can help:
#include <stdio.h>
#include <ctype.h>
void encrypt(char *message)
{
while (*message) {
*message = *message ^ 31;
message++;
}
}
int main(void)
{
char msg[80];
while (fgets(msg, 80, stdin) != NULL) {
if (!isprint((unsigned char)*msg)) break;
encrypt(msg);
printf("%s", msg);
}
return 0;
}
Add an exit condition:
if( c < 0x20 ) break;
You may need to add other checks also to support backspace without encoding it...
http://www.asciitable.com/
Just run
$> kill -l
To see the list of signals in Linux. You will not find SIGKILL (Ctrl + D) signal there :(
Ctrl + D is SIGKILL (0) signal in Linux which is not documented anywhere.
Ctrl + Z is for Windows which tell EOF and we need to press "Enter" to close.

Resources