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