I am a beginner at programming using system calls in C. I am trying to use the execve call in one of my programs. I have to pass an integer as an argument to the program that is being invoked through execve.
However, reading on the internet and seeing sample code, I can see that we can pass only strings as arguments. So, I tried converting the integer to a string using 'sprintf' and then using 'strcpy' to copy that string into one of the elements of the array of strings that has to be passed through execve.
But using strcpy leads to a segmentation fault. I checked this out by debugging and if I don't use strcpy but simply write something like -
myargv[1]="123";
then the entire program works fine.
But since I have to pass a variable integer as a parameter and not a constant, I cannot use the above method.
This problem has been bugging me for some time. Kindly help me out as to what I should do.
It's almost certainly because you haven't allocated space for your string.
The reason myargv[1]="123"; works is because you set the pointer to point to a string that already exists (the compiler generally puts that "123" into pre-initialised memory and it just gets loaded). By using something like:
char *myargv[10];
strcpy (myargv[1], "anything");
you'll generally run into problems because there's no allocated backing storage for the myargv[1] pointer.
What you can do is to simply set myargv[1] directly to the buffer where you sprintf-ed the string:
char sprintf_buffer[whatever];
sprintf (sprintf_buffer, "%d", myInteger);
myargv[1] = sprintf_buffer;
Or, if you're re-using that buffer (so that the value gets overwritten for multiple integer arguments), use strdup.
char sprintf_buffer[whatever];
sprintf (sprintf_buffer, "%d", myInteger1);
myargv[1] = strdup (sprintf_buffer);
sprintf (sprintf_buffer, "%d", myInteger2);
myargv[2] = strdup (sprintf_buffer);
And if, for some reason, your platform doesn't have a strdup, here's one for you:
char *strdup (const char *s) {
char *d = (char *)(malloc (strlen (s) + 1));
if (d != NULL)
strcpy (d,s);
return d;
}
Keep in mind you should always check the return value from strdup to make sure the memory allocation worked. I've left it out here since it's not relevant to the question at hand.
You can avoid memory allocation with multiple buffers (provided you know the absolute number of buffers you'll need in advance):
char sprintf_buffer1[whatever];
char sprintf_buffer2[whatever];
sprintf (sprintf_buffer1, "%d", myInteger1);
myargv[1] = sprintf_buffer1;
sprintf (sprintf_buffer2, "%d", myInteger2);
myargv[2] = sprintf_buffer2;
I'm unclear as to why you are using strcpy at all. Just snprintf the number into a string and make that one of the arguments.
e.g.
char numberArgBuffer[20]; // more than big enough for a 32 bit integer
snprintf(numberArgBuffer, 20, "%d", numberArg);
char* argv[3];
char* envp[1];
argv[0] = exeName; // could be same as path
argv[1] = numberArgBuffer;
argv[2] = NULL;
envp[0] = NULL;
int ret = execve(path, argv, envp);
// if you get here execve failed, so handle the error
Your strcpy is probably seg faulting because you haven't allocated a buffer for the destination, but as the above example shows, it's an unnecessary step anyway.
Related
I am trying to use the C's strtok function in order to process a char* and print it in a display, and looks like that for some reason I don't know the character '\n' is not substituted by '\0' as I believe strtok does. The code is as follows:
-Declaration of char* and pass to the function where it will be processed:
char *string_to_write = "Some text\nSome other text\nNewtext";
malloc(sizeof string_to_write);
screen_write(string_to_write,ALIGN_LEFT_TOP,I2C0);
-Processing of char* in function:
void screen_write(char *string_to_write,short alignment,short I2C)
{
char *stw;
stw = string_to_write;
char* text_to_send;
text_to_send=strtok(stw,"\n");
while(text_to_send != NULL)
{
write_text(text_to_send,I2C);
text_to_send=strtok(NULL, "\n");
}
}
When applying the code, the result can be seen in imgur (Sorry, I am having problems with format adding the image here in the post), where it can be seen that the \n is not substituted as it is the strange character appearing in the image, and the debugger still showed the character as well. Any hints of where can the problem be?
Thanks for your help,
Javier
strtok expects to be able to mutate the string you pass it: instead of allocating new memory for each token, it puts \0 characters into the string at token boundaries, then returns a series of pointers into that string.
But in this case, your string is immutable: it's a constant stored in your program, and can't be changed. So strtok is doing its best: it's returning indices into the string for each token's starting point, but it can't insert the \0s to mark the ends. Your device can't handle \ns in the way you'd expect, so it displays them with that error character instead. (Which is presumably why you're using this code in the first place.)
The key is to pass in only mutable strings. To define a mutable string with a literal value, you need char my_string[] = "..."; rather than char* my_string = "...". In the latter case, it just gives you a pointer to some constant memory; in the former case, it actually makes an array for you to use. Alternately, you can use strlen to find out how long the string is, malloc some memory for it, then strcpy it over.
P.S. I'm concerned by your malloc: you're not saving the memory it gives you anywhere, and you're not doing anything with it. Be sure you know what you're doing before working with dynamic memory allocation! C is not friendly about that, and it's easy to start leaking without realizing it.
1.
malloc(sizeof string_to_write); - it allocates the sizeof(char *) bytes not as many bytes as your string needs. You also do not assign the allocated block to anything
2.
char *string_to_write = "Some text\nSome other text\nNewtext";
char *ptr;
ptr = malloc(strlen(string_to_write) + 1);
strcpy(ptr, string_to_write);
screen_write(ptr,ALIGN_LEFT_TOP,I2C0);
char test[10]="ab cd";
char* save=NULL;
save = strtok(test," ");
printf("%s\n",save);
result : ab
First, above code works very well.
Next, I tryed to excute this code. but, segmentfault occurs.
char test[10]="ab cd";
char* save=NULL;
char* cpy=NULL;
save = strtok(test," ");
strcpy(cpy,save);
printf("%s\n",cpy);
I know strtok() returns read-only *char type.
but, i guess, 'save' is used only copied object.
it is not change. why strcpy() makes segmentfault error by get 'save' as parameter?
cpy is explicitly NULL when you copy into the location it's pointing to. That's guaranteed to give you a memory write error of some kind.
I suggest you initialize cpy to point to some memory that's actually available, e.g.:
char temp[100];
char test[10]="ab cd";
char* save=NULL;
char* cpy=temp; // Set cpy to point to temp buffer
save = strtok(test," ");
strcpy(cpy,save);
printf("%s\n",cpy);
It's not strtok() that's causing the problem, it's the strcpy() into address 0.
Your char *cpy is not referencing any allocated memory. (You initialized it to NULL. So when you call strcpy(cpy,save), you are writing to a NULL-pointer.
You might want to allocate memory first:
cpy = malloc(strlen(save)+1);
strcyp(cpy,save);
In strcpy case you have to first allocate memory for "cpy" so that "save" can be copied to "cpy". Here "save" is working fine because strtok only return pointer on success...That's why you don't need to allocate memory for "save".And you are passing an address by save so it's fine..So overall first allocate memory for "cpy" so that strcpy can copy "save" into "cpy".
Use strdup
save = strtok(test," ");
cpy = strdup(save);
printf("%s\n",cpy);
free(cpy);
Don't forget to free the memory when you're done with it.
Also read this
As provided earlier, strcpy() like most string routines will segfault if passed a NULL argument. This applies to both the src and dest args (at least in older versions of glibc), which makes it impossible to do simple things like:
strcpy(dest, strtok(NULL, “ “));
strcpy(dest, getenv(“NOTHNG”);
Either strtok() or getenv() could return a NULl, which is passed to strcpy() causing a segfault. I didn’t want to put a lot of NULL checking into my code, like:
if (getenv(“NOTHING”) != NULL)
*dest = ‘\0’;
else
strcpy(dest, getenv(“NOTHING”));
So, I created a strcpy_w() wrapper that treats a NULL src argument the same as if *src is ‘\0’. I did the same for other string functions, also checking for buffer overflows. Then, I just had to add the following to always use the wrapper:
#define strcpy(x, y) strcpy_w(x, y)
Or I could call strcpy_w(dest, getenv(“NOTHING”)) instead.
In C I have a path in one of my strings
/home/frankv/
I now want to add the name of files that are contained in this folder - e.g. file1.txt file123.txt etc.
Having declared my variable either like this
char pathToFile[strlen("/home/frankv/")+1]
or
char *pathToFile = malloc(strlen("/home/frankv/")+1)
My problem is that I cannot simply add more characters because it would cause a buffer overflow. Also, what do I do in case I do not know how long the filenames will be?
I've really gotten used to PHP lazy $string1.$string2 .. What is the easiest way to do this in C?
If you've allocated a buffer with malloc(), you can use realloc() to expand it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *buf;
const char s1[] = "hello";
const char s2[] = ", world";
buf = malloc(sizeof s1);
strcpy(buf, s1);
buf = realloc(buf, sizeof s1 + sizeof s2 - 1);
strcat(buf, s2);
puts(buf);
return 0;
}
NOTE: I have omitted error checking. You shouldn't. Always check whether malloc() returns a null pointer; if it does, take some corrective action, even if it's just terminating the program. Likewise for realloc(). And if you want to be able to recover from a realloc() failure, store the result in a temporary so you don't clobber your original pointer.
Use std::string, if possible. Else, reallocate another block of memory and use strcpy and strcat.
You have a couple options, but, if you want to do this dynamically using no additional libraries, realloc() is the stdlib function you're looking for:
char *pathToFile = malloc(strlen("/home/frankv/")+1);
char *string_to_add = "filename.txt";
char *p = realloc(pathToFile, strlen(pathToFile) + strlen(string_to_add) + 1);
if (!p) abort();
pathToFile = p;
strcat(p, string_to_add);
Note: you should always assign the result of realloc to a new pointer first, as realloc() returns NULL on failure. If you assign to the original pointer, you are begging for a memory leak.
If you're going to be doing much string manipulation, though, you may want to consider using a string library. Two I've found useful are bstring and ustr.
In case you can use C++, use the std::string. In case you must to use pure C, use what's call doubling - i.e. when out of space in the string - double the memory and copy the string into the new memory. And you'll have to use the second syntax:
char *pathToFile = malloc(strlen("/home/frankv/")+1);
You have chosen the wrong language for manipulating strings!
The easy and conventional way out is to do something like:
#define MAX_PATH 260
char pathToFile[MAX_PATH+1] = "/home/frankv/";
strcat(pathToFile, "wibble/");
Of course, this is error prone - if the resulting string exceeds MAX_PATH characters, anything can happen, and it is this sort of programming which is the route many trojans and worms use to penetrate security (by corrupting memory in a carefully defined way). Hence my deliberate choice of 260 for MAX_PATH, which is what it used to be in Windows - you can still make Windows Explorer do strange things to your files with paths over 260 characters, possibly because of code like this!
strncat may be a small help - you can at least tell it the maximum size of the destination, and it won't copy beyond that.
To do it robustly you need a string library which does variable length strings correctly. But I don't know if there is such a thing for C (C++ is a different matter, of course).
I want to read string from standart input and output it in on console. I use this way:
char* cmdline;
do{
scanf("%s\n", &cmdline);
printf("%s\n", cmdline);
}while(cmdline != "quit");
But this doesn't work. I have this error Segmentation fault (core dumped)
char* cmdline
is a pointer. You are not allocating space for storing the string.
You should do:
cmdline = malloc(size_of_string);
for allocating dynamic memory for storing the string.
Otherwise use an array of char instead of a pointer:
char cmdline[size_of_string];
cmdline is just a pointer -- you need to actually allocate space for it using malloc or a fixed-size array.
char cmdline[80];
do {
scanf("%79s\n", cmdline);
printf("%s\n", cmdline);
} while(strcmp(cmdline, "quit"));
I spotted three errors with your code:
Not allocating memory for the input buffer
Not passing a buffer to scanf
Not using strcmp to compare strings
You have defined char *cmdline but not allocated the cmdline pointer
do
cmdline = malloc (sizeof (char) * n);
first
Adjust the string length n as per your need.
EDIT1:
In your version when you use cmdline without allocation it, then actually cmdline contains a value which can be anything, and using that for memory access is an attempt to access some memory area which you do not know where and is not permitted in OSes with memory protection (all the OSes nowadays). So when you store something in cmdline it will go in an invalid location, which is not permitted and the OS will issue segmentation fault for illegal memory access.
After you have allocated the memory from the OS (heap) with the malloc call the cmdline will contain a value which will have a memory location address which was issued by the OS for your code and is reserved for you, in which you have permission to write. So referring the location with the variable makes a proper memory reference and you can you it as normal. Also note if you try to go beyond the allocated memory block, ie access beyond the n th location (if you have allocated n bytes), then you can also get a segfault, as the memory locations beyond that limit is not registered/allocated for you. Although you might not get a segfault in this case, but writing in such location can be unpredective.
The sole cause for an attempt to elaborate this is that this is a very common malpractice to define a char * and without allocating it use it in codes, because the old Turbo C++ 3.1 does not complain, which is used by a LOT of people out there. Then they call me and tell that the GCC compiler is broken as the code does not run in it and runs perfect in TC++ 3.1.
EDIT2:
Or simply use static array
char cmdline[MAX_SIZE];
where MAX_SIZE is set as per your need
EDIT3: OMG
You have done cmdline != "quit" this will never work. The solution is
while (strcmp (cmdline, "quit") != 0);
in your code. This will match the cmdline string character by character with the static string "quit"
Your solution will never work because when you do cmdline != "quit" then simply two addresses are being compared. First, the cmdline represents the address which you allocated with the malloc call, Second the address of the string "quit" which lies inside the data section of the executable, or simply in some area inside the memory where your program is loaded, which you have no idea. Comparing these two values will not compare the contents of these addresses, ie will not compare the strings inside it.
EDIT4:
Also scanf ("%s", &cmdline); is incorrect as cmdline itself represents the address of the location where you want to store the string. The correct code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void)
{
char *cmdline;
cmdline = malloc (sizeof (char) * 128); /* or whatever size */
do
{
scanf ("%s", cmdline);
printf ("%s\n", cmdline);
}
while (strcmp (cmdline, "quit") != 0);
return 0;
}
I have a old program in which some library function is used and i dont have that library.
So I am writing that program using libraries of c++.
In that old code some function is there which is called like this
*string = newstrdup("Some string goes here");
the string variable is declared as char **string;
What he may be doing in that function named "newstrdup" ?
I tried many things but i dont know what he is doing ... Can anyone help
The function is used to make a copy of c-strings. That's often needed to get a writable version of a string literal. They (string literals) are itself not writable, so such a function copies them into an allocated writable buffer. You can then pass them to functions that modify their argument given, like strtok which writes into the string it has to tokenize.
I think you can come up with something like this, since it is called newstrdup:
char * newstrdup(char const* str) {
char *c = new char[std::strlen(str) + 1];
std::strcpy(c, str);
return c;
}
You would be supposed to free it once done using the string using
delete[] *string;
An alternative way of writing it is using malloc. If the library is old, it may have used that, which C++ inherited from C:
char * newstrdup(char const* str) {
char *c = (char*) malloc(std::strlen(str) + 1);
if(c != NULL) {
std::strcpy(c, str);
}
return c;
}
Now, you are supposed to free the string using free when done:
free(*string);
Prefer the first version if you are writing with C++. But if the existing code uses free to deallocate the memory again, use the second version. Beware that the second version returns NULL if no memory is available for dup'ing the string, while the first throws an exception in that case. Another note should be taken about behavior when you pass a NULL argument to your newstrdup. Depending on your library that may be allowed or may be not allowed. So insert appropriate checks into the above functions if necessary. There is a function called strdup available in POSIX systems, but that one allows neither NULL arguments nor does it use the C++ operator new to allocate memory.
Anyway, i've looked with google codesearch for newstrdup functions and found quite a few. Maybe your library is among the results:
Google CodeSearch, newstrdup
there has to be a reason that they wrote a "new" version of strdup. So there must be a corner case that it handles differently. like perhaps a null string returns an empty string.
litb's answer is a replacement for strdup, but I would think there is a reason they did what they did.
If you want to use strdup directly, use a define to rename it, rather than write new code.
The line *string = newstrdup("Some string goes here"); is not showing any weirdness to newstrdup. If string has type char ** then newstrdup is just returning char * as expected. Presumably string was already set to point to a variable of type char * in which the result is to be placed. Otherwise the code is writing through an uninitialized pointer..
newstrdup is probably making a new string that is a duplicate of the passed string; it returns a pointer to the string (which is itself a pointier to the characters).
It looks like he's written a strdup() function to operate on an existing pointer, probably to re-allocate it to a new size and then fill its contents. Likely, he's doing this to re-use the same pointer in a loop where *string is going to change frequently while preventing a leak on every subsequent call to strdup().
I'd probably implement that like string = redup(&string, "new contents") .. but that's just me.
Edit:
Here's a snip of my 'redup' function which might be doing something similar to what you posted, just in a different way:
int redup(char **s1, const char *s2)
{
size_t len, size;
if (s2 == NULL)
return -1;
len = strlen(s2);
size = len + 1;
*s1 = realloc(*s1, size);
if (*s1 == NULL)
return -1;
memset(*s1, 0, size);
memcpy(*s1, s2, len);
return len;
}
Of course, I should probably save a copy of *s1 and restore it if realloc() fails, but I didn't need to get that paranoid.
I think you need to look at what is happening with the "string" variable within the code as the prototype for the newstrdup() function would appear to be identical to the library strdup() version.
Are there any free(*string) calls in the code?
It would appear to be a strange thing do to, unless it's internally keeping a copy of the duplicated string and returning a pointer back to the same string again.
Again, I would ask why?