Search code examples
clinuxprocesspipefork

Using pipes on Linux to get the process of a user


Im trying to make a code that pass the argument 1 as the name of the user whose process used you want to see, Im using pipes to get the users with getent, then I pass the result to greep argv[1] to search in that result for the user of the parameter and then pass it to ps -fu to get the process of that user but Im only getting the process of the user1 (main user) and I don't know why, thank you.

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define error(a) {perror(a); exit(1);};

int main(int argc, char *argv[])
{
    if(argc != 2)
    {
       error("Incorrect number of arguments");
    }

    int pfd1[2], pfd2[2], pid;

    if(pipe(pfd1) != 0){error("First pipe");}

    switch(pid = fork())
    {
        case -1: error("fork");
        case 0:
        if(close(1)==-1){error ("close");}
        if(dup(pfd1[1]) != 1){error("dup");}
        close(pfd1[0]); close(pfd1[1]);
        execlp("getent", "getent", "passwd",NULL);
        error("getent");
    }

    close(pfd1[1]);

    if(pipe(pfd2) != 0){error("Second pipe");}

    switch(pid = fork())
    {
        case -1: error("fork");
        case 0:
        close(pfd2[0]);
        if(close(0)==-1){error("close");}
        if(dup(pfd1[0]) != 0){error("dup");}
        close(pfd1[0]);
        if(close(1)==-1){error("close");}
        if(dup(pfd2[1]) !=1){error("dup");}
        close(pfd2[1]);
        execlp("grep", "grep", argv[1], NULL);
        error("grep");
    }

    printf("Parent: grep(%d) process launched\n", pid);

    close(pfd1[0]);
    close(pfd2[1]);

    switch(pid = fork())
    {
        case -1: error("fork");
        case 0:
        if(close(0)==-1){error("close");}
        if(dup(pfd2[0]) !=0){error("dup")};
        execlp("ps", "ps", "-fu", NULL);
        error("ps");
    }

    close(pfd2[0]);

    while ((pid = wait(NULL)) != -1)
    {
        printf("Parent: %d process finished\n", pid);
    }
    return 0;
}

Solution

  • Enough with two pipes, one for the ps aux and another for the grep user to filter the results

    #include <sys/wait.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define error(a) {perror(a); exit(1);};
    
    int main(int argc, char *argv[])
    {
        if(argc != 2){error("Incorrect number of arguments")};
        int pfd[2], pid;
        char user[100];
        sprintf(user, "%s", argv[1]);
        if (pipe(pfd) == -1) error("pipe");
        printf("parent: pipe created, channels: READ=%d and WRITE=%d\n", pfd[0], pfd[1]);
        switch (pid = fork()) {
            case -1: error("fork");
            case 0: /* 1st child: who */
            printf("1st child process created\n");
            if (close(1) == -1) error("close");
            if (dup(pfd[1]) != 1) error("dup");
            close(pfd[0]); close(pfd[1]);
            execlp("ps", "ps", "aux", NULL);
            error("execlp");
        }
        printf("parent: ps(%d) process launched\n", pid);
        switch (pid = fork())
        {
            case -1: error("fork");
            case 0: /* 2nd child process: wc -l */
            printf("2nd child process created\n");
            if (close(0) == -1) error("close");
            if (dup(pfd[0]) != 0) error("grep");
            close(pfd[0]); close(pfd[1]);
            execlp("grep", "grep", user, NULL);
            error("execlp");
        }
        printf("parent: grep(%d) process launched\n", pid);
        close(pfd[0]); close(pfd[1]);
        while ((pid = wait(NULL)) != -1)
        {
            printf("parent: %d process finished\n", pid);
        }
        return 0;
    }