Core implementation of mysystem (to emulate the system builtin)
- Here we present our own implementation of the mysystem function, which executes the provided command (guaranteed to be a '\0'-terminated C string) by calling "/bin/sh -c command" and ultimately returning once the surrogate command has finished.
- If the execution of command exits normally (either via an exit system call, or via a normal return statement from main), then our mysystem implementation should return that exact same exit status.
- If the execution exits abnormally (e.g. it segfaults), then we'll assume it aborted because some signal was ignored, and we'll return that negative of that signal number (e.g. -11 for SIGSEGV).
- Here's the implementation (online right here)
static int mysystem(const char *command) {
pid_t pid = fork();
if (pid == 0) {
char *arguments[] = {"/bin/sh", "-c", (char *) command, NULL};
execvp("/bin/sh", arguments);
exitIf(true, kExecFailed, stderr, "execvp failed to invoke this: %s.\n", command);
}
int status;
waitpid(pid, &status, 0);
if (WIFEXITED(status))
return WEXITSTATUS(status);
else
return -WTERMSIG(status);
}
- Here's a trivial unit test that I'll run in lecture to prove this thing really works:
static const size_t kMaxLine = 2048;
int main(int argc, char *argv[]) {
char buf[kMaxLine];
while (true) {
printf("> ");
fgets(buf, kMaxLine, stdin);
if (feof(stdin)) break;
buf[strlen(buf) - 1] = '\0'; // overwrite '\n'
printf("retcode = %d\n", mysystem(buf));
}
printf("\n");
return 0;
}