I18nEnv.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  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: I18nEnv.c /main/4 1997/08/11 12:31:10 samborn $ */
  24. /*
  25. * (c) Copyright 1996 Digital Equipment Corporation.
  26. * (c) Copyright 1996 Hewlett-Packard Company.
  27. * (c) Copyright 1996 International Business Machines Corp.
  28. * (c) Copyright 1996 Sun Microsystems, Inc.
  29. * (c) Copyright 1996 Novell, Inc.
  30. * (c) Copyright 1996 FUJITSU LIMITED.
  31. * (c) Copyright 1996 Hitachi.
  32. */
  33. /************************************<+>*************************************
  34. ****************************************************************************
  35. **
  36. ** File: I18nEnv.c
  37. **
  38. ** Description: Controls the Dtstyle I18N component interaction with
  39. ** the environment.
  40. **
  41. **
  42. ****************************************************************************
  43. ************************************<+>*************************************/
  44. /*+++++++++++++++++++++++++++++++++++++++*/
  45. /* include files */
  46. /*+++++++++++++++++++++++++++++++++++++++*/
  47. #include <pwd.h>
  48. #include <X11/Xlib.h>
  49. #include <X11/Intrinsic.h>
  50. #include <DtHelp/LocaleXlate.h> /* for locale equivalence between platforms */
  51. #include "Main.h"
  52. #include "I18nEnv.h"
  53. /*+++++++++++++++++++++++++++++++++++++++*/
  54. /* include extern functions */
  55. /*+++++++++++++++++++++++++++++++++++++++*/
  56. /*+++++++++++++++++++++++++++++++++++++++*/
  57. /* Local #defines */
  58. /*+++++++++++++++++++++++++++++++++++++++*/
  59. /*+++++++++++++++++++++++++++++++++++++++*/
  60. /* Internal Functions */
  61. /*+++++++++++++++++++++++++++++++++++++++*/
  62. static int GetUserEnv(I18nEnv *env);
  63. static int FindCDELocaleName(UserEnv *uenv);
  64. static int GetUserIMSelectionFile(I18nEnv *env);
  65. static int GetUserFileName(I18nEnv *env);
  66. static int ReadImSelectionFile(FileSel *fsel, FILE *fp);
  67. static int GetImsList(I18nEnv *env, char *hostname);
  68. static void TimeOutProc(XtPointer client_data, XtIntervalId* timer);
  69. static void ReadPipe(XtPointer client_data, int *fd, XtInputId *id);
  70. static int ProcessBuf(char *savebuf, I18nEnv *env);
  71. static int CheckHostname(I18nEnv *env, char *hostname);
  72. static void PutSelectMode(FILE *fp, int start_mode);
  73. static void PutImsName(FILE *fp, char *im_name);
  74. static void PutHostname(FILE *fp, char *hostname);
  75. static void PutSelectionEntry(FILE *fp, char *tag, char *value);
  76. /*+++++++++++++++++++++++++++++++++++++++*/
  77. /* Internal Variables */
  78. /*+++++++++++++++++++++++++++++++++++++++*/
  79. /*+++++++++++++++++++++++++++++++++++++++*/
  80. /* Global Variables */
  81. /*+++++++++++++++++++++++++++++++++++++++*/
  82. I18nEnv i18n_env;
  83. /*+++++++++++++++++++++++++++++++++++++++*/
  84. /* strcasecmp */
  85. /*+++++++++++++++++++++++++++++++++++++++*/
  86. #ifdef NEED_STRCASECMP
  87. /*
  88. * In case strcasecmp is not provided by the system here is one
  89. * which does the trick.
  90. */
  91. static int
  92. strcasecmp(const char *s1,
  93. const char *s2)
  94. {
  95. int c1, c2;
  96. while (*s1 && *s2) {
  97. c1 = isupper(*s1) ? tolower(*s1) : *s1;
  98. c2 = isupper(*s2) ? tolower(*s2) : *s2;
  99. if (c1 != c2)
  100. return (c1 - c2);
  101. s1++;
  102. s2++;
  103. }
  104. return (int) (*s1 - *s2);
  105. }
  106. #endif
  107. /*+++++++++++++++++++++++++++++++++++++++*/
  108. /* _DtI18nGetEnvValues */
  109. /*+++++++++++++++++++++++++++++++++++++++*/
  110. int
  111. _DtI18nGetEnvValues(
  112. I18nEnv *env
  113. )
  114. {
  115. int ret = NoError;
  116. /* Get the user environment */
  117. env->user_env = (UserEnv *) XtMalloc(sizeof(UserEnv));
  118. ret = GetUserEnv(env);
  119. /* Get the user selection stored in the IM Selection File */
  120. if (ret == NoError) {
  121. env->file_sel = (FileSel *) XtMalloc(sizeof(FileSel));
  122. ret = GetUserIMSelectionFile(env);
  123. }
  124. /* Alloc the user selection */
  125. env->ims_sel = (ImsSel *) XtMalloc(sizeof(ImsSel));
  126. env->ims_sel->ims_list = NULL;
  127. env->ims_sel->ims_list_size = 0 ;
  128. env->ims_sel->host_name = NULL ;
  129. /* Get the Input Method available on the selected host.
  130. * The selected host is the one stored in the IMS Selection File.
  131. */
  132. if (ret == NoError)
  133. ret = _DtI18nGetImList(env, env->file_sel->hostname);
  134. return ret;
  135. }
  136. /*+++++++++++++++++++++++++++++++++++++++*/
  137. /* GetUserEnv */
  138. /*+++++++++++++++++++++++++++++++++++++++*/
  139. static int
  140. GetUserEnv(
  141. I18nEnv *env
  142. )
  143. {
  144. UserEnv *uenv = env->user_env ;
  145. int ret = NoError;
  146. char buf[BUFSIZ], *p;
  147. /* get the host name */
  148. gethostname(buf, BUFSIZ);
  149. uenv->localhostname = XtNewString(buf);
  150. /* get the user name */
  151. if ((p = getlogin()) == NULL) {
  152. struct passwd *pw;
  153. pw = getpwuid(getuid());
  154. p = pw->pw_name;
  155. }
  156. uenv->username = XtNewString(p);
  157. /* get the display name */
  158. uenv->displayname = XtNewString(XDisplayString(XtDisplay(env->shell)));
  159. /* get the locale */
  160. if ((p = getenv("LANG")) && *p)
  161. uenv->locale = XtNewString(p);
  162. else
  163. return ErrNoLocale;
  164. /* find the CDE generic locale name */
  165. if (FindCDELocaleName(uenv) != NoError)
  166. return ErrNoCDELocale;
  167. /* get the home directory */
  168. if ((p = getenv("HOME")) && *p)
  169. uenv->homedir = XtNewString(p);
  170. else
  171. ret = ErrNoHome;
  172. return ret;
  173. }
  174. static int
  175. FindCDELocaleName(
  176. UserEnv *uenv
  177. )
  178. {
  179. _DtXlateDb db = NULL;
  180. int ret = NoError;
  181. char plat[_DtPLATFORM_MAX_LEN];
  182. int execver;
  183. int compver;
  184. ret = _DtLcxOpenAllDbs(&db);
  185. if (ret == NoError)
  186. ret = _DtXlateGetXlateEnv(db, plat, &execver, &compver);
  187. if (ret == NoError)
  188. ret = _DtLcxXlateOpToStd(db, plat, compver, DtLCX_OPER_SETLOCALE,
  189. uenv->locale, &uenv->CDE_locale,
  190. NULL, NULL, NULL);
  191. if (ret == NoError)
  192. ret = _DtLcxCloseDb(&db);
  193. return ret;
  194. }
  195. static int
  196. GetUserIMSelectionFile(
  197. I18nEnv *env
  198. )
  199. {
  200. int ret = NoError;
  201. FILE *fp = NULL;
  202. ret = GetUserFileName(env);
  203. if (ret == NoError) {
  204. /* Look if this file is readable */
  205. if ((fp = fopen(env->file_sel->fname, "r")) == NULL) {
  206. env->file_sel->start_mode = -1;
  207. return ErrNoSelectionFile;
  208. }
  209. }
  210. start_tag_line(env->file_sel->fname);
  211. ret = ReadImSelectionFile(env->file_sel, fp);
  212. if(fp) {
  213. fclose(fp);
  214. }
  215. return ret;
  216. }
  217. static int
  218. GetUserFileName(
  219. I18nEnv *env
  220. )
  221. {
  222. int status, ret = NoError;
  223. char *path, *tmp_path;
  224. int len = 0;
  225. struct stat buf;
  226. /* The user IMS Selection File should be of the following form:
  227. * $HOME/.dt/ims/[display-name]/CDE-locale
  228. */
  229. path = (char *) XtMalloc((MAXPATHLEN + 1) * sizeof(char));
  230. strcpy(path, env->user_env->homedir);
  231. strcat(path, DtUSER_IMSFS_DIR);
  232. /* Look if there is a display specific directory */
  233. tmp_path = (char *) XtMalloc((MAXPATHLEN + 1) * sizeof(char));
  234. strcpy(tmp_path, path);
  235. strcat(tmp_path, "/");
  236. strcat(tmp_path, env->user_env->displayname);
  237. if ((status = stat (tmp_path, &buf)) == 0) {
  238. strcat(path, "/");
  239. strcat(path, env->user_env->displayname);
  240. }
  241. XtFree(tmp_path);
  242. /* Now add the CDE-specific locale name */
  243. strcat(path, "/");
  244. strcat(path, env->user_env->CDE_locale);
  245. env->file_sel->fname = path;
  246. return ret;
  247. }
  248. static int
  249. ReadImSelectionFile(
  250. FileSel *fsel,
  251. FILE *fp
  252. )
  253. {
  254. int ret = NoError;
  255. char *lp, *valp, *vp, *p;
  256. int select_mode = 0;
  257. char *imsname, *hostname;
  258. int line_num, i;
  259. imsname = hostname = NULL;
  260. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  261. if (!valp) {
  262. continue;
  263. }
  264. if (lp[0] != STR_PREFIX_CHAR) {
  265. continue;
  266. }
  267. if (strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
  268. if (str_to_int(valp, &i) && i >= 0) {
  269. select_mode = i;
  270. }
  271. } else if (strncmp(lp + 1, STR_IMSNAME, 4) == 0) {
  272. vp = valp; cut_field(valp);
  273. if (*vp) {
  274. XtFree(imsname);
  275. imsname = XtNewString(vp);
  276. }
  277. } else if (strncmp(lp + 1, STR_HOSTNAME, 4) == 0) {
  278. vp = valp; cut_field(valp);
  279. if (*vp) {
  280. XtFree(hostname);
  281. if (strcmp(vp, NAME_LOCAL)) {
  282. hostname = XtNewString(vp);
  283. }
  284. }
  285. }
  286. }
  287. fsel->im_name = imsname;
  288. fsel->hostname = hostname;
  289. fsel->start_mode = select_mode;
  290. return ret;
  291. }
  292. int
  293. _DtI18nGetImList(
  294. I18nEnv *env,
  295. char *hostname )
  296. {
  297. int ret = NoError;
  298. int host_type = HOST_LOCAL;
  299. if (hostname)
  300. host_type = CheckHostname(env, hostname);
  301. switch (host_type) {
  302. case HOST_UNKNOWN:
  303. ret = ErrUnknownHost;
  304. break;
  305. case HOST_REMOTE:
  306. /* Put the host name in the ImsSel structure */
  307. env->ims_sel->host_name = hostname;
  308. ret = GetImsList(env, hostname);
  309. break;
  310. case HOST_LOCAL:
  311. if (hostname && strcasecmp(hostname, "local") != 0)
  312. env->ims_sel->host_name = hostname;
  313. ret = GetImsList(env, env->user_env->localhostname);
  314. break;
  315. }
  316. return ret;
  317. }
  318. static int
  319. GetImsList(
  320. I18nEnv *env,
  321. char *hostname )
  322. {
  323. int ret = NoError;
  324. char pipe_command[255];
  325. FILE *fp;
  326. struct stat buf;
  327. unsigned long timeout;
  328. /* First check if dtimsstart is installed correctly */
  329. if ((ret = stat ("/usr/dt/bin/dtimsstart", &buf)) != NoError) {
  330. return ErrNoDtimsstart;
  331. }
  332. sprintf(pipe_command, "/usr/dt/bin/dtimsstart -listname -hostname %s",
  333. hostname);
  334. if (fp = popen(pipe_command, "r")) {
  335. /* Set the sensitivity of the InputMethod Title Box to False until we
  336. * are done reading the new information. */
  337. _DtI18nSetSensitiveImTB(env, False);
  338. /* Initialize the pipe record. */
  339. if (!(env->pipe_info))
  340. env->pipe_info = (PipeRec *) XtMalloc(sizeof(PipeRec));
  341. env->pipe_info->pipe = fp; /* to close it */
  342. env->pipe_info->input_id = /* to remove it */
  343. XtAppAddInput (XtWidgetToApplicationContext(env->shell),
  344. fileno(fp), (XtPointer) XtInputReadMask,
  345. ReadPipe, (XtPointer) env);
  346. /* Also add a timeout in case the pipe ain't talk */
  347. timeout = (unsigned long) (style.xrdb.pipeTimeOut) * 1000;
  348. env->pipe_info->timer_id =
  349. XtAppAddTimeOut(XtWidgetToApplicationContext(env->shell),
  350. timeout, TimeOutProc, (XtPointer)env);
  351. } else {
  352. ret = ErrNoPopen;
  353. }
  354. return ret;
  355. }
  356. static void TimeOutProc (XtPointer client_data,
  357. XtIntervalId* timer)
  358. {
  359. I18nEnv *env = (I18nEnv *) client_data;
  360. /* the command is not fast enough, but calling pclose blocks
  361. and then print "Broken Pipe". I need to kill the child somehow
  362. pclose(env->pipe_info->pipe);*/
  363. XtRemoveInput(env->pipe_info->input_id);
  364. /* Set the sensitivity of the InputMethod Title Box back to True. */
  365. _DtI18nSetSensitiveImTB(env, True);
  366. _DtI18nErrorDialog(ErrTimeOut) ;
  367. }
  368. static void
  369. ReadPipe (
  370. XtPointer client_data,
  371. int *fd,
  372. XtInputId *id )
  373. {
  374. char buf[512];
  375. int i, nbytes;
  376. int status = NoError;
  377. static char * savebuf = NULL;
  378. static int savebuf_bytes = 0 ;
  379. I18nEnv *env = (I18nEnv *) client_data;
  380. nbytes = read (*fd, buf, 512);
  381. if (nbytes > 0) {
  382. savebuf = XtRealloc(savebuf, savebuf_bytes + nbytes);
  383. memcpy(savebuf+savebuf_bytes, buf, nbytes);
  384. savebuf_bytes += nbytes ;
  385. } else {
  386. if (savebuf)
  387. *(savebuf + savebuf_bytes) = '\0';
  388. status = ProcessBuf(savebuf, client_data);
  389. savebuf_bytes = 0;
  390. if (savebuf) {
  391. XtFree(savebuf);
  392. savebuf = NULL;
  393. }
  394. pclose(env->pipe_info->pipe);
  395. XtRemoveInput(*id);
  396. /* Set the sensitivity of the InputMethod Title Box back to True. */
  397. _DtI18nSetSensitiveImTB(env, True);
  398. /* Remove timer too */
  399. XtRemoveTimeOut(env->pipe_info->timer_id);
  400. if (status != NoError)
  401. _DtI18nErrorDialog(status) ;
  402. }
  403. }
  404. static int
  405. ProcessBuf(
  406. char *savebuf,
  407. I18nEnv *env )
  408. {
  409. int i, n = 0;
  410. int ret = NoError;
  411. ImsEnt *ims_ent;
  412. char * filename, * label ;
  413. /* The dtimsstart execution gave back an empty buffer */
  414. if (!savebuf)
  415. return(ErrRemoteFailed);
  416. /* parse savebuf: The lines have the following syntax:
  417. * [#](im_filename) im_label or
  418. * [#]im_filename im_label
  419. * where "#" if present means the default IM,
  420. * im_filename is the file name where all the IM info is stored,
  421. * im_label is the label to present to the user.
  422. */
  423. while (*savebuf) {
  424. /* We're at the beginning of a new line */
  425. /* grow the array */
  426. env->ims_sel->ims_list =
  427. (ImsEnt *) XtRealloc((char *) env->ims_sel->ims_list,
  428. sizeof(ImsEnt)*(n+1));
  429. ims_ent = &(env->ims_sel->ims_list[n]);
  430. /* Look to see if this is the default one. */
  431. if (*savebuf == '#') {
  432. ims_ent->im_default = 1;
  433. savebuf++;
  434. } else
  435. ims_ent->im_default = 0;
  436. /* Look to see if it is not reachable. */
  437. if (*savebuf == '(') {
  438. ims_ent->inactive = 1;
  439. savebuf++ ;
  440. } else
  441. ims_ent->inactive = 0 ;
  442. /* Mark begin of im filename */
  443. filename = savebuf ;
  444. /* Go to the end of it */
  445. while (!isspace(*savebuf++)) ;
  446. /* We're on the first space, mark the end of the im filename,
  447. * don't forget to count the ')' if inactive. */
  448. *(savebuf - ims_ent->inactive - 1) = '\0';
  449. /* Mark the beginning of the im name */
  450. label = savebuf ;
  451. while (*savebuf != '\n') savebuf++ ;
  452. /* mark the end */
  453. *savebuf = '\0';
  454. savebuf++;
  455. /* copy the string data here. it's gonna be freed after that */
  456. ims_ent->im_name = XtNewString(filename) ;
  457. ims_ent->im_label = XtNewString(label) ;
  458. n++;
  459. }
  460. env->ims_sel->ims_list_size = n;
  461. return(ret);
  462. }
  463. static int
  464. CheckHostname(
  465. I18nEnv *env,
  466. char *hostname
  467. )
  468. {
  469. int host_type = HOST_UNKNOWN;
  470. char *local = env->user_env->localhostname;
  471. struct hostent *hp;
  472. unsigned long addr = 0L;
  473. static unsigned long local_addr = 0L;
  474. if (!hostname || !*hostname || strcasecmp(hostname, "local") == 0
  475. || strcasecmp(hostname, local) == 0) {
  476. host_type = HOST_LOCAL;
  477. } else { /* compare inet address */
  478. if (!local_addr) {
  479. if ((hp = gethostbyname(local)) && hp->h_addrtype == AF_INET) {
  480. local_addr = *((unsigned long *) hp->h_addr_list[0]);
  481. } else {
  482. host_type = HOST_REMOTE;
  483. }
  484. }
  485. if (host_type == HOST_UNKNOWN) {
  486. if ((hp = gethostbyname(hostname)) && hp->h_addrtype == AF_INET) {
  487. addr = *((unsigned long *) hp->h_addr_list[0]);
  488. if (addr == local_addr)
  489. host_type = HOST_LOCAL;
  490. else
  491. host_type = HOST_REMOTE;
  492. } else {
  493. host_type = HOST_UNKNOWN;
  494. }
  495. }
  496. }
  497. return host_type;
  498. }
  499. /*+++++++++++++++++++++++++++++++++++++++*/
  500. /* _DtI18nWriteImSelectionFile - writes */
  501. /* the values saved in the FileSel */
  502. /* structure to the IMS Selection File. */
  503. /*+++++++++++++++++++++++++++++++++++++++*/
  504. int
  505. _DtI18nWriteImSelectionFile(
  506. I18nEnv *env
  507. )
  508. {
  509. FILE *fp;
  510. /* Look if this file is writable */
  511. if ((fp = fopen(env->file_sel->fname, "w")) == NULL)
  512. return ErrFileCreate;
  513. /* Write the select mode */
  514. PutSelectMode(fp, env->file_sel->start_mode);
  515. /* Write the IM selected if not null */
  516. PutImsName(fp, env->file_sel->im_name);
  517. /* Write the hostname if not null */
  518. PutHostname(fp, env->file_sel->hostname);
  519. /* Close the file */
  520. fclose(fp);
  521. return NoError;
  522. }
  523. static void
  524. PutSelectMode(
  525. FILE *fp,
  526. int start_mode
  527. )
  528. {
  529. char val[20];
  530. sprintf(val, "%ld", (long)start_mode);
  531. PutSelectionEntry(fp, STR_SELECTMODE, val);
  532. }
  533. static void
  534. PutImsName(
  535. FILE *fp,
  536. char *im_name
  537. )
  538. {
  539. char *valp;
  540. if ((valp = im_name) && *valp)
  541. PutSelectionEntry(fp, STR_IMSNAME, valp);
  542. }
  543. static void
  544. PutHostname(
  545. FILE *fp,
  546. char *hostname
  547. )
  548. {
  549. char *valp;
  550. if ((valp = hostname) && *valp)
  551. PutSelectionEntry(fp, STR_HOSTNAME, valp);
  552. }
  553. static void
  554. PutSelectionEntry(
  555. FILE *fp,
  556. char *tag,
  557. char *value
  558. )
  559. {
  560. fprintf(fp, "%c%s%c\t%s\n", STR_PREFIX_CHAR, tag, TAG_END_CHAR, value);
  561. }