嘿所以我用夏天学习unix和c。我想通过实现管道来扩展我当前的程序。如何修改我的代码以便解析" |"。我将使用execvp
来运行命令。在shell中,如果我输入cat file | tr a A
,我想要分割cat
和tr
,以便它同时执行这是我当前的代码
numBytes = read(0, buffer, INPUT_BUFFER_SIZE);
char *token;
inputBuffer[numBytes] = '\0';
token = strtok(buffer, " \n");
int i = 0;
while(token != NULL){
userInput[i] = token;
token = strtok(NULL, " \n");
++i;
}
userInput[i] = 0;
答案 0 :(得分:0)
您可以使用我们的程序pipeline.c
,它向您展示如何实现管道。您拆分管道who | awk '{print $1}' | sort | uniq -c | sort -n
并使用数组来执行管道:
static char *cmd0[] = {"who", 0};
static char *cmd1[] = {"awk", "{print $1}", 0};
static char *cmd2[] = {"sort", 0};
static char *cmd3[] = {"uniq", "-c", 0};
static char *cmd4[] = {"sort", "-n", 0};
将命令拆分为上述数组后,可以使用如下代码。
#define _XOPEN_SOURCE 500
/*
* pipeline.c
* One way to create a pipeline of N processes using execvp
* written 2015 by: Jonathan Leffler
* test, packaging and maintenance by Niklas Rosencrantz nik@kth.se
* /
#ifndef STDERR_H_INCLUDED
#define STDERR_H_INCLU, DED
#endif /* STDERR_H_INCLUDED */
/* pipeline.c */
#include <assert.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
typedef int Pipe[2];
/* exec_nth_command() and exec_pipe_command() are mutually recursive */
static void exec_pipe_command(int ncmds, char ***cmds, Pipe output);
static void err_vsyswarn(char const *fmt, va_list args)
{
int errnum = errno;
//fprintf(stderr, "%s:%d: ", arg0, (int)getpid());
vfprintf(stderr, fmt, args);
if (errnum != 0)
fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
putc('\n', stderr);
}
static void err_syswarn(char const *fmt, ...) {
va_list args;
// va_start(args, fmt);
err_vsyswarn(fmt, args);
// va_end(args);
}
static void err_sysexit(char const *fmt, ...)
{
va_list args;
//va_start(args, fmt);
err_vsyswarn(fmt, args);
//va_end(args);
exit(1);
}
/* With the standard output plumbing sorted, execute Nth command */
static void exec_nth_command(int ncmds, char ***cmds) {
assert(ncmds >= 1);
if (ncmds > 1) {
pid_t pid;
Pipe input;
if (pipe(input) != 0)
err_sysexit("Failed to create pipe");
if ((pid = fork()) < 0)
err_sysexit("Failed to fork");
if (pid == 0) {
/* Child */
exec_pipe_command(ncmds - 1, cmds, input);
}
/* Fix standard input to read end of pipe */
dup2(input[0], 0);
close(input[0]);
close(input[1]);
}
execvp(cmds[ncmds - 1][0], cmds[ncmds - 1]);
err_sysexit("Failed to exec %s", cmds[ncmds - 1][0]);
/*NOTREACHED*/
}
/* exec_nth_command() and exec_pipe_command() are mutually recursive */
/* Given pipe, plumb it to standard output, then execute Nth command */
static void exec_pipe_command(int ncmds, char ***cmds, Pipe output) {
assert(ncmds >= 1);
/* Fix stdout to write end of pipe */
dup2(output[1], 1);
close(output[0]);
close(output[1]);
exec_nth_command(ncmds, cmds);
}
/* Execute the N commands in the pipeline */
static void exec_pipeline(int ncmds, char ***cmds) {
assert(ncmds >= 1);
pid_t pid;
if ((pid = fork()) < 0)
err_syswarn("Failed to fork");
if (pid != 0)
return;
exec_nth_command(ncmds, cmds);
}
static void exec_arguments(int argc, char **argv)
{
/* Split the command line into sequences of arguments */
/* Break at pipe symbols as arguments on their own */
char **cmdv[argc/2]; // Way too many
char *args[argc+1];
int cmdn = 0;
int argn = 0;
cmdv[cmdn++] = &args[argn];
for (int i = 1; i < argc; i++)
{
char *arg = argv[i];
if (strcmp(arg, "|") == 0)
{
if (i == 1)
err_sysexit("Syntax error: pipe before any command");
if (args[argn-1] == 0)
err_sysexit("Syntax error: two pipes with no command between");
arg = 0;
}
args[argn++] = arg;
if (arg == 0)
cmdv[cmdn++] = &args[argn];
}
if (args[argn-1] == 0)
err_sysexit("Syntax error: pipe with no command following");
args[argn] = 0;
exec_pipeline(cmdn, cmdv);
}
/* who | awk '{print $1}' | sort | uniq -c | sort -n */
static char *cmd0[] = {"who", 0};
static char *cmd1[] = {"awk", "{print $1}", 0};
static char *cmd2[] = {"sort", 0};
static char *cmd3[] = {"uniq", "-c", 0};
static char *cmd4[] = {"sort", "-n", 0};
static char **cmds[] = {cmd0, cmd1, cmd2, cmd3, cmd4};
static int ncmds = sizeof(cmds) / sizeof(cmds[0]);
int main(int argc, char **argv) {
/* The most basic example */
char *execArgs[] = { "ls", "-al", 0 };
execvp("ls", execArgs);
if (argc == 1) {
/* Run the built in pipe-line */
exec_pipeline(ncmds, cmds);
} else {
/* Run command line specified by user */
exec_arguments(argc, argv);
}
return(0);
}