我正在尝试使用 execvp 运行命令" wc -l << END
",所以我正在解析命令并使用"wc -l
"运行 execvp,但随后它进入无限循环。
如何使其工作,以便在找到关键字时停止(在本例中为 END)?
- 我必须使用 execvp
- 该命令来自用户输入,在本例中为"
wc -l << END
编辑
这是我的代码(不会有太大帮助,但可以提供一些背景)[here-doc 的代码在最后一个 else 语句中]:
redirect(int proc, char * input){
char * comm;
int proc2;
int append = 0;
if(proc == 1){ //in
comm = strsep(&input, "<");
proc2 = check(input);
}
else{ //out
comm = strsep(&input, ">");
proc2 = check(input);
if(proc2 == 2){ //append
strsep(&input, ">");
append = 1;
}
}
if(proc2 == 0 || append == 1){ //only one redirection
if(proc == 1){ //in
input = trim(input);
int fd = open(input, O_RDWR);
close(0);
dup2(fd, 0);
close(fd);
comm = trim(comm);
char ** words = parse(comm);
if(!execvp(words[0], words)){ /*exec failed */
exit(1);
}
}
else{ //out
input = trim(input);
int fd;
if(append == 0){ //create
fd = open(input, O_CREAT | O_RDWR | O_TRUNC,
S_IRUSR | S_IWUSR);
}
else{ //append
fd = open(input, O_CREAT | O_RDWR | O_APPEND,
S_IRUSR | S_IWUSR);
}
dup2(fd, 1);
close(fd);
comm = trim(comm);
char ** words = parse(comm);
if(!execvp(words[0], words)){ /*exec failed */
exit(1);
}
}
}
else{ //more than one redirection/pipe
if(proc == proc2){ //here-doc
strsep(&input, "<");
input = trim(input);
}
}
}
一种解决方案是将用户输入存储到临时文件中,然后将临时文件作为 stdin 传递,但我想知道是否有更好的方法可以做到这一点。
使用临时文件并将子进程的 stdin 指向该文件,而是可以通过管道将输入从父进程或其他子进程提供给子进程。 然后,父进程或第二个子进程将负责读取输入,监视输入标记的末尾,并将数据传递到(原始)子进程。
下面的示例演示如何使用管道和第二个子进程读取 stdin,监视输入结束标记,并将输入传递到原始子进程,直到找到它。 该示例省略了错误检查(应添加),并对要运行的命令和输入标记的末尾使用硬编码值。 请注意,在父管道中关闭管道的写入端非常重要,这样命令才能在输入读取器退出后看到它的 stdin 关闭。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main(int argc, char *argv[])
{
pid_t rdr, /* input reader process */
cmd, /* command runner process */
wres; /* wait() result */
/* pipe for passing input from rdr to cmd */
int pipefd[2] = {0};
/* command and args to pass to execvp() */
char *command = "wc";
char *cmdargs[] = { "wc", "-l", NULL };
/* end of input marker */
char *endinp = "ENDn";
/* create a pipe:
- read end's fd will be pipefd[0],
- write end's fd will be pipefd[1] */
pipe(pipefd);
cmd = fork();
if (!cmd) { /* COMMAND RUNNER PROCESS */
dup2(pipefd[0],0); /* set stdin to pipe's read end */
close(pipefd[1]); /* close pipe's write end */
/* exec command (will read from stdin) */
execvp(command, cmdargs);
}
rdr = fork();
if (!rdr) { /* INPUT READER PROCESS */
close(pipefd[0]); /* close pipe's read end */
/* read input from stdin until a line containing only
the end of input marker is found */
char buf[1024];
while (fgets(buf,sizeof(buf),stdin)) {
/* break when end of input marker is read */
if (!strcmp(buf,endinp)) break;
/* write data to pipe */
write(pipefd[1],buf,strlen(buf));
}
return 0;
}
/* PARENT PROCESS */
close(pipefd[0]); /* close pipe's read end */
close(pipefd[1]); /* close pipe's write end */
/* wait for both children to exit */
do {
wres = wait(NULL);
if (wres == rdr) rdr = 0;
if (wres == cmd) cmd = 0;
} while (rdr || cmd);
return 0;
}
通常,您将问题与代码一起发布,否则我们将无法正确帮助您发展编程技能。这次我会给你一个小菜一碟,给你一个示例代码(这可能是完整的答案)。
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
pid_t pid;
int status;
// you must provide the full path for the executable
// such as /bin/echo, /usr/bin/wc ...
if(argc < 2)
{
printf("expected format example /usr/bin/wc -l << ENDn");
return (-1);
}
// fork your process since EXEC family
// takes control over your process
// This way you may do other things
if((pid = fork()) < 0)
err(1, "fork() error");
if(pid == 0) /* child */
{
// argv[0] is the name of your program executable
// first argument to execvp is the target executable
// with the full path, again /bin/echo
// segund argument is a list of arguments for your
// target null terminated. Note that the first
// argument of that list is the name of the executable/location
// itself
// illustrative: execvp("/bin/echo", {"/bin/echo", "example", NULL})
if(execvp(argv[1], &argv[1]) < 0)
err(1, "execvp() error");
}
else /* father */
{
printf(">> father waiting child..n");
while(wait(&status) != pid);
printf(">> child finishedn");
}
return (0);
}
如果你想深入了解这个主题,你可以看看这个。