Здравствуйте. Может тут найдуться люди которые знают хорошо эти вещи и смогут подсказать. Мне нужно написать простую shell программу. Должна быть реализована возможность работы с конвейерами. Тоесть пользователь вводит что-то как в bash через | , а программа должна запустить, показать результат и дождаться когда все завершат работу. (только на функции начинающийся со слова parse не смотрите так они очень громоздкие но работают нормально и создаю впечатление запутанного кода) (и тройной массив у меня нужен, так как я хочу ещё реализовать запуск программ отделённых & в фоновом режиме) У меня получился вот такой вот код Код (Text): //--------------------------------------------------------------------------- #pragma hdrstop #include <fcntl.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <netinet/in.h> #include <resolv.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> void parseA(char* input); void parseB(char* input); void parseC(char* input); void parseD(char* input); char* cmdparams[20][20][20] = {NULL}; int block = 0; int cmd = 0; int param = 0; void parseA(char* input) { while (input[0] != 0) { cmd = 0; const char* delim = strchr(input, '|'); if (delim) { int len = delim-input; char* subcmd = (char*)malloc(len); strncpy(subcmd, input, len); subcmd[len] = '\0'; parseB(subcmd); block++; strcpy(input, delim+1); } else { parseB(input); return; } } } void parseB(char* input) { while (input[0] != 0) { param = 0; char* delim = strchr(input, '&'); if (delim) { int len = delim-input; char* subcmd = (char*)malloc(len); strncpy(subcmd, input, len); subcmd[len] = '\0'; parseC(subcmd); cmd++; strcpy(input, delim+1); } else { parseC(input); return; } } } void parseC(char* input) { while (input[0] == ' ') strcpy(input, input+1); while (input[strlen(input)-1] == ' ') input[strlen(input)-1] = '\0'; while (input[0] != 0) { char* delim = strchr(input, ' '); if (delim) { int len = delim-input; char* subcmd = (char*)malloc(len); strncpy(subcmd, input, len); subcmd[len] = '\0'; parseD(subcmd); param++; strcpy(input, delim+1); } else { parseD(input); return; } } } void parseD(char* input) { cmdparams[block][cmd][param] = input; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- int main(int argc, char* argv[]) { char input[] = "ls -l | cut -c 1-20 | cut -c 1-1 \0"; //char input[] = "sleep 1 & sleep 2 \0"; parseA(input); if (input[0] == 0) {perror("no params"); exit(1);} int i = 0; int e = 0; int ids[20]; int pipes[20][2]; for (int i = 0; i < block; i++) pipe(pipes[i]); while (cmdparams[i][e][0] != NULL) { while (cmdparams[i][e][0] != NULL) { if (pipe(pipes[i]) == -1) {perror("error creating pipe"); exit(1);} if (cmdparams[i][e][0] != NULL) { if ((ids[i*e] = fork()) == -1) {perror("error creating child process"); exit(1);} if (ids[i*e] != 0) { if (cmdparams[i-1][e][0] != NULL) { dup2(pipes[i-1][0], 0); close(pipes[i-1][0]); close(pipes[i-1][1]); } if (cmdparams[i+1][e][0] != NULL) { close(pipes[i][0]); dup2(pipes[i][1], 1); close(pipes[i][1]); } //printf("%s\n", cmdparams[i][e][0]); execvp(cmdparams[i][e][0], cmdparams[i][e]); printf("%s ", cmdparams[i][e][0]); //perror("error executing child process"); exit(1); } else { if (cmdparams[i-1][e][0] != NULL) { close(pipes[i-1][0]); close(pipes[i-1][1]); } if (cmdparams[i+1][e][0] != NULL) { pipes[i-1][0] = pipes[i][0]; pipes[i-1][1] = pipes[i][0]; } dup2(pipes[i][1], 0); } } e++; } i++; e = 0; } for (int i = 0; i < block*cmd; i++) { int childExitStatus; pid_t ws = waitpid(ids[i*e], &childExitStatus, WNOHANG); if( WIFEXITED(childExitStatus) ) { printf("Result of waitpid: Child process exited thus exec failed."); } } printf("exited ok\n"); //getchar(); return 0; } //--------------------------------------------------------------------------- Проблема в том что у меня програма не доходит до слова printf("exited ok\n"); но результат выдаёт. Вся реализация очень сложна (по крайне мере для меня ) и руководствовался http://stackoverflow.com/questions/916900?tab=newest#tab-top Там я чётко не могу выловить код.
Отлаживайте программу - поставьте точки останова на printf("exited ok\n"); и на ключевые места программы. Вот это Код (Text): if ((ids[i*e] = fork()) == -1) {...} if (ids[i*e] != 0) { ... exit(1); } сравнивает результат fork с нулем. И если это не ноль - то процесс завершает работу. В документации сказано что fork возвращает > 0 родительскому процессу, а дочернему - 0. Думаю, у вас просто завершаются все процессы (и самый первый родительский - тоже) на этом exit(1), поэтому до printf("exited ok\n") дело не доходит. Попробуйте первое fork-ветвление сделать без exit(1), например, сохраняя кол-во сделанных ветвлений в счетчике. Если счетчик > 0, сделать exit(1).
А в man execvp написано следующее: The execv() and execvp() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer. Остальное не разглядывал.
Не, завершится он у меня не может из-за того что его id всегда равно 0, следовательно на exit(1) он не попадёт. А дочернии процессы тоже не должны попадать на exit(1) так это тольок должно случится если указать неправильно параметры execvp r90 А у меня сама функция execvp работает правильно исходя из того что результат сам (с работой двух пайпов) я получаю правильный.
Ещё раз присмотрел код на свежую голову и понял, что проблема в другом. У меня почему-то не происходит корректный возврат в консоль иногда.
Слушайте можете подсказать что за код такой тут такой http://stackoverflow.com/questions/916900?tab=newest#tab-top например Как его применить к исходнику что-бы он подправил его? (там-же есть исходик)
nbyte, тогда добавляйте отладочную печать в подозрительные места программы и поглядывайте - что не выводится на экран. Можно даже выводить на экран саму строчку исходного кода - будет понятно - что выполнилось, а что - нет.