remote.c 14 KB

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