Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / lib / DtSvc / DtEncap / pipe.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * File:         pipe.c $XConsortium: pipe.c /main/4 1996/04/21 19:10:09 drk $
25  * Language:     C
26  *
27  * (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
28  *
29  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
30  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
31  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
32  * (c) Copyright 1993, 1994 Novell, Inc.                                *
33  */
34
35 #include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
36 #include <errno.h>
37
38 #include <SPC/spcP.h>
39
40 /*----------------------------------------------------------------------+*/
41 void pipe_channel_class_init(object_clasp t)
42 /*----------------------------------------------------------------------+*/
43 {
44   pipe_channel_clasp c = (pipe_channel_clasp) t;
45   
46   c->new_obj    = alloc_channel_object;
47   
48   c->open       = open_pipe_channel_object;
49   c->close      = close_local_channel_object;
50   c->read       = read_pipe_channel_object;
51   c->write      = write_local_channel_object;
52   c->reset      = reset_pipe_channel_object;
53   c->pre_fork   = pre_fork_pipe_channel_object;
54   c->post_fork  = post_fork_pipe_channel_object;
55   c->exec_proc  = exec_proc_local_channel_object;
56   c->signal     = signal_local_channel_object;
57   c->wait_for_termination = local_channel_object_wait_for_termination;
58   c->attach     = attach_pipe_channel_object;
59   c->add_input  = add_input_pipe_channel_object;
60   c->input      = local_channel_object_input_handler;
61   c->remove_logfile = remove_logfile_local_channel_object;
62
63   /* New B.00 methods */
64
65   c->send_eof = local_channel_object_send_eof;
66   c->set_termio = set_termio_noio_channel_object;
67 }
68
69 static struct pipe_channel_class pipe_channel_class_struct = {
70   (channel_clasp) &channel_class, /* base class pointer */
71   "pipe_channel",           /* class name */
72   pipe_channel_class_init,  /* class initialize function */
73   sizeof(SPC_Channel),      /* size */
74   0
75   };
76
77 pipe_channel_clasp pipe_channel_class = &pipe_channel_class_struct;
78
79 /*----------------------------------------------------------------------+*/
80 Wire *getpipe(Wire *prevwire)
81 /*----------------------------------------------------------------------+*/
82 {
83   Wire *wire_ptr=get_new_wire();
84
85   if(!wire_ptr)
86     return(SPC_ERROR);
87
88   wire_ptr->next=prevwire;
89   /* Get file descriptors for pipe */
90   if (pipe(wire_ptr->fd) < OK) {
91     SPC_Error(SPC_No_Pipe);
92     XeFree(wire_ptr);
93     return(SPC_ERROR);
94   }
95   return(wire_ptr);
96 }
97
98 /*
99  ***
100  *** Method definitions for pipe channel objects
101  ***
102 */
103
104 /*
105  * This routine handles initialization for pipe channels
106  */
107
108 /*----------------------------------------------------------------------+*/
109 SPC_Channel_Ptr open_pipe_channel_object(SPC_Channel_Ptr channel,
110                                          int iomode,
111                                          XeString hostname)
112 /*----------------------------------------------------------------------+*/
113 {
114
115   Wire *tmpwire=NULL;
116   SPC_Channel_Ptr result;
117   
118   call_parent_method(channel, open, (channel, iomode, hostname), result);
119
120   if(result==SPC_ERROR)
121     return(SPC_ERROR);
122
123   if (IS_SPCIO_STDIN(iomode)) {
124     tmpwire=channel->wires[STDIN]=getpipe(NULL);
125     if(!tmpwire)
126       return(SPC_ERROR);
127   }
128   
129   if (IS_SPCIO_STDOUT(iomode)) {
130     tmpwire=channel->wires[STDOUT]=getpipe(tmpwire);
131     if(!tmpwire)
132       return(SPC_ERROR);
133   }
134
135   if(IS_SPCIO_STDERR(iomode)) {
136     if (!tmpwire ||
137         IS_SPCIO_SEPARATE(iomode)) {
138       tmpwire=channel->wires[STDERR]=getpipe(tmpwire);
139       if(!tmpwire)
140         return(SPC_ERROR);
141     } else {
142       channel->wires[STDERR]=channel->wires[STDOUT];
143     }
144   }
145   
146   channel->file_descs[STDIN] =(channel->wires[STDIN]) ->fd[WRITE_SIDE];
147   channel->file_descs[STDOUT]=(channel->wires[STDOUT])->fd[READ_SIDE];
148   channel->file_descs[STDERR]=(channel->wires[STDERR])->fd[READ_SIDE];
149
150   channel->wire_list=tmpwire;
151   
152   return(channel);
153 }
154
155 /*----------------------------------------------------------------------+*/
156 int read_pipe_channel_object(SPC_Channel_Ptr channel,
157                              int connector,           /* STDOUT or STDERR */
158                              XeString buffer,
159                              int nbytes)
160 /*----------------------------------------------------------------------+*/
161 {
162   int result;
163
164   call_parent_method(channel,
165                      read,
166                      (channel, connector, buffer, nbytes),
167                      result);
168
169   if(result==Undefined)
170     return(Undefined);
171
172   do {
173     result = read(channel->file_descs[connector], buffer, nbytes);
174   } while (result<0 && errno == EINTR);
175
176   if(result == 0) {
177
178     SPC_XtRemoveInput(&channel->wires[connector]->read_toolkit_id, SPC_Input);
179     SPC_Change_State(channel, connector, 0, -1);
180
181   }
182
183   return(result);
184 }
185
186 /*----------------------------------------------------------------------+*/
187 int pre_fork_pipe_channel_object(SPC_Channel_Ptr channel)
188 /*----------------------------------------------------------------------+*/
189 {
190
191   int result;
192   
193   call_parent_method(channel, pre_fork, (channel), result);
194   
195   if(result==SPC_ERROR)
196     return(SPC_ERROR);
197
198   return(TRUE);
199 }
200
201 /*----------------------------------------------------------------------+*/
202 int post_fork_pipe_channel_object(SPC_Channel_Ptr channel,
203                                   int parentp)
204 /*----------------------------------------------------------------------+*/
205 {
206   int result;
207   
208   call_parent_method(channel, post_fork, (channel, parentp), result);
209
210   if(result==SPC_ERROR)
211     return(SPC_ERROR);
212
213   
214   if (parentp) {                /* Master process */
215     
216     spc_close(channel->wires[STDIN]->fd[READ_SIDE]);
217     spc_close(channel->wires[STDOUT]->fd[WRITE_SIDE]);
218     spc_close(channel->wires[STDERR]->fd[WRITE_SIDE]);
219
220     channel->wires[STDIN]->fd[READ_SIDE]   = (-1);
221     channel->wires[STDOUT]->fd[WRITE_SIDE] = (-1);
222     channel->wires[STDERR]->fd[WRITE_SIDE] = (-1);
223
224     return(TRUE);
225   }
226   else {                        /* Slave process */
227     
228     /* Close the "other" side of the pipes */
229     
230     spc_close(channel->wires[STDIN]->fd[WRITE_SIDE]);
231     spc_close(channel->wires[STDOUT]->fd[READ_SIDE]);
232     spc_close(channel->wires[STDERR]->fd[READ_SIDE]);
233
234     /* Dup the file descriptors to fd's 3, 4, 5.
235        spc_dup2 is used to make sure these guys are hooked to something
236        (/dev/null if necessary).  We do this step here just in case any
237        of the source file descriptors are 0, 1, or 2. */
238     
239     spc_dup2(channel->wires[STDIN]->fd[READ_SIDE], 3);
240     spc_dup2(channel->wires[STDOUT]->fd[WRITE_SIDE], 4);
241     spc_dup2(channel->wires[STDERR]->fd[WRITE_SIDE], 5);
242
243     /* Go to STDIN, STDOUT, STDERR */
244     
245     spc_dup2(3, STDIN);
246     spc_dup2(4, STDOUT);
247     spc_dup2(5, STDERR);
248     
249     /* Close any other open file descriptors in the child */
250     SPC_Close_Unused();
251
252     return(TRUE);
253   }
254 }
255
256 /*----------------------------------------------------------------------+*/
257 int reset_pipe_channel_object(SPC_Channel_Ptr channel)
258 /*----------------------------------------------------------------------+*/
259 {
260   int result;  
261   int iomode=channel->IOMode;
262   Wire *wirelist;
263   
264   call_parent_method(channel, reset, (channel), result);
265
266   if(result==SPC_ERROR)
267     return(SPC_ERROR);
268
269   /* Close the file descriptors */
270   
271   for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next) {
272     SPC_XtRemoveInput(&wirelist->read_toolkit_id, SPC_Input);
273     close(wirelist->fd[READ_SIDE]);
274     close(wirelist->fd[WRITE_SIDE]);
275     wirelist->flags &= ~SPCIO_DATA;
276   }
277
278   /* Allocate new file descriptors */
279   
280   for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next) {
281     if(pipe(wirelist->fd) < 0) {
282       SPC_Error(SPC_No_Pipe);
283       return(SPC_ERROR);
284     }
285   }
286
287   /* set the file_descs array to the new file descriptors & set up
288      the new read mask */
289   
290   channel->file_descs[STDIN]  = (channel->wires[STDIN])->fd[WRITE_SIDE];
291   channel->file_descs[STDOUT] = (channel->wires[STDOUT])->fd[READ_SIDE];
292   channel->file_descs[STDERR] = (channel->wires[STDERR])->fd[READ_SIDE];
293
294   XeSPCAddInput(channel, NULL, NULL);
295   
296   return(TRUE);
297   
298 }
299
300 /*----------------------------------------------------------------------+*/
301 int attach_pipe_channel_object(SPC_Channel_Ptr UNUSED_PARM(channel), 
302                                int             UNUSED_PARM(foo))
303 /*----------------------------------------------------------------------+*/
304 {
305   /* It is an error to try to attach to a pipe channel... */
306   SPC_Error(SPC_Bad_Operation);
307   return(SPC_ERROR);
308 }
309
310 /*----------------------------------------------------------------------+*/
311 int add_input_pipe_channel_object(SPC_Channel_Ptr channel,
312                                   SbInputHandlerProc handler, 
313                                   void *data)
314 /*----------------------------------------------------------------------+*/
315 {
316   int result, fd;
317   Wire *wirelist, *stdinwire;
318   
319   call_parent_method(channel, add_input, (channel, handler, data), result);
320
321   if(result==SPC_ERROR)
322     return(SPC_ERROR);
323
324   stdinwire=channel->wires[STDIN];
325   
326   for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next) {
327     
328     if(wirelist == stdinwire)
329       continue;
330     
331     if(wirelist->read_toolkit_id != -1)
332       continue;
333     
334     fd=wirelist->fd[READ_SIDE];
335     SPC_XtAddInput(channel,
336                    &wirelist->read_toolkit_id,
337                    fd,
338                    channel->class_ptr->input,
339                    SPC_Input);
340
341   }
342   
343   return(TRUE);
344   
345 }