summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/pipestream.h
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-05-28 23:56:03 +0000
committerKarl Berry <karl@freefriends.org>2009-05-28 23:56:03 +0000
commite767448d0591f5dbb0cd485e4b014becdcbd1ba4 (patch)
tree83bec5bd1ee117130f3e9dcee985dcd42f5145d9 /Build/source/utils/asymptote/pipestream.h
parent20751a51df382b884807d8b9ef1ff7f7cc7739a5 (diff)
asymptote 1.74
git-svn-id: svn://tug.org/texlive/trunk@13514 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/pipestream.h')
-rw-r--r--Build/source/utils/asymptote/pipestream.h100
1 files changed, 60 insertions, 40 deletions
diff --git a/Build/source/utils/asymptote/pipestream.h b/Build/source/utils/asymptote/pipestream.h
index ee8193635c3..191dfcffe85 100644
--- a/Build/source/utils/asymptote/pipestream.h
+++ b/Build/source/utils/asymptote/pipestream.h
@@ -1,5 +1,5 @@
/* Pipestream: A simple C++ interface to UNIX pipes
- Version 0.03
+ Version 0.04
Copyright (C) 2005-2009 John C. Bowman
This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
#include <sstream>
#include <unistd.h>
#include <signal.h>
+#include <fcntl.h>
#include "common.h"
#include "errormsg.h"
@@ -41,7 +42,9 @@ protected:
static const int BUFSIZE=SHRT_MAX;
char buffer[BUFSIZE];
int pid;
+ bool Running;
bool pipeopen;
+ bool pipein;
ostringstream transcript;
public:
@@ -73,44 +76,43 @@ public:
}
cout.flush(); // Flush stdout to avoid duplicate output.
- int wrapperpid;
-
- // Portable way of forking that avoids zombie child processes
- if((wrapperpid=fork()) < 0) {
- cerr << "fork failed: " << command << endl;
- exit(-1);
+ if((pid=fork()) < 0) {
+ ostringstream buf;
+ buf << "fork failed: " << command << endl;
+ camp::reportError(buf);
}
- if(wrapperpid == 0) {
- if((pid=fork()) < 0) {
- ostringstream buf;
- buf << "fork failed: " << command << endl;
- camp::reportError(buf);
- }
-
- if(pid == 0) {
- if(interact::interactive) signal(SIGINT,SIG_IGN);
- close(in[1]);
- close(out[0]);
- close(STDIN_FILENO);
- close(out_fileno);
- dup2(in[0],STDIN_FILENO);
- dup2(out[1],out_fileno);
- close(in[0]);
- close(out[1]);
- char **argv=args(command);
- if(argv) execvp(argv[0],argv);
- execError(command,hint,application);
- kill(0,SIGTERM);
- _exit(-1);
- }
- _exit(0);
- } else {
- close(out[1]);
+ if(pid == 0) {
+ if(interact::interactive) signal(SIGINT,SIG_IGN);
+ close(in[1]);
+ close(out[0]);
+ close(STDIN_FILENO);
+ close(out_fileno);
+ dup2(in[0],STDIN_FILENO);
+ dup2(out[1],out_fileno);
close(in[0]);
- *buffer=0;
- pipeopen=true;
- waitpid(wrapperpid,NULL,0);
+ close(out[1]);
+ char **argv=args(command);
+ if(argv) execvp(argv[0],argv);
+ execError(command,hint,application);
+ kill(0,SIGTERM);
+ _exit(-1);
+ }
+ close(out[1]);
+ close(in[0]);
+ *buffer=0;
+ pipeopen=true;
+ pipein=true;
+ Running=true;
+ }
+
+ void block(bool block=true) {
+ if(pipeopen) {
+ int flags=fcntl(out[0],F_GETFL);
+ if(block)
+ fcntl(out[0],F_SETFL,flags & ~O_NONBLOCK);
+ else
+ fcntl(out[0],F_SETFL,flags | O_NONBLOCK);
}
}
@@ -124,11 +126,21 @@ public:
open(command,hint,application,out_fileno);
}
+ void eof() {
+ if(pipeopen && pipein) {
+ close(in[1]);
+ pipein=false;
+ }
+ }
+
virtual void pipeclose() {
if(pipeopen) {
- close(in[1]);
+ eof();
close(out[0]);
+ Running=false;
pipeopen=false;
+ kill(pid,SIGQUIT);
+ waitpid(pid,NULL,0); // Avoid zombies.
}
}
@@ -141,10 +153,16 @@ public:
char *p=buffer;
ssize_t size=BUFSIZE-1;
for(;;) {
- if((nc=read(out[0],p,size)) < 0)
- camp::reportError("read from pipe failed");
+ if((nc=read(out[0],p,size)) < 0) {
+ if(errno == EAGAIN) {p[0]=0; break;}
+ else camp::reportError("read from pipe failed");
+ }
p[nc]=0;
- if(nc == 0) break;
+ if(nc == 0) {
+ if(waitpid(pid, NULL, WNOHANG) == pid)
+ Running=false;
+ break;
+ }
if(nc > 0) {
if(settings::verbose > 2) cerr << p;
if(strchr(p,'\n')) break;
@@ -155,6 +173,8 @@ public:
return p+nc-buffer;
}
+ bool running() {return Running;}
+
typedef iopipestream& (*imanip)(iopipestream&);
iopipestream& operator << (imanip func) { return (*func)(*this); }