recvfrom - How to convert buffer to string - c

I'm currently learning the network programming with C/C++... I have experience .NET but not in C (esp: in Unix network programming)
The problem that I'm facing right now is that when I receive the message, I like to split it into two parts. The format of message will be like [command] filepath (For example: get a.txt or put a.txt)
I'm using recvform to receive the message.
int recvfrom(int sockfd, void *buf, int len, unsigned int flags,
struct sockaddr *from, int *fromlen);
The problem is that I dont know how to convert "void *buff" into string so that I can do String.Split(" ") to get the command and file name.
Could anyone please explain me a way to convert "void *buff" to string?

You actually pass the pointer to the start of a character array as the buffer. The recvfrom() system call writes into that array. You then process the array as a character string - after ensuring that it is properly null terminated (which recvfrom() will not do). Of course, the sending end has to put the data on in a compatible format, but the recvfrom() will give you what the sender sent you.
So, the direct answer is "You don't convert the void * into a character string; you convert the character string into a void * by passing it to recvfrom()".

You will want a character buffer and the size of the buffer. Like this:
char buf[1024];
const size_t buf_len = sizeof(buf);
Then you can call recvfrom like so:
ssize_t r;
r = recvfrom(sock, buf, buf_len-1, flags, &sock_from, &sock_from_len);
if(r<0) {
handle_error(r);
} else if(r == 0) {
handle_closed_socket(sock);
} else {
buf[r] = '\0';
}
The buf[r] = '\0'; will guarantee that your buffer is a proper null-terminated C string. Then you can pass buf around as a string.

C is not C++. There's no string class. The strtok function might help you get what you want, assuming you null terminate your buffer manually.

Related

How to call a void pointer-type function in C

I'm writing a socket program and trying to parse command line arguments from the user. Let's say I have a function that looks like this:
void *parseUserReq(char *arg)
{
int sock;
char buffer[1024];
int readIn;
char *str1, *str2, *str3;
//cast sock back to int
sock = (int)arg;
//Get input from client
readIn = recv(sock, buffer, 1024, 0);
buffer[readIn] = '\0';
//parse the 3 strings the user is supposed to enter
str1 = (char*)malloc(sizeof(buffer)+1);
strcpy(str1, buffer); // copy header data into str1
str1 = strtok(str1, " ");
printf("%s\n", str1);
str2 = strtok(str2, " ");
printf("%s\n", str2);
str3 = strtok(str3, "\r\n");
printf("%s\n", str3);
} // End of parseUserReq
How would I call that function in main? Currently I'm doing something like this:
int main(int argc, char** argv)
{
// ^^^Calls for create, bind, listen, accept, and send^^^
char buffer[1024];
parseUserReq(buffer); // segmentation fault
return 0;
}
I can add my code for creating and binding the socket, and listening, accepting,sending if necessary.
EDIT: Just spent a while on this, and found that the issue is more complex than I initially described. I will use Valgrind to identify the source of the problem, or just rewrite the function entirely in accordance with your commentary. I'll hunt around for answers more extensively before posting next time.
Thanks again for the help everyone!
str1 = (char*)malloc(sizeof(buffer)+1);
strcpy(str1, buffer); // copy header data into str1
recv didn't null-terminate buffer. recv returns the number of bytes received. Therefore:
str1 = (char*)malloc(readIn);
memcpy(str1, buffer, readIn); // copy header data into str1
str1[readIn] = 0;
Incidentally, recv probably failed due to
sock = (int)arg;
You need to pass the buffer and socket as two different arguments.
You are about to find out there's a host of problems with this model but something's gotta run so you can learn it.
You declared your function to return a void POINTER not only void which you probably meant.
Either redefine your function or, if you really want a pointer back, declare a void pointer where it's called and assign the return value to that pointer.
In the answer I assume that within the function everything is fine.

Passing a char buffer to function

I have some problems with a pointer. My idea was to pass a buffer to a function in order to store the return data in this buffer. But, I do not know if it will work.
void main()
{
char *buf = malloc(sizeof(char) *buf);
memset(buf, 0x00, BUF_SIZE);
sendCommand(buf);
}
sendCommand(char *buf)
{
write(fd, "some commands", strlen("some commands"));
readResponse(buf);
}
readResponse(char *buf)
{
read(fd, buf, nbytes);
}
I know there is no error handling up to now. And some variables are not well defined. It just depends on the passing buffer. Will I see the data that I get in readResponse() in my main function?
As in readResponse() as you read nbytes into buffer pointed by buf ,so you will get that data in main .
Some improvements to be done -
1. void main() -> int main(void) or int main(int argc, char *argv[])
2. char *buf = malloc(sizeof(char) *buf); -> char *buf = malloc(BUF_SIZE); // sizeof(char)=1 or maybe something you desire (not sure though what you want ??)
Note - remember to free allocated memory.
You have a remarkable number of significant problems in the code you presented, considering how short it is. Other answers have addressed those, though, and your question is not actually about any of them:
Will I see the data I get in readResponse() in my main function?
Yes, provided that argument buf is a pointer to an array large enough to accommodate nbytes bytes, and that the read() call in fact successfully reads any bytes, those bytes will afterward be visible in main() via the pointer it passed to readResponse(). More generally, if you pass a pointer as a function argument, the called function may manipulate the pointed-to object, including by modifying those parts of it that are not const. That's how the read() function itself is able to store the bytes it reads into your buffer, after all.
This won't do what you think it does:
char *buf = malloc(sizeof(char) *buf);
Did you mean to multiply with BUF_SIZE?

