C - Color characters in console window (Linux) - c

I'm building a server and client (chatroom) in Linux, and I want to colorize one word (the username) in the character buffer that echoes in the client. Here how the buffer is echoed when a user enters the chat:
strncpy(clients[clientIndex].username, buf, BUF_SIZE); // copy buffer to username
bzero(buf, BUF_SIZE); // zero out buffer
strncpy(buf, "User added to chat.", BUF_SIZE); // new user added
strncpy(buf, "Welcome, ", 9); // add welcome message to buffer
// concatenate so that the buffer reads "Welcome, [username]"
strncat(buf, clients[clientIndex].username, BUF_SIZE - 9);
The only method I know of coloring text is:
#define KMAG "\x1B[35m"
.
.
.
printf(KMAG "Welcome\n");
But obviously I am not using printf() since the server and client must send and receive these messages. I need a way to color only one word in the buffer. I imagine something that might look like this:
strcpy(clients[clientIndex].username, KMAG);
Where I can assign a color to characters themselves, and not just change the way it is printed.
Does such a method of coloring text exist?
EDIT: my mistake. I am using printf... just very unsure how to implement a color on certain characters in the buffer I am printing
This is how the code is printed in client:
void recvMessageFromServer() {
while (1) {
/* print the server's reply */
n = recvfrom(sockfd, buf, BUFSIZE, 0, (struct sockaddr *) &serveraddr,
&serverlen);
if (n < 0)
error("ERROR in recvfrom");
printf("%s\n", buf);
}
}

