readline might not be the problem, but i can't reproduce this behavior without it
here is a minimalist reproduction of a shell, it prints a prompt on STDOUT and if the command start with "echo " it prints what comes next :
mybash.c :
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <readline/readline.h>
int main(void)
{
char *prompt;
char *line_input;
prompt = "[mybash]> ";
while (1)
{
line_input = readline(prompt);
if (line_input)
{
if (!strncmp(line_input, "echo ", 5))
{
write(1, line_input + 5, strlen(line_input) - 5);
write(1, "\n", 1);
}
free(line_input);
}
if (!line_input)
{
write(2, "exit\n", 5);
exit(0);
}
}
return (0);
}
at first it looks like it works fine :
exit happens because i press Ctrl-D, or in later examples because pipes ends
[bash]$ gcc mybash.c -lreadline
[bash]$ ./a.out
[mybash]> echo hello
hello
[mybash]> anything
[mybash]> exit
[bash]$
now i put it in a pipe to capture the output
[bash]$ echo "echo hello" | ./a.out &>file.log
[bash]$ cat file.log
[mybash]> echo hello
hello
[mybash]> exit
[bash]$
(i added the empty space at beginning of lines in cat output for readability)
ok, now i change the prompt for something very long :
prompt = WHITE"[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> "RESET;
and the output works fine in classic interactivity, it works also fine in pipes with a redirection of only STDERR or STDOUT, but if i redirect both, it breaks :
interactive prompt :
[bash]$ ./a.out
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> echo hello
hello
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> anything
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> exit
[bash]$
pipe without redirection :
[bash]$ echo "echo hello" | ./a.out
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> echo hello
hello
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> anything
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> exit
[bash]$
in case it's not clear, i only wrote the first command echo "echo hello" | ./a.out, the rest prompted "automatically", unlike the previous example
STDOUT redirection :
[bash]$ echo "echo hello" | ./a.out 1>file.log
exit
[bash]$ cat file.log
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> echo hello
hello
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> [%]
[bash]$
STDERR redirection :
[bash]$ echo "echo hello" | ./a.out 2>file.log
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> echo hello
hello
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> [%]
[bash]$ cat file.log
exit
[bash]$
STDOUT and STDERR redirections in interactive mode :
[bash]$ ./a.out &>file.log
(i type here without seeing anything)
[bash]$ cat file.log
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> echo hello
hello
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> anything
[mybash_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]> exit
[bash]$
and STDOUT & STDERR redirections in pipe :
[bash]$ echo "echo hello" | ./a.out &>file.log
[bash]$ cat file.log
_file]>echo hellog_prompt_to_test_the_output_in_case_of_a_redirection_in_a
hello
exith_a_very_long_prompt_to_test_the_output_in_case_of_a_redirection_in_a_file]>
[bash]$
sorry, colors of stackoverflow breaks a little in this example
as you can see, in the last example the prompt line doesn't go to a new line, it writes over itself at the beginning, but it only occurs with &> redirection and pipes, i don't understand why ?
and of course, the same tests on bash instead of mybash works very well, the prompt doesn't break