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