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