Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / DtSvc / DtEncap / remote.c
1 /*
2  * File:         remote.c $XConsortium: remote.c /main/5 1996/06/21 17:34:53 ageorge $
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 #include <bms/sbport.h>
14 #include <bms/usersig.h>
15
16 #include <SPC/spcP.h>
17 #include <SPC/spc-proto.h>
18 #include "DtSvcLock.h"
19
20 /*----------------------------------------------------------------------+*/
21 void remote_channel_class_init(object_clasp t)
22 /*----------------------------------------------------------------------+*/
23 {
24   channel_clasp c=(channel_clasp) t;
25   
26   c->new_obj   = alloc_channel_object;
27   
28   c->open      = open_remote_channel_object;
29   c->close     = close_remote_channel_object;
30   c->read      = read_remote_channel_object;
31   c->write     = write_remote_channel_object;
32   c->reset     = reset_remote_channel_object;
33   /* pre_fork & post_fork have no method */
34   c->exec_proc = exec_proc_remote_channel_object;
35   c->signal    = signal_remote_channel_object;
36   /* wait_for_termination has no method */
37   c->attach    = attach_remote_channel_object;
38   c->add_input = add_input_remote_channel_object;
39   c->input     = SPC_Conditional_Packet_Handler;
40   c->remove_logfile = remove_logfile_remote_channel_object;
41
42   /* New B.00 methods */
43
44   c->send_eof = send_eof_remote_channel_object;
45   c->set_termio = set_termio_remote_channel_object;
46   
47 }
48
49 static struct remote_channel_class remote_channel_class_struct = {
50   (channel_clasp) &channel_class, /* base class pointer */
51   "remote_channel",         /* class name */
52   remote_channel_class_init,/* class initialize function */
53   sizeof(SPC_Channel),      /* size */
54   0
55   };
56
57 remote_channel_clasp remote_channel_class = &remote_channel_class_struct;
58
59 /*----------------------------------------------------------------------+*/
60 Wire *get_new_remote_wire(Wire *prevwire)
61 /*----------------------------------------------------------------------+*/
62 {
63   Wire *mywire=get_new_wire();
64
65   if(mywire==SPC_ERROR)
66     return(SPC_ERROR);
67   mywire->next=prevwire;
68   return(mywire);
69 }
70   
71 /*
72  ***
73  *** Method definitions for remote channel objects
74  ***
75 */
76
77 /*----------------------------------------------------------------------+*/
78 SPC_Channel_Ptr open_remote_channel_object(SPC_Channel_Ptr channel,
79                                            int iomode,
80                                            XeString hostname)
81 /*----------------------------------------------------------------------+*/
82 {
83
84   SPC_Channel_Ptr result;
85   int seqno, retval;
86   Wire *tmpwire=NULL;
87   int sid;
88   
89   call_parent_method(channel, open, (channel, iomode, hostname), result);
90
91   if(result==SPC_ERROR)
92     return(SPC_ERROR);
93   
94   channel->cid=0;
95   channel->queued_remote_data=Xe_make_queue(NULL);
96   iomode=channel->IOMode;
97
98   if(IS_SPCIO_STDIN(iomode)) {
99     tmpwire=get_new_remote_wire(tmpwire);
100     channel->wires[STDIN]=tmpwire;
101   }
102   if(IS_SPCIO_STDOUT(iomode)) {
103     tmpwire=get_new_remote_wire(tmpwire);
104     channel->wires[STDOUT]=tmpwire;
105   }
106   if(IS_SPCIO_STDERR(iomode)) {
107     if(!tmpwire ||                      /* ERRORONLY */
108        IS_SPCIO_SEPARATE(iomode))
109       tmpwire=get_new_remote_wire(tmpwire);
110     channel->wires[STDERR]=tmpwire;
111   }
112
113   channel->wire_list=tmpwire;
114   
115   if(!(channel->connection=SPC_Open_Connection(hostname)))
116     return(SPC_ERROR);
117
118   seqno=SPC_Write_Protocol_Request(channel->connection, channel,
119                                    CHANNEL_OPEN, iomode);
120   retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
121   if(retval==SPC_ERROR)
122     return(SPC_ERROR);
123   channel->cid=retval;
124   sid=channel->connection->sid;
125   channel->file_descs[STDIN]=sid;
126   channel->file_descs[STDOUT]=sid;
127   channel->file_descs[STDERR]=sid;
128
129   if ((SPC_client_version_number >= SPC_PROTOCOL_VERSION_CDE_BASE) &&
130       (SPC_who_am_i == SPC_I_AM_A_CLIENT)) {
131     channel->wires[STDIN]->master_name = NULL;
132     channel->wires[STDIN]->slave_name = NULL;
133     channel->wires[STDOUT]->master_name = NULL;
134     channel->wires[STDOUT]->slave_name = NULL;
135     channel->wires[STDERR]->master_name = NULL;
136     channel->wires[STDERR]->slave_name = NULL;
137   }
138   else
139     SPC_Query_Devices(channel);
140
141   SPC_Query_Logfile(channel);
142   
143   return(channel);
144 }
145
146 /*
147  **
148  ** Note that the close routines call the parent method AFTER the
149  ** work done for the child method.  This is because the parent method
150  ** will do all the deallocation.
151  **
152 */
153
154 /*----------------------------------------------------------------------+*/
155 int close_remote_channel_object(SPC_Channel_Ptr channel)
156 /*----------------------------------------------------------------------+*/
157 {
158
159   int result;
160   int seqno, retval;
161
162   channel->IOMode |= SPCIO_DELAY_CLOSE;
163   
164   seqno=SPC_Write_Protocol_Request(channel->connection, channel,
165                                    CHANNEL_CLOSE);
166   retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
167
168   call_parent_method(channel, close, (channel), result);
169
170   if(result==SPC_ERROR)
171     return(SPC_ERROR);
172
173   return(retval);
174 }
175
176 /*----------------------------------------------------------------------+*/
177 int reset_remote_channel_object(SPC_Channel_Ptr channel)
178 /*----------------------------------------------------------------------+*/
179 {
180
181   int result;
182   int seqno, retval;
183   XeQueue tmpqueue;
184   protocol_request_ptr prot;
185   
186   call_parent_method(channel, reset, (channel), result);
187
188   if(result==SPC_ERROR)
189     return(SPC_ERROR);
190
191   seqno=SPC_Write_Protocol_Request(channel->connection, channel,
192                                    CHANNEL_RESET);
193   retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
194   if(retval==SPC_ERROR)
195     return(SPC_ERROR);
196
197   /* At this point, we know that the remote server has sent us all
198      necessary data (since RESET expects a reply).  So, we are safe to
199      flush any queued data on this channel. */
200
201   {
202     if (tmpqueue=channel->queued_remote_data)
203     {
204       Xe_for_queue(protocol_request_ptr, prot, tmpqueue) {
205         Xe_delete_queue_element(channel->queued_remote_data, prot);
206         SPC_Free_Protocol_Ptr(prot);
207       }
208     }
209   }
210   
211   return(TRUE);
212 }
213
214 /*----------------------------------------------------------------------+*/
215 int exec_proc_remote_channel_object(SPC_Channel_Ptr channel)
216 /*----------------------------------------------------------------------+*/
217 {
218   int result;
219   int retval, seqno;
220   int tmp_errorno;
221   
222   call_parent_method(channel, exec_proc, (channel), result);
223   
224   if(result==SPC_ERROR)
225     return(SPC_ERROR);
226   
227   call_parent_method(channel, pre_fork, (channel), result);
228   
229   if(result==SPC_ERROR)
230     return(SPC_ERROR);
231
232   if((channel->connection->protocol_version > 2) ||
233      IS_SPCIO_FORCE_CONTEXT(channel->IOMode))
234     seqno=SPC_Write_Protocol_Request(channel->connection, channel,
235                                      APP_B00_SPAWN,
236                                      channel->path, channel->context_dir,
237                                      channel->argv, channel->envp);
238   else
239     seqno=SPC_Write_Protocol_Request(channel->connection, channel,
240                                      APPLICATION_SPAWN,
241                                      channel->path, channel->context_dir,
242                                      channel->argv, channel->envp);
243
244   _DtSvcProcessLock();
245   tmp_errorno = XeSPCErrorNumber;
246   retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
247   if (tmp_errorno != 0)
248      XeSPCErrorNumber = tmp_errorno;
249   _DtSvcProcessUnlock();
250   if(retval==SPC_ERROR)
251     return(SPC_ERROR);
252
253   channel->pid=retval;
254
255   call_parent_method(channel, post_fork, (channel, retval), result);
256   
257   if(result==SPC_ERROR)
258     return(SPC_ERROR);
259   
260   return(TRUE);
261 }
262
263 /*----------------------------------------------------------------------+*/
264 int write_remote_channel_object(SPC_Channel_Ptr channel,
265                                 XeString buffer,
266                                 int len)
267 /*----------------------------------------------------------------------+*/
268 {
269   int result;
270   int seqno, retval;
271   int lentogo=len, lentowrite;
272   
273   call_parent_method(channel, write, (channel, buffer, len), result);
274   
275   if(result==SPC_ERROR)
276     return(SPC_ERROR);
277
278   do {
279
280     lentowrite=min(lentogo, SPC_BUFSIZ);
281     seqno=SPC_Write_Protocol_Request(channel->connection, channel,
282                                       APPLICATION_DATA, buffer, lentowrite);
283     retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
284
285     if(retval==SPC_ERROR)
286       return(SPC_ERROR);
287
288     lentogo -= lentowrite;
289     buffer  += lentowrite;
290     
291   } while(lentogo>0);
292   
293   return(len);
294 }
295   
296 /*----------------------------------------------------------------------+*/
297 int read_remote_channel_object(SPC_Channel_Ptr channel,
298                                int connection,
299                                XeString buffer,
300                                int len)
301 /*----------------------------------------------------------------------+*/
302 {
303   int result;
304   
305   call_parent_method(channel, read, (channel, connection, buffer, len), result);
306   
307   if(result==SPC_ERROR)
308     return(SPC_ERROR);
309
310   if(!IS_SPCIO_DATA(channel->wires[connection]->flags))
311     return(0);
312   
313   result=SPC_Read_Remote_Data(channel, connection, buffer, len);
314   if(result == 0)
315     /* Got EOF.  Yank the data line */
316     SPC_Change_State(channel, connection, 0, -1);
317   
318   return(result);
319 }
320
321 /*----------------------------------------------------------------------+*/
322 int signal_remote_channel_object(SPC_Channel_Ptr channel,
323                                  int sig)
324 /*----------------------------------------------------------------------+*/
325 {
326   int result;
327   int seqno, retval;
328   
329   call_parent_method(channel, signal, (channel, sig), result);
330   
331   if(result==SPC_ERROR)
332     return(SPC_ERROR);
333   
334   if (channel->connection->protocol_version >= 2) {
335       XeString signame = XeSignalToName( sig );
336       
337       if (!signame)
338       {
339           SPC_Error(SPC_Bad_Signal_Value, sig);
340           return (SPC_ERROR);
341       }
342       seqno=SPC_Write_Protocol_Request(channel->connection, channel,
343                                        APPLICATION_SIGNAL, signame);
344   }
345   else
346       seqno=SPC_Write_Protocol_Request(channel->connection, channel,
347                                        APPLICATION_SIGNAL, sig);
348
349   retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
350
351   return(retval);
352 }
353
354 /*----------------------------------------------------------------------+*/
355 int attach_remote_channel_object(SPC_Channel_Ptr channel,
356                                  int pid)
357 /*----------------------------------------------------------------------+*/
358 {
359   int result;
360   int seqno, retval;
361   
362   call_parent_method(channel, attach, (channel, pid), result);
363   
364   if(result==SPC_ERROR)
365     return(SPC_ERROR);
366   
367   seqno=SPC_Write_Protocol_Request(channel->connection, channel,
368                                    CHANNEL_ATTACH, pid);
369   retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
370   if(retval==SPC_ERROR)
371     return(SPC_ERROR);
372
373   SPC_Flush_Queued_Data(channel);
374   
375   if(!mempf0(channel, pre_fork))
376     return(SPC_ERROR);
377   channel->pid = pid;
378
379   return(TRUE);
380 }
381
382 /*----------------------------------------------------------------------+*/
383 remove_logfile_remote_channel_object(SPC_Channel_Ptr channel)
384 /*----------------------------------------------------------------------+*/
385 {
386   int result;
387   int seqno, retval;
388   
389   call_parent_method(channel, remove_logfile, (channel), result);
390   
391   if(result==SPC_ERROR)
392     return(SPC_ERROR);
393   
394   seqno=SPC_Write_Protocol_Request(channel->connection, channel, DELETE_LOGFILE);
395   retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
396   if(retval==SPC_ERROR)
397     return(SPC_ERROR);
398   return(retval);
399 }
400
401 /*----------------------------------------------------------------------+*/
402 int add_input_remote_channel_object(SPC_Channel_Ptr channel,
403                                     SbInputHandlerProc handler, 
404                                     void *data)
405 /*----------------------------------------------------------------------+*/
406 {
407   int result;
408   SPC_Connection_Ptr conn=channel->connection;
409   
410   call_parent_method(channel, add_input, (channel, handler, data), result);
411
412   if(result==SPC_ERROR)
413     return(SPC_ERROR);
414   
415   if(conn->termination_id != -1)
416     /* We already have a handler, don't need another one */
417     return(TRUE);
418
419   SPC_XtAddInput(channel,
420                  &conn->termination_id,
421                  conn->sid,
422                  channel->class_ptr->input,
423                  SPC_Input);
424   return(TRUE);
425   
426 }
427
428 /*----------------------------------------------------------------------+*/
429 SPC_Debug_Mode(SPC_Channel_Ptr channel,
430                XeString file)
431 /*----------------------------------------------------------------------+*/
432 {
433
434   int retval, seqno;
435   
436   if(!channel->connection)
437     return(SPC_ERROR);
438
439   retval=SPC_Write_Protocol_Request(channel->connection, channel,
440                                     SERVER_DEBUG, file);
441   seqno=SPC_Waitfor_Reply(channel->connection, channel, retval);
442
443   if(retval==SPC_ERROR)
444     return(SPC_ERROR);
445   return(seqno);
446
447 }
448
449 int send_eof_remote_channel_object(SPC_Channel_Ptr channel)
450 {
451   int retval, seqno;
452
453   if(!channel->connection)
454     return(SPC_ERROR);
455   
456   retval =
457     SPC_Write_Protocol_Request(channel->connection, channel, CHANNEL_SEND_EOF);
458   seqno = SPC_Waitfor_Reply(channel->connection, channel, retval);
459
460   if(retval==SPC_ERROR)
461     return(SPC_ERROR);
462
463   return(seqno);
464
465 }
466
467 int set_termio_remote_channel_object(SPC_Channel_Ptr channel,
468                                      int connector,
469                                      int side,
470                                      struct termios *termios)
471 {
472   int retval, seqno;
473
474   if(!channel->connection)
475     return(SPC_ERROR);
476
477   retval =
478     SPC_Write_Protocol_Request(channel->connection, channel,
479                                CHANNEL_TERMIOS,
480                                connector, side, termios);
481   seqno = SPC_Waitfor_Reply(channel->connection, channel, retval);
482
483   if(retval==SPC_ERROR)
484     return(SPC_ERROR);
485
486   return(seqno);
487
488 }