Build with debug symbols enabled.
[oweals/cde.git] / cde / lib / DtSvc / DtEncap / local.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 librararies 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:         local.c $TOG: local.c /main/5 1999/10/14 15:05:57 mgreess $
25  * Language:     C
26  *
27  * (c) Copyright 1989, 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 #define __need_timeval   /* Needed for "struct timeval" from <time.h>. */
36 #define __need_fd_set
37
38 #include <bms/sbport.h> 
39 #ifdef __osf__
40 #include <sys/time.h>     /* For declaration of select(). */
41 #else
42 #include <time.h>
43 #endif
44 #include <errno.h>
45 #include <signal.h>
46
47 #include <SPC/spcP.h>
48 #include <SPC/spc-proto.h>
49
50 /*
51  **
52  ** Note that the close routines call the parent method AFTER the
53  ** work done for the child method.  This is because the parent method
54  ** will do all the deallocation.
55  **
56 */
57
58 /*----------------------------------------------------------------------+*/
59 int close_local_channel_object(SPC_Channel_Ptr channel)
60 /*----------------------------------------------------------------------+*/
61 {
62   Wire *wirelist;
63   int result;
64   
65   for(wirelist=channel->wire_list; wirelist; wirelist=wirelist->next){
66     spc_close(wirelist->fd[READ_SIDE]);
67     spc_close(wirelist->fd[WRITE_SIDE]);
68     SPC_XtRemoveInput(&wirelist->read_toolkit_id, SPC_Input);
69     SPC_XtRemoveInput(&wirelist->except_toolkit_id, SPC_Exception);
70   }
71
72   call_parent_method(channel, close, (channel), result);
73
74   if(result==SPC_ERROR)
75     return(SPC_ERROR);
76
77   return(TRUE);
78 }
79
80 /*----------------------------------------------------------------------+*/
81 int write_local_channel_object(SPC_Channel_Ptr channel,
82                                XeString buffer,
83                                int nbytes)
84 /*----------------------------------------------------------------------+*/
85   
86 {
87   int result;
88   
89   call_parent_method(channel,
90                      write,
91                      (channel, buffer, nbytes),
92                      result);
93
94   if(result==SPC_ERROR)
95     return(SPC_ERROR);
96   result = SPC_Write_Chars(channel->file_descs[STDIN], buffer, nbytes);
97   if(result==ERROR) {
98     SPC_Error(SPC_Writing);
99     return(SPC_ERROR);
100   }
101   
102   return(result);
103 }
104
105 /* the function exec_proc_local_channel_object is defined in spc-exec.c */
106
107 /*----------------------------------------------------------------------+*/
108 int signal_local_channel_object (SPC_Channel_Ptr channel,
109                                  int sig)
110 /*----------------------------------------------------------------------+*/
111
112 {
113   int result;
114   
115   call_parent_method(channel, signal, (channel, sig), result);
116
117   if(result==SPC_ERROR)
118     return(SPC_ERROR);
119
120   if(sig == SIGKILL || IS_SPCIO_SIGNAL_PGRP(channel->IOMode))
121     result=kill(-(channel->pid), sig);
122   else
123     result=kill(channel->pid, sig);
124
125   if(result==ERROR)
126     return(errno!=ESRCH);
127
128   return(TRUE);
129 }
130
131 /*----------------------------------------------------------------------+*/
132 int local_channel_object_wait_for_termination(SPC_Channel_Ptr channel)
133 /*----------------------------------------------------------------------+*/
134 {
135
136   int result;
137   
138   call_parent_method(channel, wait_for_termination, (channel), result);
139   
140   if(result==SPC_ERROR)
141     return(SPC_ERROR);
142   
143   /* Do we need to check for remote channel input here? */
144   
145   while(IS_ACTIVE(channel)) {
146     sigset_t mask;
147     sigemptyset(&mask);
148     /* the SIGCLD signal handler will take care of us here */
149     sigsuspend(&mask);
150   }
151
152   return(TRUE);
153   
154 }
155
156 /*----------------------------------------------------------------------+*/
157 remove_logfile_local_channel_object(SPC_Channel_Ptr channel)
158 /*----------------------------------------------------------------------+*/
159 {
160   int result;
161
162   call_parent_method(channel, remove_logfile, (channel), result);
163   
164   if(unlink(channel->logfile)==ERROR) {
165     SPC_Error(SPC_Unlink_Logfile);
166     return(SPC_ERROR);
167   }
168
169   /* This is malloc'ed memory from open_noio_channel_object() and tempnam() */
170   XeFree(channel->logfile);
171   
172   return(TRUE);
173 }
174
175 extern SPC_Channel_Ptr spc_activation_list;
176
177 /* All this routine does is to look up the channel, and
178    call the generic input handler routine */
179
180 /*----------------------------------------------------------------------+*/
181 void local_channel_object_input_handler(void * client_data,
182                                    int *source,
183                                    SPCInputId * UNUSED_PARM(id))
184 /*----------------------------------------------------------------------+*/
185 {
186
187 /* WARNING!!! This routine is NOT XPG3 compliant.  The timeval struct */
188 /*            is the problem here.                                    */
189
190   SPC_Channel_Ptr channel=(SPC_Channel_Ptr) client_data;
191   int fd=(*source);
192   int connector;
193   int len;
194   fd_set read_fd_vect, except_fd_vect;
195   SPC_Channel_Ptr tmp, this_ptr;
196   struct timeval timeout;                 /* Not part of XPG3 !!! */
197
198   /* This ^&@$#% select is here to get around an X toolkit bug */
199
200   FD_ZERO(&read_fd_vect);
201   FD_ZERO(&except_fd_vect);
202
203   FD_SET(fd, &read_fd_vect);
204   FD_SET(fd, &except_fd_vect);
205
206   timeout.tv_sec = 0;
207   timeout.tv_usec = 0;
208   
209 #if defined(SVR4) || defined(__osf__) || defined(__hpux)
210   select(max_fds, (fd_set*)&read_fd_vect, NULL, (fd_set*)&except_fd_vect, &timeout);
211 #else
212   /* UX has select defined with int*, not fd_set* parms */
213   select(max_fds, (int*)&read_fd_vect, NULL, (int*)&except_fd_vect, &timeout);
214 #endif
215   if(! (FD_ISSET(fd, &read_fd_vect) || FD_ISSET(fd, &except_fd_vect))) {
216     return /* (FALSE) */;
217   }
218
219   /* The following is to get around an apparent Xt bug where sometimes
220      the client data pointer passed to me is not the one I was expecting.
221      */
222   
223   tmp = spc_activation_list;
224   this_ptr = NULL;
225   while(tmp) {
226     if((fd == Stdin(tmp)) || (fd == Stderr(tmp)))
227       this_ptr = tmp;
228     tmp = tmp->next;
229   }
230   
231   if(this_ptr == NULL)
232     this_ptr = channel;
233   if(this_ptr != channel)
234     channel = this_ptr;
235   
236   if((connector=SPC_fd_to_connector(channel, fd)) == ERROR) {
237     SPC_Error(SPC_Bad_Fd);
238     return /* (SPC_ERROR) */;
239   }
240   len = SPC_Input_Handler(channel, connector);
241   return /* (len) */;
242 }
243
244 int local_channel_object_send_eof(SPC_Channel_Ptr channel)
245 {
246   Wire *wire = channel->wires[STDIN];
247
248   spc_close(wire->fd[READ_SIDE]);
249   spc_close(wire->fd[WRITE_SIDE]);
250   SPC_XtRemoveInput(&wire->read_toolkit_id, SPC_Input);
251   SPC_XtRemoveInput(&wire->except_toolkit_id, SPC_Exception);
252
253   return(TRUE);
254 }