version 1.4.31b
[polyglot.git] / pipex_posix.c
1 #ifndef _WIN32
2
3 // includes
4
5 #include <string.h>
6 #include <errno.h>
7 #include "pipex.h"
8
9 // constants
10
11 static const unsigned int StringSize = 4096;
12
13 // prototypes
14
15 static void my_close(int fd);
16 static void my_dup2(int old_fd, int new_fd) ;
17
18 // functions
19
20 // pipex_open()
21
22 void pipex_open(pipex_t *pipex, const char *name, const char *command){
23     char string[StringSize];
24     int argc;
25     char * ptr;
26     char * argv[256];
27     int from_child[2], to_child[2];
28
29     pipex->pid=-1;
30     pipex->io->name=name;
31     
32     if(command==NULL){
33         pipex->io->in_fd = STDIN_FILENO;
34         pipex->io->out_fd = STDOUT_FILENO;
35
36             // attach standard error to standard output
37         
38         my_dup2(STDOUT_FILENO,STDERR_FILENO);
39         io_init(pipex->io);
40     }else{
41     
42         // parse the command line and create the argument list
43     
44         if (strlen(command) >= StringSize) my_fatal("pipex_open(): buffer overflow\n");
45         strcpy(string,command);
46         argc = 0;
47         
48         for (ptr = strtok(string," "); ptr != NULL; ptr = strtok(NULL," ")) {
49             argv[argc++] = ptr;
50         }
51
52         argv[argc] = NULL;
53         
54       // create the pipes
55         
56         if (pipe(from_child) == -1) {
57             my_fatal("pipex_open(): pipe(): %s\n",strerror(errno));
58         }
59         
60         if (pipe(to_child) == -1) {
61             my_fatal("pipex_open(): pipe(): %s\n",strerror(errno));
62         }
63         
64             // create the child process
65         
66         pipex->pid = fork();
67         
68         if (pipex->pid == -1) {
69             
70             my_fatal("pipex_open(): fork(): %s\n",strerror(errno));
71             
72         } else if (pipex->pid == 0) {
73             
74                 // child 
75             
76                 // close unused pipe descriptors to avoid deadlocks
77             
78             my_close(from_child[0]);
79             my_close(to_child[1]);
80             
81                 // attach the pipe to standard input
82             
83             my_dup2(to_child[0],STDIN_FILENO);
84             my_close(to_child[0]);
85             
86                 // attach the pipe to standard output
87             
88             my_dup2(from_child[1],STDOUT_FILENO);
89             my_close(from_child[1]);
90             
91                 // attach standard error to standard output
92                 // commenting this out gives error messages on the console
93             
94            /* my_dup2(STDOUT_FILENO,STDERR_FILENO); */
95             
96                 // launch the new executable file
97             
98             execvp(argv[0],&argv[0]);
99             
100                 // execvp() only returns when an error has occured
101             
102             my_fatal("engine_open(): execvp(): %s\n",strerror(errno));
103             
104         } else { // pid > 0
105             
106             ASSERT(pipex->pid>0);
107             
108                 // parent 
109             
110                 // close unused pipe descriptors to avoid deadlocks
111             
112             my_close(from_child[1]);
113             my_close(to_child[0]);
114             
115                 // fill in the pipex struct
116             
117             pipex->io->in_fd = from_child[0];
118             pipex->io->out_fd = to_child[1];
119             pipex->state|=PIPEX_ACTIVE; // can we test if this really TRUE?
120             
121             io_init(pipex->io);
122         } 
123     }
124 }
125
126 void pipex_wait_event(pipex_t *pipex[]){
127
128     fd_set set[1];
129     pipex_t *p;
130     int fd_max;
131     int val;
132     pipex_t **q;
133
134     q=pipex;
135
136         // init
137
138    FD_ZERO(set);
139    fd_max = -1; // HACK
140    while((p=*(q++))!=NULL){
141        ASSERT(p->io->in_fd>=0);
142        FD_SET(p->io->in_fd,set);
143        if (p->io->in_fd > fd_max){
144            fd_max = p->io->in_fd;
145        }
146    }
147    
148    // wait for something to read (no timeout)
149
150    ASSERT(fd_max>=0);
151    val = select(fd_max+1,set,NULL,NULL,NULL);
152    if (val == -1 && errno != EINTR) my_fatal("pipex_wait_event(): select(): %s\n",strerror(errno));
153
154    q=pipex;
155    if (val > 0) {
156        while((p=*(q++))!=NULL){
157            if (FD_ISSET(p->io->in_fd,set)) io_get_update(p->io); 
158        }
159    }    
160 }
161
162 // pipex_active()
163
164 bool pipex_active(pipex_t *pipex){
165     return (pipex->state&PIPEX_ACTIVE)!=0;
166 }
167
168 // pipex_eof()
169
170 bool pipex_eof(pipex_t *pipex){
171     return (pipex->state&PIPEX_EOF)!=0;
172 }
173
174
175 // pipex_set_priority()
176
177 void pipex_set_priority(pipex_t *pipex, int value){
178     if(pipex->pid!=-1){
179         setpriority(PRIO_PROCESS,pipex->pid,value);
180     }
181 }
182
183 // pipex_set_affinity()
184
185 void pipex_set_affinity(pipex_t *pipex, int value){
186     my_log("POLYGLOT Setting affinity is not yet implemented on posix\n");
187 }
188
189 // pipex_send_eof()
190
191 void pipex_send_eof(pipex_t *pipex){
192     io_close(pipex->io);
193 }
194
195 // pipex_exit()
196
197 void pipex_exit(pipex_t *pipex){
198         // NOOP for now
199     return;
200 }
201
202 // pipex_readln()
203
204 bool pipex_readln(pipex_t *pipex, char *string){
205     while (!io_line_ready(pipex->io)) {
206       io_get_update(pipex->io);
207    }
208    if (!io_get_line(pipex->io,string,StringSize)) { // EOF
209        string[0]='\0';
210        pipex->state|=PIPEX_EOF;
211        return FALSE;
212    }
213    
214
215    return TRUE;
216 }
217
218 // pipex_readln_nb()
219
220 bool pipex_readln_nb(pipex_t *pipex, char *string){
221     if(io_line_ready(pipex->io)){
222         return pipex_readln(pipex,string);
223     }else{  
224         string[0]='\0';
225         return FALSE;
226     }
227 }
228
229 // pipex_writeln()
230
231 void pipex_writeln(pipex_t *pipex, const char *string){
232        io_send(pipex->io,"%s",string);
233 }
234
235 // my_close()
236
237 static void my_close(int fd) {
238
239    ASSERT(fd>=0);
240
241    if (close(fd) == -1) my_fatal("my_close(): close(): %s\n",strerror(errno));
242 }
243
244 // my_dup2()
245
246 static void my_dup2(int old_fd, int new_fd) {
247
248    ASSERT(old_fd>=0);
249    ASSERT(new_fd>=0);
250
251    if (dup2(old_fd,new_fd) == -1) my_fatal("my_dup2(): dup2(): %s\n",strerror(errno));
252 }
253
254
255 #endif