0

I am trying to create a call to system using custom parameters. However I think that I am incorrectly malloc-ing the size of the final char*. So I instead get a Failed to Open source file error during the system call. Am I doing something wrong in terms of syntax?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
  char program_name[] = "/usr/local/bin/some_program";
  char argument_1[] = "foo";
  char argument_2[] = "foo2";
  char space[] = " ";
  char *runProgram = malloc( strlen(program_name) + strlen(argument_1)+
                             strlen(argument_2) + 2*strlen(space) + 1);

  strcpy(runProgram, program_name);
  strcat(runProgram, space);
  strcat(runProgram, argument_1);
  strcat(runProgram, space);
  strcat(runProgram, argument_2);

  system(runProgram);
  free(runProgram);
  exit(0);
}
Vasfed
  • 18,013
  • 10
  • 47
  • 53
Satbir Kira
  • 792
  • 6
  • 21
  • You already have all your parameters as separate strings. Why on Earth are you bothering using `system` at all? Just fork+execv this thing (well in your particular case, with your main program terminating right after `system` returns I'd do just the exec to replace the process). – datenwolf Jan 16 '16 at 21:03
  • @datenwolf Good point, however could you point out the problem with my code above? – Satbir Kira Jan 16 '16 at 21:05
  • 3
    A bit inefficient to do so many string operations (could just use a single `snprintf`). But it looks functionally ok. Suggest you post the full and exact code including a standard executable for `progam_name` and how you are checking the error code. Also wouldn't hurt to print out the final `runProgram` contents for verification. Could then cut and paste the command and run it directly in the shell to verify that the command line does work. – kaylum Jan 16 '16 at 21:07
  • 1
    *Why on Earth are you bothering using system at all?* Because `system()` is **one** line of code that's been fully tested and OP doesn't want to reinvent the wheel - and then have to test it? – Andrew Henle Jan 16 '16 at 21:08
  • 3
    Try `puts(runProgram)` before the `system` call, then copy/paste the line and see if it works from the shell. – jamieguinan Jan 16 '16 at 21:09
  • You can also try running under `strace` or `truss`, depending on your OS. – Andrew Henle Jan 16 '16 at 21:10
  • 2
    *"I get a `Failed to Open source file` error"* is perhaps a file spec error rather than a program error. – Weather Vane Jan 16 '16 at 21:10
  • Omg guys I'm a moron, "Failed to open source file" was coming from IN program_name. Saying there was no foo file. Thank you everyone and @WeatherVane for pointing that out – Satbir Kira Jan 16 '16 at 21:14
  • @AndrewHenle: It also does things you probably don't want to happen. For instance it doesn't launch the program directly but invokes a shell to do the actual program launch. – datenwolf Jan 17 '16 at 00:05

2 Answers2

3

When I run your code, your string appears to contain exactly what it needs to to be called. I do have a suggestion to simplify building it though:

...
int ret=0;
int len = strlen(program_name) + strlen(argument_1)+ strlen(argument_2) + 2*strlen(space) + 1;
char *runProgram = malloc( len);

ret = snprintf(runProgram, len, "%s %s %s", program_name, argument_1, argument_2);
if(ret < 0)
{
    //handle if truncation occurred (returns -1 for truncation)
}
if(ret >= len)
{
    //use runProgram buffer
}
system(runProgram);
free(runProgram);
//exit(0);
return 0;
...

Have you verified the chmod settings on the file to be executed are correct?

chmod +x /usr/local/bin/some_program

EDIT:
To address concern in comments regarding variations in implementation/documentation for snprintf(). When discussing standard C functions, the hope would be that implementations of the same function would be equal across platforms, but for snprintf(), it appears that some implementations are more equal than others...
1) snprintf some have referred to this as Microsoft's broken implementation.
2) snprintf from skrenta.com
3) snprintf from opengroup.org.
4) snprintf from linux.die.net, (includes glibc references, macros and other comments)

Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • 1
    better use `snprintf` to avoid buffer overflow – Vasfed Jan 16 '16 at 21:17
  • I solved it, "Failed to Open source file" was a print out from some_program. Thank you :) – Satbir Kira Jan 16 '16 at 21:19
  • @Vasfed - edited. Good idea. – ryyker Jan 16 '16 at 21:23
  • `if (ret < len)` is the OK case, isn't it, because [`snprintf()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html) returns the number of characters that would have been necessary had no truncation occurred? You mean `if (ret >= len) …process truncation…`, I think (I'm will to negotiate on which way equality goes). – Jonathan Leffler Jan 17 '16 at 05:09
  • @JonathanLeffler - I think you are right. Let me edit. Thank you. – ryyker Jan 17 '16 at 05:18
  • Are you discussing [Microsoft's broken implementation](https://msdn.microsoft.com/en-us/library/2ts7cx93.aspx) or the C standard implementation (described on the POSIX page I linked to). Hmmm...that's a GNU manual page you link to. Here's another: [`snprintf()`](http://linux.die.net/man/3/snprintf). It says what POSIX says; the notes document glibc 2.0.6 and earlier supporting the return value your page links to. Time to abandon skrenta.com as a source of manual pages (or time to upgrade to a newer glibc — 2.22 is current, I believe, based on Google's response to 'glibc current version'). – Jonathan Leffler Jan 17 '16 at 05:19
  • @JonathanLeffler - my previous (and incorrect comment) has been deleted. I used the illustration _[here](http://joequery.me/code/snprintf-c/)_ , where the conditional statement `if (nchars > -1)` is used to qualify the output, to verify the simple edits in the post, – ryyker Jan 17 '16 at 05:28
  • That's now correct per standard C. It might be worth including links to the variant definitions (at least Microsoft vs Standard C/POSIX — antique glibc is probably less important, but linking to a recent version of that would cover the point for those that need to know). OTOH, of course, Google works for other people too — but they need to know that they need to look, and telling them where to look helps them. Or maybe all these comments cover the point and the answer doesn't need to. – Jonathan Leffler Jan 17 '16 at 05:31
  • @JonathanLeffler - Yes, well, your comments are pretty complete, but the links are included all the same. (And citing at least one moniker provided by you.) – ryyker Jan 17 '16 at 05:50
1

Your code should work fine, printf("cmd is '%s'\n", runProgram); to check if generated command can be run in shell and produces expected results:

  • command string is correct
  • /usr/local/bin/some_program exists and has correct permissions
  • some_program does not fail
Vasfed
  • 18,013
  • 10
  • 47
  • 53