144743Smarkm/*
244743Smarkm * Copyright 2007, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
344743Smarkm * Distributed under the terms of the MIT License.
444743Smarkm *
544743Smarkm * Copyright 2002, Manuel J. Petit. All rights reserved.
644743Smarkm * Distributed under the terms of the NewOS License.
744743Smarkm */
844743Smarkm
944743Smarkm
1044743Smarkm#include <image.h>
1144743Smarkm
1244743Smarkm#include <errno.h>
1344743Smarkm#include <string.h>
1444743Smarkm#include <stdlib.h>
1544743Smarkm#include <stdio.h>
1644743Smarkm#include <unistd.h>
1744743Smarkm
1844743Smarkm
1944743Smarkmstatic void
2044743Smarkmusage(char const *app)
2144743Smarkm{
2244743Smarkm	printf("usage: %s [-s] ###\n", app);
2344743Smarkm	exit(-1);
2444743Smarkm}
2544743Smarkm
2644743Smarkm
2744743Smarkmint
2844743Smarkmmain(int argc, char *argv[])
2944743Smarkm{
3044743Smarkm	bool silent = false;
3144743Smarkm	int num = 0;
3244743Smarkm	int result;
3344743Smarkm
3444743Smarkm	switch (argc) {
3544743Smarkm		case 2:
3644743Smarkm			num = atoi(argv[1]);
3744743Smarkm			break;
3844743Smarkm		case 3:
3944743Smarkm			if (!strcmp(argv[1], "-s")) {
4044743Smarkm				num = atoi(argv[2]);
4144743Smarkm				silent = true;
4244743Smarkm				break;
4344743Smarkm			}
4444743Smarkm			// supposed to fall through
4544743Smarkm
4644743Smarkm		default:
4744743Smarkm			usage(argv[0]);
4844743Smarkm			break;
4944743Smarkm	}
5044743Smarkm
5144743Smarkm	if (num < 2) {
5244743Smarkm		result = num;
5344743Smarkm	} else {
5444743Smarkm		pid_t childA = fork();
5544743Smarkm		if (childA == 0) {
5644743Smarkm			// we're the child
5744743Smarkm			char buffer[64];
5844743Smarkm			char* args[]= { argv[0], "-s", buffer, NULL };
5944743Smarkm
6044743Smarkm			snprintf(buffer, sizeof(buffer), "%d", num - 1);
6144743Smarkm			if (execv(args[0], args) < 0) {
6244743Smarkm				fprintf(stderr, "Could not create exec A: %s\n", strerror(errno));
6344743Smarkm				return -1;
6444743Smarkm			}
6544743Smarkm		} else if (childA < 0) {
6644743Smarkm			fprintf(stderr, "fork() failed for child A: %s\n", strerror(errno));
6744743Smarkm			return -1;
6844743Smarkm		}
6944743Smarkm
7044743Smarkm		pid_t childB = fork();
7144743Smarkm		if (childB == 0) {
7244743Smarkm			// we're the child
7344743Smarkm			char buffer[64];
7444743Smarkm			char* args[]= { argv[0], "-s", buffer, NULL };
7544743Smarkm
7644743Smarkm			snprintf(buffer, sizeof(buffer), "%d", num - 2);
7744743Smarkm			if (execv(args[0], args) < 0) {
7844743Smarkm				fprintf(stderr, "Could not create exec B: %s\n", strerror(errno));
7944743Smarkm				return -1;
8044743Smarkm			}
8144743Smarkm		} else if (childB < 0) {
8244743Smarkm			fprintf(stderr, "fork() failed for child B: %s\n", strerror(errno));
8344743Smarkm			return -1;
8444743Smarkm		}
8544743Smarkm
8644743Smarkm		status_t status, returnValue = 0;
8744743Smarkm		do {
8844743Smarkm			status = wait_for_thread(childA, &returnValue);
8944743Smarkm		} while (status == B_INTERRUPTED);
9044743Smarkm
9144743Smarkm		if (status == B_OK)
9244743Smarkm			result = returnValue;
9344743Smarkm		else
9444743Smarkm			fprintf(stderr, "wait_for_thread(%ld) A failed: %s\n", childA, strerror(status));
9544743Smarkm
9644743Smarkm		do {
9744743Smarkm			status = wait_for_thread(childB, &returnValue);
9844743Smarkm		} while (status == B_INTERRUPTED);
99
100		if (status == B_OK)
101			result += returnValue;
102		else
103			fprintf(stderr, "wait_for_thread(%ld) B failed: %s\n", childB, strerror(status));
104	}
105
106	if (silent) {
107		return result;
108	} else {
109		printf("%d\n", result);
110		return 0;
111	}
112}
113
114