Всем привет,
решаю простую задачу на flex: в сканируемом тексте найти пару тэгов [exec] и [/exec], вывести текст без изменений, за исключением текста между этой парой тэгов, который следует принять за команды оболочки и заменить из выводом. Ну т.е.:
На системе [exec] uname -a [/exec] количество подключенных модулей после загрузки составляет [exec] lsmod | wc -l [/exec] штуки.
Должно давать вывод:
На системе Linux encke 2.6.32-24-generic #42-Ubuntu SMP Fri Aug 20 14:24:04 UTC 2010 i686 GNU/Linux количество подключенных модулей после загрузки составляет 83 штуки.
Для этого написан примерно такой lex-код:
%{
#include <unistd.h> /* fork+exec() */
char *exec_string;
%}
%x exec
%%
"[exec]" BEGIN(exec);
<exec>"[/exec]" { /* saw closing tag, all done */
pid_t cpid = fork();
if (cpid == 0) {
execl("/bin/sh", "/bin/sh", "-c", exec_string, (char *) NULL);
} else {
wait();
}
BEGIN(INITIAL);
}
<exec>[^[]+ exec_string = strdup(yytext); /* fill the exec string */
/* .|\n printf("%s", yytext); [> default <] */
который отрабатывает хорошо, за исключением того, что вывод execl() выводится первым перед всем остальным текстом, т.е. получается:
Linux encke 2.6.32-24-generic #42-Ubuntu SMP Fri Aug 20 14:24:04 UTC 2010 i686 GNU/Linux
83
На системе количество подключенных модулей после загрузки составляет штуки.
Проблема, как кажется, связана с тем, что flex не выводит символы по правилу .|\n, а буфферизирует их и выплевывает лишь на <<EOF>>. Как добиться «правильного» поведения из чтения сгенерированного исходника я не понял. Есть идеи?