Thread: Piping/Redirection/Background processing help needed

  1. #1
    Registered User
    Join Date
    Apr 2009
    Posts
    4

    Piping/Redirection/Background processing help needed

    First off, this a homework assignment so most of the syntax in the code that I'm about to append to this thread is required by my professor. Anywho...I'm having trouble with the piping in my code. Here is what I have:
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <fcntl.h>
    #include <assert.h>
    
    
    int fg_id = 0;
    
    void sigchldHandler(int sig)
    {
    int status = 0;
    int pid = wait(&status);
    
    if (pid == fg_id)
    {
    fg_id = 0;
    }
    }
    
    
    int main()
    {
    char* dosCmd[] = {"exit", "dir", "md", "type", "sort", "del", "copy", ">", ">>", "&"};
    char* unixCmd[] = {"exit", "ls", "mkdir", "cat", "sort", "rm", "cp", ">", ">>", "&"};
    
    signal(SIGCHLD, sigchldHandler);
    
    while (1)
    {
    int args = 0;
    char* argv[10];
    char* delimiter = " \n";
    char command[80] = {0};
    
    int redir = 0;
    int reder = 0;
    bool foreground = true;
    
    printf("terminal@piping> ");
    fgets(command, sizeof(command), stdin);
    
    if (command[0] == '\n') continue;
    
    // gather input tokens
    argv[args++] = strtok(command, delimiter);
    do
    {
    int z = 0;
    for(; (z < 10) && (strcmp(argv[args-1], dosCmd[z]) != 0); ++z);
    
    switch(z)
    {
    case 0: return 0; break;
    
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6: argv[args-1] = unixCmd[z]; break;
    
    case 7: reder = args-1; argv[args-1] = NULL; break;
    case 8: redir = args-1; argv[args-1] = NULL; break;
    case 9: foreground = false; argv[args-1] = NULL; break;
    }
    } while ((argv[args] = strtok(NULL, delimiter)) != NULL && (++args < 10));
    
    if (args > 0)
    {
    int file_des[2];
    int new_cid;
    
    pipe(file_des);
    
    if ((new_cid = fork()) == 0)
    {
    // child process
    usleep(10000); // delay for parent to setup semaphore for foreground processes
    
    close(file_des[1]);
    assert(dup2(file_des[0], 0) != -1);
    
    int file_ptr = 0;
    
    if (reder)
    {
    file_ptr = open(argv[reder+1], O_WRONLY | O_CREAT | O_TRUNC, 0666);
    }
    else if (redir)
    {
    file_ptr = open(argv[redir+1], O_WRONLY | O_APPEND, 0666);
    }
    
    if (file_des[1]) dup2(file_des[1], 1);
    
    execvp(argv[0], argv);
    
    close(file_des[0]);
    
    if (file_ptr) close(file_ptr);
    }
    else if (foreground)
    {
    fg_id = new_cid;
    while(fg_id) usleep(10000); // don't pound the CPU
    }
    }
    }
    
    return 0;
    }
    Everything compiles just fine, but for instance when the shell is running I type in "type hunt program5.c | sort" it is supposed to translate DOS commands into Unix commands(which it does correctly) but when I try to cat(or type is the DOS syntax..etc) my program called hunt and program5.c and then pipe it by sorting the two programs it gives me the following prompt
    Code:
    terminal@piping> type hunt program5.c | sort
    #!/bin/csh
    # Chad Reynolds - CSC 60 - Section 1
    
    set directoryCount = 0
    set fileCount = 0
    
    ### Test to see if no arguments get inputted on the command line
    if($#argv == 0)then
       echo Usage: Missing arguments, please re-execute hunt
    else
       while(1)
          foreach val (`ls`)
             if(-d $val) then
          ### If val is a directory then increment its value to see
          ### the total amount of directories searched
                @ directoryCount = $directoryCount + 1
          ### Push back to the current directory and add to the stack
                pushd $val >> ~/dump
                pushd +1 >> ~/dump
             else if($val =~ $1) then
          ### Echo full path
                @ fileCount = $fileCount + 1
                echo `pwd`/$val
             else if(-e $val) then
          ### Increment file count if val is a file
                @ fileCount = $fileCount + 1
             endif
          ### End for
          end
          ### If directory or word  count is greater than 1,
          ### then pop the directory off the stack
          if(`dirs | wc -w` > 1) then
             popd >> ~/dump
          else
          ### Else, the stack is complete, so output the file count,
          ### directory count, and delete temp file dump
             rm ~/dump
             echo Files Searched: $fileCount
             echo Directories Searched: $directoryCount
          ### Infinite loop, so a break statement is needed
             break
          endif
          ### End while
       end
    
    ### End if($#argv == 0)/Else
    endif
    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
    #include <unistd.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <sys/wait.h>
    #include <sys/file.h>
    #include <fcntl.h>
    #include <assert.h>
    
    
    int fg_id = 0;
    int pid = 0;
    int status = 0;
    int file_ptr = 0;
    int file_des[2];
    
    void sigchldHandler(int sig)
    {
            pid = wait(&status);
            if (pid == fg_id)
            {
              fg_id = 0;
            }
            signal(SIGCHLD, sigchldHandler);
    }
    
    int main()
    {
    char* dosCmd[] = {"exit", "dir", "md", "type", "sort", "del", "copy", ">",
            ">>", "&", "|" };
    char* unixCmd[] = {"exit", "ls", "mkdir", "cat", "sort", "rm", "cp", ">",
            ">>", "&", "|"};
    
    signal(SIGCHLD, sigchldHandler);
    
    while (1)
    {
            int args = 0;
            char* argv[10];
            char* delimiter = " \n";
            char command[80] = {0};
    
            int redir = 0;
            int reder = 0;
            bool foreground = true;
    
            printf("terminal@piping> ");
            fgets(command, sizeof(command), stdin);
    
            if (command[0] == '\n') continue;
    
            // gather input tokens
            argv[args++] = strtok(command, delimiter);
          do
          {
            int z = 0;
            for(; (z < 10) && (strcmp(argv[args-1], dosCmd[z]) != 0); ++z);
    
            switch(z)
            {
               case 0: return 0; break;
               case 1:
               case 2:
               case 3:
               case 4:
               case 5:
               case 6: argv[args-1] = unixCmd[z]; break;
               case 7: reder = args-1; argv[args-1] = NULL; break;
               case 8: redir = args-1; argv[args-1] = NULL; break;
               case 9: foreground = false; argv[args-1] = NULL; break;
            }
          }//end do
          while ((argv[args] = strtok(NULL, delimiter)) != NULL && (++args < 10));
    
            if (args > 0)
            {
                int new_cid;
    
                pipe(file_des);
    
                if ((new_cid = fork()) == 0)
                {
                    // child process
                    usleep(10000); // delay for parent to setup semaphore for foreground processes
                    close(file_des[1]);
                    assert(dup2(file_des[0], 0) != -1);
    
                    if (reder)
                    {
                      file_ptr = open(argv[reder+1], O_WRONLY | O_CREAT | O_TRUNC, 0666);
                    }
                    else if (redir)
                    {
                      file_ptr = open(argv[redir+1], O_WRONLY | O_APPEND, 0666);
                    }
    
                    if (file_des[1])
                    {
                      dup2(file_des[1], 1);
                    }
    
                    execvp(argv[0], argv);
                    close(file_des[0]);
    
                    if (file_ptr)
                    {
                      close(file_ptr);
                    }
               }//end if((new_cid = fork()) == 0)
               else if (foreground)
               {
                 fg_id = new_cid;
                 while(fg_id)
                 usleep(10000); // don't pound the CPU
               }
          }//end if(args > 0)
    }
    return 0;
    }
    cat: |: No such file or directory
    cat: sort: No such file or directory
    terminal@piping>
    When I type "type hunt" it displays my program hunt's source code just fine but once I try to pipe the programs it doesn't do as I expected. Any suggestions? My apologies if I didn't elaborate very well on my struggles.

  2. #2
    30 Helens Agree neandrake's Avatar
    Join Date
    Jan 2002
    Posts
    640
    Looks like you are just executing the first command, passing in all arguments you were passed in. This would effectively pass in "type hunt program5.c | sort" into the type command (which is normal for argument passing). However don't get confused -- the pipe | and sort are being passed in as arguments, which you don't want to do. On typical normal shells, the pipe (or other) is a special character that the input is examined for, so that it can handle it separately, and not as an argument into a command. You need to parse/check for special symbols before executing the commands. Maybe start by adding the pipe to your delimeters, perhaps.
    Environment: OS X, GCC / G++
    Codes: Java, C#, C/C++
    AOL IM: neandrake, Email: neandrake (at) gmail (dot) com

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help needed on parallel processing using fork() in C
    By smithu.simi in forum C Programming
    Replies: 7
    Last Post: 03-27-2009, 07:15 AM
  2. Sub Array Processing
    By GCNDoug in forum C++ Programming
    Replies: 8
    Last Post: 11-28-2007, 04:41 PM
  3. Using a lot of processing time!
    By nickname_changed in forum C++ Programming
    Replies: 0
    Last Post: 09-25-2003, 03:44 AM
  4. file writing crashes
    By test in forum C Programming
    Replies: 25
    Last Post: 08-13-2002, 08:44 AM