1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
|
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/select.h>
const int ReadEnd = 0, WriteEnd = 1;
void die(const char *msg) {
fprintf(stderr,"Grrr:%s:%d:%s\n",strerror(errno),errno,msg);
exit(1);
}
void child() {
char* argv[] = {
(char*)"sqlite3",
(char*)NULL
};
execvp(argv[0],argv);
}
void parent(int readfrom, int writeto) {
char buff[BUFSIZ];
int done = 0;
while ( !done && fgets(buff,BUFSIZ,stdin) ) {
write(writeto,buff,strlen(buff));
fd_set set;
FD_ZERO(&set);
FD_SET(readfrom,&set);
struct timeval tmo = { 1, 0 }; // 1 second
// use select to see if there is any data
while ( select(readfrom+1,&set,NULL,NULL,&tmo) == 1 ) {
ssize_t n = read(readfrom,buff,BUFSIZ);
if ( n > 0 ) {
write(STDOUT_FILENO,buff,n);
} else {
// read error, pipe closed by child exit
done = 1;
break;
}
tmo.tv_sec = 1; // reset timeout
}
}
close(readfrom);
close(writeto);
}
#define CHECK(op,expected,msg) \
if ( op != expected ) die(msg)
int main ()
{
int parent2child[2];
int child2parent[2];
CHECK(pipe(parent2child),0,"pipe1");
CHECK(pipe(child2parent),0,"pipe2");
pid_t p = fork();
if ( p == 0 ) {
CHECK(close(parent2child[WriteEnd]),0,"close1");
CHECK(close(child2parent[ReadEnd]),0,"close2");
CHECK(dup2(parent2child[ReadEnd],STDIN_FILENO),STDIN_FILENO,"dup2a");
CHECK(dup2(child2parent[WriteEnd],STDOUT_FILENO),STDOUT_FILENO,"dup2b");
child();
} else {
CHECK(close(parent2child[ReadEnd]),0,"close3");
CHECK(close(child2parent[WriteEnd]),0,"close4");
parent(child2parent[ReadEnd],parent2child[WriteEnd]);
int status;
CHECK(waitpid(p,&status,0),p,"wait");
printf("Exit status=%d\n",status);
}
return 0;
}
|