2016-06-24 9 views
0

ねえ、私は夏を使ってUNIXとCを学んでいます。パイプを実装することで現在のプログラムを拡張したいと思います。コードを変更して "|"を解析するにはどうしたらいいですか?私はexecvpを使用してコマンドを実行します。それは実行の両方ここであなたはパイプを実装する方法を示しているである私たちのプログラムpipeline.cを使用することができ、私の現在のコードC: "|"を解析する方法

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

未定義の変数とマクロがいくつかあります。 '|'が指定された文字列内にある場合でも、 '" | \ n "'のように区切り文字に含める必要があります。あなたの例には、分離したいトークンのスペースが含まれているので、私は 'space'を削除しました。しかし、それは静かです。 –

+1

@WeatherVaneセパレータに '|'を置くと、 'strtok()'は入力文字列からセパレータを削除するので、セパレータが空白かパイプかを判断できません。 – Barmar

+0

単純なので、パイプシンボルの周りに空白を入れなければならないと仮定すると、 'if(strcmp(token、" | ")== 0)'のようなものを使用して、パイプ。 – Barmar

答えて

0

になるように、私はcat file | tr a Aを入力すると、シェルでは、私はcattrを分割したいです。あなたは上記のような配列にコマンドを分割したら、あなたは以下のようなコードを使用することができます

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}; 

:あなたは、パイプライン who | awk '{print $1}' | sort | uniq -c | sort -nを分割してパイプラインを実行するために配列を使用します。

#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 [email protected] 
*/

#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); 
} 
関連する問題