我正在制作一个自制的外壳(非常简单的外壳)。我决定采用execvp的路线,因为我的路径不是我的shell的可变元素。我遇到了一个关于如何一次分叉和执行多个进程的逻辑的问题。
我的程序应该使用命令:
ls ; echo hello ; cat shell.c
每个“;”表示我们希望同时运行这些进程。因此,在我们的终端输出上,我们应该立即将这些命令混合起来。
详细说明我想解释一下我的程序是如何工作的:
A. Intake full command line into char array with a grab line function
B. Split the char array received from the last function by delimiters and place into an array of char arrays (pointer to pointer).
C. If one of the elements in our array of char arrays is ";" we can assume that multi commands are necessary. This is where I have trouble.
我已经知道到底需要多少进程来分叉等等,但我似乎无法理解如何将所有这些函数及其参数一次性传递给execvp函数。我应该使用临时数组吗?我知道这不应该是这么复杂,但由于某种原因,我无法弄明白。我正在下面提交我的启动函数,它会引入一个char数组并根据我的“multiCommand”变量执行相应的操作,该变量在需要多个命令时设置(通过我的分割线函数)
int launch(char **args){
pid_t pid;
int status;
int i = 0;
if(strcmp(args[0], "quit") == 0){
exit(EXIT_SUCCESS);
}
if(strcmp(args[0], ";") != 0){
printf("Essential Command Found : %s\n", args[0]);
numFork++;
}
if(multiCommand == 1){
//Handle Multicommands here
printf("Multi Commands Handling Here\n");
for(; i < elements - 1; i++){
if(strcmp(args[i], ";") == 0){
if((i + 1) < elements){
printf("Essential Command Found : %s\n", args[i + 1]);
numFork++;
}
}
}
//This is where I need to figure out what to do
printf("Fork: %d times\n", numFork);
}else if (multiCommand == 0){
pid = fork();
if(pid == 0){
execvp(args[0], args);
}else{
wait(&status);
}
}
multiCommand = 0;
elements = 0;
return 1;
}
答案 0 :(得分:5)
一般的想法是对不同的命令进行for循环并分叉它们。
E.g。
for(int i = 0; i < commandCount; i++) {
int pid = fork();
if(pid == 0) { //this is the child (don't forget to check for errors and what-not)
execCommand(all, of, the, info, needed);
}
}
您可以使用strtok()
轻松获取不同的命令
这是一个例子:
#include <string.h>
#include <stdio.h>
int main() {
char input[] = "abc;def;ghi";
char *token = strtok(input, ";");
while(token != NULL) {
printf("%s\n", token);
token = strtok(NULL, ";");
}
return 0;
}
输出:
abc
def
ghi
最终的功能看起来像这样:
char *token = strtok(input, ";");
while(token != NULL) {
int pid = fork();
if(pid == 0) {
//token is one command
//parse the different parts here
execCommand(args, to, exec);
}
token = strtok(NULL, ";");
}