views:

61

answers:

2

Hello

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.

+3  A: 

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;
paxdiablo
A: 

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* anvp[1];
argv[0] = exeName;           // couild 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.

JeremyP