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.
>Solution :
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]);
...