/* Copyright (C) 2008 Emmanuel Varoquaux This file is part of XOS. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "print_cmd.h" #include "command.h" #include "safe_malloc.h" #include #include /* string_buffer */ void string_buffer_init(struct string_buffer_struct *string_buffer) { string_buffer->buf = NULL; string_buffer->size = 0; } char *string_buffer_release(struct string_buffer_struct *string_buffer) { char *string; string = string_buffer->buf; string_buffer->buf = NULL; string_buffer->size = 0; return string; } static void string_buffer_append(struct string_buffer_struct *string_buffer, const char *str) { size_t str_len; size_t size; str_len = strlen(str); if (!string_buffer->buf) { size = 1; while (size <= str_len) size *= 2; string_buffer->buf = safe_malloc(size); string_buffer->size = size; strcpy(string_buffer->buf, str); string_buffer->pos = str_len; } else { if (string_buffer->pos + str_len >= string_buffer->size) { size = string_buffer->size; while (size <= string_buffer->pos + str_len) size *= 2; string_buffer->buf = safe_realloc(string_buffer->buf, size); string_buffer->size = size; } strcpy(string_buffer->buf + string_buffer->pos, str); string_buffer->pos += str_len; } } /* print_cmd */ static void do_print_command(const struct command_struct *command, struct string_buffer_struct *string_buffer); static void do_print_pipeline(const struct pipeline_struct *pipeline, struct string_buffer_struct *string_buffer); static void do_print_and_or_list(const struct and_or_list_struct *and_or_list, struct string_buffer_struct *string_buffer); static void do_print_list(const struct list_struct *list, struct string_buffer_struct *string_buffer); static void print_argument(const struct argument_struct *argument, struct string_buffer_struct *string_buffer) { string_buffer_append(string_buffer, argument->word); } static void append_number(int num, struct string_buffer_struct *string_buffer) { char buf[sizeof (int) * 8 + 1]; sprintf(buf, "%d", num); string_buffer_append(string_buffer, buf); } static void print_redirect(const struct redirect_struct *redirect, struct string_buffer_struct *string_buffer) { switch (redirect->type) { case RT_REDIRECT_INPUT: case RT_DUPLICATE_INPUT: case RT_READ_WRITE: if (redirect->fd != 0) append_number(redirect->fd, string_buffer); break; case RT_REDIRECT_OUTPUT: case RT_REDIRECT_OUTPUT_FORCE: case RT_REDIRECT_OUTPUT_APPEND: case RT_DUPLICATE_OUTPUT: if (redirect->fd != 1) append_number(redirect->fd, string_buffer); break; } switch (redirect->type) { case RT_REDIRECT_INPUT: string_buffer_append(string_buffer, "< "); break; case RT_REDIRECT_OUTPUT: string_buffer_append(string_buffer, "> "); break; case RT_REDIRECT_OUTPUT_FORCE: string_buffer_append(string_buffer, ">| "); break; case RT_REDIRECT_OUTPUT_APPEND: string_buffer_append(string_buffer, ">> "); break; case RT_DUPLICATE_INPUT: string_buffer_append(string_buffer, "<&"); break; case RT_DUPLICATE_OUTPUT: string_buffer_append(string_buffer, ">&"); break; case RT_READ_WRITE: string_buffer_append(string_buffer, "<> "); break; } string_buffer_append(string_buffer, redirect->filename); } static void print_simple_command(const struct simple_command_struct *simple_command, struct string_buffer_struct *string_buffer) { const struct argument_struct *argument; const struct redirect_struct *redirect; if (simple_command->command_name) { string_buffer_append(string_buffer, simple_command->command_name); for (argument = simple_command->first_argument; argument; argument = argument->next) { string_buffer_append(string_buffer, " "); print_argument(argument, string_buffer); } if (simple_command->first_redirect) string_buffer_append(string_buffer, " "); } for (redirect = simple_command->first_redirect; redirect; redirect = redirect->next) { print_redirect(redirect, string_buffer); if (redirect->next) string_buffer_append(string_buffer, " "); } } static void print_compound_command(const struct compound_command_struct *compound_command, struct string_buffer_struct *string_buffer) { const struct redirect_struct *redirect; switch (compound_command->type) { case CC_SUBSHELL: string_buffer_append(string_buffer, "( "); do_print_list(compound_command->list, string_buffer); string_buffer_append(string_buffer, " )"); if (compound_command->first_redirect) string_buffer_append(string_buffer, " "); break; } for (redirect = compound_command->first_redirect; redirect; redirect = redirect->next) { print_redirect(redirect, string_buffer); if (redirect->next) string_buffer_append(string_buffer, " "); } } static void do_print_command(const struct command_struct *command, struct string_buffer_struct *string_buffer) { switch (command->type) { case CT_SIMPLE: return print_simple_command(&command->simple_command, string_buffer); case CT_COMPOUND: return print_compound_command(&command->compound_command, string_buffer); } } void print_command(const struct command_struct *command, int *line_number, struct string_buffer_struct *string_buffer) { *line_number = command->line_number; do_print_command(command, string_buffer); } static void do_print_pipeline(const struct pipeline_struct *pipeline, struct string_buffer_struct *string_buffer) { const struct command_struct *command; for (command = pipeline->first_command; command; command = command->next) { do_print_command(command, string_buffer); if (command->next) string_buffer_append(string_buffer, " | "); } } void print_pipeline(const struct pipeline_struct *pipeline, int *line_number, struct string_buffer_struct *string_buffer) { *line_number = pipeline->line_number; do_print_pipeline(pipeline, string_buffer); } static void do_print_and_or_list(const struct and_or_list_struct *and_or_list, struct string_buffer_struct *string_buffer) { const struct pipeline_struct *pipeline; for (pipeline = and_or_list->first_pipeline; pipeline; pipeline = pipeline->next) { do_print_pipeline(pipeline, string_buffer); if (pipeline->next) switch (pipeline->operator) { case AO_AND: string_buffer_append(string_buffer, " && "); break; case AO_OR: string_buffer_append(string_buffer, " || "); break; } } } /* Attention, n'imprime pas le " &" pour les listes asynchrones. */ void print_and_or_list(const struct and_or_list_struct *and_or_list, int *line_number, struct string_buffer_struct *string_buffer) { *line_number = and_or_list->line_number; do_print_and_or_list(and_or_list, string_buffer); } static void do_print_list(const struct list_struct *list, struct string_buffer_struct *string_buffer) { const struct and_or_list_struct *and_or_list; for (and_or_list = list->first_and_or_list; and_or_list; and_or_list = and_or_list->next) { do_print_and_or_list(and_or_list, string_buffer); if (and_or_list->asynchronous) { string_buffer_append(string_buffer, " &"); if (and_or_list->next) string_buffer_append(string_buffer, " "); } else if (and_or_list->next) string_buffer_append(string_buffer, "; "); } } void print_list(const struct list_struct *list, int *line_number, struct string_buffer_struct *string_buffer) { *line_number = list->line_number; do_print_list(list, string_buffer); }