int main(int argc, char **argv) { int ret, r2; runcmd_init(); t_set_colors(0); t_start("exec output comparison"); { int i; char *out = calloc(1, BUF_SIZE); for (i = 0; cases[i].input != NULL; i++) { memset(out, 0, BUF_SIZE); int pfd[2] = {-1, -1}, pfderr[2] = {-1, -1}; int fd; char *cmd; asprintf(&cmd, "/bin/echo -n %s", cases[i].input); fd = runcmd_open(cmd, pfd, pfderr, NULL); read(pfd[0], out, BUF_SIZE); ok_str(cases[i].output, out, "Echoing a command should give expected output"); close(pfd[0]); close(pfderr[0]); close(fd); } } ret = t_end(); t_reset(); t_start("anomaly detection"); { int i; for (i = 0; anomaly[i].cmd; i++) { int out_argc; char *out_argv[256]; int result = runcmd_cmd2strv(anomaly[i].cmd, &out_argc, out_argv); ok_int(result, anomaly[i].ret, anomaly[i].cmd); } } r2 = t_end(); ret = r2 ? r2 : ret; t_reset(); t_start("argument splitting"); { int i; for (i = 0; parse_case[i].cmd; i++) { int x, out_argc; char *out_argv[256]; int result = runcmd_cmd2strv(parse_case[i].cmd, &out_argc, out_argv); out_argv[out_argc] = NULL; ok_int(result, 0, parse_case[i].cmd); ok_int(out_argc, parse_case[i].argc_exp, parse_case[i].cmd); for (x = 0; x < parse_case[x].argc_exp && out_argv[x]; x++) { ok_str(parse_case[i].argv_exp[x], out_argv[x], "argv comparison test"); } } } r2 = t_end(); return r2 ? r2 : ret; }
int main(int argc, char **argv) { int ret, r2; runcmd_init(); t_set_colors(0); t_start("exec output comparison"); { int i; char *out = calloc(1, BUF_SIZE); for (i = 0; cases[i].input != NULL; i++) { memset(out, 0, BUF_SIZE); int pfd[2] = {-1, -1}, pfderr[2] = {-1, -1}; /* We need a stub iobregarg since runcmd_open()'s prototype * declares it attribute non-null. */ int stub_iobregarg = 0; int fd; char *cmd; asprintf(&cmd, ECHO_COMMAND " -n %s", cases[i].input); fd = runcmd_open(cmd, pfd, pfderr, NULL, stub_iobreg, &stub_iobregarg); free(cmd); read(pfd[0], out, BUF_SIZE); ok_str(cases[i].output, out, "Echoing a command should give expected output"); close(pfd[0]); close(pfderr[0]); close(fd); } free(out); } ret = t_end(); t_reset(); t_start("anomaly detection"); { int i; for (i = 0; anomaly[i].cmd; i++) { int out_argc; char *out_argv[256]; int result = runcmd_cmd2strv(anomaly[i].cmd, &out_argc, out_argv); ok_int(result, anomaly[i].ret, anomaly[i].cmd); if (out_argv[0]) free(out_argv[0]); } } r2 = t_end(); ret = r2 ? r2 : ret; t_reset(); t_start("argument splitting"); { int i; for (i = 0; parse_case[i].cmd; i++) { int x, out_argc; char *out_argv[256]; int result = runcmd_cmd2strv(parse_case[i].cmd, &out_argc, out_argv); /*out_argv[out_argc] = NULL;*//* This must be NULL terminated already. */ ok_int(result, parse_case[i].ret, parse_case[i].cmd); ok_int(out_argc, parse_case[i].argc_exp, parse_case[i].cmd); for (x = 0; x < parse_case[x].argc_exp && out_argv[x]; x++) { ok_str(parse_case[i].argv_exp[x], out_argv[x], "argv comparison test"); } if (out_argv[0]) free(out_argv[0]); } } r2 = t_end(); return r2 ? r2 : ret; }
/* Start running a command */ int runcmd_open(const char *cmd, int *pfd, int *pfderr, char **env) { char **argv = NULL; int cmd2strv_errors, argc = 0; size_t cmdlen; pid_t pid; int i = 0; if(!pids) runcmd_init(); /* if no command was passed, return with no error */ if (!cmd || !*cmd) return RUNCMD_EINVAL; cmdlen = strlen(cmd); argv = calloc((cmdlen / 2) + 5, sizeof(char *)); if (!argv) return RUNCMD_EALLOC; cmd2strv_errors = runcmd_cmd2strv(cmd, &argc, argv); if (cmd2strv_errors) { /* * if there are complications, we fall back to running * the command via the shell */ free(argv[0]); argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = strdup(cmd); if (!argv[2]) { free(argv); return RUNCMD_EALLOC; } argv[3] = NULL; } if (pipe(pfd) < 0) { if (!cmd2strv_errors) free(argv[0]); else free(argv[2]); free(argv); return RUNCMD_ECMD; } if (pipe(pfderr) < 0) { if (!cmd2strv_errors) free(argv[0]); else free(argv[2]); free(argv); close(pfd[0]); close(pfd[1]); return RUNCMD_EFD; } pid = fork(); if (pid < 0) { if (!cmd2strv_errors) free(argv[0]); else free(argv[2]); free(argv); close(pfd[0]); close(pfd[1]); close(pfderr[0]); close(pfderr[1]); return RUNCMD_EFORK; /* errno set by the failing function */ } /* child runs excevp() and _exit. */ if (pid == 0) { close (pfd[0]); if (pfd[1] != STDOUT_FILENO) { dup2 (pfd[1], STDOUT_FILENO); close (pfd[1]); } close (pfderr[0]); if (pfderr[1] != STDERR_FILENO) { dup2 (pfderr[1], STDERR_FILENO); close (pfderr[1]); } /* close all descriptors in pids[] * This is executed in a separate address space (pure child), * so we don't have to worry about async safety */ for (i = 0; i < maxfd; i++) if(pids[i] > 0) close (i); i = execvp(argv[0], argv); fprintf(stderr, "execvp(%s, ...) failed. errno is %d: %s\n", argv[0], errno, strerror(errno)); if (!cmd2strv_errors) free(argv[0]); else free(argv[2]); _exit (errno); } /* parent picks up execution here */ /* * close childs file descriptors in our address space and * release the memory we used that won't get passed to the * caller. */ close(pfd[1]); close(pfderr[1]); if (!cmd2strv_errors) free(argv[0]); else free(argv[2]); free(argv); /* tag our file's entry in the pid-list and return it */ pids[pfd[0]] = pid; return pfd[0]; }