Home > OS >  Sort users' shells
Sort users' shells

Time:02-02

I am trying to this in C - get the users' in /etc/passwd their shells, sort them and then use uniq -c to see how many times a shell is used.

cat /etc/passwd | cut -d ':' -f 7 | sort | uniq -c

The output should be sth like that:

94 /bin/bash

1 /bin/sync

27 /usr/sbin/nologin

What I have done:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>

int main(int argc, char* argv[]){
        int a[2];
        if((pipe(a))==-1){
                printf("error in creating a pipe");
                exit(-1);
        }
        pid_t p = fork();
        if(p==-1){
                printf("error in fork");
                exit(-1);
        }

        if(p==0){
                close(a[0]);
                dup2(a[1], 1);
                execlp("cat", "cat", "/etc/passwd", NULL);
        }

        int b[2];
        if((pipe(b))==-1){
                printf("error in creating the second pipe");
                exit(-1);
        }

        pid_t k=fork();
        if(k==-1){
                printf("error in the 2nd fork");
                exit(-1);
        }

        if(k==0){
                close(b[0]);
                dup2(a[0], 0);
                dup2(b[1], 1);
                execlp("cut", "cut", "-d:", "-f", "7", NULL);
        }

        int c[2];
        if((pipe(c))==-1){
                printf("error in the 3rd pipe");
                exit(-1);
        }

        pid_t l=fork();
        if(l==-1){
                printf("error in 3rd fork");
                exit(-1);
        }

        if(l==0){
                close(c[0]);
                dup2(b[0], 0);
                dup2(c[1], 1);
                execlp("sort", "sort", NULL);
        }

        close(c[1]);
        dup2(c[0], 0);
        execlp("uniq", "uniq", "-c", NULL);

        exit(0);
}

and when I compile it and start it, it looks like it does not terminate, the propt just stays empty and I have to use cntrl c to stop the program.

CodePudding user response:

You have to close all these open pipes.

    if(p==0){
            close(a[0]);
            dup2(a[1], 1);
            execlp("cat", "cat", "/etc/passwd", NULL);
    }
    close(a[1];
   
     ...


    if(k==0){
            close(b[0]);
            dup2(a[0], 0);
            dup2(b[1], 1);
            execlp("cut", "cut", "-d:", "-f", "7", NULL);
    }
    close(a[0]);
    close(b[1]);

     ...

    if(l==0){
            close(c[0]);
            dup2(b[0], 0);
            dup2(c[1], 1);
            execlp("sort", "sort", NULL);
    }
    close(b[0]);
    close(c[1]);

    ...

CodePudding user response:

the problem is that there are a bunch of pipes that aren't properly closed. This is why read() calls block.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>

char buf[1024];

int main(int argc, char* argv[]){
        int a[2];
        if((pipe(a))==-1){
                fprintf(stderr, "error in creating a pipe");
                exit(-1);
        }
        pid_t p = fork();
        if(p==-1){
                fprintf(stderr, "error in fork");
                exit(-1);
        }

        if(p==0){
        fprintf(stderr, "starting cat (%d)\nstdout = a[1], stdin = closed\n", p);
                close(a[0]);
                dup2(a[1], 1);
                execlp("cat", "cat", "/etc/passwd", NULL);
        }
    close(a[1]);    /* the parent process is not going to write to a[1] */

        int b[2];
        if((pipe(b))==-1){
                fprintf(stderr, "error in creating the second pipe");
                exit(-1);
        }

        pid_t k=fork();
        if(k==-1){
                fprintf(stderr, "error in the 2nd fork");
                exit(-1);
        }

        if(k==0){
        fprintf(stderr, "starting cut (%d)\nstdout = b[1], stdin = a[0]\n", k);
                close(b[0]);
                dup2(a[0], 0);
                dup2(b[1], 1);
                execlp("cut", "cut", "-d:", "-f", "7", NULL);
        }
    close(b[1]);

        int c[2];
        if((pipe(c))==-1){
                fprintf(stderr, "error in the 3rd pipe");
                exit(-1);
        }

        pid_t l=fork();
        if(l==-1){
                fprintf(stderr, "error in 3rd fork");
                exit(-1);
        }

        if(l==0){
        fprintf(stderr, "starting sort (%d)\nstdout = c[1], stdin = b[0]\n", l);
                close(c[0]);
                dup2(b[0], 0);
                dup2(c[1], 1);
                execlp("sort", "sort", NULL);
        }

    fprintf(stderr, "Exec uniq\nstdout = stdout, stdin = c[0]\n");
        close(c[1]);
        dup2(c[0], 0);
        execlp("uniq", "uniq", "-c", NULL);

        exit(0);
}
  •  Tags:  
  • Related