I am have implemented the two programs from section 7.6 of http://beej.us/guide/bgipc/output/html/multipage/mq.html.
I have extended it so that there are two receiving programs and which one it goes to is determined by the message type.
The problem arises in the receiving program, B and C. They are supposed to print out the messages entered into program A everytime, however they only print the messages every other time.
This is where the message is sent, it reads the first 6 chars and if it is URGENT it sets the the message type.
buf.mtype = 2;
while(fgets(buf.mtext, sizeof buf.mtext, stdin) != NULL) {
int len = strlen(buf.mtext);
strncpy(typeTest, buf.mtext, 6);
if(strncmp(typeTest, "URGENT", 6) == 0){
buf.mtype = 1;
}
printf("This is the message %s \n", buf.mtext);
/* ditch newline at end, if it exists */
if (buf.mtext[len-1] == '\n') buf.mtext[len-1] = '\0';
if (msgsnd(msqid, &buf, len+1, 0) == -1) /* +1 for '\0' */
perror("msgsnd");
}
This is where the message is received, then the if statement checks the type to then print out.
for(;;) { /* Spock never quits! */
if (msgrcv(msqid, &buf, sizeof buf.mtext, 0, 0) == -1) {
perror("msgrcv");
exit(1);
}
if(buf.mtype == 2){
printf("spock: \"%s\"\n", buf.mtext);
}
}
Can anyone shed some light on why it only prints out every other message?
Thanks.
In your program A you must set buf.mtype to 2 if the input is not "URGENT..." You must do that in the loop, every time.
while(fgets(buf.mtext, sizeof buf.mtext, stdin) != NULL) {
int len = strlen(buf.mtext);
strncpy(typeTest, buf.mtext, 6);
if(strncmp(typeTest, "URGENT", 6) == 0){
buf.mtype = 1;
}
else buf.mtype= 2; // always set the default
printf("This is the message %s \n", buf.mtext);
/* ditch newline at end, if it exists */
if (buf.mtext[len-1] == '\n') buf.mtext[len-1] = '\0';
if (msgsnd(msqid, &buf, len+1, 0) == -1) /* +1 for '\0' */
perror("msgsnd");
}
In your programs B and C you must set msgtyp to 1 or 2 for each program to get the right message from the queue, for example:
int main(argc, argv)
{
int msgtype;
if (*argv[1]=='A')
msgtype= 1;
else if (*argv[1]=='B')
msgtype= 2;
else
msgtype= 0;
...
for(;;) { /* Spock never quits! */
if (msgrcv(msqid, &buf, sizeof buf.mtext, msgtype, 0) == -1) {
perror("msgrcv");
exit(1);
}
if(buf.mtype == msgtype){
printf("spock: \"%s\"\n", buf.mtext);
}
}
return 0;
}
Related
So coded a client which is recieving only chars in the Buffer which I print out afterwards:
//CODE FROM BJ'S GUIDE TO NETWORK PROGRAMMING *1
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("%s",buf);
//MY CODE
while (numbytes > 0) {
numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0);
if (numbytes > 0) {
buf[numbytes] = '\0';
printf("\%s",buf);
}
}
buf is a char[512]-array
I want to also recv() "\0" and "\n" and print them out as "\0" and "\n"
as code this would look like this
printf("this contains a \\n byte and a \\0 byte");
I cannot change something server-sided because So i have to edit the recieving side
*1: https://beej.us/guide/bgnet/
I want to also recv() "\0" and "\n" and print them out as "\0" and "\n"
Do not use string functions on buf. Handle it as an array of characters.
while (numbytes > 0) {
numbytes = recv(sockfd, buf, MAXDATASIZE, 0);
for (i = 0; i < numbytes; i++) {
unsigned char ch = buf[numbytes];
if (ch <= '\n') { // Escape characters 0 to 13
putc('\\');
putc("0123456abtrvfn"[ch]);
} else if (ch == '\\') { // I suspect OP will also want this
putc('\\');
putc('\\');
} else {
putc(ch);
}
}
}
Ok we did it by using fwrite() like this
fwrite(buf, numbytes, sizeof(char), stdout);
So I'm writing a program and there is this bit of code where I have to take the user input in stdin and make a choice of what to do. I've taken the bit of code corresponding to it and made another program (that is bellow) to check if the error keeps on. And it does. The error is when doing if(sscanf(buffer, "%*s %d %s %s%c", &key, succ_ip, succ_gate, &eol) == 4 && eol == '\n'), the second sscanf(), and i've figured that that sscanf() is != 4 witch was the value I was expecting since I'm asking for 4 variables.
The strange part is that it works just fine when strcmp(token, "new") == 0 but when strcmp(token, "sentry") == 0 it doesn't...
If anyone could help me I'dd be very thankful.
Here is the bit of my code where I'm having problems
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 150
int main(){
int key;
char* succ_ip;
succ_ip = (char*)malloc((Max+1)*sizeof(char));
char* succ_gate;
succ_gate = (char*)malloc((Max+1)*sizeof(char));
char* s_succ_ip;
s_succ_ip = (char*)malloc((Max+1)*sizeof(char));
char* s_succ_gate;
s_succ_gate = (char*)malloc((Max+1)*sizeof(char));
char* buffer;
buffer = (char*)malloc((5*Max+1)*sizeof(char));
char* token;
token = (char*)malloc((Max+1)*sizeof(char));
char eol = 0;
int block = 0;
int exit_flag = 0;
while(fgets(buffer, sizeof(buffer), stdin)){
sscanf(buffer, "%s", token);
/*NEW: creating the first server*/
if(strcmp(token, "new") == 0 && block == 0){
if(sscanf(buffer, "%*s %d%c", &key, &eol) == 2 && eol == '\n'){
/*strcpy(succ_ip, argv[1]);
strcpy(succ_gate, argv[2]);
strcpy(s_succ_ip, argv[1]);
strcpy(s_succ_gate, argv[2]);*/
block = 1;
printf("Chave : %d\n", key);
printf("-> Ring created.\n");
}
else{
printf("-> The command \\new is of type \"new i\". Where i is a key.\n");
fflush(stdin);
memset(buffer,0,sizeof(buffer));
memset(token,0,sizeof(token));
}
}
/*ENTRY: ... */
else if(strcmp(token, "entry") == 0 && block == 0){
/* do stuff */
block = 1;
printf("-> Server entered.\n");
}
/*SENTRY: adding a server specifying it's successor */
else if(strcmp(token, "sentry") == 0 && block == 0){
if(sscanf(buffer, "%*s %d %s %s%c", &key, succ_ip, succ_gate, &eol) == 4 && eol == '\n'){
/*test for unique case when there are only 2 servers*/
/*otherwise do the normal procedure*/
/*tcp_client = init_tcp_cl(succ_ip, succ_gate);
tcp_client = request_tcp_cl(tcp_client, "SUCCCONF\n");
close_tcp_cl(tcp_client);*/
printf("Chave : %d\n", key);
printf("Next server ip: %s\n", succ_ip);
printf("Next server ip: %s\n", succ_gate);
block = 1;
printf("-> Server sentered.\n");
}
else{
printf("-> The command \\sentry is of type \"sentry i succ.ip succ.gate\". Where i is a key.\n");
fflush(stdin);
memset(buffer,0,sizeof(buffer));
memset(token,0,sizeof(token));
}
}
/*LEAVE: ... */
else if(strcmp(buffer, "leave\n") == 0 && block == 1){
/* do stuff */
block = 0;
printf("-> Left the ring.\n");
}
/* FALTA ADICIONAR O ESTADO DO SERVIDOR!!! */
else if(strcmp(buffer, "show\n") == 0 && block == 1){
/*printf("-> Key: %d\n-> IP: %s\n-> PORT: %s\n-> SuccIP: %s\n"
"-> SuccPORT: %s\n", key, argv[1], argv[2],
succ_ip, succ_gate);*/
}
/*FIND: ... */
else if(strcmp(token, "find") == 0){
/* do stuff */
}
/*EXIT: exits the application successfully*/
else if(strcmp(buffer, "exit\n") == 0){
printf("\nExiting the application...\n");
exit_flag = 1;
}
/*Invalid command, ignores it*/
else{
printf("-> Invalid command.\n");
}
}
return 1;
}
Like #NateEldredge said:
"sizeof(buffer) returns the size of the variable buffer, which being a char * is likely 4 or 8 bytes."
Which was clearly causing the problem because when I wrote the input like:
sentry 2 127.0.0.1 59001
the buffer wouldn't save all the info. so, of course, the sscanf() function couldn't get all variables. they weren't there.
ps: That fflush() shouldn't be there. I'm sorry...
I am trying to create a client that communicate with a server by sending 2 types of messages:
The word QUIT that communicate to the server to close the connection.
An operation with the following syntax: operator first_operand second_operand. For example: + 3 3, - 5 6 etc. (the operands must be positive integers, and there must be only 2 operands).
If the server receive an operation, it executes it and returns the result to the client. The problem is that the first operation I send returns the right result, while the following ones work randomly (sometimes they return the right result, other times the function strtok() doesn't get the second operand and returns NULL...).
This is code of the client that process the message written by the user in the prompt and that scan the message to check if the operation is written with the correct syntax (WARNING: the code is written in an extremely unprofessional and unclean way).
The code part that creates the problem is inside the while(1).
#define MAXLENGTH 256
int main (int argc, char *argv[]) {
int simpleSocket = 0;
int simplePort = 0;
int returnStatus = 0;
char first[10], second[10];
char* operator;
char buffer[MAXLENGTH] = "";
char message[50];
char terminationCommand[] = "QUIT\n";
char space[2] = " ";
struct sockaddr_in simpleServer;
if (3 != argc) {
fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
exit(1);
}
/* create a streaming socket */
simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (simpleSocket == -1) {
fprintf(stderr, "Could not create a socket!\n");
exit(1);
} else {
fprintf(stderr, "Socket created!\n");
}
/* retrieve the port number for connecting */
simplePort = atoi(argv[2]);
/* setup the address structure */
/* use the IP address sent as an argument for the server address */
//bzero(&simpleServer, sizeof(simpleServer));
memset(&simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family = AF_INET;
//inet_addr(argv[2], &simpleServer.sin_addr.s_addr);
simpleServer.sin_addr.s_addr=inet_addr(argv[1]);
simpleServer.sin_port = htons(simplePort);
/* connect to the address and port with our socket */
returnStatus = connect(simpleSocket, (struct sockaddr *)&simpleServer, sizeof(simpleServer));
if (returnStatus == 0) {
fprintf(stderr, "Connect successful!\n\n");
} else {
fprintf(stderr, "Could not connect to address!\n");
close(simpleSocket);
exit(1);
}
/* get the message from the server */
returnStatus = read(simpleSocket, buffer, sizeof(buffer));
if (returnStatus > 0) {
printf("%s\n", &buffer[3]);
} else {
fprintf(stderr, "Return Status = %d \n", returnStatus);
}
memset(&buffer, '\0', sizeof(buffer));
printf("You can execute 2 commands:\n");
printf("1. Operations ( +, -, *, /, % ) with the following syntax: operator + first operand + second operand.\n");
printf("Example: + 5 2 \n");
printf("2. Termination of the connection with the following syntax: QUIT + press Enter.\n");
while(1) {
printf("\nEnter a command:\n");
fgets(message, 1000, stdin);
// the if with the termination command works fine
if (strcmp(message, terminationCommand) == 0) {
if (send(simpleSocket, message, strlen(message), 0) < 0) {
printf("Send failed.");
return 1;
}
returnStatus = read(simpleSocket, buffer, sizeof(buffer));
if (returnStatus > 0) {
printf("%s\n", &buffer[4]);
} else {
fprintf(stderr, "Return Status = %d \n", returnStatus);
}
close(simpleSocket);
exit(1);
}
operator = strtok(message, space);
if (strcmp(operator, "+") == 0 || strcmp(operator, "-") == 0 || strcmp(operator, "/") == 0 || strcmp(operator, "%") == 0 || strcmp(operator, "*") == 0) {
char *first_operand = strtok(NULL, space);
if (first_operand != NULL) {
if (strcmp(first_operand, "ANS") == 0)
strcpy(first, "ANS");
else
strcpy(first, first_operand);
printf("%s\n", operator);
printf("%s\n", first);
char *second_operand = strtok(NULL, space);
printf("%s\n", second_operand);
if (second_operand != NULL && strtok(NULL, space) == NULL && (atoi(first) > 0 || strcmp(first, "ANS") == 0)) {
if (strcmp(second_operand, "ANS\n") == 0)
strcpy(second, "ANS");
else {
strcpy(second, second_operand);
}
if (atoi(second) > 0 || strcmp(second, "ANS") == 0) {
printf("OK\n");
char operation[] = "";
strcat(operation, operator);
strcat(operation, " ");
strcat(operation, first);
strcat(operation, " ");
strcat(operation, second);
if (send(simpleSocket, operation, strlen(operation), 0) < 0) {
printf("Send failed.");
return 1;
}
returnStatus = read(simpleSocket, buffer, sizeof(buffer));
if (returnStatus > 0) {
printf("%s\n", buffer);
} else {
fprintf(stderr, "Return Status = %d \n", returnStatus);
}
}
}
}
}
// after everything I reset the buffers I use to memorize the message and the elements of the message
memset(&buffer, '\0', sizeof(buffer));
memset(&first, '\0', sizeof(first));
memset(&second, '\0', sizeof(second));
memset(&message, '\0', sizeof(message));
memset(operator, '\0', sizeof(operator));
}
}
Can someone tell me why the second strtok() acts weird 90% of the times? What am I doing wrong?
There are multiple issues in you program:
You send newline terminated messages and you assume on the other end the read will return exactly the bytes sent by the other party, which is an incorrect assumption for the TCP/IP communications, only the order of bytes received is guaranteed, but the messages can be split on the way and received in chunks different from the sending sequence. You should instead read the socket into a buffer and only handle it once you receive a newline.
In your case, there is another problem which is more pressing: the buffer into which you read the data is not null terminated, so you should not pass it to standard C functions such as strtok().
I want to implement a simple TCP server with blocking read, that receives messages sent from a client character by character until a separator. Once a message is received, it has to wait until the next message appears. Here is my pseudocode:
// Messages sent from the client
char *message1 = "mssg1\n"
char *message2 = "mssg2\n"
// On server side
char buffer;
char completeMessage[5]
while(1){
while(buffer != '\n'){
recv(sock, &buffer, 1, 0); // 1 is the read size
if(buffer != '\n') {
printf("buffer: %c\n", buffer);
completeMessage[n] = buffer;
count ++;
}
else{
printf("Complete message: %s\n", completeMessage);
count = 0;
}
}
}
And the result is the following:
buffer: m
buffer: s
buffer: s
buffer: g
buffer: 1
Complete message: mssg1
buffer:
buffer:
buffer:
buffer:
buffer:
buffer:
// Error due to buffer overflow
I don't know why recv instead of waiting for the next message character (blocking read), it continues reading blank spaces. My questions are the following:
Is recv really a socket blocking read function?
Is there something wrong or missing in the code?
Any other suggestions for implementing this?
Is recv really a socket blocking read function?
Yes, unless you made the handle non-blocking.
Is there something wrong or missing in the code?,
You're not checking what recv returns. 0 indicates EOF, and -1 indicates an error.
You don't check how full your buffer is, so you risk buffer overflows.
You're not terminating the string in completeMessage with a NUL as required by printf %s.
Any other suggestions for implementing this?
You shouldn't read a character at a time!
#define BUFFER_SIZE (64*1024)
char* extract_string(const char* start, const char* end) {
size_t len = end - start;
char* dst = malloc(len+1);
if (dst == NULL)
return NULL;
memcpy(dst, src, len);
dst[len] = '\0';
return dst;
}
{
char buf_start[BUFFER_SIZE];
char* buf_end = buf_start + BUFFER_SIZE;
char* window_start = buf_start;
char* window_end = buf_start;
while (1) {
if (window_end == buf_end) { // No more space.
fprintf(stderr, "Overly large message");
return 0;
}
ssize_t rv = recv(sock, window_end, buf_end-window_end, 0);
if (rv == -1) { // Error.
perror("recv");
return 0;
}
if (rv == 0) { // EOF.
return 1;
}
while (rv--) {
if (*(window_end++) == '\n') {
char* msg = extract_string(window_start, window_end-1); // Excl LF.
if (msg == NULL) {
fprintf(stderr, "Out of memory");
return 0;
}
// Do something with msg
printf("Complete message: %s\n", msg);
free(msg);
window_start = window_end;
}
}
memmove(buf_start, window_start, window_end-window_start);
window_end -= (window_start - buf_start);
window_start = buf_start;
}
}
There are quite a number of problems with your code, namely that you are ignoring the return value of recv(), you are not null-terminating your buffer before printing it, and you are not protecting yourself from a buffer overflow.
Try something more like this instead:
char ch, *tmp, *message = NULL;
int ret, length = 0, allocated = 0;
while (1)
{
ret = recv(sock, &ch, 1, 0);
if (ret <= 0)
{
if (ret < 0)
printf("Read error: %d\n", errno); // or WSAGetLastError() on Windows
else
printf("Client disconnected\n");
break;
}
if (ch == '\n')
{
if ((length > 0) && (message[length-1] == '\r'))
--length;
printf("Complete message: '%.*s'\n", length, message);
length = 0;
}
else
{
printf("ch: %c\n", ch);
if (length == allocated)
{
if (length >= 5000) // some max length of your choosing...
{
printf("Message length too large!\n");
break;
}
// just for example. You should use a more robust growth algorithm in production code...
tmp = (char*) realloc(message, allocated + 10);
if (!tmp)
{
printf("Memory allocation failed\n");
break;
}
message = tmp;
allocated += 10;
}
message[length] = ch;
++length;
}
}
free(message);
Alternatively, don't read char-by-char. Read as much data as you can from the socket on any given read and store it all in a growing buffer, and then scan that buffer for complete messages, eg:
char *buffer = (char*) malloc(100);
if (!buffer)
{
printf("Memory allocation failed\n");
}
else
{
int ret, offset, remaining, inbuf = 0, allocated = 100;
char *ptr;
while (1)
{
if (inbuf == allocated)
{
if (inbuf >= 5000) // some max length of your choosing...
{
printf("Buffer length too large!\n");
break;
}
// just for example. You should use a more robust growth algorithm in production code...
tmp = (char*) realloc(buffer, allocated + 100);
if (!tmp)
{
printf("Memory allocation failed\n");
break;
}
buffer = tmp;
allocated += 100;
}
ret = recv(sock, buffer+inbuf, allocated-inbuf, 0);
if (ret <= 0)
{
if (ret < 0)
printf("Read error: %d\n", errno); // or WSAGetLastError() on Windows
else
printf("Client disconnected\n");
break;
}
printf("Received: %.*s\n", ret, buffer+inbuf);
inbuf += ret;
while (ptr = (char*)memchr(buffer, '\n', inbuf))
{
offset = (ptr-buffer);
if ((offset > 0) && (buffer[offset-1] == '\r'))
--offset;
printf("Complete message: '%.s'\n", offset, buffer);
++ptr;
remaining = (inbuf - (ptr - buffer));
if (remaining > 0)
memmove(buffer, ptr, remaining);
inbuf = remaining;
}
}
free(buffer);
}
I wrote a C application for a socialization network and also a simple room-based chat. I used ncurses, sockets and basic networking stuff.
The problem is that my function uses select() to read from server socket AND stdin so when I start to write a message, the output window freezes and only shows messages from other clients after I hit enter.
I tried everything possible .. Is there a way to fix this ?
I also tried to force nocbreak().It works okay but if I do that, when I write the message, the echoing is disabled and nothing shows up in the input window as I type, even though the message is there but like "invisible".
Here is the code :
ssize_t safePrefRead(int sock, void *buffer)
{
size_t length = strlen(buffer);
ssize_t nbytesR = read(sock, &length, sizeof(size_t));
if (nbytesR == -1)
{
perror("read() error for length ! Exiting !\n");
exit(EXIT_FAILURE);
}
nbytesR = read(sock, buffer, length);
if (nbytesR == -1)
{
perror("read() error for data ! Exiting !\n");
exit(EXIT_FAILURE);
}
return nbytesR;
}
ssize_t safePrefWrite(int sock, const void *buffer)
{
size_t length = strlen(buffer);
ssize_t nbytesW = write(sock, &length, sizeof(size_t));
if (nbytesW == -1)
{
perror("write() error for length ! Exiting !\n");
exit(EXIT_FAILURE);
}
nbytesW = write(sock, buffer, length);
if (nbytesW == -1)
{
perror("write() error for data ! Exiting !\n");
exit(EXIT_FAILURE);
}
return nbytesW;
}
void activeChat(int sC, const char *currentUser, const char *room)
{
char inMesg[513], outMesg[513];
char user[33];
int winrows, wincols;
WINDOW *winput, *woutput;
initscr();
nocbreak();
getmaxyx(stdscr, winrows, wincols);
winput = newwin(1, wincols, winrows - 1, 0);
woutput = newwin(winrows - 1, wincols, 0, 0);
keypad(winput, true);
scrollok(woutput, true);
wrefresh(woutput);
wrefresh(winput);
fd_set all;
fd_set read_fds;
FD_ZERO(&all);
FD_ZERO(&read_fds);
FD_SET(0, &all);
FD_SET(sC, &all);
wprintw(woutput, "Welcome to room '%s' \n Use /quitChat to exit !\n!", room);
wrefresh(woutput);
while (true)
{
memcpy( &read_fds, &all, sizeof read_fds );
if (select(sC + 1, &read_fds, NULL, NULL, NULL) == -1)
{
perror("select() error or forced exit !\n");
break;
}
if (FD_ISSET(sC, &read_fds))
{
memset(inMesg, 0, 513);
safePrefRead(sC, user);
safePrefRead(sC, inMesg);
wprintw(woutput, "%s : %s\n", user, inMesg);
wrefresh(woutput);
wrefresh(winput);
}
if (FD_ISSET(0, &read_fds))
{
//wgetnstr(winput, "%s", outMesg);
int a, i = 0;
while ( i < MAX_BUF_LEN && (a = wgetch(winput)) != '\n')
{
outMesg[i] = (char)a;
i++;
}
outMesg[i] = 0;
if (outMesg[0] == 0)
continue;
if (strcmp(outMesg, "/quitChat") == 0)
{
safePrefWrite(sC, outMesg);
break;
}
safePrefWrite(sC, outMesg);
delwin(winput);
winput = newwin(1, wincols, winrows - 1, 0);
keypad(winput, true);
wrefresh(winput);
}
}
delwin(winput);
delwin(woutput);
endwin();
}
-safePrefWrite and safePrefRead are wrappers for prexied read / write and error treating
-sC is the server socket.
LE: I tried using fork and threads. Using fork was behaving the same and threads were a disaster, the terminal was messed up.
Thank you.
modify the while(true) loop to only handle one char at a time for the stdin.
Which mostly means for stdin, read a single char:
if char is '\n' then handle as currently,
otherwise, just append char to the buffer to write.
Always, before appending a char to buffer to write, check that buffer is not full.
add code to handle the case where the buffer to write is full
end the function with this sequence:
delwin(winput);
delwin(woutput);
endwin();
endwin();
to end both windows.
Do not call endwin() during processing of the socket input.
Do not call endwin() when select() returns an error condition
the fd_set is not an intrinsic size in C, so use memcpy() to set
read_fds from all. suggest:
memcpy( &read_fds, &all, sizeof read_fds );
the parameter: currentUser is not used, suggest inserting the line:
(void)currentUser;
to eliminate a compiler warning message.
for readability, and ease of understandability, suggest #define the magic numbers 513 and 33 with meaningful names, then use those meaningful names throughout the code.
#define MAX_BUF_LEN (513)
#define MAX_USER_LEN (33)
this line: outMesg[i] = a; raises a compiler warning, suggest:
outMesg[i] = (char)a;
This line: while ( (a = wgetch(winput)) != '\n') can allow the buffer outMesg[] to be overrun, resulting in undefined behaviour and can lead to a seg fault event. suggest:
while ( i < MAX_BUF_LEN && (a = wgetch(winput)) != '\n')
Suggest posting the prototypes for the safePrefWrite() and safePrefRead() functions, similar to:
void safePrefRead( int, char * );
void safePrefWrite( int, char * );
As noted by #user3629249, there are several criticisms which can be applied to the sample code. However, OP's question is not addressed by those improvements.
OP seems to have overlooked these functions:
cbreak or raw, to make wgetch read unbuffered data, i.e., not waiting for '\n'.
nodelay or timeout, to control the amount of time wgetch spends waiting for input.
By the way, making select work with a curses program will make assumptions about the curses library internal behavior: getting that to work reliably can be troublesome.
Fixed it finally by using only the big loop.
Here is the code if anyone has the same problem in the future :
if (FD_ISSET(0, &read_fds))
{
inChar = wgetch(winput);
if (inChar == 27)
{
safePrefWrite(sC, "/quit");
break;
}
if (inChar == KEY_UP || inChar == KEY_DOWN || inChar == KEY_LEFT || inChar == KEY_RIGHT)
continue;
if (inChar == KEY_BACKSPACE || inChar == KEY_DC || inChar == 127)
{
wdelch(winput);
wrefresh(winput);
if (i != 0)
{
outMesg[i - 1] = 0;
i--;
}
}
else
{
outMesg[i] = (char)inChar;
i++;
}
if (outMesg[i - 1] == '\n')
{
outMesg[i - 1] = 0;
i = 0;
if (outMesg[0] == 0)
continue;
if (strcmp(outMesg, "/quit") == 0)
{
safePrefWrite(sC, outMesg);
break;
}
safePrefWrite(sC, outMesg);
delwin(winput);
winput = newwin(1, wincols, winrows - 1, 0);
keypad(winput, true);
wrefresh(winput);
memset(outMesg, 0, 513);
}
}
I also use raw() to disable signals and to treat the codes how I want.
Anything else above and below this "if" is just like in the 1st post.