diff --git a/c_src/alcove.c b/c_src/alcove.c index 4bb45a5..2a95366 100644 --- a/c_src/alcove.c +++ b/c_src/alcove.c @@ -88,16 +88,21 @@ main(int argc, char *argv[]) if (!ap) erl_err_sys("calloc"); - ap->child = calloc(ALCOVE_MAX_CHILD, sizeof(alcove_child_t)); - if (!ap->child) - erl_err_sys("calloc"); - act.sa_handler = sighandler; if (sigaction(SIGCHLD, &act, NULL) < 0) erl_err_sys("sigaction"); - while ( (ch = getopt(argc, argv, "hv")) != -1) { + /* 3 pipes per child */ + ap->maxchild = FD_SETSIZE / 3 - 3; + + while ( (ch = getopt(argc, argv, "am:hv")) != -1) { switch (ch) { + case 'm': { + u_int16_t n = (u_int16_t)atoi(optarg); + + if (n < ap->maxchild) + ap->maxchild = n; + } case 'v': ap->verbose++; break; @@ -107,6 +112,10 @@ main(int argc, char *argv[]) } } + ap->child = calloc(ap->maxchild, sizeof(alcove_child_t)); + if (!ap->child) + erl_err_sys("calloc"); + alcove_ctl(ap); exit(0); } @@ -119,7 +128,7 @@ alcove_ctl(alcove_state_t *ap) erl_init(NULL, 0); - (void)memset(ap->child, 0, sizeof(alcove_child_t) * ALCOVE_MAX_CHILD); + (void)memset(ap->child, 0, sizeof(alcove_child_t) * ap->maxchild); sigcaught = 0; for ( ; ; ) { @@ -380,7 +389,7 @@ pid_foreach(alcove_state_t *ap, pid_t pid, void *arg1, void *arg2, int i = 0; int rv = 0; - for (i = 0; i < ALCOVE_MAX_CHILD; i++) { + for (i = 0; i < ap->maxchild; i++) { if ((*comp)(ap->child[i].pid, pid) == 0) continue; @@ -555,6 +564,7 @@ usage(alcove_state_t *ap) __progname, ALCOVE_VERSION); (void)fprintf(stderr, "usage: %s \n" + " -m max children\n" " -v verbose mode\n", __progname ); diff --git a/c_src/alcove.h b/c_src/alcove.h index 74024df..663cd28 100644 --- a/c_src/alcove.h +++ b/c_src/alcove.h @@ -46,11 +46,10 @@ typedef struct { int fderr; } alcove_child_t; -#define ALCOVE_MAX_CHILD 16 - typedef struct { u_int32_t opt; u_int8_t verbose; + u_int16_t maxchild; alcove_child_t *child; } alcove_state_t; diff --git a/c_src/alcove_call.c b/c_src/alcove_call.c index 9b875b5..5b0e164 100644 --- a/c_src/alcove_call.c +++ b/c_src/alcove_call.c @@ -26,6 +26,8 @@ #include +static int cons_pid(alcove_child_t *c, void *arg1, void *arg2); + ETERM * alcove_call(alcove_state_t *ap, u_int32_t call, ETERM *arg) { @@ -52,15 +54,7 @@ alcove_version(alcove_state_t *ap, ETERM *arg) alcove_pid(alcove_state_t *ap, ETERM *arg) { ETERM *t = erl_mk_empty_list(); - int i = 0; - - for (i = 0; i < ALCOVE_MAX_CHILD; i++) { - if (ap->child[i].pid <= 0) - continue; - - t = erl_cons(erl_mk_int(ap->child[i].pid), t); - } - + (void)pid_foreach(ap, 0, &t, NULL, pid_not_equal, cons_pid); return t; } @@ -114,3 +108,11 @@ alcove_free_argv(char **argv) free(argv); } + + static int +cons_pid(alcove_child_t *c, void *arg1, void *arg2) +{ + ETERM **t = arg1; + *t = erl_cons(erl_mk_int(c->pid), *t); + return 1; +} diff --git a/src/alcove_drv.erl b/src/alcove_drv.erl index 4bc2ea9..d5062ba 100644 --- a/src/alcove_drv.erl +++ b/src/alcove_drv.erl @@ -325,25 +325,21 @@ getopts(Options) when is_list(Options) -> Exec = proplists:get_value(exec, Options, ""), Progname = proplists:get_value(progname, Options, progname()), - Options1 = proplists:substitute_aliases([{ns, namespace}], Options), - - Options2 = lists:map(fun + Options1 = lists:map(fun (verbose) -> {verbose, 1}; - ({Tag, [H|_] = N}) when is_atom(Tag), (is_list(H) orelse is_binary(H)) -> - [{Tag, X} || X <- N]; (N) when is_atom(N) -> {N, true}; ({_,_} = N) -> N - end, Options1), + end, Options), - Switches = lists:append([ optarg(N) || N <- lists:flatten(Options2) ]), + Switches = lists:append([ optarg(N) || N <- Options1 ]), [Cmd|Argv] = [ N || N <- string:tokens(Exec, " ") ++ [Progname|Switches], N /= ""], [find_executable(Cmd)|Argv]. optarg({verbose, Arg}) -> switch(string:copies("v", Arg)); -optarg({namespace, Arg}) -> switch("n", Arg); +optarg({maxchild, Arg}) -> switch("m", Arg); optarg(_) -> "". switch(Switch) -> @@ -352,7 +348,7 @@ switch(Switch) -> switch(Switch, Arg) when is_binary(Arg) -> switch(Switch, binary_to_list(Arg)); switch(Switch, Arg) -> - [lists:concat(["-", Switch]), Arg]. + [lists:concat(["-", Switch, " ", Arg])]. find_executable(Exe) -> case os:find_executable(Exe) of diff --git a/test/alcove_tests.erl b/test/alcove_tests.erl index 8f6eb14..63e49e5 100644 --- a/test/alcove_tests.erl +++ b/test/alcove_tests.erl @@ -51,7 +51,7 @@ run(State) -> ]. start() -> - Port = alcove_drv:start([{exec, "sudo"}]), + Port = alcove_drv:start([{exec, "sudo"}, {maxchild, 16}]), case os:type() of {unix,linux} = OS -> Flags = alcove:define(Port, clone, [