C: A safer way to check buffer in function and append to it?

I have a function of which I need to return the time for another logging function, and it looks like this:
//put time in to buf, format 00:00:00\0
void gettimestr(char buf[9]) {
if(strlen(buf) != 9) { //experimental error checking
fprintf(stderr, "Buf appears to be %d bytes and not 9!\n", strlen( buf ));
}
time_t cur_time;
time(&cur_time);
struct tm *ts = localtime(&cur_time);
sprintf(buf, "%02d:%02d:%02d",
ts->tm_hour,
ts->tm_min,
ts->tm_sec );
strncat(buf, "\0", 1);
}
Now I guess the main problem is checking if the buffer is long enough, sizeof() returns a pointer size and strlen seems to randomly return 0 or something such as 12 on two different calls.
My first question is, how would I be able to detect the size of the buffer safely, is it possible?
My other question is, is accepting buf[9] a favourable method or should I accept a pointer to a buffer, and use strcat() instead of sprintf() to append the time to it? sprintf makes it easier for padding zeros to the time values, although it seems to only accept a character array and not a pointer.
Your function assumes that the buffer being passed in already contains a null-terminated string with 9 characters. That doesn't make sense.
The proper way would be to request the size as an argument:
void gettimestr(char *buf, int bufferSize) {
and use snprintf:
snprintf(buf, bufferSize, "%02dx....", ....);<sub>*</sub>
And terminate the string since snprintf won't do that if you exceed the limit:
buf[bufferSize-1] = 0;
You can call your function like this:
char buffer[16];
gettimestr(buffer, sizeof(buffer));
There is no other way to determine the size. This isn't Java where an array knows its size. Passing a char * will simply send a pointer down to the function with no further information, so your only way to get the size of the buffer is by requiring the caller to specify it.
(EDIT: snprintf should always terminate the string properly, as pointed out in the comments.)
#EboMike is right. Just to complement his answer, you could check the buffer with:
void gettimestr(char *buf, int bufferSize) {
if (!buf) {
fprintf(stderr, "Null buffer\n");
return;
}
// rest of the code
}

Why am I getting 'Incompatible pointer type' warning?

I'm working through the curve to learn C and I don't understand why compiler is reporting this this warning.
I have a char* that is declared in global space (outside of any function). I want to read a file descriptor and return it's contents to the calling code.
At the top of the file I have the buffer declared:
char * buffer[256];
And this is the function that returns the char*
char * readMessage()
{
int n;
bzero(buffer,256);
n = read(sockfd,buffer,255);
if(n < 0)
error("Error reading from the socket");
return buffer;
}
How can the return type be of an incompatible type? Thanks!
You wrote:
char * buffer[256];
That is, an array of 256 char pointers.
It seems to me what you really want is:
char buffer[256];
Or, an array of 256 characters (also known as a 'string' :-))
Off-topic, but related to your code: This is not a good way to read from a socket. Chances are, read() will at some point return fewer characters than you expect. You should have some mechanism in place to communicate the length of your messages, and read from the socket in a loop, buffering characters until you get a complete message. You should also handle the case where read() returns zero (likely disconnect) or when it fails and sets errno to EINTR (meaning you got a signal while inside read and you should try again).
char *buffer[256] declares an array of 256 pointers-to-char. You probably want char buffer[256].

Using strcat in C

