frabill | J'ai un programme à faire en C qui doit être capable d'exécuter les commandes de base suivantes : # % ls
# % ls > filelist
# % cat filelist
# % cat < filelist
# % ls | wc
# % ls | cat | cat | cat | wc
les quatres premiers types de commandes fonctionnent (simples, redirections), mais j'ai des problèmes avec les pipes
J'avais une structure de base avec des fonctions déjà opérationnelles : parser...
donc il reste deux fonctions importantes :
Code :
- static char* progname; /* name of this shell program. */
- static char input_buf[MAXBUF]; /* input is placed here. */
- static char token_buf[2 * MAXBUF]; /* tokens are placed here. */
- static char* input_char; /* next character to check. */
- static char* token; /* a token such as /bin/ls */
- static list_t* path_dir_list; /* list of directories in PATH. */
- static int input_fd; /* for i/o redirection or pipe. */
- static int output_fd; /* for i/o redirection or pipe */
- /* run_program: fork and exec a program. */
- void run_program(char** argv, int argc, bool foreground, bool doing_pipe)
- {
- /* you need to fork, search for the command in argv[0],
- * setup stdin and stdout of the child process, execv it.
- * the parent should sometimes wait and sometimes not wait for
- * the child process (you must figure out when). if foreground
- * is true then basically you should wait but when we are
- * running a command in a pipe such as PROG1 | PROG2 you might
- * not want to wait for each of PROG1 and PROG2...
- *
- * hints:
- * sprintf is useful for constructing strings.
- * access is useful for checking wether a path refers to an
- * executable program.
- *
- *
- */
- int child_pid;
- char file[MAXBUF];
- sprintf(file,"/usr/bin/%s",argv[0]);
- if (doing_pipe) {
- printf("pipe\n" );
- if (access(file,X_OK) == 0) {
- if ((child_pid = fork()) < 0) {
- perror("fork failed" );
- exit(1);
- }
- else if (child_pid == 0) {
- if (output_fd != 0) {
- dup2(output_fd,1); // > case
- }
- if (input_fd != 0) {
- dup2(input_fd,0); // < case
- }
- execv(file,argv);
- }
- }
- else {
- printf("command does not exist : %s \n",argv[0]);
- }
- }
- else {
- if (access(file,X_OK) == 0) {
- if ((child_pid = fork()) < 0) {
- perror("fork failed" );
- exit(1);
- }
- else if (child_pid == 0) {
- if (output_fd != 0) {
- dup2(output_fd,1); // > case
- }
- if (input_fd != 0) {
- dup2(input_fd,0); // < case
- }
- execv(file,argv);
- }
- }
- else {
- printf("command does not exist : %s \n",argv[0]);
- }
- }
- }
- void parse_line(void)
- {
- char* argv[MAX_ARG + 1];
- int argc;
- int pipe_fd[2]; /* 1 for producer and 0 for consumer. */
- token_type_t type;
- bool foreground;
- bool doing_pipe;
- input_fd = 0;
- output_fd = 0;
- argc = 0;
- for (;;) {
- foreground = true;
- doing_pipe = false;
- type = gettoken(&argv[argc]);
- switch (type) {
- case NORMAL:
- argc += 1;
- break;
- case INPUT:
- type = gettoken(&argv[argc]);
- if (type != NORMAL) {
- error("expected file name: but found %s",
- argv[argc]);
- return;
- }
- input_fd = open(argv[argc], O_RDONLY);
- if (input_fd < 0)
- error("cannot read from %s", argv[argc]);
- break;
- case OUTPUT:
- type = gettoken(&argv[argc]);
- if (type != NORMAL) {
- error("expected file name: but found %s",
- argv[argc]);
- return;
- }
- output_fd = open(argv[argc], O_CREAT | O_WRONLY, PERM);
- if (output_fd < 0)
- error("cannot write to %s", argv[argc]);
- break;
- case PIPE:
- doing_pipe = true;
- pipe(pipe_fd);
- output_fd = pipe_fd[1];
- printf("output_fd : %d \n",output_fd);
- /*FALLTHROUGH*/
- case AMPERSAND:
- foreground = false;
- /*FALLTHROUGH*/
- case NEWLINE:
- case SEMICOLON:
- if (argc == 0)
- return;
- argv[argc] = NULL;
- run_program(argv, argc, foreground, doing_pipe);
- input_fd = 0;
- output_fd = 0;
- argc = 0;
- input_fd = pipe_fd[0];
- printf("input_fd : %d \n",input_fd);
- if (type == NEWLINE)
- return;
- break;
- }
- }
- }
|
j'explique un peu le principe : la fonction parse_line analyse la ligne de commande et place les arguments (nom de commande,"<",">","|","&",fin de ligne) dans un tableau.
Ensuite run_program est appelé. Elle a pour but de créer le nouveau processus. La partie redirection fonctionne, c'est pour la gestion des pipes que je ne m'en sors pas. Message édité par frabill le 29-04-2004 à 18:18:47
|