X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=blobdiff_plain;f=src%2Faction.c;h=913a06fb54cf6869bc4ef00b7e10ecf77c3ce671;hp=04d605dd8b562001ce0a934176eba9e146f96486;hb=d01351502311c061d2747f32c4b7797b53144987;hpb=e198b8176ac0d6b80677d1fcdd5a4cd379b019b9 diff --git a/src/action.c b/src/action.c index 04d605dd8..913a06fb5 100644 --- a/src/action.c +++ b/src/action.c @@ -26,7 +26,9 @@ #include #include #include -#include +#ifdef GDK_WINDOWING_X11 +# include +#endif /* GDK_WINDOWING_X11 */ #include #include #include @@ -47,7 +49,6 @@ #include "action.h" #include "compose.h" #include "procmsg.h" -#include "gtkstext.h" #include "textview.h" typedef struct _Children Children; @@ -60,25 +61,28 @@ struct _Children GtkWidget *text; GtkWidget *input_entry; GtkWidget *input_hbox; + GtkWidget *progress_bar; GtkWidget *abort_btn; GtkWidget *close_btn; GtkWidget *scrolledwin; gchar *action; + ActionType action_type; GSList *list; gint nb; + gint initial_nb; gint open_in; gboolean output; GtkWidget *msg_text; - GdkFont *msgfont; + + gboolean is_selection; }; struct _ChildInfo { Children *children; gchar *cmd; - guint type; pid_t pid; gint chld_in; gint chld_out; @@ -113,7 +117,6 @@ static void message_actions_execute (MessageView *msgview, static gboolean execute_actions (gchar *action, GSList *msg_list, GtkWidget *text, - GdkFont *msgfont, gint body_pos, MimeInfo *partinfo); @@ -132,7 +135,6 @@ static gboolean parse_append_msgpart (GString *cmd, MimeInfo *partinfo); static ChildInfo *fork_child (gchar *cmd, - gint action_type, const gchar *msg_str, Children *children); @@ -344,23 +346,8 @@ static gboolean parse_append_msgpart(GString *cmd, MsgInfo *msginfo, gint ret; if (!partinfo) { - FILE *fp; -#if USE_GPGME - if ((fp = procmsg_open_message_decrypted(msginfo, &partinfo)) - == NULL) { - alertpanel_error(_("Could not get message file.")); - return FALSE; - } -#else - if ((fp = procmsg_open_message(msginfo)) == NULL) { - alertpanel_error(_("Could not get message file.")); - return FALSE; - } - partinfo = procmime_scan_mime_header(fp); -#endif - fclose(fp); + partinfo = procmime_scan_message(msginfo); if (!partinfo) { - procmime_mimeinfo_free_all(partinfo); alertpanel_error(_("Could not get message part.")); return FALSE; } @@ -469,7 +456,7 @@ static void compose_actions_execute_cb(Compose *compose, guint action_nb, GtkWidget *widget) { gchar *buf, *action; - guint action_type; + ActionType action_type; g_return_if_fail(action_nb < g_slist_length(prefs_common.actions_list)); @@ -489,7 +476,7 @@ static void compose_actions_execute_cb(Compose *compose, guint action_nb, return; } - execute_actions(action, NULL, compose->text, NULL, 0, NULL); + execute_actions(action, NULL, compose->text, 0, NULL); } static void mainwin_actions_execute_cb(MainWindow *mainwin, guint action_nb, @@ -521,15 +508,15 @@ static void message_actions_execute(MessageView *msgview, guint action_nb, gchar *buf; gchar *action; GtkWidget *text = NULL; - GdkFont *msgfont = NULL; guint body_pos = 0; - + ActionType action_type; + g_return_if_fail(action_nb < g_slist_length(prefs_common.actions_list)); buf = (gchar *)g_slist_nth_data(prefs_common.actions_list, action_nb); g_return_if_fail(buf); - g_return_if_fail(action = strstr(buf, ": ")); + g_return_if_fail((action = strstr(buf, ": "))); /* Point to the beginning of the command-line */ action += 2; @@ -537,16 +524,20 @@ static void message_actions_execute(MessageView *msgview, guint action_nb, textview = messageview_get_current_textview(msgview); if (textview) { text = textview->text; - msgfont = textview->msgfont; body_pos = textview->body_pos; } partinfo = messageview_get_selected_mime_part(msgview); - execute_actions(action, msg_list, text, msgfont, body_pos, partinfo); + /* this command will alter the message text */ + action_type = action_get_type(action); + if (action_type & (ACTION_PIPE_OUT | ACTION_INSERT)) + msgview->filtered = TRUE; + + execute_actions(action, msg_list, text, body_pos, partinfo); } static gboolean execute_actions(gchar *action, GSList *msg_list, - GtkWidget *text, GdkFont *msgfont, + GtkWidget *text, gint body_pos, MimeInfo *partinfo) { GSList *children_list = NULL; @@ -554,14 +545,15 @@ static gboolean execute_actions(gchar *action, GSList *msg_list, gint msg_list_len; Children *children; ChildInfo *child_info; - gint action_type; + ActionType action_type; MsgInfo *msginfo; gchar *cmd; - guint start = 0, end = 0; gchar *sel_str = NULL; gchar *msg_str = NULL; gchar *user_str = NULL; gchar *user_hidden_str = NULL; + GtkTextIter start_iter, end_iter; + gboolean is_selection = FALSE; g_return_val_if_fail(action && *action, FALSE); @@ -588,34 +580,23 @@ static gboolean execute_actions(gchar *action, GSList *msg_list, } if (text) { - if (GTK_EDITABLE(text)->has_selection) { - start = GTK_EDITABLE(text)->selection_start_pos; - end = GTK_EDITABLE(text)->selection_end_pos; - if (start > end) { - guint tmp; - tmp = start; - start = end; - end = tmp; - } - - if (start == end) { - start = body_pos; - end = gtk_stext_get_length(GTK_STEXT(text)); - msg_str = gtk_editable_get_chars(GTK_EDITABLE(text), - start, end); - } else { - sel_str = gtk_editable_get_chars(GTK_EDITABLE(text), - start, end); - msg_str = g_strdup(sel_str); - } - } else { - start = body_pos; - end = gtk_stext_get_length(GTK_STEXT(text)); - msg_str = gtk_editable_get_chars(GTK_EDITABLE(text), - start, end); - } + GtkTextBuffer *textbuf; + + textbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)); + is_selection = gtk_text_buffer_get_selection_bounds(textbuf, + &start_iter, + &end_iter); + if (!is_selection) { + gtk_text_buffer_get_start_iter(textbuf, &start_iter); + gtk_text_buffer_get_end_iter(textbuf, &end_iter); + } + msg_str = gtk_text_buffer_get_text(textbuf, + &start_iter, &end_iter, + FALSE); + if (is_selection) + sel_str = g_strdup (msg_str); } - + if (action_type & ACTION_USER_STR) { if (!(user_str = get_user_string(action, ACTION_USER_STR))) { g_free(msg_str); @@ -634,17 +615,18 @@ static gboolean execute_actions(gchar *action, GSList *msg_list, } } - if (action_type & ACTION_PIPE_OUT) { - gtk_stext_freeze(GTK_STEXT(text)); - gtk_stext_set_point(GTK_STEXT(text), start); - gtk_stext_forward_delete(GTK_STEXT(text), end - start); - gtk_stext_thaw(GTK_STEXT(text)); + if (text && (action_type & ACTION_PIPE_OUT)) { + GtkTextBuffer *textbuf; + textbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)); + gtk_text_buffer_delete(textbuf, &start_iter, &end_iter); } children = g_new0(Children, 1); - children->msg_text = text; - children->msgfont = msgfont; + children->action = g_strdup(action); + children->action_type = action_type; + children->msg_text = text; + children->is_selection = is_selection; if ((action_type & (ACTION_USER_IN | ACTION_USER_HIDDEN_IN)) && ((action_type & ACTION_SINGLE) == 0 || msg_list_len == 1)) @@ -667,8 +649,7 @@ static gboolean execute_actions(gchar *action, GSList *msg_list, is_ok = FALSE; /* ERR: incorrect command */ break; } - if ((child_info = fork_child(cmd, action_type, msg_str, - children))) { + if ((child_info = fork_child(cmd, msg_str, children))) { children_list = g_slist_append(children_list, child_info); } @@ -678,8 +659,7 @@ static gboolean execute_actions(gchar *action, GSList *msg_list, cmd = parse_action_cmd(action, NULL, msg_list, partinfo, user_str, user_hidden_str, sel_str); if (cmd) { - if ((child_info = fork_child(cmd, action_type, msg_str, - children))) { + if ((child_info = fork_child(cmd, msg_str, children))) { children_list = g_slist_append(children_list, child_info); } @@ -695,14 +675,13 @@ static gboolean execute_actions(gchar *action, GSList *msg_list, if (!children_list) { /* If not waiting for children, return */ - g_free(children); + free_children(children); } else { GSList *cur; - children->action = g_strdup(action); - children->dialog = NULL; - children->list = children_list; - children->nb = g_slist_length(children_list); + children->list = children_list; + children->nb = g_slist_length(children_list); + children->initial_nb = children->nb; for (cur = children_list; cur; cur = cur->next) { child_info = (ChildInfo *) cur->data; @@ -718,8 +697,8 @@ static gboolean execute_actions(gchar *action, GSList *msg_list, return is_ok; } -static ChildInfo *fork_child(gchar *cmd, gint action_type, - const gchar *msg_str, Children *children) +static ChildInfo *fork_child(gchar *cmd, const gchar *msg_str, + Children *children) { gint chld_in[2], chld_out[2], chld_err[2], chld_status[2]; gchar *cmdline[4]; @@ -727,7 +706,7 @@ static ChildInfo *fork_child(gchar *cmd, gint action_type, ChildInfo *child_info; gint sync; - sync = !(action_type & ACTION_ASYNC); + sync = !(children->action_type & ACTION_ASYNC); chld_in[0] = chld_in[1] = chld_out[0] = chld_out[1] = chld_err[0] = chld_err[1] = chld_status[0] = chld_status[1] = -1; @@ -758,7 +737,9 @@ static ChildInfo *fork_child(gchar *cmd, gint action_type, if (setpgid(0, 0)) perror("setpgid"); +#ifdef GDK_WINDOWING_X11 close(ConnectionNumber(gdk_display)); +#endif /* GDK_WINDOWING_X11 */ gch_pid = fork(); @@ -767,7 +748,7 @@ static ChildInfo *fork_child(gchar *cmd, gint action_type, perror("setpgid"); if (sync) { - if (action_type & + if (children->action_type & (ACTION_PIPE_IN | ACTION_USER_IN | ACTION_USER_HIDDEN_IN)) { @@ -834,7 +815,7 @@ static ChildInfo *fork_child(gchar *cmd, gint action_type, } close(chld_in[0]); - if (!(action_type & + if (!(children->action_type & (ACTION_PIPE_IN | ACTION_USER_IN | ACTION_USER_HIDDEN_IN))) close(chld_in[1]); close(chld_out[1]); @@ -847,11 +828,10 @@ static ChildInfo *fork_child(gchar *cmd, gint action_type, child_info->pid = pid; child_info->cmd = g_strdup(cmd); - child_info->type = action_type; child_info->new_out = FALSE; child_info->output = g_string_new(NULL); child_info->chld_in = - (action_type & + (children->action_type & (ACTION_PIPE_IN | ACTION_USER_IN | ACTION_USER_HIDDEN_IN)) ? chld_in [1] : -1; child_info->chld_out = chld_out[0]; @@ -863,12 +843,14 @@ static ChildInfo *fork_child(gchar *cmd, gint action_type, child_info->tag_err = gdk_input_add(chld_err[0], GDK_INPUT_READ, catch_output, child_info); - if (!(action_type & (ACTION_PIPE_IN | ACTION_PIPE_OUT | ACTION_INSERT))) + if (!(children->action_type & + (ACTION_PIPE_IN | ACTION_PIPE_OUT | ACTION_INSERT))) return child_info; - if ((action_type & ACTION_PIPE_IN) && msg_str) { + if ((children->action_type & ACTION_PIPE_IN) && msg_str) { write(chld_in[1], msg_str, strlen(msg_str)); - if (!(action_type & (ACTION_USER_IN | ACTION_USER_HIDDEN_IN))) + if (!(children->action_type & + (ACTION_USER_IN | ACTION_USER_HIDDEN_IN))) close(chld_in[1]); child_info->chld_in = -1; /* No more input */ } @@ -966,33 +948,41 @@ static gint io_dialog_key_pressed_cb(GtkWidget *widget, GdkEventKey *event, static void childinfo_close_pipes(ChildInfo *child_info) { + /* stdout and stderr pipes are guaranteed to be removed by + * their handler, but in case where we receive child exit notification + * before grand-child's pipes closing signals, we check them and close + * them if necessary + */ if (child_info->tag_in > 0) gdk_input_remove(child_info->tag_in); - gdk_input_remove(child_info->tag_out); - gdk_input_remove(child_info->tag_err); + if (child_info->tag_out > 0) + gdk_input_remove(child_info->tag_out); + if (child_info->tag_err > 0) + gdk_input_remove(child_info->tag_err); if (child_info->chld_in >= 0) close(child_info->chld_in); - close(child_info->chld_out); - close(child_info->chld_err); + if (child_info->chld_out >= 0) + close(child_info->chld_out); + if (child_info->chld_err >= 0) + close(child_info->chld_err); + close(child_info->chld_status); } static void free_children(Children *children) { - GSList *cur; ChildInfo *child_info; debug_print("Freeing children data %p\n", children); g_free(children->action); - for (cur = children->list; cur;) { - child_info = (ChildInfo *)cur->data; + while (children->list != NULL) { + child_info = (ChildInfo *)children->list->data; g_free(child_info->cmd); g_string_free(child_info->output, TRUE); children->list = g_slist_remove(children->list, child_info); g_free(child_info); - cur = children->list; } g_free(children); } @@ -1003,28 +993,36 @@ static void update_io_dialog(Children *children) debug_print("Updating actions input/output dialog.\n"); + if (children->progress_bar) { + gtk_progress_configure(GTK_PROGRESS(children->progress_bar), + children->initial_nb -children->nb, + 0.0, children->initial_nb); + } + if (!children->nb) { gtk_widget_set_sensitive(children->abort_btn, FALSE); gtk_widget_set_sensitive(children->close_btn, TRUE); if (children->input_hbox) gtk_widget_set_sensitive(children->input_hbox, FALSE); gtk_widget_grab_focus(children->close_btn); - gtk_signal_connect(GTK_OBJECT(children->dialog), - "key_press_event", - GTK_SIGNAL_FUNC(io_dialog_key_pressed_cb), - children); + g_signal_connect(G_OBJECT(children->dialog), + "key_press_event", + G_CALLBACK(io_dialog_key_pressed_cb), + children); } if (children->output) { GtkWidget *text = children->text; gchar *caption; ChildInfo *child_info; + GtkTextBuffer *textbuf; + GtkTextIter iter, start_iter, end_iter; gtk_widget_show(children->scrolledwin); - gtk_text_freeze(GTK_TEXT(text)); - gtk_text_set_point(GTK_TEXT(text), 0); - gtk_text_forward_delete(GTK_TEXT(text), - gtk_text_get_length(GTK_TEXT(text))); + textbuf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(text)); + gtk_text_buffer_get_start_iter (textbuf, &start_iter); + gtk_text_buffer_get_end_iter (textbuf, &end_iter); + iter = start_iter; for (cur = children->list; cur; cur = cur->next) { child_info = (ChildInfo *)cur->data; if (child_info->pid) @@ -1036,14 +1034,13 @@ static void update_io_dialog(Children *children) (_("--- Ended: %s\n"), child_info->cmd); - gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, - caption, -1); - gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, - child_info->output->str, -1); + gtk_text_buffer_insert(textbuf, &iter, + caption, -1); + gtk_text_buffer_insert(textbuf, &iter, + child_info->output->str, -1); g_free(caption); child_info->new_out = FALSE; } - gtk_text_thaw(GTK_TEXT(text)); } } @@ -1058,6 +1055,7 @@ static void create_io_dialog(Children *children) GtkWidget *text; GtkWidget *scrolledwin; GtkWidget *hbox; + GtkWidget *progress_bar = NULL; GtkWidget *abort_button; GtkWidget *close_button; @@ -1070,11 +1068,11 @@ static void create_io_dialog(Children *children) gtk_window_set_title(GTK_WINDOW(dialog), _("Action's input/output")); gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); manage_window_set_transient(GTK_WINDOW(dialog)); - gtk_signal_connect(GTK_OBJECT(dialog), "delete_event", - GTK_SIGNAL_FUNC(delete_io_dialog_cb), children); - gtk_signal_connect(GTK_OBJECT(dialog), "destroy", - GTK_SIGNAL_FUNC(hide_io_dialog_cb), - children); + g_signal_connect(G_OBJECT(dialog), "delete_event", + G_CALLBACK(delete_io_dialog_cb), children); + g_signal_connect(G_OBJECT(dialog), "destroy", + G_CALLBACK(hide_io_dialog_cb), + children); vbox = gtk_vbox_new(FALSE, 8); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox); @@ -1089,14 +1087,11 @@ static void create_io_dialog(Children *children) gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_box_pack_start(GTK_BOX(vbox), scrolledwin, TRUE, TRUE, 0); - gtk_widget_set_usize(scrolledwin, 480, 200); + gtk_widget_set_size_request(scrolledwin, 480, 200); gtk_widget_hide(scrolledwin); - text = gtk_text_new(gtk_scrolled_window_get_hadjustment - (GTK_SCROLLED_WINDOW(scrolledwin)), - gtk_scrolled_window_get_vadjustment - (GTK_SCROLLED_WINDOW(scrolledwin))); - gtk_text_set_editable(GTK_TEXT(text), FALSE); + text = gtk_text_view_new(); + gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE); gtk_container_add(GTK_CONTAINER(scrolledwin), text); gtk_widget_show(text); @@ -1105,17 +1100,17 @@ static void create_io_dialog(Children *children) gtk_widget_show(input_hbox); entry = gtk_entry_new(); - gtk_widget_set_usize(entry, 320, -1); - gtk_signal_connect(GTK_OBJECT(entry), "activate", - GTK_SIGNAL_FUNC(send_input), children); + gtk_widget_set_size_request(entry, 320, -1); + g_signal_connect(G_OBJECT(entry), "activate", + G_CALLBACK(send_input), children); gtk_box_pack_start(GTK_BOX(input_hbox), entry, TRUE, TRUE, 0); - if (children->open_in & ACTION_USER_HIDDEN_IN) + if (children->action_type & ACTION_USER_HIDDEN_IN) gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); gtk_widget_show(entry); send_button = gtk_button_new_with_label(_(" Send ")); - gtk_signal_connect(GTK_OBJECT(send_button), "clicked", - GTK_SIGNAL_FUNC(send_input), children); + g_signal_connect(G_OBJECT(send_button), "clicked", + G_CALLBACK(send_input), children); gtk_box_pack_start(GTK_BOX(input_hbox), send_button, FALSE, FALSE, 0); gtk_widget_show(send_button); @@ -1124,12 +1119,31 @@ static void create_io_dialog(Children *children) gtk_widget_grab_focus(entry); } + if (children->initial_nb > 1) { + progress_bar = gtk_progress_bar_new(); + gtk_progress_bar_set_bar_style(GTK_PROGRESS_BAR(progress_bar), + GTK_PROGRESS_CONTINUOUS); + gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(progress_bar), + GTK_PROGRESS_LEFT_TO_RIGHT); + gtk_progress_set_activity_mode(GTK_PROGRESS(progress_bar), + FALSE); + gtk_progress_set_format_string(GTK_PROGRESS(progress_bar), + _("Completed %v/%u")); + gtk_progress_set_show_text(GTK_PROGRESS(progress_bar), TRUE); + gtk_progress_configure(GTK_PROGRESS(progress_bar), + children->initial_nb -children->nb, + 0.0, children->initial_nb); + + gtk_box_pack_start(GTK_BOX(vbox), progress_bar, TRUE, TRUE, 0); + gtk_widget_show(progress_bar); + } + gtkut_button_set_create(&hbox, &abort_button, _("Abort"), &close_button, _("Close"), NULL, NULL); - gtk_signal_connect(GTK_OBJECT(abort_button), "clicked", - GTK_SIGNAL_FUNC(kill_children_cb), children); - gtk_signal_connect(GTK_OBJECT(close_button), "clicked", - GTK_SIGNAL_FUNC(hide_io_dialog_cb), children); + g_signal_connect(G_OBJECT(abort_button), "clicked", + G_CALLBACK(kill_children_cb), children); + g_signal_connect(G_OBJECT(close_button), "clicked", + G_CALLBACK(hide_io_dialog_cb), children); gtk_widget_show(hbox); if (children->nb) @@ -1137,13 +1151,14 @@ static void create_io_dialog(Children *children) gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), hbox); - children->dialog = dialog; - children->scrolledwin = scrolledwin; - children->text = text; - children->input_hbox = children->open_in ? input_hbox : NULL; - children->input_entry = children->open_in ? entry : NULL; - children->abort_btn = abort_button; - children->close_btn = close_button; + children->dialog = dialog; + children->scrolledwin = scrolledwin; + children->text = text; + children->input_hbox = children->open_in ? input_hbox : NULL; + children->input_entry = children->open_in ? entry : NULL; + children->progress_bar = progress_bar; + children->abort_btn = abort_button; + children->close_btn = close_button; gtk_widget_show(dialog); } @@ -1210,31 +1225,29 @@ static void catch_output(gpointer data, gint source, GdkInputCondition cond) gchar buf[BUFFSIZE]; debug_print("Catching grand child's output.\n"); - if (child_info->type & (ACTION_PIPE_OUT | ACTION_INSERT) + if (child_info->children->action_type & + (ACTION_PIPE_OUT | ACTION_INSERT) && source == child_info->chld_out) { - gboolean is_selection = FALSE; - GtkWidget *text = child_info->children->msg_text; + GtkTextView *text = GTK_TEXT_VIEW(child_info->children->msg_text); + GtkTextBuffer *textbuf = gtk_text_view_get_buffer(text); + GtkTextIter iter1, iter2; + GtkTextMark *mark; + + mark = gtk_text_buffer_get_insert(textbuf); + gtk_text_buffer_get_iter_at_mark(textbuf, &iter1, mark); + gtk_text_buffer_get_iter_at_mark(textbuf, &iter2, mark); - if (GTK_EDITABLE(text)->has_selection) - is_selection = TRUE; - gtk_stext_freeze(GTK_STEXT(text)); while (TRUE) { c = read(source, buf, sizeof(buf) - 1); if (c == 0) break; - gtk_stext_insert(GTK_STEXT(text), - child_info->children->msgfont, - NULL, NULL, buf, c); + gtk_text_buffer_insert(textbuf, &iter2, buf, c); } - if (is_selection) { - /* Using the select_region draws things. Should not. - * so we just change selection position and - * defere drawing when thawing. Hack? - */ - GTK_EDITABLE(text)->selection_end_pos = - gtk_stext_get_point(GTK_STEXT(text)); + if (child_info->children->is_selection) { + gtk_text_buffer_place_cursor(textbuf, &iter1); + gtk_text_buffer_move_mark_by_name + (textbuf, "selection_bound", &iter2); } - gtk_stext_thaw(GTK_STEXT(text)); } else { c = read(source, buf, sizeof(buf) - 1); for (i = 0; i < c; i++) @@ -1242,6 +1255,20 @@ static void catch_output(gpointer data, gint source, GdkInputCondition cond) if (c > 0) child_info->new_out = TRUE; } + if (c == 0) { + if (source == child_info->chld_out) { + gdk_input_remove(child_info->tag_out); + child_info->tag_out = -1; + close(child_info->chld_out); + child_info->chld_out = -1; + } else { + gdk_input_remove(child_info->tag_err); + child_info->tag_err = -1; + close(child_info->chld_err); + child_info->chld_err = -1; + } + } + wait_for_children(child_info->children); }