1 /*
2  *  CmdPipe.cpp
3  *
4  *  Frodo (C) 1994-1997,2002 Christian Bauer
5  *  Tcl/Tk stuff by Lutz Vieweg
6  */
7 
8 #include "CmdPipe.h"
9 
10 
11 extern "C" {
12 	#include <string.h>
13 	#include <unistd.h>
14 	#include <stdlib.h>
15 	#include <sys/wait.h>
16 	#include <sys/types.h>
17 	#include <string.h>
18 	#include <signal.h>
19 
20 #if !defined(__FreeBSD__)
21 #if defined(__alpha__)
22 	#include <cma.h>
23 #endif
24 #endif
25 
26 #if defined(AIX)
27 	#include <sys/select.h>
28 #else
29 	#include <unistd.h>
30 #endif
31 
32 #if defined(__linux__)
33 	#include <sys/time.h>
34 #endif
35 #if defined(__FreeBSD__)
36 	#include <sys/time.h>
37 #endif
38 
39 	#include <time.h>
40 	#include <errno.h>
41 }
42 
kaputt(const char * c1,const char * c2)43 static void kaputt(const char * c1, const char * c2) {
44 	fprintf(stderr,"error: %s%s\n",c1,c2);
45 	exit(20);
46 }
47 
Pipe(void)48 Pipe::Pipe(void) : fail(true) {
49 
50 	fds[0] = 0;
51 	fds[1] = 1;
52 
53 	if (-1 == pipe(fds)) {
54 		kaputt("Pipe: ","unable to create pipe");
55 		return;
56 	}
57 
58 	fail = false;
59 	return;
60 }
61 
~Pipe(void)62 Pipe::~Pipe(void) {
63 
64 	if (! fail) {
65 		close(fds[0]);
66 		 close(fds[1]);
67 	}
68 	return;
69 }
70 
ewrite(const void * buf,unsigned long len)71 unsigned long Pipe::ewrite(const void * buf, unsigned long len) {
72 
73 	unsigned long wsum = 0;
74 	while (len) {
75 		long wlen;
76 
77 		wlen = ::write(fds[1], buf, (long) len);
78 		if (wlen <= 0) {
79 			kaputt("Pipe::ewrite ","write-error");
80 		}
81 
82 		len -= wlen;
83 		buf = (void*) ((char*) buf + wlen);
84 		wsum += wlen;
85 	}
86 	return wsum;
87 }
88 
eread(void * buf,unsigned long len)89 unsigned long Pipe::eread(void * buf, unsigned long len) {
90 
91 	unsigned long rsum = 0;
92 	while (len) {
93 		long rlen;
94 
95 		rlen = ::read(fds[0], buf, (long) len);
96 
97 		if (rlen <= 0) {
98 			kaputt("Pipe::eread ","read-error");
99 		}
100 
101 		len -= rlen;
102 		buf = (void*) ((char*) buf + rlen);
103 		rsum += rlen;
104 	}
105 	return rsum;
106 }
107 
probe(void) const108 int Pipe::probe(void) const {
109 
110 	fd_set set;
111 	FD_ZERO(&set);
112 	FD_SET(fds[0], &set);
113 
114 	struct timeval tv;
115 	tv.tv_sec = 0;
116 	tv.tv_usec = 0;
117 
118 	int res;
119 // Use the following commented line for HP-UX < 10.20
120 //	res = select(FD_SETSIZE, (int *)&set, (int *)0, (int *)0, &tv);
121 	res = select(FD_SETSIZE, &set, (fd_set *)0, (fd_set *)0, &tv);
122 
123 	if (res > 0) return -1;
124 	return 0;
125 
126 }
127 
CmdPipe(const char * command,const char * arg,int nicediff)128 CmdPipe::CmdPipe(const char * command, const char * arg, int nicediff) : childpid(0), fail(true) {
129 
130 	if (tocmd.fail || fromcmd.fail) {
131 		kaputt("CmdPipe: ","unable to initialize pipes");
132 		return;
133 	}
134 
135 	childpid = fork();
136 
137 	if (childpid == -1) {
138 		childpid = 0;
139 		kaputt("CmdPipe: ","unable to fork process");
140 		return;
141 	}
142 
143 	if (childpid == 0) {
144 
145 		if (nicediff) {
146 			if (-1 == nice(nicediff)) {
147 				fprintf(stderr,"CmdPipe: unable to change nice-level (non-fatal)");
148 			}
149 		}
150 
151 		dup2(tocmd.get_read_fd(), STDIN_FILENO);
152 
153 		dup2(fromcmd.get_write_fd(), STDOUT_FILENO);
154 		execlp(command, "Frodo_GUI", arg, (char *)0);
155 		kaputt("CmdPipe: unable to execute child process ",command);
156 		_exit(0); // exit (and do NOT call destructors etc..)
157 	}
158 
159 	fail = false;
160 	return;
161 }
162 
~CmdPipe(void)163 CmdPipe::~CmdPipe(void) {
164 
165 	if (childpid) {
166 		int status;
167 		waitpid(childpid, &status, 0);
168 
169 		if (status != 0) {
170 			fprintf(stderr,"~CmdPipe child process returned error\n");
171 		}
172 	}
173 }
174