the server 'could' set the colors by:
strcat( buf, '%s", "\x1B[35m" );
strncat( buf, "clients[clientIndex].username, 9);
strcat( buf, "%s", "\x1b[30m" );
which will set the 'username' (limited to 9 characters) text to magneta, then set any following text to black

Related

How to properly concatenate a string received in parts?

I'm using sockets in C, I have a client that will send a message and the size of the message and the server that will receive this message in buffers of shorter size. The message is being sent correctly, but I'm having problems when I try to concatenate all the buffers in a single string.
The client:
char *buffer = "Hello from the client you're receiving this message";
int bytes_sent;
long msgSize = strlen(buffer);
printf("Buffer Size: %ld\n", msgSize);
int msgFileSize = send(SocketFD, &msgSize, sizeof(msgSize),0);
bytes_sent = send(SocketFD, buffer, strlen(buffer), 0);
The server:
char buffer[8];
ssize_t recsize;
long msgSize;
int msize = recv(ConnectFD, &msgSize, sizeof(msgSize), 0);
int total_byt = 0;
printf("Full Message Size: %ld\n", msgSize);
char full_msg[msgSize];
while (total_byt < msgSize) {
recsize = recv(ConnectFD, (void*)buffer, sizeof buffer, 0);
total_byt += recsize;
strcat(full_msg, buffer);
if (recsize < 0) {
fprintf(stderr, "%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
printf("recsize: %d\n ", (int)recsize);
sleep(1);
printf("datagram: %.*s\n", (int)recsize, buffer);
}
printf("full message: %s\n", full_msg);
The output of the server looks like this:
Full Message Size: 51
recsize: 8
datagram: Hello fr
recsize: 8
datagram: om the c
recsize: 8
datagram: lient yo
recsize: 8
datagram: u're rec
recsize: 8
datagram: eiving t
recsize: 8
datagram: his mess
recsize: 3
datagram: age
full message: ��9�Hello from the client you're receiving this message mess
Few problems here.
strlen returns length excluding the null char.
long msgSize = strlen(buffer);
Thus you need to have 1 additional place to hold null char.
char full_msg[msgSize+1];
full_msg[0] = '\0';
There is undefined behavior with strcat as buffer is not null terminated.
recsize = recv(ConnectFD, (void*)buffer, sizeof buffer, 0);
strcat(full_msg, buffer);
use
strncpy(full_msg, buffer, sizeof buffer);
Finally null terminate the full_msg after loop to be sure.
while (total_byt < msgSize) {
….
}
full_msg[total_byt] = '\0';
It looks like your full message variable is not initialized. It is starting out with random data in it, which is causing your unexpected results. Use the following code to initialize it:
char full_msg[msgSize] = "";
Also, using strcat in the way you are is not safe. You must keep track of how much space is left in full_msg or you will have a buffer overrun situation. strncat is the function that can solve this problem.
There's absolutely no point reading into a separate buffer and then concatenating that into another buffer. Just read directly into full_msg.
Even if you were going to append block by block, strcat is not the right way to do it. strcat needs to start by finding the current end of the output buffer, which it can only do by sequentially scanning from the beginning looking for a NUL byte. As the buffer gets more and more data, those scans get longer and longer, leading to quadratic time complexity. This particular unnecessarily quadratic append is often called a "Schlemiel the Painter" algorithm.
The scan is unnecessary because you already know where the new data should be appended, since you carefully keep track of how many bytes you've already read. So each successive block should be placed total_byt bytes past the beginning of the buffer. (That is, at location full_msg+totalbyt.) You also know how long the data to append is, so you can use memcpy to put the newly-read chunk in the right place.
Uding memcpy will also avoid the problems which will occur if data can contain NUL bytes. (Since strcat returns immediately when it encounters a NUL, your current code will not work on messages which do include NUL.)
Note thatrecv does not NUL-terminate the input received, so your strcat will also do the wrong thing if the recv doesn't fill the buffer (and it only works with the buffer as written because it happens to be the case that
There is at least one other problem with your code: nothing guarantees that recv will stop reading at the end of a message, since the sockets library doesn't know where TCP messages end. (UDP message endpoints are marked, but you can't receive a UDP message in multiple chunks.) Again, since you keep track of the number of bytes read, and you know the length of the message (once you've read that data, at least), you can easily work out what the maximum number of bytes to read is.

C Socket Reading TOO MUCH Data

I am making a server that should be able to accept requests from multiple clients. To ensure I am reading large requests properly, I made the below code segment.
Requests come in the form <START_REQUEST>a long message<END_REQUEST>
read(fd, buffer, BUFFER_SIZE);
// Keep Reading If Entire Message Not Recieved
int buffer_len = strlen(buffer);
char *end_tag = &buffer[buffer_len-strlen("<END_REQUEST>")];
while(strcmp(end_tag, "<END_REQUEST>") != 0) {
char *temp_buffer;
temp_buffer = malloc(BUFFER_SIZE);
valread = read(fd, temp_buffer, BUFFER_SIZE);
strcat(buffer, temp_buffer);
free(temp_buffer);
buffer_len = strlen(buffer);
end_tag = &buffer[buffer_len-strlen("<END_REQUEST>")];
}
However, sometimes (very often) the contents of buffer are something like:
<START_REQUEST>a long message<END_REQUEST>somegarbagedataheremaybefromanotherequest?
and thus the loop never terminates.
Why might this be happening?
How are you expecting strcat to know how many bytes to append onto the buffer?
valread = read(fd, temp_buffer, BUFFER_SIZE);
strcat(buffer, temp_buffer);
After the call to read, valread holds the number of bytes you read and it's the only thing that holds this information. However, you attempt to append data read onto the existing buffer without using this value -- so there is no possible way strcat could conceivably know how many bytes to append onto the buffer. It's no wonder you append junk that you read before.
Similar problem here:
read(fd, buffer, BUFFER_SIZE);
// Keep Reading If Entire Message Not Recieved
int buffer_len = strlen(buffer);
Here you ignore the return value of read, so you have no way to know how many bytes you read. How are you expecting strlen to figure out how many bytes read put into the buffer?

Read value from variable

I am trying to assign a string or an int to msg to send it later to a server. This code is in the client.
char msg[100];
int a;
.
.
.
bzero (msg, 100);
printf ("[client]your message: ");
fflush (stdout);
read (0, msg, 100);
/* sending message to server */
if (write (sd, msg, 100) <= 0)
{
perror ("[client]Error write() to server.\n");
return errno;
}
My question is how can I send the variable 'a', instead of writing a message from the command line.
sprintf(msg, "%d\n", a);
...
write(sd, msg, strlen(msg));
This assumes the client is expecting a string of digits (representing an integer) followed by a newline. I arbitrarly chose a newline delimiter, but you must have some convention by which the server knows what the heck you're sending.
I think you're a little confused about what is going on in your program. First, let's start with write().
The signature for the write() function is as follows:
ssize_t write(int fd, // a file descriptor
const void *buf, // a void * containing the payload
size_t count // the number of bytes of data to write
);
So what you have right now is:
read (0, msg, 100); // read from stdin a ascii message up to 100 bytes
/* sending message to server */
if (write (sd, msg, 100) <= 0) // write to a file descriptor (sd) the message
// if it works, it should return the number of bytes
// written
Now as far as I can tell, what you're saying is that you want to send the integer a instead of the char buffer msg. That's very easy to do:
int a = 0;
write(sd, &a, sizeof(a)); // send over the file descriptor "sd"
// you need a pointer for the second variable so use the &
// to get the address of a, then you need to identify
// the number of bytes to send, so use the sizeof macro
That will send a single integer over the socket.
You will likely need to be careful of endian issues using this approach for multibyte values (such as integers). From that perspective you might be better using an array of chars (shift in the values) so you know what to expect on the other end.
To be very blunt:
int a = rand(); // a random integer (assuming required headers and proper seeding)
char *msg = "Hello"; // a string
write(sd, &a, sizeof(a)); // write the integer
write(sd, msg, strlen(msg)+1); // write a string (strlen + 1 for the null terminator)

Can't print whole content in C

Got a huge problem. Let's say, that I have pointer to a large string (~1500 characters) and I want to print it. What I get in the result is only a part of that string. After the program prints that part it asks me for a newline. After I press enter the program prints the rest of the string and terminates. It happens when I try to run my program in terminal or with IDE. If I try to debug it, it works perfectly. I need it to print whole string without terminating the program. So, here's the code (there's lots of mistakes in the code):
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netdb.h>
#include<string.h>
#define SOCKET int // Apibreziame sinonima 'int' tipui, kad butu
// unix ir WIN sistemoms bendras kodas dirbant
// su soketu deskriptoriais.
#define closesocket close // Apibreziame sinonima close () funkcijai
// closesocket (), kuris yra analogas Windows
// tipo sistemose. Tai del kodo suvienodinimo.
#define INVALID_SOCKET -1 // Apibreziame del kodo suvienodinimo, klaidos
#define SOCKET_ERROR -1 // situacijai nusakyti konstantas, kurios WINSOCK'o
#define MAX_CH 255
#define POP3_PORT 110
#define MAXLEN 1024
int main()
{
SOCKET socketE;
struct sockaddr_in servaddr;
struct hostent* h = NULL;
char* Packet = NULL;
Packet = (char*)malloc(MAX_CH);
memset(Packet, 0, sizeof(Packet));
printf("POP3 server: ");
gets(Packet);
/*******{
client connects to the mail server and other stuff
server sends greeting message
client receives greeting message
}*******/
if (!strstr(Packet,"+OK")) {
print_error(Packet);
}
else {
printf("%s", Packet);
int printedData = 0;
while (1) {
Packet = (char*)realloc(NULL, 1);
memset(Packet, 0, sizeof(Packet));
gets(Packet);
strcat(Packet, "\n");
if (SOCKET_ERROR == SendPacket(&socketE, Packet)) {
print_error("Error on sending data to mail server.\n");
}
memset(Packet, '\0', sizeof(Packet));
if (SOCKET_ERROR == ReceivePacket(&socketE, &Packet)) {
print_error("Error on receiving data from mail server.\n");
}
if (!strstr(Packet,"+OK")) {
fwrite(Packet, 1, strlen(Packet), stdout);
break;
}
printf("%s", Packet); //THIS IS WHERE THE PRINT PART COMES
}
}
close(socketE);
return 0;
}
Okey, so I have found out that this if clause (I mean, even if this if is false) stops program from printing all the content. If I remove/comment it, I got my program working correctly. Is it possible, that this one causes all the problems?
if (!strstr(Packet,"+OK")) {
fwrite(Packet, 1, strlen(Packet), stdout);
break;
}
This:
Packet = (char*)realloc(NULL, 1);
memset(Packet, 0, sizeof(Packet));
causes undefined behavior. It allocates a single byte (why would you ever do this?) and then clears sizeof(Packet) bytes, which on most typical systems today is either 4 or 8 bytes. Thus, it writes outside the allocated memory. Note that sizeof cannot track dynamic allocations, so this whole pattern is wrong.
Also, please note that dynamic memory allocation can fail; you must check the return value of every call to realloc() before relying on the returned pointer being valid. If it's NULL, you can't access through it.
Further, just like with malloc(), please don't cast the return value of realloc() in C.
Try to add flush after printf:
printf("%s", Packet);
fflush(stdout);
printf use stdout, which is line buffered. So printf texts can be partly flushed (printed) if there is no '\n' in the end of the string.
In your case unflushed text is flushed when you type the newline.
Stdout is line buffered and characters in the stdout stream are saved until a newline is output or input is read from any stream attached to a terminal device, or if the stream buffer gets full.
so you may either put the '\n' character in your printf like printf("%s\n",Packet); or just disable the stdout buffering using setbuf(stdout, NULL); for printf to print the complete string

recv returns old data

This loop is supposed to take data from a socket line by line and put it in a buffer. For some reason, when there is no new data to return, recv returns the last couple lines it got. I was able to stop the bug by commenting out the first recv, but then I cant tell how long the next line will be. I know it's not a
while(this->connected){
memset(buf, '\0', sizeof(buf));
recv(this->sock, buf, sizeof(buf), MSG_PEEK); //get length of next message
ptr = strstr(buf, "\r\n");
if (ptr == NULL) continue;
err = recv(this->sock, buf, (ptr-buf), NULL); //get next message
printf("--%db\n%s\n", err, buf);
tok[0] = strtok(buf, " ");
for(i=1;tok[i-1]!=NULL;i++) tok[i] = strtok(NULL, " ");
//do more stuff
}
The manual states:
MSG_PEEK
This flag causes the receive operation to return data from the
beginning of the receive queue without
removing that data from the queue.
Thus, a subsequent receive call will
return the same data.
So I think you're getting the correct behavior, but perhaps expecting something else.
Your problem is that when you use recv with MSG_PEEK, you are giving recv the whole size of your buffer, if there are two lines already there, like "HELLO\r\nHELLO\r\n" it will read them into your buff.
ptr would point to the first \r\n, then you call recv with (ptr - buff) which will make recv to read only the first HELLO, into buf, but since you already READ that info into buff, you will process the two lines, but leaving \r\nHELLO\r\n in your queue, because you did not fully read them.
Next time you would peek into it and have info hanging that you already processed, leading you to believe that you are getting repeated data.
(I hope I wrote this clear enough, it is a very confusing bug you got there :)
I needed to add 2 to the length of the second recv so I'd take the "\r\n". Otherwise, it sees the first "\r\n" and thinks the line of the end is buf[0].
Hi i find the solution :
void receiver(int accepted_client) {
// Ready to receive data from client.
while (true) {
char buffer[256];
recv(accepted_client, &buffer, 255, 0);
int sum = 0;
for (int i = 0; i < 256; i++) // Check that buffer value is zero or not.
sum |= buffer[i];
if (sum != 0) {// If buffer value is not zero then start to print the new received message.
string string_message(buffer);
cout << string_message << endl;
}
memset(&buffer, 0, 256); // Clear the buffer.
}
}

Resources