Okay so I have the following Code which appends a string to another in C#, note that this is Just an example, so giving alternative string concatination methods in C# is not nessesary, this is just to simplify the example.
string Data = "";
Data +="\n\nHTTP/1.1 " + Status_code;
Data += "\nContent-Type: " + Content_Type;
Data += "\nServer: PT06";
Data += "\nContent-Length: " + Content_Lengt;
Data += "\nDate: " + Date;
Data += "\n" + HTML;
Now I'd like to do the exact same thing in C and I'm trying to do this the following way
time_t rawtime;
time ( &rawtime );
char *message = "\n\nHTTP/1.1 ";
message = strcat(message, Status_code);
message = strcat(message, "\nContent-Type: ");
message = strcat(message, Content_Type);
message = strcat(message, "\nServer: PT06");
message = strcat(message, "\nContent-Length: ");
message = strcat(message, Content_Lengt);
message = strcat(message, "\nDate: ");
message = strcat(message, ctime(&rawtime));
message = strcat(message, "\n");
message = strcat(message, HTML);
Now, this gives me a Segment fault, I know why, I access and read on memory that i shouldn't. But the question is, how do i solve it? Could I use string.h and just do it the same way that I did in C#?
Change
char *message = "\n\nHTTP/1.1 ";
to
char message[1024];
strcpy(message,"\n\nHTTP/1.1 ");
and you should be ok, up to a total message length of 1023.
Edit: (as per mjy's comment). Using strcat in this fashion is a great way of getting buffer overflows. You could readily write a small function that checks the size of the buffer and length of incoming string addition to overcome this, or use realloc on a dynamic buffer. IMO, the onus is on the programmer to check correct buffer sizes where they are used, as with sprintfs and other C strings functions. I assume that C is being used over C++ for performance reasons, and hence STL is not an option.
Edit: As per request from Filip's comment, a simple strcat implementation based on a fixed size char buffer:
char buffer[MAXSIZE] = "";
int mystrcat(char *addition)
{
if (strlen(buffer) + strlen(addition) + sizeof(char) >= MaxSize)
return(FAILED);
strcat(buffer,addition);
return(OK);
}
Using dynamic allocation:
char *buffer = NULL;
int mystrcat(char *addition)
{
buffer = realloc(buffer, strlen(buffer) + strlen(addition) + sizeof(char));
if (!buffer)
return(FAIL);
strcat(buffer, addition);
return(OK);
}
In this case you have to free your buffer manually when you are finished with it. (Handled by destructors in C++ equivalents)
Addendum (Pax):
Okay, since you didn't actually explain why you had to create message[1024], here it is.
With char *x = "hello", the actual bytes ('h','e','l','l','o',0) (null on the end) are stored in an area of memory separate from the variables (and quite possibly read-only) and the variable x is set to point to it. After the null, there's probably something else very important. So you can't append to that at all.
With char x[1024]; strcpy(x,"hello");, you first allocate 1K om memory which is totally dedicated to x. Then you copy "hello" into it, and still leave quite a bit of space at the end for appending more strings. You won't get into trouble until you append more than the 1K-odd allowed.
End addendum (Pax):
I wonder why no one mentioned snprintf() from stdio.h yet. That's the C way to output multiple values and you won't even have to convert your primitives to strings beforehand.
The following example uses a stack allocated fixed-sized buffer. Otherwise, you have to malloc() the buffer (and store its size), which would make it possible to realloc() on overflow...
char buffer[1024];
int len = snprintf(buffer, sizeof(buffer), "%s %i", "a string", 5);
if(len < 0 || len >= sizeof(buffer))
{
// buffer too small or error
}
Edit: You might also consider using the asprintf() function. It's a widely available GNU extension and part of TR 24731-2 (which means it might make it into the next C standard). The example from above would read
char * buffer;
if(asprintf(&buffer, "%s %i", "a string", 5) < 0)
{
// (allocation?) error
}
Remember to free() the buffer when done using it!
Start from using the safer strncat function. In general always use the safer 'n' functions that will not overflow if the size of a string is bigger than a specific size.
In C you need to take care of string sizes yourself. So you need to know how big the resulting string will be and accommodate for it. If you know the sizes of all the strings at the left side, you should create a buffer big enough to hold the resulting string.
message points to a char const[] that you can't write to, yet that's exactly where strcat is writing. You need to malloc() a sufficiently large buffer.
As said previously, you have to write to a sufficiently large buffer. Unfortunately, doing so is a lot of extra work. Most C applications that deal with strings use a dynamically resizable string buffer for doing concatenations.
glib includes an implementation of this, glib strings, which I recommend using for any application that uses strings heavily. It makes managing the memory easier, and prevents buffer overflows.
Have not seen any mention of the strlcpy, strlcat function, which is similar to the 'n' functions except also takes into account the trailing 0. Both take a third argument indicating the maximum length of the output buffer and are found in string.h.
example:
char blah[]="blah";
char buffer[1024];
strlcpy(buffer,"herro!!!",sizeof(buffer));
strlcat(buffer,blah,sizeof(buffer));
printf("%s\n",buffer);
Will output "herro!!!blah"
char blah[]="blah";
char buffer[10];
strlcpy(buffer,"herro!!!",sizeof(buffer));
strlcat(buffer,blah,sizeof(buffer));
printf("%s\n",buffer);
will output "herro!!!b" due to the limited size of buffer[], with no segfaulting. ^^
Only problem is not all platforms seem to include it in their libc (such as linux ._.), most all BSD varients DO seem to have it.
In that case, code for both functions can be found here and easily added: strlcpy, strlcat,
the rest of string.h
The safe way to do this in classic C style is:
char *strconcat(char *s1, char *s2)
{
size_t old_size;
char *t;
old_size = strlen(s1);
/* cannot use realloc() on initial const char* */
t = malloc(old_size + strlen(s2) + 1);
strcpy(t, s1);
strcpy(t + old_size, s2);
return t;
}
...
char *message = "\n\nHTTP/1.1 ";
message = strconcat (message, Status_code);
message = strconcat (message, "\nContent-Type: ");
Now you can say a lot of bad things about it: it's inefficient, it fragments your memory, it's ugly ... but it's more or less what any language with a string concatenation operator and C type (zero-terminated) strings will do (except that most of these languages will have garbage collection built-in).

Resources