简体   繁体   English

带管道的简单 Shell。 无法计算管道

[英]Simple Shell with pipes. Unable to count the pipes

I'm tasked with implementing pipes in a simple shell program sshell.c.我的任务是在一个简单的 shell 程序 sshell.c 中实现管道。 Right now, I am just trying to count the number of pipes, but for some reason I am unable to increment my pipe_count despite being able to print it out and see it from the same array args[ARR_SIZE] .现在,我只是想计算管道的数量,但由于某种原因,尽管能够打印出来并从同一个数组args[ARR_SIZE]中查看它,但我无法增加我的 pipe_count。 Each argument is printed as a string so when I type "ls | grep hello", I get "ls", "|", "grep", "hello" all in a row when i run it in a for loop (see #ifdef step1) .每个参数都打印为字符串,所以当我输入“ls | grep hello”时,当我在 for 循环中运行它时,我会连续得到“ls”、“|”、“grep”、“hello” (参见 # ifdef 步骤 1)

My question is: How should I set my conditional statement to identify the "|"我的问题是:我应该如何设置我的条件语句来识别“|” symbol?象征?

The program that was given to us does the following:提供给我们的程序执行以下操作:

  1. Reads in the Command Line在命令行中读取
  2. Stores read data into memory and sends the data into function parse_args()将读取的数据存储到 memory 并将数据发送到 function parse_args()
  3. parse_args() replaces delimiters like '\n', ' ', or '\t' with '\0'and stores those values as tokens in args[ARR_SIZE] parse_args() 将 '\n'、' ' 或 '\t' 等分隔符替换为 '\0' 并将这些值作为标记存储在 args[ARR_SIZE]
  4. if the number of arguments, num_args is greater than zero, it forks().如果 arguments, num_args 的数量大于零,则 forks()。

My implementations are in the #ifdef directives step1 and step2.我的实现在 #ifdef 指令 step1 和 step2 中。 I was trying to break it into small steps.我试图把它分成小步骤。

/*
 *  This is a simple shell program from
 *  rik0.altervista.org/snippetss/csimpleshell.html
 *  It's been modified a bit and comments were added.
 *
 *  But it doesn't allow misdirection, e.g., <, >, >>, or |
 *  The project is to fix this.
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/types.h>
#define BUFFER_SIZE 80
#define ARR_SIZE 80

#define DEBUG 1  /* In case you want debug messages */
#define step1 /*Detect the pipe char*/
//#define step2 /*create pipes*/
//#define step3 /*fork*/

/*Variables for pipes*/
int in[2], out[2], n;
char buf[255];

void error(char *s);

void parse_args(char *buffer, char** args, 
                size_t args_size, size_t *nargs)
{
    char *buf_args[args_size]; 
    
    char *wbuf = buffer;
    buf_args[0]=buffer; 
    args[0]=buffer;  /* First argument */
/*
 *  The following replaces delimiting characters with '\0'. 
 *  Example:  " Aloha World\n" becomes "\0Aloha\0World\0\0"
 *  Note that the for-loop stops when it finds a '\0' or it
 *  reaches the end of the buffer.
 */   
    for(char **cp=buf_args; (*cp=strsep(&wbuf, " \n\t")) != NULL ;){
        if ((**cp != '\0') && (++cp >= &buf_args[args_size]))
            break; 
    }


/* Copy 'buf_args' into 'args' */    
    size_t j=0;
    for (size_t i=0; buf_args[i]!=NULL; i++){ 
        if(strlen(buf_args[i])>0)  /* Store only non-empty tokens */
            args[j++]=buf_args[i];
    }
    
    *nargs=j;
    args[j]=NULL;


}

int main(int argc, char *argv[], char *envp[]){
    char buffer[BUFFER_SIZE];
    char *args[ARR_SIZE];
    int num_pipes = 0;
    size_t num_args;
    pid_t pid;
    
    while(1){
        printf("ee468>> "); 
        fgets(buffer, BUFFER_SIZE, stdin); /* Read in command line */
        parse_args(buffer, args, ARR_SIZE, &num_args);


#ifdef step1 /*Detect pipe symbol in args*/
        printf("Printing the args returned from parse_args:\n");
        for(int i = 0; i < ARR_SIZE && args[i]!= NULL; i++){
            printf("args[%d]: %s\n",i, args[i]);
            if(args[i]== "\0|\0" || args[i]=="|"){
                num_pipes++;
            }
        }
        printf("There are %d pipes in the buffer.\n",num_pipes);
#endif

        if (num_args>0) {
            if (!strcmp(args[0], "exit" )) exit(0);       
            pid = fork();
            if (pid){  /* Parent */
#ifdef DEBUG
                printf("Waiting for child (%d)\n", pid);
#endif
                pid = wait(NULL);
#ifdef DEBUG
                printf("Child (%d) finished\n", pid);
#endif
            } 
            else{  /* Child executing the command */
                if( execvp(args[0], args)) {
                    puts(strerror(errno));
                    exit(127);
                }
            }

        }
    }    
    return 0;
}

void error(char *s) 
{ 
  perror(s); 
  exit(1); 
}

Example Result示例结果

if(args[i]== "\0|\0" || args[i]=="|"){

This line does not work as you are only comparing the pointers.此行不起作用,因为您只比较指针。 To compare strings in C you have to use strcmp() , so it should look something like this:要比较 C 中的字符串,您必须使用strcmp() ,所以它应该看起来像这样:

if (!strcmp(args[i], "|")) {
    num_pipes++;
}

Moreover, you shouldn't have a string that contains a NUL character.此外,您不应该有一个包含 NUL 字符的字符串。 C treats the NUL char as the end of the string so everything that follows the NUL char is basically ignored. C 将 NUL 字符视为字符串的结尾,因此 NUL 字符后面的所有内容基本上都被忽略了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM