The_True_Eue
Power Member
Ok, estou a escrever uma pequena shell como um exercício para SO (Sistemas Operativos).
Para já tenho este código:
O problema é que, às vezes (mas só às vezes!), quando corro um comando, recebo o SIGCHLD, mas runCmd() nunca retorna. Também me acontece quando o comando não existe e recebo o SIGUSR1. O problema é que nem sempre acontece. Já consegui correr 5 ls seguidos sem problemas, mas também já tive problemas logo à primeira.
Ajuda, anyone?
Para já tenho este código:
Código:
[SIZE=2]#include <stdlib.h>[/SIZE]
[SIZE=2]#include <stdio.h>[/SIZE]
[SIZE=2]#include <readline/readline.h>[/SIZE]
[SIZE=2]#include <readline/history.h>[/SIZE]
[SIZE=2]#include <string.h>[/SIZE]
[SIZE=2]#include <unistd.h>[/SIZE]
[SIZE=2]#include <wordexp.h>[/SIZE]
[SIZE=2]#include <sys/types.h>[/SIZE]
[SIZE=2]#include <sys/wait.h>[/SIZE]
[SIZE=2]#include <signal.h>[/SIZE]
[SIZE=2]#include <errno.h>[/SIZE]
[SIZE=2]#include "utility.h"[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]// Builtins[/SIZE]
[SIZE=2]#define CMD_EXIT 1[/SIZE]
[SIZE=2]#define CMD_WHATEVER 2[/SIZE]
[SIZE=2]static char *prompt;[/SIZE]
[SIZE=2]static int chldfail = 0;[/SIZE]
[SIZE=2]int init(void);[/SIZE]
[SIZE=2]int processCmd(void);[/SIZE]
[SIZE=2]char *readCmd(void);[/SIZE]
[SIZE=2]int runCmd(wordexp_t * words);[/SIZE]
[SIZE=2]int runBuiltin(int builtin);[/SIZE]
[SIZE=2]void sighandle(int sig);[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]int init()[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]int processCmd()[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2] static int first = 1;[/SIZE]
[SIZE=2] char *cmd;[/SIZE]
[SIZE=2] static wordexp_t words;[/SIZE]
[SIZE=2] int flags;[/SIZE]
[SIZE=2] int exit_status;[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2] cmd = readCmd();[/SIZE]
[SIZE=2] // TODO: Perform some preprocessing to process the following characters:[/SIZE]
[SIZE=2] // |&;<>[/SIZE]
[SIZE=2] if(first)[/SIZE]
[SIZE=2] flags = first = 0;[/SIZE]
[SIZE=2] else[/SIZE]
[SIZE=2] flags = WRDE_REUSE;[/SIZE]
[SIZE=2] if(wordexp(cmd, &words, flags))[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] puts("Syntax error");[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] else[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] if(strcmp(words.we_wordv[0], "exit") == 0)[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] wordfree(&words);[/SIZE]
[SIZE=2] return runBuiltin(CMD_EXIT);[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] exit_status = runCmd(&words);[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] return 0;[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2]char *readCmd()[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2] char *cmd;[/SIZE]
[SIZE=2] cmd = readline(prompt);[/SIZE]
[SIZE=2] add_history(cmd);[/SIZE]
[SIZE=2] return cmd;[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]int runCmd(wordexp_t * words)[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2] pid_t cpid;[/SIZE]
[SIZE=2] int i;[/SIZE]
[SIZE=2] TRACE("Command: %s", words->we_wordv[0]);[/SIZE]
[SIZE=2] TRACE("Args:");[/SIZE]
[SIZE=2] for(i = 1; i < words->we_wordc; i++)[/SIZE]
[SIZE=2] TRACE("%s", words->we_wordv[i]);[/SIZE]
[SIZE=2] cpid = fork();[/SIZE]
[SIZE=2] if(cpid == -1)[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] perror("fork");[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] else if(cpid == 0)[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] TRACE("Hello from child!");[/SIZE]
[SIZE=2] // I'm a new born child, let's build some personality![/SIZE]
[SIZE=2] execvp(words->we_wordv[0], words->we_wordv);[/SIZE]
[SIZE=2] TRACE("Ooops from child!");[/SIZE]
[SIZE=2] perror(words->we_wordv[0]);[/SIZE]
[SIZE=2] // How do I tell father something went wrong?[/SIZE]
[SIZE=2] // SIGUSR1[/SIZE]
[SIZE=2] kill(getppid(), SIGUSR1);[/SIZE]
[SIZE=2] exit(1);[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] else[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] pause();[/SIZE]
[SIZE=2] TRACE("Pause 1 done.");[/SIZE]
[SIZE=2] if(chldfail)[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] pause();[/SIZE]
[SIZE=2] TRACE("Pause 2 done.");[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] TRACE("Leaving runCmd()");[/SIZE]
[SIZE=2] return 0;[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]int runBuiltin(int builtin)[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2] switch (builtin)[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] case CMD_EXIT:[/SIZE]
[SIZE=2] return CMD_EXIT;[/SIZE]
[SIZE=2] default:[/SIZE]
[SIZE=2] return 0;[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]void sighandle(int sig)[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2] int status;[/SIZE]
[SIZE=2] switch (sig)[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] case SIGUSR1:[/SIZE]
[SIZE=2] // Child could not start[/SIZE]
[SIZE=2] TRACE("Got SIGUSR1");[/SIZE]
[SIZE=2] chldfail = 1;[/SIZE]
[SIZE=2] break;[/SIZE]
[SIZE=2] case SIGCHLD:[/SIZE]
[SIZE=2] // Child terminated[/SIZE]
[SIZE=2] TRACE("Got SIGCHLD");[/SIZE]
[SIZE=2] TRACE("Waiting for child to terminate...");[/SIZE]
[SIZE=2] waitpid(-1, &status, 0);[/SIZE]
[SIZE=2] if(chldfail)[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] TRACE("Failed child, ignoring...");[/SIZE]
[SIZE=2] chldfail = 0;[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] else if(WIFEXITED(status))[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] TRACE("Child terminated with code: %d", WEXITSTATUS(status));[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] else[/SIZE]
[SIZE=2] {[/SIZE]
[SIZE=2] TRACE("Child terminated abnormally.");[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2] break;[/SIZE]
[SIZE=2] }[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2][/SIZE]
[SIZE=2]int main(int argc, char *argv[])[/SIZE]
[SIZE=2]{[/SIZE]
[SIZE=2] struct sigaction act;[/SIZE]
[SIZE=2] // Register signal handlers[/SIZE]
[SIZE=2] act.sa_handler = sighandle;[/SIZE]
[SIZE=2] sigemptyset(&act.sa_mask);[/SIZE]
[SIZE=2] sigaddset(&act.sa_mask, SIGUSR1);[/SIZE]
[SIZE=2] sigaddset(&act.sa_mask, SIGCHLD);[/SIZE]
[SIZE=2] act.sa_flags = 0;[/SIZE]
[SIZE=2] sigaction(SIGUSR1, &act, NULL);[/SIZE]
[SIZE=2] sigaction(SIGCHLD, &act, NULL);[/SIZE]
[SIZE=2] // TODO: Decent prompt[/SIZE]
[SIZE=2] prompt = strdup("vsh> ");[/SIZE]
[SIZE=2] // (Almost) infinite (almost) empty command processing loop[/SIZE]
[SIZE=2] while(processCmd() != CMD_EXIT)[/SIZE]
[SIZE=2] DO_NOTHING_ELSE;[/SIZE]
[SIZE=2] return 0;[/SIZE]
[SIZE=2]}[/SIZE]
[SIZE=2]// vim:ts=4:sw=4:nowrap:tw=78:[/SIZE]
Ajuda, anyone?
Última edição: