2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
24 * File: remote.c $XConsortium: remote.c /main/5 1996/06/21 17:34:53 ageorge $
27 * (c) Copyright 1989, Hewlett-Packard Company, all rights reserved.
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. *
35 #include <bms/sbport.h>
36 #include <bms/usersig.h>
39 #include <SPC/spc-proto.h>
40 #include "DtSvcLock.h"
42 /*----------------------------------------------------------------------+*/
43 void remote_channel_class_init(object_clasp t)
44 /*----------------------------------------------------------------------+*/
46 channel_clasp c=(channel_clasp) t;
48 c->new_obj = alloc_channel_object;
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;
64 /* New B.00 methods */
66 c->send_eof = send_eof_remote_channel_object;
67 c->set_termio = set_termio_remote_channel_object;
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 */
79 remote_channel_clasp remote_channel_class = &remote_channel_class_struct;
81 /*----------------------------------------------------------------------+*/
82 Wire *get_new_remote_wire(Wire *prevwire)
83 /*----------------------------------------------------------------------+*/
85 Wire *mywire=get_new_wire();
89 mywire->next=prevwire;
95 *** Method definitions for remote channel objects
99 /*----------------------------------------------------------------------+*/
100 SPC_Channel_Ptr open_remote_channel_object(SPC_Channel_Ptr channel,
103 /*----------------------------------------------------------------------+*/
106 SPC_Channel_Ptr result;
111 call_parent_method(channel, open, (channel, iomode, hostname), result);
113 if(result==SPC_ERROR)
117 channel->queued_remote_data=Xe_make_queue(NULL);
118 iomode=channel->IOMode;
120 if(IS_SPCIO_STDIN(iomode)) {
121 tmpwire=get_new_remote_wire(tmpwire);
122 channel->wires[STDIN]=tmpwire;
124 if(IS_SPCIO_STDOUT(iomode)) {
125 tmpwire=get_new_remote_wire(tmpwire);
126 channel->wires[STDOUT]=tmpwire;
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;
135 channel->wire_list=tmpwire;
137 if(!(channel->connection=SPC_Open_Connection(hostname)))
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)
146 sid=channel->connection->sid;
147 channel->file_descs[STDIN]=sid;
148 channel->file_descs[STDOUT]=sid;
149 channel->file_descs[STDERR]=sid;
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;
161 SPC_Query_Devices(channel);
163 SPC_Query_Logfile(channel);
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.
176 /*----------------------------------------------------------------------+*/
177 int close_remote_channel_object(SPC_Channel_Ptr channel)
178 /*----------------------------------------------------------------------+*/
184 channel->IOMode |= SPCIO_DELAY_CLOSE;
186 seqno=SPC_Write_Protocol_Request(channel->connection, channel,
188 retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
190 call_parent_method(channel, close, (channel), result);
192 if(result==SPC_ERROR)
198 /*----------------------------------------------------------------------+*/
199 int reset_remote_channel_object(SPC_Channel_Ptr channel)
200 /*----------------------------------------------------------------------+*/
206 protocol_request_ptr prot;
208 call_parent_method(channel, reset, (channel), result);
210 if(result==SPC_ERROR)
213 seqno=SPC_Write_Protocol_Request(channel->connection, channel,
215 retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
216 if(retval==SPC_ERROR)
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. */
224 if (tmpqueue=channel->queued_remote_data)
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);
236 /*----------------------------------------------------------------------+*/
237 int exec_proc_remote_channel_object(SPC_Channel_Ptr channel)
238 /*----------------------------------------------------------------------+*/
244 call_parent_method(channel, exec_proc, (channel), result);
246 if(result==SPC_ERROR)
249 call_parent_method(channel, pre_fork, (channel), result);
251 if(result==SPC_ERROR)
254 if((channel->connection->protocol_version > 2) ||
255 IS_SPCIO_FORCE_CONTEXT(channel->IOMode))
256 seqno=SPC_Write_Protocol_Request(channel->connection, channel,
258 channel->path, channel->context_dir,
259 channel->argv, channel->envp);
261 seqno=SPC_Write_Protocol_Request(channel->connection, channel,
263 channel->path, channel->context_dir,
264 channel->argv, channel->envp);
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)
277 call_parent_method(channel, post_fork, (channel, retval), result);
279 if(result==SPC_ERROR)
285 /*----------------------------------------------------------------------+*/
286 int write_remote_channel_object(SPC_Channel_Ptr channel,
289 /*----------------------------------------------------------------------+*/
293 int lentogo=len, lentowrite;
295 call_parent_method(channel, write, (channel, buffer, len), result);
297 if(result==SPC_ERROR)
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);
307 if(retval==SPC_ERROR)
310 lentogo -= lentowrite;
311 buffer += lentowrite;
318 /*----------------------------------------------------------------------+*/
319 int read_remote_channel_object(SPC_Channel_Ptr channel,
323 /*----------------------------------------------------------------------+*/
327 call_parent_method(channel, read, (channel, connection, buffer, len), result);
329 if(result==SPC_ERROR)
332 if(!IS_SPCIO_DATA(channel->wires[connection]->flags))
335 result=SPC_Read_Remote_Data(channel, connection, buffer, len);
337 /* Got EOF. Yank the data line */
338 SPC_Change_State(channel, connection, 0, -1);
343 /*----------------------------------------------------------------------+*/
344 int signal_remote_channel_object(SPC_Channel_Ptr channel,
346 /*----------------------------------------------------------------------+*/
351 call_parent_method(channel, signal, (channel, sig), result);
353 if(result==SPC_ERROR)
356 if (channel->connection->protocol_version >= 2) {
357 XeString signame = XeSignalToName( sig );
361 SPC_Error(SPC_Bad_Signal_Value, sig);
364 seqno=SPC_Write_Protocol_Request(channel->connection, channel,
365 APPLICATION_SIGNAL, signame);
368 seqno=SPC_Write_Protocol_Request(channel->connection, channel,
369 APPLICATION_SIGNAL, sig);
371 retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
376 /*----------------------------------------------------------------------+*/
377 int attach_remote_channel_object(SPC_Channel_Ptr channel,
379 /*----------------------------------------------------------------------+*/
384 call_parent_method(channel, attach, (channel, pid), result);
386 if(result==SPC_ERROR)
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)
395 SPC_Flush_Queued_Data(channel);
397 if(!mempf0(channel, pre_fork))
404 /*----------------------------------------------------------------------+*/
405 remove_logfile_remote_channel_object(SPC_Channel_Ptr channel)
406 /*----------------------------------------------------------------------+*/
411 call_parent_method(channel, remove_logfile, (channel), result);
413 if(result==SPC_ERROR)
416 seqno=SPC_Write_Protocol_Request(channel->connection, channel, DELETE_LOGFILE);
417 retval=SPC_Waitfor_Reply(channel->connection, channel, seqno);
418 if(retval==SPC_ERROR)
423 /*----------------------------------------------------------------------+*/
424 int add_input_remote_channel_object(SPC_Channel_Ptr channel,
425 SbInputHandlerProc handler,
427 /*----------------------------------------------------------------------+*/
430 SPC_Connection_Ptr conn=channel->connection;
432 call_parent_method(channel, add_input, (channel, handler, data), result);
434 if(result==SPC_ERROR)
437 if(conn->termination_id != -1)
438 /* We already have a handler, don't need another one */
441 SPC_XtAddInput(channel,
442 &conn->termination_id,
444 channel->class_ptr->input,
450 /*----------------------------------------------------------------------+*/
451 SPC_Debug_Mode(SPC_Channel_Ptr channel,
453 /*----------------------------------------------------------------------+*/
458 if(!channel->connection)
461 retval=SPC_Write_Protocol_Request(channel->connection, channel,
463 seqno=SPC_Waitfor_Reply(channel->connection, channel, retval);
465 if(retval==SPC_ERROR)
471 int send_eof_remote_channel_object(SPC_Channel_Ptr channel)
475 if(!channel->connection)
479 SPC_Write_Protocol_Request(channel->connection, channel, CHANNEL_SEND_EOF);
480 seqno = SPC_Waitfor_Reply(channel->connection, channel, retval);
482 if(retval==SPC_ERROR)
489 int set_termio_remote_channel_object(SPC_Channel_Ptr channel,
492 struct termios *termios)
496 if(!channel->connection)
500 SPC_Write_Protocol_Request(channel->connection, channel,
502 connector, side, termios);
503 seqno = SPC_Waitfor_Reply(channel->connection, channel, retval);
505 if(retval==SPC_ERROR)