+2  A: 

Looks like you are building a recursive program. I'm not sure why you have divided the logic into beginning, middle and end operations?

I suggest you either implement this as head::tail recursion, where each invocation adds the first argument to the result of running on the remaining ones, or returns zero if it has no arguments:

Program -> 0
Program head,... -> head + program ...

OR divide and conquer, where each invocation either returns it's single argument, zero for none, or forks two sub-invocations, each with half of the remaining arguments:

Program -> 0
Program x -> x
Program (N args) -> Program (N+1/2 args) + Program (remaining args) 

No complex internal data structures are required, just some light array handling:

I should point out that it's a bad idea to communicate value through exit codes, since exit codes have a very limited set of values (256) available for this use, and if your program fails for some reason it may return a surprising value.

Here's a perl version that doesn't use exit code:

#!/usr/bin/perl
print@ARGV&&(shift(@ARGV)+‘$0 @ARGV‘)||0

While this is in perl, which not everyone can read, and perl is doing a lot of work behind the scenes for us, it demonstrates the way you can implement a recursive head::tail sum function using fork and exec.

Here's the c version that uses exit codes:

int forkexec(char**oldargv,char**newargv,char**endargv)
{
  if(!fork())
    execve(newargv[0]=oldargv[0],newargv,endargv[0]=0);
  int b;
  wait(&b);
  return b>>8;
}

main(int c, char** a)
{
  int b;for(b=0;b<c;b++)printf("%s ",a[b]);printf("\n");
  exit(!(c-1)?0 // empty head returns 0
             :atoi(a[1])+ // convert the head into a number
              forkexec(a,a+1,a+c)); // re-invoke on the remaining arguments
}

Please note that this code is NOT SAFE, and it uses undocumented features such as the main argument array argv (a) being NULL terminated. However, it works, and demonstrates recursion using fork, exec and exit codes in c. Running with the debug printf uncommented:

$ gcc sum.c
$ ./a.out 1 2 3 4 5; echo RESULT $?
./a.out 1 2 3 4 5 
./a.out 2 3 4 5 
./a.out 3 4 5 
./a.out 4 5 
./a.out 5 
./a.out 
RESULT 15

As you can see, I haven't used any trees or lists - I just re-invoke the program each time, moving the argument list pointer along by one.

Here's the divide-and-conquer version:

int forkexec(char**oldargv,char**newargv,char**endargv)
{
  if(!fork())
    execve(newargv[0]=oldargv[0],newargv,endargv[0]=0);
  int b;
  wait(&b);
  return b>>8;
}

main(int c, char** a)
{
  //int b;for(b=0;b<c;b++)printf("%s ",a[b]);printf("\n");
  exit(!(c-1)?0: // empty leaf is 0
       !(c-2)?atoi(a[1]): // leaf returns value
              forkexec(a,a,a+1+c/2)+ // Sum left half of children 
              forkexec(a,a+c/2,a+c)); // Sum right half of children
}

I would like to recommend that you don't use my code; it's ugly, unsafe and deliberately compacted to form a small example for posting here. You should re-write using functional decomposition, error checking and comments, as well as cloning the contents of argv into new, large enough and null terminated arrays. Also the third argument to execve is misleading in my example.

Uncommenting the debug printf:

int b;for(b=0;b<c;b++)printf("%s ",a[b]);printf("\n");

we get:

$ ./a.out 1 2 3 4 5 6 7 8; echo RESULT $?
./a.out 1 2 3 4 5 6 7 8 
./a.out 1 2 3 4 
./a.out 1 2 
./a.out 1 
./a.out 2 
./a.out 3 4 
./a.out 3 
./a.out 4 
./a.out 5 6 7 8 
./a.out 5 6 
./a.out 5 
./a.out 6 
./a.out 7 8 
./a.out 7 
./a.out 8 
RESULT 36

Which clearly shows the problem being split into increasingly small halves.

Alex Brown
Implement as a linked list?
foobiefoob
Thank you, now I have an idea of how to go about do this.
foobiefoob