tags:

views:

788

answers:

4

I'm feel like I'm missing something pretty obvious here, but I can't seem to figure out what's going on. I have a perl script that I'm calling from C code. The script + arguments is something like this:

my_script "/some/file/path" "arg" "arg with spaces" "arg" "/some/other/file"

When I run it in Windows, Perl correctly identifies it as 5 arguments, whereas when I ran it on the SunOS Unix machine, it identified 8, splitting the arg with spaces into separate args.

Not sure if it makes any difference, but in Windows I'm running it like:

perl my_script <args>

While in Unix I'm just running it as an executable like show above.

Any idea why Unix is not managing that argument properly?

Edit:

Here's the code for calling the perl script:

 char cmd[1000];
 char *script = "my_script";
 char *argument = "\"arg1\" \"arg2\" \"arg3 with spaces\" \"arg4\" \"arg5\"";
 sprintf( cmd, "%s %s >1 /dev/null 2>&1", script, arguments);
 system( cmd );

That's not exactly it, as I build the argument string a little more dynamically, but that's the gist.

Also, here's my code for reading the arguments in:

($arg1, $arg2, $arg3, $arg4, $arg5) = @ARGV;

I know it's ridiculously naive, but this script will only be run from the C application, so nothing more complex should be required.

A: 

Did you forget the quotes on SunOS?

If you do

perl script arg1 arg2 "arg3 with spaces" arg4 arg5

you should be good. Otherwise, try switching shells.

Dirk Eddelbuettel
+2  A: 

Presumably

system("my_script \"/some/file/path\" \"arg\" \"arg with spaces\" \"arg\" \"/some/other/file\");

causes everything to go through bash (because of the need to interpret the shebang line, eating up the quotes you pass). Again, presumably, the problem could be avoided by invoking perl directly rather than relying on the shell to find it (although this might be a problem if the perl on the path is different than the one provided on the shebang line).

Update:

Given your:

char *argument = "\"arg1\" \"arg2\" \"arg3 with spaces\" \"arg4\" \"arg5\"";

you might want to try:

char *argument = "\\\"arg1\\\" \\\"arg2\\\" \\\"arg3 with spaces\\\" \\\"arg4\\\" \\\"arg5\\\"";

Another update:

Thank you for accepting my answer, however, my whole theory might be wrong.

I tried the double-backwhacked version of argument above in GNU bash, version 4.0.28(2)-release (i686-pc-linux-gnu) and it ended up passing

[sinan@kas src]$ ./t
'"arg1"'
'"arg2"'
'"arg3'
'with'
'spaces"'
'"arg4"'
'"arg5"'

whereas the original argument worked like a charm. I am a little puzzled by this. Maybe the shell on the SUN isn't bash or maybe there is something else going on.

Sinan Ünür
Well, this seems to be the problem. When I updated the Unix cmd to actually invoke perl, it did exactly what I expected. I'm still not sure WHY it wasn't working, especially given Juliano's attempts at reproduction. Oh well. At least it works.
Morinar
+1  A: 

Now that the question was updated, I still can't reproduce your results:

~% cat test.c
#include <stdio.h>
#include <stdlib.h>
int main(void){
        char cmd[1000];
        char *script = "./my_script";
        char *arguments = "\"arg1\" \"arg2\" \"arg3 with spaces\" \"arg4\" \"arg5\"";
        sprintf( cmd, "%s %s", script, arguments);
        system( cmd );
        return 0;
}

~% cat my_script
#!/usr/bin/perl
($arg1, $arg2, $arg3, $arg4, $arg5) = @ARGV;
print "arg1 = $arg1\n";
print "arg2 = $arg2\n";
print "arg3 = $arg3\n";
print "arg4 = $arg4\n";
print "arg5 = $arg5\n";

~% gcc test.c

~% ./a.out
arg1 = arg1
arg2 = arg2
arg3 = arg3 with spaces
arg4 = arg4
arg5 = arg5

~%

There is something else with your configuration.


Previous answer:

Unix shells interpret quoted arguments as a single argument. You can do a quick test:

for i in a b "c d e" f; do echo $i; done

The result is what you expect it to be: "c d e" is treated like a single argument.

I think you have a problem in your script, in the argument handling logic.

Juliano
A: 

Is it possible that the SunOS kernel's handing of shebang interpreters is ludicrously bad? Try running it as "/path/to/perl script args" instead of "script args" and see if anything changes.

hobbs