#include #include #include #include #include #include #include #include #include "newt.h" #include "log.h" #include "run.h" #include "windows.h" int runProgramRoot(enum runType runType, char * root, char * name, char ** args) { return runProgramIORoot(runType, root, name, args, NULL, NULL); } int runProgramIO(enum runType runType, char * name, char ** args, char * in, char ** out) { return runProgramIORoot(runType, NULL, name, args, in, out); } int runProgramIORoot(enum runType runType, char * root, char * name, char ** args, char * in, char ** out) { char * buf; int infd, outfd, errfd, status, i; int resultfd = 0; pid_t pid; char ** currarg; int inputPipe[2], outputPipe[2]; char resultbuf[200]; char * result; int resultSize; char fullname[200]; /* if "in" is set, it better be short. We assume one write() call is enough */ if (root) { sprintf(fullname, "%s/%s", root, name); } else strcpy(fullname, name); i = 0; i = strlen(name) + 50; currarg = args; while (*currarg) { i += strlen(*currarg) + 1; currarg++; } buf = alloca(i); if (testing) strcpy(buf, "if I weren't testing I would run:\n\n"); else strcpy(buf, "running: "); strcat(buf, name); strcat(buf, " "); currarg = args; while (*currarg) { strcat(buf, *currarg); strcat(buf, " "); currarg++; } if (testing) { newtComponent t, f, succeed, fail; newtCenteredWindow(45, 15, "Running"); succeed = newtButton(8, 10, "Succeed"); fail = newtButton(28, 10, "Fail"); t = newtTextbox(2, 1, 40, 13, NEWT_TEXTBOX_WRAP | NEWT_TEXTBOX_SCROLL); newtTextboxSetText(t, buf); f = newtForm(NULL, NULL, 0); newtFormAddComponents(f, t, succeed, fail, NULL); t = newtRunForm(f); newtFormDestroy(f); newtPopWindow(); return t == fail; } if (access(fullname, X_OK)) { logMessage("cannot run %s: %s", fullname, strerror(errno)); newtWinMessage("Error", "Ok", "I cannot run %s: %s", fullname, strerror(errno)); return -1; } logMessage(buf); if (root) logMessage(" root is %s", root); if (in) { pipe(inputPipe); write(inputPipe[1], in, strlen(in)); close(inputPipe[1]); infd = inputPipe[0]; } else { infd = open("/dev/null", O_RDONLY); } errfd = open("/dev/tty5", O_APPEND | O_CREAT); if (errfd < 0) errfd = open("/tmp/exec.log", O_APPEND | O_CREAT); if (out) { pipe(outputPipe); outfd = outputPipe[1]; resultfd = outputPipe[0]; } else if (runType & RUN_LOG) { outfd = open("/dev/tty5", O_RDWR); if (outfd < 0) outfd = open("/tmp/exec.log", O_APPEND | O_CREAT); } else outfd = open("/dev/null", O_RDWR); if (!(pid = fork())) { close(0); close(1); close(2); if (root) { chroot(root); chdir("/"); } dup2(infd, 0); dup2(outfd, 1); dup2(errfd, 2); close(infd); close(outfd); close(errfd); if (out) close(resultfd); execv(name, args); logMessage("exec of %s failed: %s", name, strerror(errno)); exit(-1); } close(infd); close(outfd); close(errfd); if (out) { resultSize = 0; result = NULL; do { i = read(resultfd, resultbuf, sizeof(resultbuf)); if (!result) { result = malloc(i + 1); } else result = realloc(result, resultSize + i + 1); memcpy(result + resultSize, resultbuf, i); resultSize += i; result[resultSize] = '\0'; } while (i > 0); close(resultfd); *out = result; } waitpid(pid, &status, 0); if (WIFEXITED(status)) return WEXITSTATUS(status); return -1; } int runProgram(enum runType runType, char * name, char ** args) { return runProgramIO(runType, name, args, NULL, NULL); }