Здравствуйте. Вот такой у меня код вышел шелла Код (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> #include <iostream> using namespace std; 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 5 \0"; //getline(cin, input); parseA(input); if (input[0] == 0) {perror("no params"); exit(1);} int i = 0; int e = 0; int ids[20]; int pipes[20][2]; int count = 0; 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[count] = fork()) == -1) {perror("error creating child process"); exit(1);} if (ids[count] == 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 { printf("process id = %d started.\n", ids[count]); 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); } count++; } e++; //printf("here\n"); } i++; e = 0; } /*int checkid; if ((checkid = fork()) == -1) {perror("error creating child process"); exit(1);} if (checkid == 0) { while(1) { //std::cin.getline(input, 99); printf("%s\n", input); } }*/ for (int i = 0; i < count; i++) { int childExitStatus; waitpid(ids[i], &childExitStatus, 0); printf("process id = %d ended with status = %d.\n", ids[i], childExitStatus); } printf("all exited.\n"); //getchar(); return 0; } //--------------------------------------------------------------------------- Он полностью рабочий, но мне осталось ещё реализовать следующие вещи: Завершение работы получив EOF (включая Ctrl+D от клавиатуры) Завершение работы если пользователь вводит слово/команду exit с клавиатуры Команду jobs которая показывала-бы все рабочие процессы (запущенные в этом шелле) Команду fg которая возвращает на последний запущенный процесс Для меня очень туманна сама суть реализации всего этого. Подскажите(подтолкните) пожалуйста как это можно реализовать?
У меня тут главный процесс, после того как запустит все процессы переходит в ожидание их завершения и после завершения выходит Код (Text): for (int i = 0; i < count; i++) { int childExitStatus; waitpid(ids[i], &childExitStatus, 0); printf("process id = %d ended with status = %d.\n", ids[i], childExitStatus); }
Не возвращает, в смысле, не пишет? Можно перенеправить его stdout к себе в файл и проверять, не написал ли чего. Но зачем это вообще надо?
У меня вот такой код Код (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> #include <iostream> using namespace std; 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"; while (1) { printf("start.\n"); char input[255]; memset(input, 0, 255); std::cin.getline(input, 255); printf("got.\n"); if (input[0] == 0) {return 0;} parseA(input); printf("%s\n", input); int i = 0; int e = 0; int ids[20]; int pipes[20][2]; int count = 0; 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[count] = fork()) == -1) {perror("error creating child process"); exit(1);} if (ids[count] == 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 { printf("process id = %d started.\n", ids[count]); 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); } count++; } e++; //printf("here\n"); } i++; e = 0; } printf("here.\n"); } printf("exit.\n"); return 0; } //--------------------------------------------------------------------------- /* for (int i = 0; i < count; i++) { int childExitStatus; waitpid(ids[i], &childExitStatus, 0); printf("process id = %d ended with status = %d.\n", ids[i], childExitStatus); } */ Проблема в том что getline (134 строка) по второму циклу проскальзывает (ничего не спрашивая пользователя выполняется например если ввести "sleep 2") И я подозреваю что это из-за того что я делаю dup2(pipes[1], 0); на 191 строке. Тоесть sleep 2 ничего не возврашает, и это "сливается" в getline
Если честно, просматривать всю простынь кода у меня сейчас ни сил, ни времени. Но в целом суть довольно проста: запускаем процесс, если он фоновый, то просто ждем от него сигнал SIGCHILD, чтобы сделать wait, когда помрет. Если не фоновый, то сразу делаем wait и ждем завершения. Обработка каналов -- это отдельная песня вообще.