spc-proto.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980
  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. * $TOG: spc-proto.c /main/12 1999/10/14 16:00:27 mgreess $
  25. * Language: C
  26. *
  27. * (c) Copyright 1996 Digital Equipment Corporation.
  28. * (c) Copyright 1989,1993,1994,1996 Hewlett-Packard Company.
  29. * (c) Copyright 1993,1994,1996 International Business Machines Corp.
  30. * (c) Copyright 1993,1994,1996 Sun Microsystems, Inc.
  31. * (c) Copyright 1993,1994,1996 Novell, Inc.
  32. * (c) Copyright 1996 FUJITSU LIMITED.
  33. * (c) Copyright 1996 Hitachi.
  34. */
  35. #define __need_timeval
  36. #define __need_all_errors
  37. #include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
  38. #include <errno.h>
  39. #include <stdarg.h>
  40. #include <sys/utsname.h>
  41. #include <limits.h>
  42. #include <stdint.h>
  43. #define X_INCLUDE_PWD_H
  44. #define XOS_USE_XT_LOCKING
  45. #include <X11/Xos_r.h>
  46. #include <SPC/spcP.h>
  47. #include <bms/MemoryMgr.h>
  48. #include <SPC/spc-proto.h>
  49. #include <Tt/tt_c.h>
  50. #include "DtSvcLock.h"
  51. /* Externals */
  52. /*************/
  53. extern struct termios *XeTermioStruct; /* In pty.c */
  54. extern XeString *environ;
  55. extern SPC_Channel_Ptr spc_activation_list;
  56. /* Gobals */
  57. /**********/
  58. /* FILE *SPC_Print_Protocol=NULL; -- now in bmsglob.c */
  59. SPC_Connection_Ptr connection_list = NULL;
  60. protocol_request_ptr free_protocol_requests = NULL;
  61. /* Forwards */
  62. /************/
  63. static int SPC_Send_Termios(protocol_request_ptr prot_request);
  64. static int SPC_Send_B00_Spawn(SPC_Connection_Ptr connection,
  65. protocol_request_ptr prot,
  66. char *path,
  67. char *dir,
  68. char **argv,
  69. char **envp);
  70. /*----------------------------------------------------------------------+*/
  71. buffered_data_ptr SPC_New_Buffered_Data_Ptr(void)
  72. /*----------------------------------------------------------------------+*/
  73. {
  74. buffered_data_ptr bdata;
  75. bdata=(buffered_data_ptr)XeMalloc(sizeof(buffered_data));
  76. bdata->len = bdata->offset = 0;
  77. return(bdata);
  78. }
  79. /*----------------------------------------------------------------------+*/
  80. void SPC_Reset_Protocol_Ptr (protocol_request_ptr prot,
  81. SPC_Channel_Ptr channel,
  82. XeChar req,
  83. int len)
  84. /*----------------------------------------------------------------------+*/
  85. {
  86. buffered_data_ptr dptr=prot->dataptr;
  87. dptr->len = len;
  88. dptr->offset = 0;
  89. prot->seqno = 0;
  90. prot->request_type = req;
  91. prot->channel = channel;
  92. prot->next = NULL;
  93. memset(dptr->data, (XeChar)' ', REQUEST_HEADER_LENGTH);
  94. }
  95. /*----------------------------------------------------------------------+*/
  96. protocol_request_ptr SPC_New_Protocol_Ptr (SPC_Channel_Ptr channel,
  97. XeChar req,
  98. int len)
  99. /*----------------------------------------------------------------------+*/
  100. {
  101. protocol_request_ptr prot;
  102. _DtSvcProcessLock();
  103. if(free_protocol_requests) {
  104. prot = free_protocol_requests;
  105. free_protocol_requests = free_protocol_requests->next;
  106. } else {
  107. prot = (protocol_request_ptr)XeMalloc(sizeof(protocol_request));
  108. prot->dataptr = SPC_New_Buffered_Data_Ptr();
  109. }
  110. SPC_Reset_Protocol_Ptr(prot, channel, req, len);
  111. _DtSvcProcessUnlock();
  112. return(prot);
  113. }
  114. /*----------------------------------------------------------------------+*/
  115. void SPC_Free_Protocol_Ptr(protocol_request_ptr prot)
  116. /*----------------------------------------------------------------------+*/
  117. {
  118. _DtSvcProcessLock();
  119. prot->next = free_protocol_requests;
  120. free_protocol_requests = prot;
  121. _DtSvcProcessUnlock();
  122. }
  123. /*----------------------------------------------------------------------+*/
  124. SPC_Channel_Ptr SPC_Lookup_Channel(int cid,
  125. SPC_Connection_Ptr connection)
  126. /*----------------------------------------------------------------------+*/
  127. {
  128. SPC_Channel_Ptr spc;
  129. if(!cid)
  130. return(NULL);
  131. _DtSvcProcessLock();
  132. for(spc=spc_activation_list; spc; spc=spc->next)
  133. /* This test is here because:
  134. a. Only remote channels have cid's
  135. b. It is possible for multiple remote servers to have
  136. the same cid (which is simply the address of the channel),
  137. so we need to distinguish among remote channels, but
  138. c. channels on the remote daemon have cid's, but a null connection.
  139. */
  140. if((spc->cid == cid) &&
  141. (!spc->connection ||
  142. (spc->connection == connection))) {
  143. _DtSvcProcessUnlock();
  144. return(spc);
  145. }
  146. _DtSvcProcessUnlock();
  147. return(NULL);
  148. }
  149. /*
  150. * Connection management routines
  151. */
  152. /*----------------------------------------------------------------------+*/
  153. SPC_Connection_Ptr SPC_Alloc_Connection(void)
  154. /*----------------------------------------------------------------------+*/
  155. {
  156. SPC_Connection_Ptr conn;
  157. _DtSvcProcessLock();
  158. conn=(SPC_Connection_Ptr) XeMalloc(sizeof(SPC_Connection));
  159. /* Zero the connection */
  160. memset(conn, 0, sizeof(SPC_Connection));
  161. conn->queued_remote_data = Xe_make_queue(FALSE);
  162. conn->termination_id = (-1);
  163. /* Init the socket id to "-1" because "0" is a valid file descriptor. */
  164. conn->sid = (-1);
  165. _DtSvcProcessUnlock();
  166. return(conn);
  167. }
  168. /*----------------------------------------------------------------------+*/
  169. SPC_Connection_Ptr SPC_Lookup_Connection(XeString hostname)
  170. /*----------------------------------------------------------------------+*/
  171. {
  172. /* Search for an existing connection to a server */
  173. SPC_Connection_Ptr conn;
  174. _DtSvcProcessLock();
  175. for (conn = connection_list; conn != NULL; conn = conn->next) {
  176. /* Look for a connection with the same hostname */
  177. if (!strcmp(conn->hostname, hostname)) {
  178. _DtSvcProcessUnlock();
  179. return(conn);
  180. }
  181. }
  182. _DtSvcProcessUnlock();
  183. return(FALSE);
  184. }
  185. /*----------------------------------------------------------------------+*/
  186. SPC_Connection_Ptr SPC_Lookup_Connection_Fd(int fd)
  187. /*----------------------------------------------------------------------+*/
  188. {
  189. /* Search for an existing connection to a server, using fd (file descriptor)
  190. as a key */
  191. SPC_Connection_Ptr conn;
  192. _DtSvcProcessLock();
  193. for (conn = connection_list; conn != NULL; conn = conn->next) {
  194. /* Look for a connection with the same hostname */
  195. if (conn->sid==fd) {
  196. _DtSvcProcessUnlock();
  197. return(conn);
  198. }
  199. }
  200. _DtSvcProcessUnlock();
  201. return(FALSE);
  202. }
  203. /*----------------------------------------------------------------------+*/
  204. SPC_Connection_Ptr SPC_Make_Connection(XeString hostname)
  205. /*----------------------------------------------------------------------+*/
  206. {
  207. /* Search for a connection to hostname, create one if none exists */
  208. SPC_Connection_Ptr conn;
  209. /* Searching for connected host maintains only one connection per remote */
  210. if(hostname && (conn=SPC_Lookup_Connection(hostname)))
  211. return(conn);
  212. /* Not found, so make one */
  213. if((conn = SPC_Alloc_Connection())==SPC_ERROR)
  214. return(SPC_ERROR);
  215. if(hostname)
  216. strcpy(conn->hostname, hostname);
  217. SPC_Add_Connection(conn);
  218. return(conn);
  219. }
  220. /*----------------------------------------------------------------------+*/
  221. void SPC_Add_Connection(SPC_Connection_Ptr connection)
  222. /*----------------------------------------------------------------------+*/
  223. {
  224. /* Add a connection to the connection_list */
  225. _DtSvcProcessLock();
  226. connection->next = connection_list;
  227. connection_list = connection;
  228. _DtSvcProcessUnlock();
  229. }
  230. /*----------------------------------------------------------------------+*/
  231. void SPC_Close_Connection(SPC_Connection_Ptr connection)
  232. /*----------------------------------------------------------------------+*/
  233. {
  234. SPC_Channel_Ptr channel;
  235. SPC_Channel_Ptr next;
  236. SPC_Connection_Ptr trail, ptr;
  237. /* We have to be careful here. SPC_Input_Handler may call the users
  238. termination handler, which in turn might close the channel, which
  239. may deallocate the channel. Therefore, we grab the next channel
  240. from the list while we are still alive. */
  241. _DtSvcProcessLock();
  242. channel=spc_activation_list;
  243. connection->connected = FALSE;
  244. while(channel) {
  245. next=channel->next;
  246. if(channel->connection == connection) {
  247. if(!IS_SPCIO_DELAY_CLOSE(channel->IOMode))
  248. SPC_Channel_Terminated(channel);
  249. channel->connection = NULL;
  250. }
  251. channel=next;
  252. }
  253. SPC_XtRemoveInput(&connection->termination_id, SPC_Terminator);
  254. spc_close(connection->sid);
  255. connection->sid = (-1);
  256. if (connection->hostinfo)
  257. XeFree(connection->hostinfo);
  258. /* Remove the connection from the connection list */
  259. if(connection_list == connection)
  260. connection_list = connection->next;
  261. else {
  262. trail = connection_list;
  263. while(trail) {
  264. ptr = trail->next;
  265. if(ptr == connection) {
  266. trail->next = ptr->next;
  267. break;
  268. }
  269. trail=ptr;
  270. }
  271. if(!trail) {
  272. /* Here if no such connection found. */
  273. }
  274. }
  275. free((char *)connection);
  276. _DtSvcProcessUnlock();
  277. }
  278. /*
  279. **
  280. ** Read the specified number of characters, or die trying.
  281. **
  282. */
  283. /*----------------------------------------------------------------------+*/
  284. int SPC_Read_Chars(SPC_Connection_Ptr connection,
  285. int request_len,
  286. XeString charptr)
  287. /*----------------------------------------------------------------------+*/
  288. {
  289. int numchars, numread;
  290. int numtoread=request_len;
  291. int sid=connection->sid;
  292. numread=0;
  293. while(numread<request_len) {
  294. do
  295. numchars=read(sid, charptr, numtoread);
  296. while(numchars == ERROR && errno == EINTR);
  297. if(numchars == ERROR) {
  298. XeString connection_hostname = CONNECTION_HOSTNAME(connection);
  299. if(errno == ECONNRESET)
  300. SPC_Error(SPC_Connection_Reset, connection_hostname);
  301. else
  302. SPC_Error(SPC_Reading, connection_hostname);
  303. XeFree(connection_hostname);
  304. return(SPC_ERROR);
  305. }
  306. if(numchars == 0) {
  307. XeString connection_hostname = CONNECTION_HOSTNAME(connection);
  308. SPC_Error(SPC_Connection_EOF, connection_hostname);
  309. XeFree(connection_hostname);
  310. return(SPC_ERROR); /* Bad news, EOF on incoming channel */
  311. }
  312. charptr += numchars;
  313. numread += numchars;
  314. numtoread -= numchars;
  315. }
  316. *charptr=(XeChar)'\0';
  317. return(numread);
  318. }
  319. /* Write len chars, or die trying */
  320. /*----------------------------------------------------------------------+*/
  321. int SPC_Write_Chars(int fd,
  322. XeString charptr,
  323. int request_len)
  324. /*----------------------------------------------------------------------+*/
  325. {
  326. int numchars, numwritten;
  327. int numtowrite=request_len;
  328. numwritten=0;
  329. while(numwritten<request_len) {
  330. do
  331. numchars=write(fd, charptr, numtowrite);
  332. while(numchars == ERROR && errno == EINTR);
  333. #ifdef DEBUG
  334. _DtSvcProcessLock();
  335. if(SPC_Print_Protocol)
  336. fprintf(SPC_Print_Protocol,
  337. "SPC_Write_Chars -- wrote: %d of %d, expected: %d, errno: %d\n",
  338. numchars, request_len, numtowrite, errno);
  339. _DtSvcProcessUnlock();
  340. #endif
  341. if(numchars == ERROR)
  342. return(ERROR);
  343. charptr += numchars;
  344. numwritten += numchars;
  345. numtowrite -= numchars;
  346. }
  347. return(numwritten);
  348. }
  349. /*
  350. **
  351. ** Read a single protocol request from the passed channel.
  352. **
  353. */
  354. /*----------------------------------------------------------------------+*/
  355. protocol_request_ptr SPC_Read_Protocol(SPC_Connection_Ptr connection)
  356. /*----------------------------------------------------------------------+*/
  357. {
  358. int channel_id;
  359. protocol_request_ptr prot;
  360. buffered_data_ptr dptr;
  361. int len;
  362. if(!connection->connected)
  363. return(SPC_ERROR);
  364. if((prot=SPC_New_Protocol_Ptr(NULL, 0, 0))==SPC_ERROR) {
  365. SPC_Close_Connection(connection);
  366. return(SPC_ERROR);
  367. }
  368. /* read header */
  369. dptr=prot->dataptr;
  370. len=SPC_Read_Chars(connection, REQUEST_HEADER_LENGTH, dptr->data);
  371. if(len != REQUEST_HEADER_LENGTH) {
  372. SPC_Close_Connection(connection);
  373. SPC_Free_Protocol_Ptr(prot);
  374. return(SPC_ERROR);
  375. }
  376. /* we have the header. Parse out the fields */
  377. READ_HEADER(dptr,
  378. &channel_id, &prot->request_type, &dptr->len, &prot->seqno);
  379. prot->channel=SPC_Lookup_Channel(channel_id, connection);
  380. /* JET - 11/12/2001 - correct an exploitable buffer overrun where the user */
  381. /* can supply a data len that is larger than the available buffer */
  382. /* MAXREQLEN */
  383. /* CERT - VU#172583 */
  384. if (dptr->len >= MAXREQLEN)
  385. { /* we have a problem. Initiate DefCon 1 */
  386. /* and launch our missiles. */
  387. XeString connection_hostname = CONNECTION_HOSTNAME(connection);
  388. SPC_Error(SPC_Buffer_Overflow, connection_hostname);
  389. XeFree(connection_hostname);
  390. SPC_Close_Connection(connection);
  391. SPC_Free_Protocol_Ptr(prot);
  392. return(SPC_ERROR);
  393. }
  394. /* read header */
  395. len=SPC_Read_Chars(connection, dptr->len, dptr->data+REQUEST_HEADER_LENGTH);
  396. if(len != dptr->len) {
  397. SPC_Close_Connection(connection);
  398. SPC_Free_Protocol_Ptr(prot);
  399. return(SPC_ERROR);
  400. }
  401. dptr->offset=REQUEST_HEADER_LENGTH;
  402. return(prot);
  403. }
  404. /*
  405. **
  406. ** Filter the connection for the desired type of protocol request.
  407. ** If there is a protocol request of the desired type already queued,
  408. ** return it. If not, read a new one. If we read requests destined
  409. ** for another channel, or for our channel but not the correct
  410. ** request type, queue it up. If the deletep flag is TRUE, remove it
  411. ** from the queue.
  412. **
  413. */
  414. /*----------------------------------------------------------------------+*/
  415. protocol_request_ptr SPC_Filter_Connection(SPC_Connection_Ptr connection,
  416. SPC_Channel_Ptr channel,
  417. int reqtype,
  418. int deletep)
  419. /*----------------------------------------------------------------------+*/
  420. {
  421. SPC_Connection_Ptr connptr=NULL;
  422. SPC_Channel_Ptr conn_channel;
  423. XeQueue tmpqueue;
  424. protocol_request_ptr retval;
  425. int protreqtype;
  426. /* check if there are any queued prot. requests. If so,
  427. check for their having the type we want */
  428. if(channel && (tmpqueue=channel->queued_remote_data)) {
  429. tmpqueue=channel->queued_remote_data;
  430. {
  431. Xe_for_queue(protocol_request_ptr, retval, tmpqueue) {
  432. /* found a queued packet. Is it what we are looking for? */
  433. if(retval->request_type == reqtype) {
  434. /* yes. */
  435. if(deletep)
  436. Xe_delete_queue_element(channel->queued_remote_data, retval);
  437. return(retval);
  438. }
  439. }
  440. }
  441. }
  442. /* No queued elements. Read until we get the reply we
  443. are looking for */
  444. while(TRUE) {
  445. if((retval=SPC_Read_Protocol(connection))==SPC_ERROR)
  446. return(SPC_ERROR);
  447. protreqtype=retval->request_type;
  448. conn_channel=retval->channel;
  449. if(protreqtype == ABORT) {
  450. XeString connection_hostname = CONNECTION_HOSTNAME(connection);
  451. SPC_Error(SPC_Protocol_Abort, connection_hostname);
  452. XeFree (connection_hostname);
  453. return(SPC_ERROR);
  454. }
  455. _DtSvcProcessLock();
  456. if(protreqtype == SERVER_ERROR) {
  457. READ_ERROR(retval->dataptr, XeSPCErrorNumber);
  458. SPC_Error(XeSPCErrorNumber, XeString_NULL, 0);
  459. _DtSvcProcessUnlock();
  460. return(SPC_ERROR);
  461. }
  462. _DtSvcProcessUnlock();
  463. if(!conn_channel)
  464. return(retval);
  465. if((conn_channel == channel) && (protreqtype == reqtype)) {
  466. /* We found one that matches. Check if we need to queue it up. */
  467. if(!deletep)
  468. Xe_push_queue(conn_channel->queued_remote_data, retval);
  469. return(retval);
  470. }
  471. /* No match. Queue it up */
  472. if(IS_SPCIO_SYNC_TERM(channel->IOMode))
  473. Xe_push_queue(connection->queued_remote_data, retval);
  474. else
  475. Xe_push_queue(conn_channel->queued_remote_data, retval);
  476. }
  477. }
  478. /*----------------------------------------------------------------------+*/
  479. void SPC_Flush_Queued_Data(SPC_Channel_Ptr channel)
  480. /*----------------------------------------------------------------------+*/
  481. {
  482. XeQueue tmpqueue;
  483. protocol_request_ptr prot;
  484. if((tmpqueue=channel->queued_remote_data)) {
  485. while((prot=(protocol_request_ptr)Xe_pop_queue(tmpqueue)))
  486. SPC_Free_Protocol_Ptr(prot);
  487. }
  488. if(channel->connection && (tmpqueue=channel->connection->queued_remote_data))
  489. {
  490. Xe_for_queue(protocol_request_ptr, prot, tmpqueue) {
  491. if(prot->channel == channel) {
  492. Xe_delete_queue_element(tmpqueue, prot);
  493. SPC_Free_Protocol_Ptr(prot);
  494. }
  495. }
  496. }
  497. }
  498. /*----------------------------------------------------------------------+*/
  499. int SPC_Read_Remote_Data(SPC_Channel_Ptr channel,
  500. int connector,
  501. XeString client_buffer,
  502. int nbytes)
  503. /*----------------------------------------------------------------------+*/
  504. {
  505. int ret_len;
  506. SPC_Connection_Ptr connection=channel->connection;
  507. protocol_request_ptr prot;
  508. buffered_data_ptr pdata;
  509. int req_type=CONNECTOR_TO_PROT(connector);
  510. prot=SPC_Filter_Connection(connection, channel, req_type, FALSE);
  511. if(prot==SPC_ERROR)
  512. return(SPC_ERROR);
  513. pdata=prot->dataptr;
  514. ret_len = min(nbytes, pdata->len);
  515. memcpy(client_buffer, pdata->data+pdata->offset, ret_len);
  516. pdata->offset += ret_len;
  517. pdata->len -= ret_len;
  518. if(pdata->len == 0) {
  519. SPC_Filter_Connection(connection, channel, req_type, TRUE);
  520. SPC_Free_Protocol_Ptr(prot);
  521. }
  522. return(ret_len);
  523. }
  524. /* Dump out a protocol request */
  525. /*----------------------------------------------------------------------+*/
  526. int print_protocol_request(XeString name, protocol_request_ptr proto)
  527. /*----------------------------------------------------------------------+*/
  528. {
  529. buffered_data_ptr dptr = proto->dataptr;
  530. _DtSvcProcessLock();
  531. if(!SPC_Print_Protocol) {
  532. _DtSvcProcessUnlock();
  533. return FALSE;
  534. }
  535. dptr->data[dptr->offset+dptr->len]=0;
  536. fprintf(SPC_Print_Protocol,
  537. "%s channel: %p, request: %d, length: %d, seq: %d data: %s\n",
  538. name, proto->channel, proto->request_type, dptr->len, proto->seqno,
  539. dptr->data+dptr->offset);
  540. fflush(SPC_Print_Protocol);
  541. _DtSvcProcessUnlock();
  542. return TRUE;
  543. }
  544. /*
  545. * Write a protocol request to the given channel
  546. *
  547. */
  548. int current_sequence_number=1;
  549. /*----------------------------------------------------------------------+*/
  550. int SPC_Write_Protocol_Request (SPC_Connection_Ptr connection,
  551. SPC_Channel_Ptr channel,
  552. int request,
  553. ...)
  554. /*----------------------------------------------------------------------+*/
  555. {
  556. va_list ap;
  557. protocol_request_ptr prot_request;
  558. buffered_data_ptr pdata;
  559. int reply_expected;
  560. XeString prot_name=NULL;
  561. prot_request=SPC_New_Protocol_Ptr(channel, request, 0);
  562. pdata=prot_request->dataptr;
  563. _DtSvcProcessLock();
  564. prot_request->seqno = current_sequence_number++;
  565. _DtSvcProcessUnlock();
  566. /* We are overloading the "channel" field. We put the cid rather */
  567. /* than the actual channel pointer in when we pass it to the other */
  568. /* side of the connection. */
  569. prot_request->channel=(SPC_Channel_Ptr) (intptr_t) (channel ? channel->cid : 0);
  570. switch (request) {
  571. case ABORT:
  572. pdata->len=WRITE_ABORT(pdata, 0);
  573. prot_name=(XeString)" <-- ABORT";
  574. break;
  575. case REGISTER:
  576. {
  577. XeString username;
  578. XeString passwd;
  579. XeString proto_ver;
  580. XeString hostinfo;
  581. va_start(ap, request);
  582. username=va_arg(ap, XeString );
  583. passwd=va_arg(ap, XeString );
  584. proto_ver=va_arg(ap, XeString );
  585. hostinfo=va_arg(ap, XeString );
  586. va_end(ap);
  587. pdata->len=WRITE_REGISTER(pdata, username, passwd, proto_ver, hostinfo);
  588. prot_name=(XeString)" <-- REGISTER";
  589. break;
  590. }
  591. case UNREGISTER:
  592. prot_name=(XeString)" <-- UNREGISTER";
  593. break;
  594. case CHANNEL_OPEN:
  595. va_start(ap, request);
  596. pdata->len=WRITE_OPEN(pdata, va_arg(ap, int));
  597. va_end(ap);
  598. prot_name=(XeString)" <-- CHANNEL_OPEN";
  599. break;
  600. case CHANNEL_CLOSE:
  601. /* This is correct. This protocol request takes no args */
  602. prot_name=(XeString)" <-- CHANNEL_CLOSE";
  603. break;
  604. case CHANNEL_RESET:
  605. /* This one, either */
  606. prot_name=(XeString)" <-- CHANNEL_RESET";
  607. break;
  608. case CHANNEL_ATTACH:
  609. prot_name=(XeString)" <-- CHANNEL_ATTACH";
  610. va_start(ap, request);
  611. pdata->len=WRITE_ATTACH(pdata, va_arg(ap, int));
  612. va_end(ap);
  613. break;
  614. case APPLICATION_SPAWN:
  615. {
  616. XeString path;
  617. XeString dir;
  618. XeString *argv;
  619. XeString *envp;
  620. va_start(ap, request);
  621. /* It is left as an exercise to the reader to figure out
  622. what would happen if we didn't use these temp. variables
  623. and instead used the va_arg macros directly in the
  624. WRITE_APPLICATION_SPAWN... */
  625. path=va_arg(ap, XeString );
  626. dir =va_arg(ap, XeString );
  627. argv=va_arg(ap, XeString *);
  628. envp=va_arg(ap, XeString *);
  629. va_end(ap);
  630. pdata->len=WRITE_APPLICATION_SPAWN(pdata, path, dir, argv, envp);
  631. if(pdata->len == SPC_ERROR) {
  632. SPC_Free_Protocol_Ptr(prot_request);
  633. return(SPC_ERROR);
  634. }
  635. prot_name=(XeString)" <-- APPLICATION_SPAWN";
  636. break;
  637. }
  638. case APPLICATION_SIGNAL:
  639. {
  640. if (connection->protocol_version >= 2)
  641. {
  642. XeString signame;
  643. va_start(ap, request);
  644. signame = va_arg(ap, XeString);
  645. va_end(ap);
  646. pdata->len=WRITE_STRING(pdata, signame);
  647. }
  648. else
  649. {
  650. int sig;
  651. va_start(ap, request);
  652. sig = va_arg(ap, int);
  653. va_end(ap);
  654. pdata->len=WRITE_INT(pdata, sig);
  655. }
  656. prot_name=(XeString)" <-- APPLICATION_SIGNAL";
  657. break;
  658. }
  659. case APPLICATION_DIED:
  660. va_start(ap, request);
  661. pdata->len=WRITE_APPLICATION_DIED(pdata, va_arg(ap, int));
  662. va_end(ap);
  663. prot_name=(XeString)" <-- APPLICATION_DIED";
  664. break;
  665. case APPLICATION_DATA:
  666. prot_name=(XeString)" <-- APPLICATION_DATA";
  667. case APPLICATION_STDOUT:
  668. if(!prot_name)
  669. prot_name=(XeString)" <-- APPLICATION_STDOUT";
  670. case APPLICATION_STDERR:
  671. {
  672. int buflen;
  673. XeString buffer;
  674. if(!prot_name)
  675. prot_name=(XeString)" <-- APPLICATION_STDERR";
  676. va_start(ap, request);
  677. buffer=va_arg(ap, XeString );
  678. buflen=va_arg(ap, int);
  679. va_end(ap);
  680. pdata->len=WRITE_APP_DATA(pdata, buffer, buflen);
  681. break;
  682. }
  683. case SERVER_ERROR:
  684. va_start(ap, request);
  685. pdata->len=WRITE_ERROR(pdata, va_arg(ap, int));
  686. va_end(ap);
  687. prot_name=(XeString)" <-- SERVER_ERROR";
  688. break;
  689. case REPLY:
  690. {
  691. int replyval, errval;
  692. va_start(ap, request);
  693. prot_request->seqno=va_arg(ap, int);
  694. replyval=va_arg(ap, int);
  695. errval=va_arg(ap, int);
  696. va_end(ap);
  697. pdata->len=WRITE_REPLY(pdata, replyval, errval);
  698. prot_name=(XeString)" <-- REPLY";
  699. break;
  700. }
  701. case DEVICE_REPLY:
  702. {
  703. XeString m0;
  704. XeString s0;
  705. XeString m1;
  706. XeString s1;
  707. XeString m2;
  708. XeString s2;
  709. va_start(ap, request);
  710. m0=va_arg(ap, XeString );
  711. s0=va_arg(ap, XeString );
  712. m1=va_arg(ap, XeString );
  713. s1=va_arg(ap, XeString );
  714. m2=va_arg(ap, XeString );
  715. s2=va_arg(ap, XeString );
  716. va_end(ap);
  717. pdata->len=WRITE_DEVICE_REPLY(pdata, m0, s0, m1, s1, m2, s2);
  718. prot_name=(XeString)" <-- DEVICE_REPLY";
  719. break;
  720. }
  721. case QUERY_DEVICES:
  722. prot_name=(XeString)" <-- QUERY_DEVICES";
  723. break;
  724. case LOGFILE_REPLY:
  725. {
  726. XeString fname;
  727. XeString proto_ver;
  728. XeString hostinfo;
  729. va_start(ap, request);
  730. fname=va_arg(ap, XeString );
  731. proto_ver=va_arg(ap, XeString );
  732. hostinfo=va_arg(ap, XeString );
  733. va_end(ap);
  734. pdata->len=WRITE_LOGFILE_REPLY(pdata, fname, proto_ver, hostinfo);
  735. prot_name=(XeString)" <-- LOGFILE_REPLY";
  736. break;
  737. }
  738. case QUERY_LOGFILE:
  739. prot_name=(XeString)" <-- QUERY_LOGFILE";
  740. break;
  741. case DELETE_LOGFILE:
  742. prot_name=(XeString)" <-- DELETE_LOGFILE";
  743. break;
  744. case SERVER_DEBUG:
  745. va_start(ap, request);
  746. pdata->len=WRITE_DEBUG(pdata, va_arg(ap, XeString));
  747. va_end(ap);
  748. prot_name=(XeString)" <-- SERVER_DEBUG";
  749. break;
  750. case ENVIRON_RESET:
  751. return(SPC_Send_Environ(connection, prot_request));
  752. /* We used to send the hp-ux version of a termio struct */
  753. /* This is non-portable, so we don't do it anymore. */
  754. case RESET_TERMIOS:
  755. pdata->len=SPC_Send_Termios(prot_request);
  756. prot_name=(XeString)" <-- RESET_TERMIOS";
  757. break;
  758. /* B.00 (protocol version 3) requests */
  759. case CHANNEL_SEND_EOF:
  760. if(connection->protocol_version < 3) {
  761. SPC_Error(SPC_Protocol_Version_Error,
  762. 3, channel->connection->protocol_version);
  763. SPC_Free_Protocol_Ptr(prot_request);
  764. return(SPC_ERROR);
  765. }
  766. prot_name = (XeString)" <-- CHANNEL_SEND_EOF";
  767. break;
  768. case CHANNEL_TERMIOS:
  769. if(connection->protocol_version < 3) {
  770. SPC_Error(SPC_Protocol_Version_Error,
  771. 3, channel->connection->protocol_version);
  772. SPC_Free_Protocol_Ptr(prot_request);
  773. return(SPC_ERROR);
  774. }
  775. {
  776. int connector, side;
  777. struct termios *termios_ptr;
  778. char *buffer;
  779. va_start(ap, request);
  780. connector = va_arg(ap, int);
  781. side = va_arg(ap, int);
  782. termios_ptr = va_arg(ap, struct termios *);
  783. va_end(ap);
  784. buffer = SPC_Decode_Termios(termios_ptr);
  785. pdata->len=WRITE_TERMIOS(pdata, connector, side, buffer);
  786. prot_name=(XeString)" <-- CHANNEL_TERMIOS";
  787. free(buffer);
  788. break;
  789. }
  790. case APP_B00_SPAWN:
  791. if(connection->protocol_version < 3) {
  792. SPC_Error(SPC_Protocol_Version_Error,
  793. 3, channel->connection->protocol_version);
  794. SPC_Free_Protocol_Ptr(prot_request);
  795. return(SPC_ERROR);
  796. }
  797. {
  798. XeString path;
  799. XeString dir;
  800. XeString *argv;
  801. XeString *envp;
  802. int retval;
  803. va_start(ap, request);
  804. /* It is left as an exercise to the reader to figure out
  805. what would happen if we didn't use these temp. variables
  806. and instead used the va_arg macros directly in the
  807. WRITE_APPLICATION_SPAWN... */
  808. path=va_arg(ap, XeString );
  809. dir =va_arg(ap, XeString );
  810. argv=va_arg(ap, XeString *);
  811. envp=va_arg(ap, XeString *);
  812. va_end(ap);
  813. retval =
  814. SPC_Send_B00_Spawn(connection, prot_request, path, dir, argv, envp);
  815. return(retval);
  816. }
  817. }
  818. reply_expected=
  819. SPC_Write_Single_Prot_Request(connection, prot_name, prot_request);
  820. SPC_Free_Protocol_Ptr(prot_request);
  821. return(reply_expected);
  822. }
  823. /*----------------------------------------------------------------------+*/
  824. int SPC_Write_Single_Prot_Request(SPC_Connection_Ptr connection,
  825. XeString name,
  826. protocol_request_ptr prot)
  827. /*----------------------------------------------------------------------+*/
  828. {
  829. int reply_expected, length;
  830. buffered_data_ptr pdata=prot->dataptr;
  831. if(!connection->connected)
  832. return(SPC_ERROR);
  833. reply_expected=
  834. REPLY_EXPECTED(prot->request_type, prot->seqno);
  835. length=WRITE_HEADER(pdata, prot->channel,
  836. prot->request_type,
  837. pdata->len,
  838. prot->seqno);
  839. pdata->data[length]=(XeChar)' ';
  840. length=pdata->len+REQUEST_HEADER_LENGTH;
  841. if(SPC_Write_Chars(connection->sid, pdata->data, length) == ERROR) {
  842. XeString connection_hostname = CONNECTION_HOSTNAME(connection);
  843. SPC_Close_Connection(connection);
  844. SPC_Error(SPC_Write_Prot, connection_hostname);
  845. XeFree(connection_hostname);
  846. reply_expected = (SPC_ERROR);
  847. }
  848. pdata->offset=REQUEST_HEADER_LENGTH;
  849. print_protocol_request(name, prot);
  850. return(reply_expected);
  851. }
  852. /*----------------------------------------------------------------------+*/
  853. int SPC_Waitfor_Reply(SPC_Connection_Ptr connection,
  854. SPC_Channel_Ptr channel,
  855. int seqno)
  856. /*----------------------------------------------------------------------+*/
  857. {
  858. protocol_request_ptr prot;
  859. int retval, errval;
  860. int thisseq;
  861. if(seqno == NO_REPLY_VAL)
  862. return(TRUE);
  863. if(seqno==SPC_ERROR)
  864. return(SPC_ERROR);
  865. prot=SPC_Filter_Connection(connection, channel, REPLY, TRUE);
  866. if(prot==SPC_ERROR)
  867. return(SPC_ERROR);
  868. thisseq = prot->seqno;
  869. READ_REPLY(prot->dataptr, retval, errval);
  870. SPC_Free_Protocol_Ptr(prot);
  871. if(thisseq != seqno) {
  872. SPC_Error(SPC_Unexpected_Reply);
  873. return(SPC_ERROR);
  874. }
  875. if(retval<0) {
  876. errno=errval;
  877. retval = -retval;
  878. if(retval != SPC_Protocol_Abort) {
  879. if (retval == SPC_Cannot_Create_Netfilename)
  880. SPC_Error(retval, channel->context_dir, connection->hostname);
  881. else if (retval == SPC_Cannot_Exec)
  882. SPC_Error(retval, channel->path, 0);
  883. else if (retval == SPC_cannot_Chdir)
  884. SPC_Error(retval, channel->context_dir, 0);
  885. else
  886. SPC_Error(retval, XeString_NULL, 0);
  887. }
  888. return(SPC_ERROR);
  889. }
  890. return(retval);
  891. }
  892. /*----------------------------------------------------------------------+*/
  893. int SPC_Dispatch_Protocol(protocol_request_ptr proto,
  894. protocol_request_handler *table)
  895. /*----------------------------------------------------------------------+*/
  896. {
  897. int req_type;
  898. if(!proto)
  899. return(FALSE);
  900. req_type=proto->request_type;
  901. if(req_type<0 || req_type>NREQS)
  902. return(FALSE);
  903. return((* table[req_type])(proto));
  904. }
  905. /*----------------------------------------------------------------------+*/
  906. int SPC_Write_Reply(SPC_Connection_Ptr conn,
  907. protocol_request_ptr proto,
  908. int retval,
  909. int errval)
  910. /*----------------------------------------------------------------------+*/
  911. {
  912. _DtSvcProcessLock();
  913. if(retval==ERROR)
  914. retval=(-XeSPCErrorNumber);
  915. _DtSvcProcessUnlock();
  916. return(SPC_Write_Protocol_Request(conn, proto->channel, REPLY,
  917. proto->seqno, retval, errval));
  918. }
  919. /*
  920. **
  921. ** Send the current environment out to the world.
  922. **
  923. */
  924. #define valid_str(x) (((x) != NULL) && (*(x) != 0))
  925. #define NULL_STR "\001\001\001"
  926. #define EMPTY_STR "\001\002\003"
  927. int SPC_Send_Multi_Packet(SPC_Connection_Ptr connection,
  928. protocol_request_ptr prot,
  929. char **str_vect,
  930. int num_str,
  931. int req,
  932. XeString name,
  933. int errid)
  934. {
  935. int counter, tmp_len;
  936. int bytes_left, numbytes;
  937. XeString buf;
  938. int reply_seqno;
  939. int this_seqno;
  940. int valid_ep = 0;
  941. char *this_str;
  942. _DtSvcProcessLock();
  943. this_seqno=current_sequence_number;
  944. numbytes=WRITE_ENVIRON_RESET(prot->dataptr, num_str);
  945. bytes_left=SPC_BUFSIZ-numbytes;
  946. buf=(PDRP(prot->dataptr) + numbytes);
  947. reply_seqno=prot->seqno;
  948. for(counter=0; counter<num_str; counter++) {
  949. this_str = str_vect[counter];
  950. if(this_str == NULL)
  951. this_str = NULL_STR;
  952. if(*this_str == '\0')
  953. this_str = EMPTY_STR;
  954. tmp_len=strlen(this_str)+1; /* Room for NULL char */
  955. if((bytes_left-tmp_len) < 1) {
  956. *buf='\0';
  957. prot->dataptr->len=numbytes+1;
  958. SPC_Write_Single_Prot_Request(connection, name, prot);
  959. SPC_Free_Protocol_Ptr(prot);
  960. prot=SPC_New_Protocol_Ptr(0, req, 0);
  961. prot->seqno=current_sequence_number++;
  962. numbytes=0;
  963. bytes_left=SPC_BUFSIZ;
  964. buf=(PDRP(prot->dataptr) + numbytes);
  965. }
  966. if(tmp_len>SPC_BUFSIZ-1) {
  967. SPC_Error(errid,
  968. this_str,
  969. SPC_BUFSIZ-1);
  970. SPC_Free_Protocol_Ptr(prot);
  971. if(this_seqno != current_sequence_number)
  972. SPC_Write_Protocol_Request(connection, NULL, ABORT);
  973. _DtSvcProcessUnlock();
  974. return(reply_seqno);
  975. }
  976. strncpy(buf, this_str, tmp_len);
  977. bytes_left -= tmp_len;
  978. numbytes += tmp_len;
  979. buf += tmp_len;
  980. }
  981. if(numbytes) {
  982. *buf='\0';
  983. prot->dataptr->len=numbytes+1;
  984. SPC_Write_Single_Prot_Request(connection, (XeString)" <-- ENVIRON_RESET", prot);
  985. SPC_Free_Protocol_Ptr(prot);
  986. }
  987. _DtSvcProcessUnlock();
  988. return(reply_seqno);
  989. }
  990. char **SPC_Get_Multi_Packet(SPC_Connection_Ptr connection,
  991. protocol_request_ptr prot,
  992. char **out,
  993. int *outlen,
  994. int request,
  995. XeString name)
  996. {
  997. int num_vars, i, len;
  998. XeString bufptr;
  999. protocol_request_ptr localprot = NULL;
  1000. print_protocol_request(name, prot);
  1001. READ_ENVIRON_RESET(prot->dataptr, num_vars);
  1002. bufptr=strchr(PDRP(prot->dataptr), Space)+1;
  1003. if(out == NULL)
  1004. out = (char **)malloc((num_vars+1) * sizeof(char **));
  1005. for(i=0; i<num_vars; i++) {
  1006. len=strlen(bufptr);
  1007. if(len==0) {
  1008. if(localprot)
  1009. SPC_Free_Protocol_Ptr(localprot);
  1010. prot=SPC_Filter_Connection(connection, NULL, request, TRUE);
  1011. if(prot==SPC_ERROR) {
  1012. free(out);
  1013. return(SPC_ERROR);
  1014. }
  1015. print_protocol_request(name, prot);
  1016. localprot=prot;
  1017. bufptr=PDRP(prot->dataptr);
  1018. len=strlen(bufptr);
  1019. }
  1020. if(strcmp(bufptr, NULL_STR) == 0)
  1021. out[i] = NULL;
  1022. else {
  1023. if(strcmp(bufptr, EMPTY_STR) == 0)
  1024. out[i] = strdup("");
  1025. else
  1026. out[i] = strdup(bufptr);
  1027. }
  1028. bufptr += (len+1);
  1029. }
  1030. if(localprot)
  1031. SPC_Free_Protocol_Ptr(localprot);
  1032. *outlen = num_vars;
  1033. out[num_vars] = NULL;
  1034. return(out);
  1035. }
  1036. /*----------------------------------------------------------------------+*/
  1037. int SPC_Send_Environ(SPC_Connection_Ptr connection,
  1038. protocol_request_ptr prot)
  1039. /*----------------------------------------------------------------------+*/
  1040. {
  1041. int ep_count=0;
  1042. int result;
  1043. _DtSvcProcessLock();
  1044. while(environ[ep_count])
  1045. ep_count++;
  1046. result = SPC_Send_Multi_Packet(connection, prot, environ, ep_count,
  1047. ENVIRON_RESET, " <-- ENVIRON_RESET",
  1048. SPC_Env_Too_Big);
  1049. _DtSvcProcessUnlock();
  1050. return (result);
  1051. }
  1052. /*----------------------------------------------------------------------+*/
  1053. int sprint_counted_string(XeString buf,
  1054. int count,
  1055. XeString *vect,
  1056. int orig_limit)
  1057. /*----------------------------------------------------------------------+*/
  1058. {
  1059. XeString bufptr=buf;
  1060. int len;
  1061. int i;
  1062. int limit=orig_limit;
  1063. #define ERRBUFLEN 100
  1064. char errbuf[ERRBUFLEN];
  1065. len=sprintf_len(bufptr, (XeString)"%x ", count)+1;
  1066. if(len>limit) {
  1067. sprintf(errbuf, "(%d chars), max. length is %d", len, orig_limit);
  1068. SPC_Error(SPC_Arg_Too_Long,
  1069. bufptr,
  1070. errbuf);
  1071. return(SPC_ERROR);
  1072. }
  1073. bufptr += len;
  1074. limit -= len;
  1075. for(i=0; i<count; (i++, vect++)) {
  1076. if (*vect)
  1077. len = strlen(*vect)+1;
  1078. else
  1079. len = 1;
  1080. if(len>limit) {
  1081. sprintf(errbuf, "(%d chars), max. length is %d", len, orig_limit);
  1082. SPC_Error(SPC_Arg_Too_Long,
  1083. *vect,
  1084. errbuf);
  1085. return(SPC_ERROR);
  1086. }
  1087. sprintf(bufptr, "%s", *vect ? *vect : "");
  1088. bufptr += len;
  1089. limit -= len;
  1090. }
  1091. return(bufptr-buf);
  1092. }
  1093. /*----------------------------------------------------------------------+*/
  1094. XeString *sscan_counted_string(XeString buf,
  1095. XeString *newbuf)
  1096. /*----------------------------------------------------------------------+*/
  1097. {
  1098. int i, numstrings, len;
  1099. XeString bufptr;
  1100. XeString *tmpptr;
  1101. XeString *tmpidx;
  1102. sscanf(buf, (XeString)"%x", &numstrings);
  1103. len=strlen(buf)+1;
  1104. bufptr=buf+len;
  1105. tmpptr=(XeString*)XeMalloc((numstrings+1) * sizeof(XeString *));
  1106. tmpidx=tmpptr;
  1107. for(i=0; i<numstrings; (i++, tmpidx++)){
  1108. len=strlen(bufptr)+1; /* len is string SIZE (with room for NULL) */
  1109. *tmpidx=(XeString)XeMalloc(len);
  1110. strncpy(*tmpidx, bufptr, len);
  1111. (*tmpidx)[len-1]='\0';
  1112. bufptr+= len;
  1113. }
  1114. *tmpidx=NULL;
  1115. if (newbuf)
  1116. *newbuf=bufptr;
  1117. return(tmpptr);
  1118. }
  1119. /*----------------------------------------------------------------------+*/
  1120. int
  1121. sprint_application_data(XeString buf,
  1122. XeString UNUSED_PARM(fmt),
  1123. XeString path,
  1124. XeString dir,
  1125. XeString *argv,
  1126. XeString *envp,
  1127. int UNUSED_PARM(chars_used))
  1128. /*----------------------------------------------------------------------+*/
  1129. {
  1130. int av_count=0;
  1131. int ep_count=0;
  1132. int data_len=0;
  1133. int tmp_len;
  1134. int limit;
  1135. if(argv)
  1136. while(argv[av_count]) av_count++;
  1137. if(envp)
  1138. while(envp[ep_count]) ep_count++;
  1139. limit=SPC_BUFSIZ;
  1140. tmp_len = sprint_counted_string(buf, 1, &path, limit);
  1141. if(tmp_len == SPC_ERROR)
  1142. return(SPC_ERROR);
  1143. limit -= tmp_len;
  1144. buf += tmp_len;
  1145. data_len += tmp_len;
  1146. tmp_len = sprint_counted_string(buf, 1, &dir, limit);
  1147. if(tmp_len == SPC_ERROR)
  1148. return(SPC_ERROR);
  1149. limit -= tmp_len;
  1150. buf += tmp_len;
  1151. data_len += tmp_len;
  1152. tmp_len = sprint_counted_string(buf, av_count, argv, limit);
  1153. if(tmp_len == SPC_ERROR)
  1154. return(SPC_ERROR);
  1155. limit -= tmp_len;
  1156. buf += tmp_len;
  1157. data_len += tmp_len;
  1158. tmp_len = sprint_counted_string(buf, ep_count, envp, limit);
  1159. if(tmp_len == SPC_ERROR)
  1160. return(SPC_ERROR);
  1161. limit -= tmp_len;
  1162. buf += tmp_len;
  1163. data_len += tmp_len;
  1164. return(data_len);
  1165. }
  1166. /*----------------------------------------------------------------------+*/
  1167. int
  1168. sscan_application_data(XeString buf,
  1169. XeString UNUSED_PARM(fmt),
  1170. XeString *path,
  1171. XeString *dir,
  1172. XeString **argv,
  1173. XeString **envp,
  1174. int UNUSED_PARM(offset))
  1175. /*----------------------------------------------------------------------+*/
  1176. {
  1177. XeString bufptr;
  1178. XeString *tmp_vect;
  1179. bufptr=buf;
  1180. tmp_vect=sscan_counted_string(bufptr, &bufptr);
  1181. if(tmp_vect==SPC_ERROR)
  1182. return(SPC_ERROR);
  1183. *path = (*tmp_vect);
  1184. tmp_vect=sscan_counted_string(bufptr, &bufptr);
  1185. if(tmp_vect==SPC_ERROR)
  1186. return(SPC_ERROR);
  1187. *dir = (*tmp_vect);
  1188. *argv=sscan_counted_string(bufptr, &bufptr);
  1189. if(*argv==SPC_ERROR)
  1190. return(SPC_ERROR);
  1191. *envp=sscan_counted_string(bufptr, &bufptr);
  1192. if(*envp==SPC_ERROR)
  1193. return(SPC_ERROR);
  1194. return(TRUE);
  1195. }
  1196. /*----------------------------------------------------------------------+*/
  1197. int
  1198. sprint_device_data(XeString buf,
  1199. XeString m0,
  1200. XeString s0,
  1201. XeString m1,
  1202. XeString s1,
  1203. XeString m2,
  1204. XeString s2)
  1205. /*----------------------------------------------------------------------+*/
  1206. {
  1207. XeString args[6];
  1208. int i;
  1209. args[0]=m0;
  1210. args[1]=s0;
  1211. args[2]=m1;
  1212. args[3]=s1;
  1213. args[4]=m2;
  1214. args[5]=s2;
  1215. i=sprint_counted_string(buf, 6, args, SPC_BUFSIZ);
  1216. if(i==SPC_ERROR)
  1217. return(SPC_ERROR);
  1218. return(i);
  1219. }
  1220. /*----------------------------------------------------------------------+*/
  1221. int
  1222. sscan_device_data(XeString buf,
  1223. XeString *m0,
  1224. XeString *s0,
  1225. XeString *m1,
  1226. XeString *s1,
  1227. XeString *m2,
  1228. XeString *s2)
  1229. /*----------------------------------------------------------------------+*/
  1230. {
  1231. XeString *args;
  1232. args=sscan_counted_string(buf, NULL);
  1233. if(args==SPC_ERROR)
  1234. return(SPC_ERROR);
  1235. *m0=args[0];
  1236. *s0=args[1];
  1237. *m1=args[2];
  1238. *s1=args[3];
  1239. *m2=args[4];
  1240. *s2=args[5];
  1241. free((char *)args);
  1242. return(TRUE);
  1243. }
  1244. /*----------------------------------------------------------------------+*/
  1245. int
  1246. sprint_logfile_data(XeString buf,
  1247. XeString logfile,
  1248. XeString proto_ver,
  1249. XeString hostinfo)
  1250. /*----------------------------------------------------------------------+*/
  1251. {
  1252. int i;
  1253. XeString args[3];
  1254. args[0]=logfile;
  1255. args[1]=proto_ver;
  1256. args[2]=hostinfo;
  1257. i=sprint_counted_string(buf, 3, args, SPC_BUFSIZ);
  1258. if(i==SPC_ERROR)
  1259. return(SPC_ERROR);
  1260. return(i);
  1261. }
  1262. /*----------------------------------------------------------------------+*/
  1263. int
  1264. sscan_logfile_data(XeString buf,
  1265. XeString *logfile,
  1266. XeString *proto_ver,
  1267. XeString *hostinfo)
  1268. /*----------------------------------------------------------------------+*/
  1269. {
  1270. XeString *args;
  1271. args=sscan_counted_string(buf, NULL);
  1272. if(args==SPC_ERROR)
  1273. return(SPC_ERROR);
  1274. *logfile=args[0];
  1275. /* args[1] and args[2] will only be around for protocol revision 2 or later */
  1276. *proto_ver = *hostinfo = XeString_NULL;
  1277. if (args[1]) {
  1278. *proto_ver = args[1];
  1279. *hostinfo = args[2];
  1280. }
  1281. else
  1282. *hostinfo = strdup(SPC_UNKNOWN_HOSTINFO_STR);
  1283. free((char *)args);
  1284. return(TRUE);
  1285. }
  1286. /*----------------------------------------------------------------------+*/
  1287. int
  1288. sprint_register_data(XeString buf,
  1289. XeString username,
  1290. XeString passwd,
  1291. XeString proto_ver,
  1292. XeString hostinfo)
  1293. /*----------------------------------------------------------------------+*/
  1294. {
  1295. int i;
  1296. XeString args[4];
  1297. args[0]=username;
  1298. args[1]=passwd;
  1299. args[2]=proto_ver;
  1300. args[3]=hostinfo;
  1301. i=sprint_counted_string(buf, 4, args, SPC_BUFSIZ);
  1302. if(i==SPC_ERROR)
  1303. return(SPC_ERROR);
  1304. return(i);
  1305. }
  1306. /*----------------------------------------------------------------------+*/
  1307. int
  1308. sscan_register_data(XeString buf,
  1309. XeString *username,
  1310. XeString *passwd,
  1311. XeString *proto_ver,
  1312. XeString *hostinfo)
  1313. /*----------------------------------------------------------------------+*/
  1314. {
  1315. XeString *args;
  1316. args=sscan_counted_string(buf, NULL);
  1317. if(args==SPC_ERROR)
  1318. return(SPC_ERROR);
  1319. *username=args[0];
  1320. *passwd=args[1];
  1321. /* args[2] and args[3] will only be around for protocol revision 2 or later */
  1322. *proto_ver = *hostinfo = XeString_NULL;
  1323. if (args[2]) {
  1324. *proto_ver = args[2];
  1325. *hostinfo = args[3];
  1326. }
  1327. else
  1328. *hostinfo = strdup(SPC_UNKNOWN_HOSTINFO_STR);
  1329. free((char *)args);
  1330. return(TRUE);
  1331. }
  1332. /*
  1333. **
  1334. ** Request / reply protocol requests
  1335. **
  1336. */
  1337. /*----------------------------------------------------------------------+*/
  1338. int SPC_Query_Devices(SPC_Channel_Ptr channel)
  1339. /*----------------------------------------------------------------------+*/
  1340. {
  1341. SPC_Connection_Ptr connection=channel->connection;
  1342. protocol_request_ptr prot;
  1343. SPC_Write_Protocol_Request(connection, channel, QUERY_DEVICES);
  1344. prot=SPC_Filter_Connection(connection, channel, DEVICE_REPLY, TRUE);
  1345. if(prot==SPC_ERROR)
  1346. return(SPC_ERROR);
  1347. READ_DEVICE_REPLY(prot->dataptr,
  1348. &(channel->wires[STDIN]->master_name),
  1349. &(channel->wires[STDIN]->slave_name),
  1350. &(channel->wires[STDOUT]->master_name),
  1351. &(channel->wires[STDOUT]->slave_name),
  1352. &(channel->wires[STDERR]->master_name),
  1353. &(channel->wires[STDERR]->slave_name));
  1354. SPC_Free_Protocol_Ptr(prot);
  1355. return (TRUE);
  1356. }
  1357. /*----------------------------------------------------------------------+*/
  1358. int SPC_Query_Logfile(SPC_Channel_Ptr channel)
  1359. /*----------------------------------------------------------------------+*/
  1360. {
  1361. SPC_Connection_Ptr connection=channel->connection;
  1362. protocol_request_ptr prot;
  1363. XeString junk1 = NULL, junk2 = NULL;
  1364. SPC_Write_Protocol_Request(connection, channel, QUERY_LOGFILE);
  1365. prot=SPC_Filter_Connection(connection, channel, LOGFILE_REPLY, TRUE);
  1366. if(prot==SPC_ERROR)
  1367. return(SPC_ERROR);
  1368. READ_LOGFILE_REPLY(prot->dataptr, &channel->logfile, &junk1, &junk2);
  1369. if (junk1) XeFree(junk1);
  1370. if (junk2) XeFree(junk2);
  1371. SPC_Free_Protocol_Ptr(prot);
  1372. return (TRUE);
  1373. }
  1374. #define UNK_TOKEN "unknown"
  1375. /*----------------------------------------------------------------------+*/
  1376. XeString SPC_LocalHostinfo(void)
  1377. /*----------------------------------------------------------------------+*/
  1378. {
  1379. struct utsname name;
  1380. int s_len;
  1381. static XeString s = 0;
  1382. _DtSvcProcessLock();
  1383. if (!s) {
  1384. if (uname(&name) >= 0) {
  1385. s_len = strlen(name.sysname) +
  1386. strlen(name.nodename) +
  1387. strlen(name.release) +
  1388. strlen(name.machine) + 4;
  1389. s = (XeString) XeMalloc(s_len * sizeof(XeChar));
  1390. sprintf(s, "%s:%s:%s:%s", name.nodename, name.sysname, name.release, name.machine);
  1391. }
  1392. else {
  1393. s_len = 4 * strlen(UNK_TOKEN) + 4;
  1394. s = (XeString) XeMalloc(s_len * sizeof(XeChar));
  1395. sprintf(s, "%s:%s:%s:%s", UNK_TOKEN, UNK_TOKEN, UNK_TOKEN, UNK_TOKEN);
  1396. }
  1397. }
  1398. _DtSvcProcessUnlock();
  1399. return s;
  1400. }
  1401. /*----------------------------------------------------------------------+*/
  1402. int
  1403. SPC_Validate_User(XeString hostname,
  1404. SPC_Connection_Ptr connection)
  1405. /*----------------------------------------------------------------------+*/
  1406. /* Called by client to register itself to spcd */
  1407. {
  1408. XeString username = XeString_NULL;
  1409. uid_t this_uid;
  1410. XeString proto_ver = NULL;
  1411. XeString hostinfo;
  1412. XeString path;
  1413. protocol_request_ptr prot;
  1414. int open_status, chmod_status;
  1415. XeString logfile = NULL;
  1416. XeString junk1 = NULL, junk2 = NULL;
  1417. XeString connection_hostname=CONNECTION_HOSTNAME(connection);
  1418. _Xgetpwparams pwd_buf;
  1419. struct passwd * pwd_ret;
  1420. hostinfo = SPC_LocalHostinfo();
  1421. /*
  1422. * We are now including the user ID to generate the LOGFILE
  1423. * (i.e., the authentication file)
  1424. */
  1425. this_uid=getuid();
  1426. if((pwd_ret = _XGetpwuid(this_uid, pwd_buf)) == NULL) {
  1427. /*
  1428. * Very strange situation - the uid isn't in the passwd file
  1429. */
  1430. username = XeString_NULL; /* we'll use the original /tmp subdirectory */
  1431. }
  1432. else {
  1433. username=(XeString)(pwd_ret->pw_name);
  1434. }
  1435. SPC_Write_Protocol_Request(connection, NULL, REGISTER,
  1436. username, XeString_Empty,
  1437. SPC_PROTOCOL_VERSION_STR, hostinfo);
  1438. prot=SPC_Filter_Connection(connection, NULL, LOGFILE_REPLY, TRUE);
  1439. if(prot==SPC_ERROR) {
  1440. XeFree(connection_hostname);
  1441. return(SPC_ERROR);
  1442. }
  1443. /* In repsonse to the register, the daemon will send back a LOGFILE_REPLY */
  1444. /* message that contains the name of a logfile to be used to do user */
  1445. /* authentication. For A.02 and later daemons, it will also contain */
  1446. /* the spc protocol version and info about the host the daemon is on. */
  1447. READ_LOGFILE_REPLY(prot->dataptr, &logfile, &proto_ver, &hostinfo);
  1448. /* For Pre A.01, this will be defaulted to (hpux 7.0 s300) */
  1449. connection->hostinfo = hostinfo;
  1450. if (proto_ver) {
  1451. sscanf(proto_ver, "%d", &connection->protocol_version);
  1452. XeFree(proto_ver);
  1453. }
  1454. SPC_Free_Protocol_Ptr(prot);
  1455. if(!strcmp(logfile, PASSED_FILE_NAME))
  1456. return(TRUE);
  1457. if(!strcmp(logfile, FAILED_FILE_NAME)) {
  1458. SPC_Error(SPC_Register_Username,
  1459. (username) ? username : (XeString)"<empty user>",
  1460. connection_hostname);
  1461. XeFree(connection_hostname);
  1462. if (logfile) XeFree(logfile);
  1463. return(SPC_ERROR);
  1464. }
  1465. /*
  1466. * Get a pathname to the authentication file.
  1467. */
  1468. path=tt_netfile_file(logfile);
  1469. if(tt_ptr_error (path) != TT_OK) {
  1470. SPC_Write_Protocol_Request(connection, NULL, ABORT);
  1471. SPC_Error(SPC_Register_Netrc,
  1472. logfile,
  1473. connection_hostname);
  1474. XeFree(connection_hostname);
  1475. if (logfile) XeFree(logfile);
  1476. return(SPC_ERROR);
  1477. }
  1478. open_status=open(path, O_CREAT, S_ISUID);
  1479. if(open_status==ERROR) {
  1480. SPC_Write_Protocol_Request(connection, NULL, ABORT);
  1481. SPC_Error(SPC_Register_Open,
  1482. path,
  1483. connection_hostname);
  1484. tt_free (path);
  1485. XeFree(connection_hostname);
  1486. if (logfile) XeFree(logfile);
  1487. return(SPC_ERROR);
  1488. }
  1489. /* We need to also do a chmod because of an apparent Domain/OS bug
  1490. where the open call does not properly set the UID bit. We
  1491. let chmod set the bit. */
  1492. chmod_status=chmod(path, S_ISUID);
  1493. if(chmod_status==ERROR) {
  1494. SPC_Write_Protocol_Request(connection, NULL, ABORT);
  1495. SPC_Error(SPC_Register_Open,
  1496. path,
  1497. connection_hostname);
  1498. tt_free (path);
  1499. XeFree(connection_hostname);
  1500. if (logfile) XeFree(logfile);
  1501. close(open_status);
  1502. return(SPC_ERROR);
  1503. }
  1504. SPC_Write_Protocol_Request(connection, NULL, REGISTER, logfile, NULL, NULL, NULL);
  1505. prot=SPC_Filter_Connection(connection, NULL, LOGFILE_REPLY, TRUE);
  1506. close(open_status);
  1507. unlink(path);
  1508. tt_free (path);
  1509. if(prot==SPC_ERROR) {
  1510. XeFree(connection_hostname);
  1511. return(SPC_ERROR);
  1512. }
  1513. /*
  1514. * Free logfile before it gets malloc'd again.
  1515. */
  1516. XeFree(logfile);
  1517. logfile = NULL;
  1518. READ_LOGFILE_REPLY(prot->dataptr, &logfile, &junk1, &junk2);
  1519. if (junk1) XeFree(junk1);
  1520. if (junk2) XeFree(junk2);
  1521. SPC_Free_Protocol_Ptr(prot);
  1522. if(!strcmp(logfile, PASSED_FILE_NAME)) {
  1523. XeFree(connection_hostname);
  1524. if (logfile) XeFree(logfile);
  1525. return(TRUE);
  1526. }
  1527. if(!strcmp(logfile, FAILED_FILE_NAME)) {
  1528. SPC_Error(SPC_Register_Handshake,
  1529. username,
  1530. connection_hostname);
  1531. XeFree(connection_hostname);
  1532. if (logfile) XeFree(logfile);
  1533. return(SPC_ERROR);
  1534. }
  1535. if (logfile) XeFree(logfile);
  1536. XeFree(connection_hostname);
  1537. SPC_Error(SPC_Protocol);
  1538. return(SPC_ERROR);
  1539. }
  1540. /*----------------------------------------------------------------------+*/
  1541. static int SPC_Send_Termios(protocol_request_ptr prot_request)
  1542. /*----------------------------------------------------------------------+*/
  1543. {
  1544. struct termios *tio;
  1545. int retval;
  1546. XeString s;
  1547. tio = SPC_Get_Current_Termio(); /* Gets a (malloced) copy */
  1548. s = SPC_Decode_Termios( tio ); /* Get ASCII representation */
  1549. retval = WRITE_STRING(prot_request->dataptr, s);
  1550. XeFree(tio);
  1551. XeFree(s);
  1552. return(retval);
  1553. }
  1554. /*----------------------------------------------------------------------+*/
  1555. int SPC_Get_Termios(protocol_request_ptr prot_request)
  1556. /*----------------------------------------------------------------------+*/
  1557. {
  1558. XeString s;
  1559. int i;
  1560. _DtSvcProcessLock();
  1561. if(XeTermioStruct == NULL) {
  1562. XeTermioStruct = (struct termios *)XeMalloc(sizeof(struct termios));
  1563. for(i=0; i<NCCS; i++)
  1564. XeTermioStruct->c_cc[i] = 0;
  1565. }
  1566. READ_STRING_NO_COPY(prot_request->dataptr, s);
  1567. SPC_Encode_Termios(s, XeTermioStruct);
  1568. _DtSvcProcessUnlock();
  1569. return(XeSetpgrp(FALSE));
  1570. }
  1571. /*----------------------------------------------------------------------+*/
  1572. int SPC_Get_Termio(protocol_request_ptr UNUSED_PARM(prot_request))
  1573. /*----------------------------------------------------------------------+*/
  1574. {
  1575. /* This is for old 1.0, 1.1 versions of the SPC code. We used to */
  1576. /* pass an HPUX version of the termio struct around. This was not */
  1577. /* portable. If we get one of these requests, just bit bucket it */
  1578. /* as we do not know how to deal with it. */
  1579. return(XeSetpgrp(FALSE));
  1580. }
  1581. static int SPC_Send_B00_Spawn(SPC_Connection_Ptr connection,
  1582. protocol_request_ptr prot,
  1583. char *path,
  1584. char *dir,
  1585. char **argv,
  1586. char **envp)
  1587. {
  1588. char **merged_ptr;
  1589. int num_elts=0, this_elt, num_argv, num_envp;
  1590. char argv_buf[20], envp_buf[20];
  1591. int retval;
  1592. num_argv = 0;
  1593. while(argv && argv[num_argv++])
  1594. num_elts++;
  1595. num_envp = 0;
  1596. while(envp && envp[num_envp++])
  1597. num_elts++;
  1598. merged_ptr = (char **)malloc((num_elts+6) * sizeof(char *));
  1599. sprintf(argv_buf, "%d", num_argv);
  1600. sprintf(envp_buf, "%d", num_envp);
  1601. num_elts=0;
  1602. merged_ptr[num_elts++] = path;
  1603. merged_ptr[num_elts++] = dir;
  1604. merged_ptr[num_elts++] = argv_buf;
  1605. merged_ptr[num_elts++] = envp_buf;
  1606. this_elt = 0;
  1607. while(argv && argv[this_elt])
  1608. merged_ptr[num_elts++] = argv[this_elt++];
  1609. merged_ptr[num_elts++] = "DUMMY";
  1610. this_elt = 0;
  1611. while(envp && envp[this_elt])
  1612. merged_ptr[num_elts++] = envp[this_elt++];
  1613. merged_ptr[num_elts] = NULL;
  1614. retval = SPC_Send_Multi_Packet(connection, prot,
  1615. merged_ptr, num_elts,
  1616. APP_B00_SPAWN, " <-- APP_B00_SPAWN",
  1617. SPC_Arg_Too_Long);
  1618. free((char *)merged_ptr);
  1619. return(retval);
  1620. }