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);
}
