1

I've forked a child process which then calls a bash script using execv, the way i'm passing command line arguments to the script, It does not print first argument on doing echo $1 inside the script.

std::string s = std::to_string(c_no);    
char *args[] = {(char *)s.c_str(), NULL};

pid_t pid = fork();
if(pid == 0){
    execv("./ckpnt.sh", &args[0]);
}

consider c_no to be any integer.

What is the correct way to do this?

I've already refrenced this link How to pass command line arguments from C program to the bash script? but this answer uses system system call and i try to not use that.

ram
  • 83
  • 6

1 Answers1

2

First argument passed to a program is its name so currently your number ends up in $0. args should be:

char *args[] = {"./ckpnt.sh", (char *)s.c_str(), NULL};
Botje
  • 26,269
  • 3
  • 31
  • 41
  • Still it doesn't print anything. – ram Oct 29 '20 at 21:39
  • Works locally. Can you run the program under `strace -Ff` and see if it is passing arguments correctly? – Botje Oct 29 '20 at 21:45
  • I just checked `echo "$0"` is printing `./ckpnt.sh` but `echo "$1"` is not printing anything – ram Oct 29 '20 at 21:50
  • Make sure you're properly recompiling, and again, check with `strace -Ff` to see what is being passed. – Botje Oct 29 '20 at 21:51
  • the way i've passed arguments in `exec` line is correct ? – ram Oct 29 '20 at 21:51
  • It has printed so many logs i cannot trace. does `F` option was very useful? – ram Oct 29 '20 at 21:59
  • @ram Are you waiting on the child after you fork? The string might have been destroyed before `execv` – Artyer Oct 29 '20 at 21:59
  • Look for the line that contains execve. For me, the second looks like `execve("./ckpnt.sh", ["./ckpnt.sh", "42"], 0x7ffe1b287738 /* 25 vars */) = 0` – Botje Oct 29 '20 at 22:05
  • @Artyer yes i'm waiting – ram Oct 29 '20 at 22:05
  • @Botje this is some part of it : – ram Oct 29 '20 at 22:07
  • `strace: deprecated option -F ignored execve("./a.out", ["./a.out"], 0x7ffcbc4bc2d8 /* 17 vars */) = 0 brk(NULL) = 0x55eac7b8a000 arch_prctl(0x3001 /* ARCH_??? */, 0x7ffcfd4dc5e0) = -1 EINVAL (Invalid argument) access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=116217, ...}) = 0 mmap(NULL, 116217, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f4ff3a6f000 close(3) = 0` – ram Oct 29 '20 at 22:07
  • Actually, just use `strace -fe execve` to trace just the execve call. – Botje Oct 29 '20 at 22:08
  • yes, these are the lines: `execve("./a.out", ["./a.out"], 0x7ffe6416ae10 /* 17 vars */) = 0 strace: Process 23891 attached [pid 23891] execve("./ckpnt.sh", ["1"], 0x7ffc1f671698 /* 17 vars */) = 0` – ram Oct 29 '20 at 22:10
  • See the difference? You're only passing one argument to execve, I am passing two. Are you *sure* your code is according to my answer? And that you're running that newly compiled code? – Botje Oct 29 '20 at 22:13
  • Ok i'll try this too, but in the above code, i've passed `&arg[0]` to the `exec` and after your answer i just changed it to `&arg[1]` – ram Oct 29 '20 at 22:15
  • That means you're back to the original behavior: passing one argument. You need to pass *two* arguments to execve in order for one to show up in $1. – Botje Oct 29 '20 at 22:17
  • @Botje Thanks, now it's printing 1 but i still don't understand why it was giving wrong answer earlier. – ram Oct 29 '20 at 22:17