我正在开发linux来创建一个使用各种命令的shell。 我有不同的内置命令,其中一个是“历史”。 我有一个reshist()函数来重置包含由用户输入的输入的数组。 我也想使用execvp()来启用系统命令,并且还需要多个管道操作。
reshist()函数和多管道操作不在一起时,它们运行良好,但是当我使用它们时,会导致execvp()引发“错误地址”错误。
我知道reshist()函数不能正确地将输入添加到列表中,但这不是什么大问题。 问题是为什么我得到错误。
可能是什么原因? 任何更好的想法,使他们一起工作?
#include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/stat.h> #include <fcntl.h> #include <stdbool.h> #include <sys/types.h> #include <signal.h> #include <errno.h> #define MAX_BUFFER 129 // max line buffer #define MAX_ARGS 32 // max # args #define SEPARATORS " \t\n" // token sparators char *args[MAX_ARGS]; int print[16]; int get[16]; int fd[2]; char histarr[10][129]; // History array char histel[129]; void reshist(void) { //HISTORY RESORTING int counter = 0; while (counter < 10) { //shifting all elements by one from the last element of the list if (histarr[counter] == NULL ) { strcpy(histarr[counter], histel); //first element of the history will contain the last command break; } counter++; } if (counter == 10) { counter = 1; while (counter < 10) { strcpy(histarr[counter - 1], histarr[counter]); counter++; } strcpy(histarr[9], histel); } memset(histel, 0, 127); //HISTORY RESORT ENDS } void setup(void) { char buf[MAX_BUFFER]; // line buffer //char * args[MAX_ARGS]; // pointers to arg strings char ** arg; // working pointer thru args char * prompt = "333.sh>"; // shell prompt /* keep reading input until "quit" command or eof of redirected input */ while (!feof(stdin)) { /* get command line from input */ fputs(prompt, stdout); // write prompt if (fgets(buf, MAX_BUFFER, stdin)) { // read a line /* tokenize the input into args array */ arg = args; *arg++ = strtok(buf, SEPARATORS); // tokenize input while ((*arg++ = strtok(NULL, SEPARATORS))) ; // last entry will be NULL strcpy(histel, buf); reshist(); pid_t pid; int print[16]; int get[16]; int fd[2]; int count = 0; int i = 0; while (args[i] != NULL ) { if (0 == strcmp(args[i], "|")) { count++; } i++; } char *arrays[count + 1][i - count]; // array lines bordered as arrays[numberOfPipes+1][numberofArguments-numberOfPipes] i = 0; int x = 0; int y = 0; while (args[i] != NULL ) { if (strcmp(args[i], "|") != 0) { arrays[x][y] = args[i]; //builting arrays that is going to be sent to the each process, each row of the matrix is an array to be sent to another process y++; } else { x++; y = 0; } i++; } int h = 0; int a = 0; int k = 0; for (k = 0; k <= count; k++) { get[k] = -1; print[k] = -1; } //create required number of pipes for (a = 0; a < count; a++) { if (pipe(fd) == -1) { perror("Pipe failure"); continue; } get[a + 1] = fd[0]; print[a] = fd[1]; } for (k = 0; k <= count; k++) { pid = fork(); if (pid < 0) { printf("fork failed\n"); } else if (pid == 0) { if (print[k] != -1) { if (dup2(print[k], 1) == -1) { perror("dup2 error"); exit(1); } } if (get[k] != -1) { if (dup2(get[k], 0) == -1) { perror("dup2read error"); exit(1); } } for (h = 0; h <= count; h++) { close(print[h]); close(get[h]); } if (execvp((const char*) arrays[k][0], arrays[k]) < 1) { perror("error"); exit(1); } exit(0); } else { int stat; close(print[k]); close(get[k]); waitpid(pid, &stat, 0); } } } // system command else ends } } int main(void) { setup(); /** * After reading user input, the steps are: * (1) fork a child process using fork() * (2) the child process will invoke execvp() * (3) if command included &, parent will invoke wait() */ return 0; }I am working on linux to create a shell serving with various commands. I have different built in commands and one of them is "history". I have a reshist() function to reset the array that contains the inputs entered by user. I also want to enable system commands using execvp() and also multiple pipe operation.
reshist() function and multiple pipe operation works well when they are not together, but when I use them both, it causes execvp() to raise "bad address" error.
I know that reshist() function does not works correct to add inputs to the list, but that is not a big deal. The problem is why I get the error.
What could be the reason? Any better ideas to make them work together?
#include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/stat.h> #include <fcntl.h> #include <stdbool.h> #include <sys/types.h> #include <signal.h> #include <errno.h> #define MAX_BUFFER 129 // max line buffer #define MAX_ARGS 32 // max # args #define SEPARATORS " \t\n" // token sparators char *args[MAX_ARGS]; int print[16]; int get[16]; int fd[2]; char histarr[10][129]; // History array char histel[129]; void reshist(void) { //HISTORY RESORTING int counter = 0; while (counter < 10) { //shifting all elements by one from the last element of the list if (histarr[counter] == NULL ) { strcpy(histarr[counter], histel); //first element of the history will contain the last command break; } counter++; } if (counter == 10) { counter = 1; while (counter < 10) { strcpy(histarr[counter - 1], histarr[counter]); counter++; } strcpy(histarr[9], histel); } memset(histel, 0, 127); //HISTORY RESORT ENDS } void setup(void) { char buf[MAX_BUFFER]; // line buffer //char * args[MAX_ARGS]; // pointers to arg strings char ** arg; // working pointer thru args char * prompt = "333.sh>"; // shell prompt /* keep reading input until "quit" command or eof of redirected input */ while (!feof(stdin)) { /* get command line from input */ fputs(prompt, stdout); // write prompt if (fgets(buf, MAX_BUFFER, stdin)) { // read a line /* tokenize the input into args array */ arg = args; *arg++ = strtok(buf, SEPARATORS); // tokenize input while ((*arg++ = strtok(NULL, SEPARATORS))) ; // last entry will be NULL strcpy(histel, buf); reshist(); pid_t pid; int print[16]; int get[16]; int fd[2]; int count = 0; int i = 0; while (args[i] != NULL ) { if (0 == strcmp(args[i], "|")) { count++; } i++; } char *arrays[count + 1][i - count]; // array lines bordered as arrays[numberOfPipes+1][numberofArguments-numberOfPipes] i = 0; int x = 0; int y = 0; while (args[i] != NULL ) { if (strcmp(args[i], "|") != 0) { arrays[x][y] = args[i]; //builting arrays that is going to be sent to the each process, each row of the matrix is an array to be sent to another process y++; } else { x++; y = 0; } i++; } int h = 0; int a = 0; int k = 0; for (k = 0; k <= count; k++) { get[k] = -1; print[k] = -1; } //create required number of pipes for (a = 0; a < count; a++) { if (pipe(fd) == -1) { perror("Pipe failure"); continue; } get[a + 1] = fd[0]; print[a] = fd[1]; } for (k = 0; k <= count; k++) { pid = fork(); if (pid < 0) { printf("fork failed\n"); } else if (pid == 0) { if (print[k] != -1) { if (dup2(print[k], 1) == -1) { perror("dup2 error"); exit(1); } } if (get[k] != -1) { if (dup2(get[k], 0) == -1) { perror("dup2read error"); exit(1); } } for (h = 0; h <= count; h++) { close(print[h]); close(get[h]); } if (execvp((const char*) arrays[k][0], arrays[k]) < 1) { perror("error"); exit(1); } exit(0); } else { int stat; close(print[k]); close(get[k]); waitpid(pid, &stat, 0); } } } // system command else ends } } int main(void) { setup(); /** * After reading user input, the steps are: * (1) fork a child process using fork() * (2) the child process will invoke execvp() * (3) if command included &, parent will invoke wait() */ return 0; }最满意答案
该代码似乎错过了NULL终止arrays[k] 。 使arrays[k]的最后一项进入NULL 。
更新 :
这个
if (execvp((const char*) arrays[k][0], arrays[k]) < 1)应该
if (execvp(arrays[k][0], arrays[k]) == -1)更直截了当的只是:
execvp(arrays[k][0], arrays[k]); perror("execvp() failed");因为exec*()函数的成员函数仅在错误时返回。
The code seems to miss to NULL-terminate arrays[k]. Make the last entry in arrays[k] carry NULL.
Update:
This
if (execvp((const char*) arrays[k][0], arrays[k]) < 1)should be
if (execvp(arrays[k][0], arrays[k]) == -1)of even more straight forward just:
execvp(arrays[k][0], arrays[k]); perror("execvp() failed");as the members of the exec*()-family of functions return on error only.
更多推荐
发布评论