LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Question regarding pipes (https://www.linuxquestions.org/questions/programming-9/question-regarding-pipes-313642/)

alltime 04-15-2005 03:39 PM

Question regarding pipes
 
If I initialize a pipe as follows:

int pfd[2];
pipe(pfd);

Does this mean, I have the range of pfd[] from 0 to 2 to do whatever?

What I mean is, can I copy stdin to pfd[0], stdout to pfd[1] and error to pfd[2] in any order I feel? For example stdout to pfd[0], stdin to pfd[2] etc.

alltime 04-15-2005 04:03 PM

Okay, below is some code that I am trying to write:

Code:

#include <linux/limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>

#define DEBUGON                0
#define DEBUGOFF        1

const char my_prompt[] = "(***SHELL***)";

void  parse(char *line, char **argv)
{
        /* While we are not at the end of the line */
        while (*line != '\0') {      /* if not the end of line ....... */
       
                /* If line is space tab or newline */
                while (*line == ' ' || *line == '\t' || *line == '\n')
                                /* Replace with whitespace */
                                *line++ = '\0';
                                *argv++ = line;
                        while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n')
                                line++;
        }
                *argv = '\0';
}

void  execute(char **argv)
{
        pid_t  pid;
        int i, ai;
        int fout;
        int fin;
        char **mycmd;
        int status;
        int fd[2];
       
        strcpy(*mycmd, *argv);
       
        if ((pid = fork()) < 0) {
                /* Execute process */
                printf("errno is %d\n", errno);
                exit(1);
        }
        else if (pid == 0) {
               
                /* Go through the string */
                for(i=0; argv[i] != NULL; i++){
               
/* -----------------------------------------------If we reach > */
                        if(!strcmp(argv[i], ">")){
                               
                                /* Replace > with a 0*/
                                argv[i] = '\0';
                                printf("I found a > \n");
                               
                                /* If the next character is Null */
                                i++;
                                if(argv[i] == NULL){
                                /* Print error for wrong syntax */
                                        printf("ERROR > usage: program > file ");
                                        break;
                                }
                               
                                if ((fout = open(argv[i], O_CREAT | O_WRONLY, 0666)) < 0){
                                        printf("Unable to create target file, check permissions\n");
                                }
                                        /* Make STDOUT the file */
                                        if(dup2(fout, 1) == -1){
                                                printf("ERROR errno is: %d\n", errno);
                                        }
                                               
                        }
/* -----------------------------------------------If we reach < */
                        if(!strcmp(argv[i], "<")){
                       
                                        /* Replace > with a 0*/
                                        argv[i] = '\0';

                                        /* If the next character is Null */
                                        i++;
                                        if(argv[ai] == NULL){
                                       
                                        /* Print error for wrong syntax */
                                                printf("ERROR < usage: program < file ");
                                                break;
                                        }
                                       
                                        /* make file name to outfile */                                       
                                        if ((fin = open(argv[i], O_RDONLY, 0666)) < 0){
                                                printf("Unable to open file for reading, check permissions\n");
                                        }
                                                /* Make STDOUT the file */
                                                if(dup2(fin, 0) == -1){
                                                        printf("ERROR errno is: %d\n", errno);
                                                }
                        }
/* -----------------------------------------------If we reach | */
                        if(!strcmp(argv[i], "|")){
                                argv[i] = '\0';

                                if(-1 == pipe(fd)){
                                        perror("pipe error");
                                        exit(1);
                                }
                               
                                if((pid = fork()) < 0){
                                        perror("fork error");
                                        exit(1);
                                       
                                }else if (pid){
                               
                                        /* Make STDOUT the same as fd[1] */
                                        if (-1 == dup2(fd[1], STDOUT_FILENO)){
                                                perror("dup2 error on first process");
                                                exit(1);
                                        }
                                       
                                        /* Unecessary to have open */
                                        close(fd[0]);
                                       
                                        /* Begin the first process */
                                        if (execvp(*argv, argv)){
                                                perror("execvp failure on first process");
                                                exit(1);
                                        }
                                       
                                }else{
                                        if(-1 == dup2(fd[0], STDOUT_FILENO)){
                                                perror("dup2 error on second process");
                                                exit(1);
                                        }
                                       
                                        /* Unecessary to have open */
                                        close(fd[1]);
                               
                                        /* Begin the second process */
                                        if (execvp(argv[i+1], &argv[i+1])){
                                                perror("execvp failure on second process");
                                                exit(1);
                                        }
                                       
                                    }                   
                        }
                       
                }
/* -----------------------------------------------Now exec */

                        if (execvp(*argv, argv) < 0) {
                               
                                /* Execvp should return value < 0 if command execution fails */
                                printf("%s: %s\n", *argv, "command not found\n");
                                exit(1);
                        }
/*------------------------------------ Wait for processes to finish */
        }
        else {
                /* Parent waiting for program to finish */
                while (wait(&status) != pid);
        }
}

int main(int argc, char* argv[])
{
        char line[256];
        char linecopied[256];
        char linecopied2[256];
        char cmd[sizeof(line)], *args;
        int i;
        int linelen;
       
        system("clear");
       
        while (1)
        {
                /* Prints out my prompts */
                printf(my_prompt);
               
                /* Get the users line STDIN */
                if(fgets(line, sizeof(line), stdin) == NULL) continue;
                printf("lines is %s\n", line);
               
                /* Copy the line to linecopied */
                strcpy(linecopied, line);
                strcpy(linecopied2, line);
                printf("linecopied is %s\n", linecopied);
               
                /* Return the lenght of the line */
                linelen = strlen(line);
               
                /* Remove end of line character from string */
                if(line[linelen-1]=='\n') line[linelen-1]='\0';
               
                cmd[0] = '\0';
               
                args = line + strlen(line);
               
                /* Scan users input */
                sscanf(line, "%s ", cmd);
               
                for(i=strlen(cmd); i<linelen; i++){
                        args = line+i;
                        /* If does not return */
                        if(!isspace(args[0]))break;
                }
               
                /* Print the command */
                printf("cmd = \"%s\"; args = \"%s\"\n", cmd, args);
               
                /* If the command is change directories */       
                if(strcmp(cmd, "cd") == 0){
                       
                        /* If we cannot change directories return error changing */
                        if(chdir(args)<0)
                                perror("Error changing directory");
                        continue;
                }
               
                /* If the command is pwd */       
                if(strcmp(cmd, "pwd")==0){
                        char curdir[PATH_MAX];
                       
                        /* Use getcwd to print the current directories */
                        if(getcwd(curdir, sizeof(curdir))!=NULL)
                        {
                                printf("%s\n", curdir);
                        }
                        /* If pwd fails, print error */
                        else
                                perror("Error calling getcwd");
                        continue;
                }
               
                /* If the command is umask */
                if(strcmp(cmd, "umask")==0){
                       
                        mode_t mode;
                        int r;
                        if((r=sscanf(args, "%o", &mode) == 1))
                        {
                                umask(mode);
                        }
                        else
                        {
                                fprintf(stderr, "umask: argument missing!\n");
                        }
                        continue;
                }
               
                /* If the command is exit */
                if(strcmp(cmd, "exit") == 0){
                        /* Break */
                        exit(1);
                }
                /* If the command is clear */
                if(strcmp(cmd, "clear")==0){
                        system("clear");
                        continue;
                       
                }
                printf("command cmd:%s\n", cmd);
                /* Parse the copied users input */
                parse(linecopied, argv);
               
                /* Execute the users command */
                execute(argv);
        }
        printf("Exited normally\n");
        return 0;
}

In case anyone asks, the reason why I replaced | \0 at argv[i] = '\0'; is because execvp reads until null and executes everything untill null.

The problem is that I need to get everything on the other side of the | (now NULL) so that it can be executed in the area under the comments saying "second process".

The program will eventually be run like this (example): gcc myfile.c | uname

zer0python 04-15-2005 06:59 PM

According to `man 2 pipe`

Quote:


pipe creates a pair of file descriptors, pointing to a pipe inode, and places them in the array pointed to by filedes. filedes[0] is for reading, filedes[1] is for writing.

so, there you have it..

also perhaps something like:

Code:


/* ... */

char *secapp = strchr(argv[i], '|');
if(!secapp) {
  fprintf(stderr, "invalid use of pipe.\n");
  exit(i);
}

*secapp++ = 0;

/* ... */

Hope this helps .. good luck! :-)

aluser 04-15-2005 07:54 PM

Code:

int foo[2];
creates a 2 element array. The only valid indices are therefore 0 and 1.

If you want the stdout of the first process to feed the stdin of the second process, the first process will dup2(foo[1], fileno(stdout)) and close foo[0], and the second will dup2(foo[0], fileno(stdin)) and close foo[1].

I use the fileno() function to avoid having too many "magic numbers", but I don't think there are any platforms where the number's aren't 0 and 1, so it doesn't really matter.

If you need to get stderr as well, you'll need another pipe() and dup2() call. (And you'll have to decide what to do with it -- | as implemented by the shell does nothing special with stderr streams.)


All times are GMT -5. The time now is 09:47 PM.