views:

114

answers:

2

I 'm writing a little program that implements pipes like they work in the shell. ie:

ls -hal | sort | grep p | wc

it works fine, with the minor issue that on one line, when CMD_NO=n, the comparison i biggerthan CMD_NO does not work, but i!=(CMD_NO-1) does. I'm trying to figure out why in this particular case (the line is ocmmented as TROUBLED LINE in the code) these statements are not equivalent. Many thanks.

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#define READ_END 0
#define WRITE_END 1
#define CMDS_NO 5

int main (int argc, char **argv) 
{
    pid_t pid;
    int new_fds[2];
    int old_fds[2];

    char *array[CMDS_NO];
    char *param[CMDS_NO];

    array[0]="ls";
    array[1]="sort";
    array[2]="grep";
    array[3]="grep";
    array[4]="wc";

    param[0]="-hal";
    param[1]=NULL;
    param[2]="p";
    param[3]="out";
    param[4]=NULL;


    for (int i=0; i<CMDS_NO; i++) {

        if (i<CMDS_NO) //if there is a next command 
           pipe(new_fds);

        pid=fork();

        if (pid==0) { //if child
            if (i!=0) { //if there is ap revoius commmand
                dup2(old_fds[0], 0);
                close(old_fds[0]);
                close(old_fds[1]);
            }

            if (i!=(CMDS_NO-1)) { //TROUBLED LINE i<CMDS_NO does not work,  
                                  //if there is a next command
                close(new_fds[0]);
                dup2(new_fds[1],1);
                close(new_fds[1]);
            }
            execlp(array[i], array[i], param[i], NULL);

            } else {
                if (i!=0) { //if there is a previous command
                    close(old_fds[0]);
                    close(old_fds[1]);
                }

                if (i<CMDS_NO) { //if there is a next command
                    old_fds[0] = new_fds[0];
                    old_fds[1] = new_fds[1];
                }
            }
     }
     if (CMDS_NO>1) {
        close(old_fds[0]);
        close(old_fds[1]);
     }     

     while (1) { //wait for child processes to end
         wait(NULL);
         if(errno== ECHILD) {
             printf("all children ended\n"); 
             break;
         }
     }

return 0;
}
+1  A: 

The condition i<CMDS_NO will always be true because i runs from 0 to CMDS_NO-1. I think you meant to write your condition as i<CMDS_NO-1. Of course, i!=CMDS_NO-1 is equally valid.

Note that this affects several other places where you have if (i<CMDS_NO); these should also read if (i<CMDS_NO-1).

Martin B
A: 

That's normal.

for (int i=0; i<CMDS_NO; i++) {

This means "loop as long as i is less than CMDS_NO". As soon as i == CMDS_NO the loop will stop; so, inside the loop, the highest i will ever reach is CMDS_NO - 1.

PS: CMDS_NO is a really poor variable name, call it MAX_COMMANDS for example

Andreas Bonini