Reputation: 1603
I'm building a string here based on 4 arguments and calling it with system(), but seems kinda messy the way i have done it. Is there a more correct way i should have done this and not use all those strcat and str1-4?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char str1[40] = "sed -n 's/.*\\(";
char str2[] = "\\)\\(.*\\)\\(";
char str3[] = "\\).*/\\2/p' ";
char str4[] = " > ";
if (argc != 5)
{
fprintf (stderr, "Usage %s <LogFile> <token1> <token2> <DumpFile>\n",
argv[0]);
exit(EXIT_FAILURE);
}
strcat(str1, argv[2]);
strcat(str1, str2);
strcat(str1, argv[3]);
strcat(str1, str3);
strcat(str1, argv[1]);
strcat(str1, str4);
strcat(str1, argv[4]);
system(str1);
return 0;
}
Upvotes: 3
Views: 7360
Reputation: 182619
One problem with your code is that you're not checking the arguments fit in the 40 bytes.
I would probably use snprintf
:
snprintf(str, LENGTH, "sed -n 's/.*\\(%s...", argv[2]...);
Upvotes: 8
Reputation: 612914
If you want your code to handle arbitrarily long arguments then you will need to allocate the character buffer dynamically with malloc
.
strlen
to calculate that length.malloc
remembering to add one more character for the null-terminator. strcpy
or strcat
multiple times to build up the string.system
.free
(or don't bother if your process is about to terminate).Upvotes: 1
Reputation: 753665
This saves on the quadratic behaviour of repeated strcat()
. OTOH, that is lost in the noise if you call system()
.
char str1[4096];
char str0[] = "sed -n 's/.*\\(";
sprintf(str1, "%s%s%s%s%s%s%s%s", str0, argv[2], str2, argv[3], str3, argv[1], str4, argv[4]);
You could use snprintf()
if you're worried about buffer overflows (and you should be; 40 bytes in str1
is not enough; you left the 96 off the end, as in char str1[4096];
). You could check the return value to see how many characters got written.
Upvotes: 3
Reputation: 32240
str1
is only 40 bytes long, and you're appending too much data to it. An stack overflow is likely to occur. I would do:
char buffer[1000]; // Choose a reasonable size
snprintf(buffer, sizeof(buffer),
"sed -n 's/.*\\(%s\\)\\(.*\\)\\(%s\\).*/\\2/p' %s > %s",
argv[2], argv[3], argv[1], argv[4]);
Upvotes: 2
Reputation: 5456
The only problem is that you may get buffer overflow (if the input is too long). to fix it, check the length of the strings (using strlen
), and allocate enough memory to contain the string you want.
After you allocated enough memory, you can use a loop, or let sprintf
do the work for you.
Upvotes: 2