remote.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  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. /* @(#)$TOG: remote.c /main/9 1998/04/06 13:36:26 mgreess $ */
  24. #include "xims.h"
  25. #include <signal.h>
  26. #include <sys/wait.h>
  27. #include <netdb.h>
  28. #include <netinet/in.h>
  29. #include <arpa/inet.h>
  30. #include <sys/socket.h>
  31. #include <sys/errno.h>
  32. #include <setjmp.h>
  33. #include <fcntl.h>
  34. #include <limits.h>
  35. #include <X11/Xproto.h> /* for X_ChangeHosts */
  36. #include <X11/Xatom.h> /* for XA_STRING */
  37. #if !defined(__linux__) && !defined(CSRG_BASED)
  38. extern char *sys_errlist[];
  39. #endif
  40. static char *conf_msg_id = STR_CONFDATA;
  41. #define CONF_MSG_ID_LEN strlen(conf_msg_id)
  42. #define CONF_MSG_DATASIZE_LEN 8
  43. #define CONF_MSG_HEADER_LEN (CONF_MSG_ID_LEN + CONF_MSG_DATASIZE_LEN)
  44. #define CONF_MSG_SIZE_MAX (8*1024 - 64) /* < PIPE_BUF (PIPSIZ) */
  45. static int mk_remote_conf(/* list, locale, ims_name, status, confbuf, conflen */);
  46. static char *mk_ims_ent(/* bp, idx, ent */);
  47. static int parse_ims_list(/* ptr, list */);
  48. static int parse_remote_conf(/* listp, locale, confbuf, conflen */);
  49. static int prepare_action(/* act_typ, av, ac */);
  50. static int read_property(/* prop, type, format, remove, datapp, lenp */);
  51. #if 0 /* README */
  52. Atom:
  53. _DTIMSSTART_MAIN _DTIMSSTART_STATUS _DTIMSSTART_DATA
  54. Property:
  55. _DTIMSSTART_STATUS (format: 32) _DTIMSSTART_DATA (format: 8)
  56. ClientMessage:
  57. message_type: _DTIMSSTART_STATUS
  58. format: 32
  59. data.l[0]: _REMOTE_CONF or _REMOTE_RUN
  60. data.l[1]: ErrorCode
  61. data.l[2-4]: 0 (unused)
  62. Status:
  63. _NONE _INIT _REMOTE_CONF _REMOTE_RUN
  64. Actions:
  65. DtImsGetRemoteConf DtImsRunRemoteIms
  66. Procedure:
  67. <initialization>
  68. * own _MAIN property
  69. * set _STATUS property to _INIT
  70. * set _DATA property to _INIT
  71. <get remote configuratuon (DtImsGetRemoteConf)>
  72. * clear _DATA property
  73. * change _STATUS property to _REMOTE_CONF
  74. * set additional command line options to _DATA property
  75. * invoke DtImsGetRemoteConf action
  76. [on remote dtimsstart]
  77. - collect data
  78. - check _STATUS property whether its value is _REMOTE_CONF
  79. - set collected data to _DATA property of owner of _MAIN (Replace)
  80. - send ClientMessage of ErrorCode to owner of _MAIN
  81. - exit
  82. * receive ClientMessage from remote dtimsstart (or action finished)
  83. * change _STATUS property to _INIT
  84. * read data from _DATA property (Delete)
  85. * parse ErrCode and data (conf data or ErrorPath)
  86. * update selection window
  87. <run IMS on remote host (DtImsRunRemoteIms)>
  88. * change _STATUS property to _REMOTE_RUN
  89. * set additional command line options to _DATA property
  90. * invoke DtImsRunRemoteIms action
  91. * popdown selection window (if sucessfully invoked)
  92. [on remote dtimsstart]
  93. - check _STATUS property whether its value is _REMOTE_RUN
  94. - invoke IMS and wait its preparation
  95. - set ErrorPath to _DATA property of owner of _MAIN (Replace)
  96. - send ClientMessage of ErrorCode to owner of _MAIN
  97. - exit
  98. * receive ClientMessage from remote dtimsstart (or action finished)
  99. * change _STATUS property to _INIT
  100. * parse ErrCode and data (ErrorPath)
  101. <termination>
  102. * disown _MAIN property
  103. * exit
  104. #endif /* README */
  105. #ifdef NEED_STRCASECMP
  106. /*
  107. * In case strcasecmp is not provided by the system here is one
  108. * which does the trick.
  109. */
  110. static int
  111. strcasecmp(const char *s1,
  112. const char *s2)
  113. {
  114. int c1, c2;
  115. while (*s1 && *s2) {
  116. c1 = isupper(*s1) ? tolower(*s1) : *s1;
  117. c2 = isupper(*s2) ? tolower(*s2) : *s2;
  118. if (c1 != c2)
  119. return (c1 - c2);
  120. s1++;
  121. s2++;
  122. }
  123. return (int) (*s1 - *s2);
  124. }
  125. #endif
  126. int put_remote_conf(char *locale, char *ims_name)
  127. {
  128. int ret;
  129. int msg_status = NoError;
  130. int conflen;
  131. char confbuf[CONF_MSG_SIZE_MAX];
  132. ImsList *list = (ImsList *) 0;
  133. DPR(("put_remote_conf(locale=%s, ims=%s)\n", locale, ims_name));
  134. ret = get_ims_list(&list, NULL, True);
  135. msg_status = ret;
  136. ret = mk_remote_conf(list, locale, ims_name, msg_status, confbuf, &conflen);
  137. if (list) {
  138. clear_ImsList(list);
  139. FREE(list);
  140. }
  141. ret = set_remote_confdata(confbuf, conflen);
  142. send_dtims_msg(WIN_ST_REMOTE_CONF, ret);
  143. #if 0
  144. NotifyErrCode(NoError);
  145. (void) fwrite((void *)confbuf, (size_t)conflen, (size_t)1, stdout);
  146. fflush(stdout);
  147. #endif
  148. return ret;
  149. }
  150. int get_remote_conf(ImsList **listp, char *hostname, char *locale, char *ims_name)
  151. {
  152. int ret = NoError;
  153. int conflen = 0;
  154. char *confbuf = 0;
  155. char *opts[16];
  156. int n, num_opts;
  157. char *CDE_locale = NULL;
  158. if (!locale)
  159. locale = userEnv.real_locale ? userEnv.real_locale : userEnv.locale;
  160. CDE_locale = userEnv.CDE_locale;
  161. if (CDE_locale)
  162. DPR2(("get_remote_conf(%s, %s, %s)\n",
  163. hostname, CDE_locale, ims_name ? ims_name : "<all>"));
  164. else
  165. DPR2(("get_remote_conf(%s, %s, %s)\n",
  166. hostname, locale, ims_name ? ims_name : "<all>"));
  167. n = 0;
  168. /* Try to first use the CDE locale, else fallback to the locale. */
  169. if (CDE_locale) {
  170. opts[n++] = "-CDE_locale";
  171. opts[n++] = CDE_locale;
  172. }
  173. else {
  174. if (locale) {
  175. opts[n++] = "-locale";
  176. opts[n++] = locale;
  177. }
  178. }
  179. if (ims_name) {
  180. opts[n++] = "-ims";
  181. opts[n++] = ims_name;
  182. }
  183. #ifdef DEBUG
  184. if (DebugLvl >= 1) {
  185. int i;
  186. for (i = 0; i < DebugLvl; i++) opts[n++] = "-debug";
  187. }
  188. #endif
  189. opts[n] = NULL;
  190. num_opts = n;
  191. ret = prepare_action(ACT_GETREMCONF, opts, num_opts);
  192. if (ret != NoError) return ret;
  193. ret = invoke_action(Conf.action[ACT_GETREMCONF], hostname);
  194. change_window_status(WIN_ST_INIT);
  195. if (ret != NoError) return ret;
  196. ret = read_remote_confdata(&confbuf, &conflen);
  197. if (ret != NoError) return ret;
  198. if (ret == NoError) {
  199. ret = parse_remote_conf(listp, locale, confbuf, conflen);
  200. FREE(confbuf);
  201. if (ims_name && ret == ErrRemoteNoIms)
  202. ret = ErrRemoteMissIms;
  203. }
  204. return ret;
  205. }
  206. #define PUT_DATA(nm, val) *bp++ = ' ', bp = strcpyx(bp, (nm)), \
  207. *bp++ = '=', bp = strcpyx(bp, (val)), *bp++ = '\n'
  208. static int mk_remote_conf(ImsList *list, char *locale,
  209. char *ims_name, int status,
  210. char *confbuf, int *conflen)
  211. {
  212. int num_ent;
  213. int i, j;
  214. char *bp;
  215. int len;
  216. int data_sz;
  217. char sz_ptr[20];
  218. ImsEnt *ent;
  219. char var[20];
  220. DPR(("mk_remote_conf(locale=%s, ims=%s)\n", locale, ims_name));
  221. #ifdef DEBUG
  222. if (DebugLvl >= 2 && list) pr_ImsList(list);
  223. #endif
  224. bp = confbuf + CONF_MSG_HEADER_LEN;
  225. num_ent = 0;
  226. if (status == NoError) {
  227. for (i = 0; i < list->num_ent; i++) {
  228. ent = list->elist[i];
  229. if ((ims_name && strcmp(ent->name, ims_name))
  230. || (ent->ims && (ent->ims->flags & F_NO_REMOTE)))
  231. ent->status = ErrRemoteIms;
  232. else
  233. num_ent++;
  234. }
  235. if (num_ent <= 0)
  236. status = ErrRemoteNoIms;
  237. }
  238. bp = strcpyx(bp, "ImsList: "); bp = strcpyx(bp, locale); *bp++ = '\n';
  239. sprintf(var, "%ld", (long) status);
  240. PUT_DATA("ST", var);
  241. if (num_ent > 0) {
  242. sprintf(var, "%ld", (long) num_ent);
  243. PUT_DATA("ne", var);
  244. if (list->elist[list->default_idx]->status != ErrRemoteIms) {
  245. PUT_DATA("df", list->elist[list->default_idx]->name);
  246. }
  247. sprintf(var, "%ld", (long) (list->def_selmode));
  248. PUT_DATA("sm", var);
  249. for (i = j = 0; i < list->num_ent; i++)
  250. if (list->elist[i]->status != ErrRemoteIms)
  251. bp = mk_ims_ent(bp, j++, list->elist[i]);
  252. }
  253. bp = strcpyx(bp, "END"); *bp++ = '\n';
  254. data_sz = bp - (confbuf + CONF_MSG_HEADER_LEN);
  255. /* header (conf_msg_id & data_sz) */
  256. bp = confbuf;
  257. memset((void *) bp, (int) ' ', (size_t) CONF_MSG_HEADER_LEN);
  258. memcpy((void *) bp, conf_msg_id, CONF_MSG_ID_LEN);
  259. sprintf(sz_ptr, "%ld", (long) data_sz);
  260. len = strlen(sz_ptr);
  261. bp = confbuf + CONF_MSG_HEADER_LEN - 1 - len;
  262. memcpy((void *) bp, (void *) sz_ptr, (size_t) len);
  263. confbuf[CONF_MSG_HEADER_LEN - 1] = '\n';
  264. *conflen = CONF_MSG_HEADER_LEN + data_sz;
  265. DPR2(("mk_remote_conf(): conflen=%d data_sz=%d\n confbuf=%s",
  266. *conflen, data_sz, confbuf));
  267. return NoError;
  268. }
  269. static char *mk_ims_ent(char *bp, int idx, ImsEnt *ent)
  270. {
  271. ImsConf *ims = ent->ims;
  272. char val[20];
  273. sprintf(val, "%ld", (long) idx);
  274. bp = strcpyx(bp, "Ent-"); bp = strcpyx(bp, val); *bp++ = '\n';
  275. PUT_DATA("nm", ent->name);
  276. sprintf(val, "%ld", (long) ent->status);
  277. PUT_DATA("st", val);
  278. sprintf(val, "%ld", (long) ims->flags);
  279. PUT_DATA("fg", val);
  280. sprintf(val, "%ld", (long) ims->protocols);
  281. PUT_DATA("pr", val);
  282. if (ent->label) { PUT_DATA("lb", ent->label); }
  283. if (ims->timeout)
  284. {
  285. sprintf(val, "%ld", (long) ims->timeout);
  286. PUT_DATA("to", val);
  287. }
  288. if (ims->interval)
  289. {
  290. sprintf(val, "%ld", (long) ims->interval);
  291. PUT_DATA("it", val);
  292. }
  293. if (ims->servername) { PUT_DATA("sn", ims->servername); }
  294. if (ims->servername2) { PUT_DATA("sN", ims->servername2); }
  295. if (ims->classname) { PUT_DATA("cn", ims->classname); }
  296. if (ims->property) { PUT_DATA("pp", ims->property); }
  297. if (ims->cmd_path) { PUT_DATA("cp", ims->cmd_path); }
  298. if (ims->cmd_param) { PUT_DATA("cr", ims->cmd_param); }
  299. if (ims->env_set) { PUT_DATA("es", ims->env_set); }
  300. if (ims->env_unset) { PUT_DATA("eu", ims->env_unset); }
  301. if (ims->env_pass) { PUT_DATA("ep", ims->env_pass); }
  302. return bp;
  303. }
  304. #undef PUT_DATA
  305. static int parse_ims_list(char *ptr, ImsList *list)
  306. {
  307. char *bp = ptr;
  308. char *np, *vp;
  309. char *def_name;
  310. int i, num_ent;
  311. ImsEnt *ent = 0;
  312. ImsConf *ims;
  313. CLR(list, ImsList);
  314. list->default_idx = -1;
  315. list->def_selmode = SEL_MODE_NOAUTO;
  316. list->num_ent = 0;
  317. def_name = NULL;
  318. num_ent = 0;
  319. while (np = strchr(bp, '\n')) {
  320. if (np == bp) {
  321. bp++;
  322. continue;
  323. }
  324. *np = 0;
  325. if (strncmp(bp, "Ent-", 4) == 0) {
  326. #ifdef DEBUG
  327. if (list->num_ent <= 0) {
  328. DPR(("parse_ims_list(): ImsEnt: list->num_ent=%d\n", list->num_ent));
  329. }
  330. #endif
  331. if (!list->elist)
  332. list->elist = ALLOC(list->num_ent, ImsEnt *);
  333. if (num_ent >= list->num_ent) {
  334. DPR(("parse_ims_list(): too many entry: '%s'\n", bp));
  335. break;
  336. }
  337. ent = list->elist[num_ent] = ALLOC(1, ImsEnt);
  338. ims = ent->ims = ALLOC(1, ImsConf);
  339. num_ent++;
  340. } else if (strncmp(bp, "END", 3) == 0) {
  341. break;
  342. } else if (bp[0] == ' ' && bp[3] == '=') {
  343. bp++; vp = bp + 3;
  344. /*list */
  345. if (strncmp(bp, "ST", 2) == 0) list->status = atoi(vp);
  346. else if (strncmp(bp, "ne", 2) == 0) list->num_ent = atoi(vp);
  347. else if (strncmp(bp, "df", 2) == 0) def_name = vp;
  348. else if (strncmp(bp, "sm", 2) == 0) list->def_selmode = atoi(vp);
  349. #ifdef DEBUG
  350. else if (!ent) {
  351. DPR(("parse_ims_list(): ImsEnt: list->elist[%d]=%%x\n", num_ent, ent));
  352. }
  353. #endif
  354. /* ent */
  355. else if (strncmp(bp, "nm", 2) == 0) { RENEWSTR(ent->name, vp); }
  356. else if (strncmp(bp, "lb", 2) == 0) { RENEWSTR(ent->label, vp); }
  357. else if (strncmp(bp, "st", 2) == 0) { ent->status = atoi(vp); }
  358. else if (strncmp(bp, "fg", 2) == 0) { ims->flags = atoi(vp); }
  359. else if (strncmp(bp, "pr", 2) == 0) { ims->protocols = atoi(vp); }
  360. else if (strncmp(bp, "to", 2) == 0) { ims->timeout = atoi(vp); }
  361. else if (strncmp(bp, "it", 2) == 0) { ims->interval = atoi(vp); }
  362. else if (strncmp(bp, "sn", 2) == 0) { RENEWSTR(ims->servername, vp); }
  363. else if (strncmp(bp, "sN", 2) == 0) { RENEWSTR(ims->servername2, vp); }
  364. else if (strncmp(bp, "cn", 2) == 0) { RENEWSTR(ims->classname, vp); }
  365. else if (strncmp(bp, "pp", 2) == 0) { RENEWSTR(ims->property, vp); }
  366. else if (strncmp(bp, "cp", 2) == 0) { RENEWSTR(ims->cmd_path, vp); }
  367. else if (strncmp(bp, "cr", 2) == 0) { RENEWSTR(ims->cmd_param, vp); }
  368. else if (strncmp(bp, "es", 2) == 0) { RENEWSTR(ims->env_set, vp); }
  369. else if (strncmp(bp, "eu", 2) == 0) { RENEWSTR(ims->env_unset, vp); }
  370. else if (strncmp(bp, "ep", 2) == 0) { RENEWSTR(ims->env_pass, vp); }
  371. else {
  372. DPR(("parse_ims_list(): invalid line '%s'\n", bp - 1));
  373. }
  374. } else {
  375. DPR(("parse_ims_list(): invalid line '%s'\n", bp));
  376. }
  377. bp = np + 1;
  378. }
  379. #ifdef DEBUG
  380. if (num_ent != list->num_ent) {
  381. DPR(("parse_ims_list(): num_ent(%d) != list->num_ent(%d)\n",
  382. num_ent, list->num_ent));
  383. }
  384. #endif
  385. list->num_ent = num_ent;
  386. list->default_idx = -1;
  387. if (num_ent > 0) {
  388. for (i = 0; i < num_ent; i++) { /* check indispensable entry */
  389. ent = list->elist[i];
  390. if (ent->status == NoError)
  391. ent->status = check_ims_conf(ent->ims, ent->name);
  392. }
  393. if (def_name) { /* set default_idx */
  394. for (i = 0; i < num_ent; i++)
  395. if (strcmp(list->elist[i]->name, def_name) == 0) {
  396. list->default_idx = i;
  397. break;
  398. }
  399. }
  400. }
  401. return list->status;
  402. }
  403. static int parse_remote_conf(ImsList **listp, char *locale, char *confbuf, int conflen)
  404. {
  405. int ret = NoError;
  406. char *bp = confbuf;
  407. ImsList *list;
  408. int data_sz = 0;
  409. DPR(("parse_remote_conf(%s)\n", locale));
  410. if (conflen < (int) CONF_MSG_HEADER_LEN /* check header */
  411. || strncmp(confbuf, conf_msg_id, CONF_MSG_ID_LEN)) {
  412. ret = ErrNoImsstart;
  413. } else {
  414. confbuf[CONF_MSG_HEADER_LEN - 1] = 0; /* <= '\n' */
  415. bp = confbuf + CONF_MSG_ID_LEN;
  416. while (*bp == ' ') bp++;
  417. if (!str_to_int(bp, &data_sz) || data_sz < 0) {
  418. ret = ErrNoImsstart;
  419. } else if (conflen < data_sz + (int) CONF_MSG_HEADER_LEN) {
  420. DPR(("\tconflen(%d) != data_sz(%d) + HDR\n", conflen, data_sz));
  421. data_sz = conflen - CONF_MSG_HEADER_LEN;
  422. ret = ErrNoImsstart;
  423. }
  424. }
  425. #ifdef DEBUG
  426. if (ret != NoError && conflen > (int) CONF_MSG_HEADER_LEN) {
  427. if (!confbuf[CONF_MSG_HEADER_LEN - 1])
  428. confbuf[CONF_MSG_HEADER_LEN - 1] = '@';
  429. confbuf[conflen] = 0;
  430. DPR(("\tinvalid header[len=%d]: %s\n", conflen, confbuf));
  431. }
  432. #endif
  433. if (ret != NoError) return ErrRemoteAction;
  434. bp = confbuf + CONF_MSG_HEADER_LEN;
  435. bp[data_sz] = 0;
  436. if (strncmp(bp, "ImsList:", 8)
  437. /* || strncmp(bp + 9, locale, strlen(locale)) */
  438. || !(bp = strchr(bp, '\n'))) {
  439. return ErrRemoteAction;
  440. }
  441. /* confbuf[conflen] = 0; */
  442. list = ALLOC(1, ImsList);
  443. ret = parse_ims_list(bp, list);
  444. if (ret != NoError || list->num_ent == 0) {
  445. clear_ImsList(list);
  446. FREE(list);
  447. list = (ImsList *) 0;
  448. ret = ErrRemoteNoIms;
  449. }
  450. *listp = list;
  451. return ret;
  452. }
  453. int exec_remote_ims(UserSelection *sel)
  454. {
  455. int ret = NoError;
  456. int n, num_opts, binc;
  457. char *bp, *np;
  458. char envbuf[BUFSIZ];
  459. char tmpbuf[BUFSIZ];
  460. char *opts[32];
  461. char **av;
  462. int ac;
  463. char *ims_name = sel->name;
  464. ImsConf *ims = sel->ent->ims;
  465. char val[20];
  466. DPR(("exec_remote_ims(): '%s' on %s\n", ims_name, sel->hostname));
  467. /* build options */
  468. n = 0;
  469. bp = tmpbuf; tmpbuf[0] = 0;
  470. opts[n++] = "-ims"; opts[n++] = ims_name;
  471. opts[n++] = "-notify";
  472. opts[n++] = "-nosave";
  473. opts[n++] = "-nowindow";
  474. #if 0
  475. binc = expand_string(bp, "%L", BUFSIZ, 0);
  476. opts[n++] = "-locale";
  477. opts[n++] = bp; bp += binc + 1;
  478. binc = expand_string(bp, "%d.%s", BUFSIZ, 0);
  479. opts[n++] = "-display";
  480. opts[n++] = bp; bp += binc = 1;
  481. #endif
  482. #ifdef DEBUG
  483. if (DebugLvl >= 1) {
  484. int i;
  485. for (i = 0; i < DebugLvl; i++) opts[n++] = "-debug";
  486. }
  487. #endif
  488. /* options */
  489. if (OpFlag & FLAG_NOWAIT) opts[n++] = "-nowait";
  490. if (OpFlag & FLAG_NOTIMEOUT) opts[n++] = "-notimeout";
  491. if (OpFlag & FLAG_CONNECT) opts[n++] = "-connect";
  492. if (Opt.Timeout > 0) {
  493. sprintf(val, "%ld", (long)Opt.Timeout);
  494. np = strcpyx(bp, val);
  495. opts[n++] = "-timeout";
  496. opts[n++] = bp; bp = np + 1;
  497. }
  498. if (Opt.Interval > 0) {
  499. sprintf(val, "%ld", (long)Opt.Interval);
  500. np = strcpyx(bp, val);
  501. opts[n++] = "-interval";
  502. opts[n++] = bp; bp = np + 1;
  503. }
  504. if (mk_ims_option(bp, sel)) {
  505. sprintf(val, "%ld", (long)Opt.Interval);
  506. np = strcpyx(bp, val);
  507. opts[n++] = "-imsopt";
  508. opts[n++] = bp; bp = np + 1;
  509. }
  510. bp = NULL;
  511. opts[n] = NULL;
  512. num_opts = n;
  513. /* env variables */
  514. set_remote_env(envbuf, ims->env_pass);
  515. ret = prepare_action(ACT_RUNREMIMS, opts, num_opts);
  516. if (ret != NoError) return ret;
  517. ret = invoke_action(Conf.action[ACT_RUNREMIMS], sel->hostname);
  518. change_window_status(WIN_ST_INIT);
  519. if (ret != NoError) return ret;
  520. ac = 0;
  521. av = NULL;
  522. ret = get_window_data(&ac, &av);
  523. put_xims_log("'%s' started for %s on %s.",
  524. sel->name, userEnv.displayname, sel->hostname);
  525. DPR2(("exec_remote_ims(): ret=%s[%d]\n", error_name(ret), ret));
  526. return ret;
  527. }
  528. int check_hostname(char *hostname)
  529. {
  530. int host_type = HOST_UNKNOWN;
  531. char *local = userEnv.hostname;
  532. struct hostent *hp;
  533. unsigned long addr = 0L;
  534. static unsigned long local_addr = 0L;
  535. if (!hostname || !*hostname || strcasecmp(hostname, "local") == 0
  536. || strcasecmp(hostname, userEnv.hostname) == 0) {
  537. host_type = HOST_LOCAL;
  538. } else { /* compare inet address */
  539. if (!local_addr) {
  540. if ((hp = gethostbyname(local)) && hp->h_addrtype == AF_INET) {
  541. local_addr = *((unsigned long *) hp->h_addr_list[0]);
  542. } else {
  543. DPR(("check_hostname(%s)\tgethostbyname() failed\n", local));
  544. host_type = HOST_REMOTE;
  545. }
  546. }
  547. if (host_type == HOST_UNKNOWN) {
  548. if ((hp = gethostbyname(hostname)) && hp->h_addrtype == AF_INET) {
  549. addr = *((unsigned long *) hp->h_addr_list[0]);
  550. if (addr == local_addr)
  551. host_type = HOST_LOCAL;
  552. else
  553. host_type = HOST_REMOTE;
  554. } else {
  555. DPR(("check_hostname(%s)\tunknown\n", hostname));
  556. host_type = HOST_UNKNOWN;
  557. }
  558. }
  559. }
  560. DPR(("check_hostname(%s): [%s] addr=%#x, local=%#x\n", hostname,
  561. host_type == HOST_LOCAL ? "LOCAL" :
  562. (host_type == HOST_REMOTE ? "REMOTE" : "UNKNOWN"),
  563. addr, local_addr));
  564. return host_type;
  565. }
  566. int set_remote_confdata(char *confbuf, int conflen)
  567. {
  568. char *av[2];
  569. av[0] = confbuf; av[1] = NULL;
  570. return set_window_data(1, av);
  571. }
  572. int read_remote_confdata(char **confbuf, int *conflen)
  573. {
  574. char **av = NULL;
  575. int ac = 0;
  576. int ret;
  577. ret = get_window_data(&ac, &av);
  578. /* if (ac != 1) { FREE av[i]; return ErrBabData; } */
  579. *confbuf = av[0];
  580. *conflen = strlen(av[0]);
  581. return NoError;
  582. }
  583. static int prepare_action(int act_typ, char **av, int ac)
  584. {
  585. int ret;
  586. ret = init_window_env();
  587. if (ret != NoError) return ret;
  588. switch (act_typ) {
  589. case ACT_GETREMCONF:
  590. change_window_status(WIN_ST_REMOTE_CONF);
  591. break;
  592. case ACT_RUNREMIMS:
  593. change_window_status(WIN_ST_REMOTE_RUN);
  594. break;
  595. default: return ErrInternal;
  596. }
  597. ret = set_window_data(ac, av);
  598. return NoError;
  599. }
  600. int get_window_status(void)
  601. {
  602. long *datap;
  603. int len = 0;
  604. int win_st;
  605. if (winEnv.atom_status == None || winEnv.atom_owner == None)
  606. return WIN_ST_NONE;
  607. if (winEnv.atom_owner == None) return WIN_ST_NONE;
  608. #if 0
  609. if (winEnv.atom_owner == XtWindow(winEnv.TopW))
  610. return winEnv.status;
  611. #endif
  612. win_st = WIN_ST_NONE;
  613. if (read_property(winEnv.atom_status, XA_INTEGER, 32, False,
  614. (char **)&datap, &len) == True && len > 0) {
  615. win_st = datap[0];
  616. FREE(datap);
  617. }
  618. return win_st;
  619. }
  620. int change_window_status(int status)
  621. {
  622. if (winEnv.atom_status == None || winEnv.atom_owner == None)
  623. return ErrInternal;
  624. winEnv.status = status;
  625. (void)XChangeProperty(winEnv.Dpy, winEnv.atom_owner,
  626. winEnv.atom_status, XA_INTEGER,
  627. 32, PropModeReplace, (unsigned char *)&status, 1);
  628. XSync(winEnv.Dpy, False);
  629. DPR(("change_window_status(): new status=%d\n", status));
  630. return NoError;
  631. }
  632. int set_window_data(int ac, char **av)
  633. {
  634. int i;
  635. int nbytes;
  636. char *buf, *bp;
  637. if (winEnv.atom_data == None || winEnv.atom_owner == None)
  638. return ErrInternal;
  639. #ifdef DEBUG
  640. if (DebugLvl >= 1) {
  641. int i;
  642. printf("set_window_data() av[%d] = { ", ac);
  643. for (i = 0; i < ac; i++)
  644. printf("\"%s\", ", av[i]);
  645. printf("}\n");
  646. }
  647. #endif
  648. for (i = 0, nbytes = 1; i < ac; i++)
  649. nbytes += strlen(av[i]) + 1;
  650. if (bp = buf = XtMalloc(nbytes)) { /* copy args into single buffer */
  651. for (i = 0; i < ac; i++) {
  652. if (av[i]) {
  653. (void) strcpy(bp, av[i]);
  654. bp += strlen(av[i]) + 1;
  655. } else
  656. *bp++ = '\0';
  657. }
  658. (void)XChangeProperty(winEnv.Dpy, winEnv.atom_owner,
  659. winEnv.atom_data, XA_STRING, 8,
  660. PropModeReplace, (unsigned char *)buf, nbytes);
  661. XSync(winEnv.Dpy, False);
  662. XtFree(buf);
  663. }
  664. DPR(("set_window_data(): len=%d data=\"%s\"\n", nbytes, buf));
  665. return NoError;
  666. }
  667. int get_window_data(int *acp, char ***avp)
  668. {
  669. int ac;
  670. char *data;
  671. char **av;
  672. int len = 0;
  673. int i, j;
  674. if (winEnv.atom_data == None || winEnv.atom_owner == None)
  675. return ErrInternal;
  676. if (read_property(winEnv.atom_data, XA_STRING, 8, True, &data, &len) != True) {
  677. *acp = 0;
  678. *avp = NULL;
  679. return ErrRemoteData;
  680. }
  681. ac = 0; av = NULL;
  682. if (len > 0) {
  683. for (i = 1; i < len - 1; i++) if (data[i] == '\0') ac++;
  684. av = (char **) ALLOC(ac + 1, char *);
  685. j = 0;
  686. if (ac == 1) {
  687. av[j++] = data;
  688. } else {
  689. av[j++] = NEWSTR(data);
  690. for (i = 1; i < len - 1; i++)
  691. if (data[i] == '\0') {
  692. av[j++] = NEWSTR(data + i + 1);
  693. }
  694. FREE(data);
  695. }
  696. av[j] = NULL;
  697. }
  698. #ifdef DEBUG
  699. if (DebugLvl >= 2) {
  700. int i;
  701. printf("get_window_data() av[%d] = { ", ac);
  702. for (i = 0; i < ac; i++)
  703. printf("\"%s\", ", av[i]);
  704. printf("}\n");
  705. }
  706. #endif
  707. *acp = ac;
  708. *avp = av;
  709. return NoError;
  710. }
  711. static int read_property(Atom prop, Atom type, int format,
  712. int del_flag, unsigned char **datapp,
  713. unsigned long *lenp)
  714. {
  715. Atom realtype;
  716. int realformat;
  717. unsigned long bytesafter;
  718. *datapp = NULL;
  719. (void)XGetWindowProperty(winEnv.Dpy, winEnv.atom_owner,
  720. prop, 0L, 1000000L, del_flag, type,
  721. &realtype, &realformat, lenp,
  722. &bytesafter, datapp);
  723. if (realtype == None) {
  724. return False;
  725. } else if (realtype != type) { /* wrong type */
  726. return False;
  727. } else if (realformat != format) { /* wrong format */
  728. if (*datapp != NULL) XtFree((char *)*datapp);
  729. *datapp = NULL;
  730. return False;
  731. }
  732. return True;
  733. }