file.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  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. /* @(#)$XConsortium: file.c /main/7 1996/05/07 13:59:24 drk $ */
  24. #include "xims.h"
  25. #include <fcntl.h>
  26. #include <sys/stat.h>
  27. /* local func */
  28. static void put_selection_entry(FILE *fp, int ent_type, bool is_valid, char *val, char *val2);
  29. static void put_ims_conf(/* fp, sel */);
  30. static void put_select_mode(/* fp, select_mode */);
  31. static void put_selection_header(/* fp */);
  32. static void put_selection_sep(/* fp */);
  33. static int user_selection_fname(/* buf, buf_len, dpy_specific */);
  34. static char *SelectFileFormat = NULL;
  35. static bool cmdconf_initialized = False;
  36. int create_xims_dir(void)
  37. {
  38. int ret = NoError;
  39. char path[MAXPATHLEN];
  40. /* if (!userEnv.homedir || !Conf.userImsDir) return ErrNoHome; */
  41. /* get_user_environ() & read_cmd_conf() must be successfully */
  42. /* executed prior to calling this function */
  43. /* check directory */
  44. expand_string("%S", path, MAXPATHLEN, 0);
  45. if (!make_user_dir(path)) {
  46. setErrFile(path);
  47. expand_string("%U", path, MAXPATHLEN, 0);
  48. if (!make_user_dir(path))
  49. return ErrDirCreate;
  50. expand_string("%S", path, MAXPATHLEN, 0);
  51. if (!make_user_dir(path))
  52. return ErrDirCreate;
  53. }
  54. #if 0
  55. expand_string("%T", path, MAXPATHLEN, 0);
  56. if (!make_user_dir(path)) {
  57. /* setErrFile(path); return ErrDirCreate; */ /* ignore */
  58. }
  59. #endif
  60. if (OpMode == MODE_START) {
  61. ret = init_log_file(Opt.LogPath, True);
  62. if (ret != NoError && Opt.LogPath) /* try default log file */
  63. ret = init_log_file(NULL, True);
  64. if (ret != NoError) /* try alternate log file */
  65. ret = init_log_file(ALT_LOGPATH, True);
  66. DPR(("Opt.LogPath='%s'\n", Opt.LogPath));
  67. }
  68. return ret;
  69. }
  70. int init_log_file(char *org_path, int check_size)
  71. {
  72. char path[MAXPATHLEN];
  73. bool log_exists = False;
  74. int fd;
  75. struct stat stb;
  76. /* check log file */ /* if not writable, ims execution will abort */
  77. if (!org_path) org_path = DEFAULT_LOGPATH;
  78. expand_string(org_path, path, MAXPATHLEN, 0);
  79. log_exists = stat(path, &stb) == 0; /* access(path, F_OK) == 0; */
  80. if (log_exists) {
  81. if (access(path, W_OK) == -1
  82. || stat(path, &stb) == -1 || !S_ISREG(stb.st_mode))
  83. goto _err;
  84. /* rename log file if its size is larger than MAX_LOGSIZE (20 KB) */
  85. if (check_size && stb.st_size > MAX_LOGSIZE) {
  86. char save_path[MAXPATHLEN], *bp;
  87. bp = strcpyx(save_path, path); strcpyx(bp, ".old");
  88. if (rename(path, save_path) == 0) {
  89. log_exists = False;
  90. DPR(("init_log_file(): %s renamed.\n", path));
  91. } else {
  92. DPR(("init_log_file(): rename(to: %s) failed.\n", save_path));
  93. }
  94. }
  95. }
  96. if (!log_exists) {
  97. if ((fd = creat(path, 0666)) == -1)
  98. goto _err;
  99. (void) close(fd);
  100. }
  101. Opt.LogPath = NEWSTR(path);
  102. return NoError;
  103. _err:
  104. if (Verbose > 1) perror(path);
  105. setErrFile(path);
  106. return ErrFileCreate;
  107. }
  108. int set_errorlog(char *path)
  109. {
  110. int fd;
  111. /* if (!path) return; */
  112. (void) make_user_dir(dirname(path));
  113. fd = open(Opt.LogPath, O_WRONLY|O_CREAT|O_APPEND, 0666);
  114. if (fd >= 0) {
  115. if (dup2(fd, 2) >= 0) {
  116. /* LogFp = stderr; */
  117. return NoError;
  118. }
  119. close(fd);
  120. }
  121. if (Verbose > 1) perror(path);
  122. setErrFile(path);
  123. return ErrFileCreate;
  124. }
  125. int read_cmd_conf(void)
  126. {
  127. char buf[MAXPATHLEN];
  128. CmdConf *conf = &Conf;
  129. char *conf_dir, *path;
  130. char *p, *lp, *valp;
  131. int line_num, num_alias;
  132. DtEnv *dt;
  133. RemoteEnv *remote;
  134. FILE *fp;
  135. # ifdef old_hpux
  136. VueEnv *vue;
  137. LocaleAlias *tmp_alias[MAXIMSENT], *ap;
  138. # endif /* old_hpux */
  139. conf_dir = DTIMS_CONFDIR;
  140. if (!(path = Opt.ConfPath) || !*path) {
  141. if (!(path = getenv("DTIMS_STARTCONF")) || !*path) {
  142. if ((p = getenv("DTIMS_CONFDIR")) && *p)
  143. conf_dir = p;
  144. snprintf(path = buf, sizeof(buf), "%s/%s", conf_dir, DTIMS_CONFFILE);
  145. }
  146. }
  147. DPR3(("read_cmd_conf(): path=%s\n", path));
  148. if ((fp = fopen(path, "r")) == NULL) {
  149. DPR3(("\tcannot open '%s'\n", path));
  150. #ifdef DEBUG2
  151. DPR(("cannot open '%s' -- continue with default config\n", path));
  152. goto _default;
  153. #else
  154. setErrFile(path);
  155. return ErrFileOpen;
  156. #endif
  157. }
  158. remote = conf->remote = ALLOC(1, RemoteEnv);
  159. remote->disabled = remote->useRemsh = False;
  160. remote->timeout = REMOTE_TIMEOUT;
  161. remote->passEnv = NULL;
  162. num_alias = 0;
  163. start_tag_line(path);
  164. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  165. if (!valp) {
  166. DPR3(("\t[line=%d] no value for '%s'\n", line_num, lp));
  167. continue;
  168. }
  169. if (strncmp(lp, "Ims", 3) == 0) {
  170. p = lp + 3;
  171. if (strncmp(p, "ConfigDir", 4) == 0) {
  172. RENEWSTR(conf->imsConfDir, valp);
  173. } else if (strncmp(p, "AppDefDir", 4) == 0) {
  174. RENEWSTR(conf->imsAppDir, valp);
  175. } else if (strncmp(p, "LogDir", 4) == 0) {
  176. RENEWSTR(conf->imsLogDir, valp);
  177. } else if (strncmp(p, "LogFile", 4) == 0) {
  178. RENEWSTR(conf->imsLogFile, valp);
  179. } else if (strncmp(p, "DirName", 3) == 0) {
  180. RENEWSTR(conf->imsDir, valp);
  181. } else
  182. goto _inv;
  183. } else if (strncmp(lp, "User", 4) == 0) {
  184. p = lp + 4;
  185. if (strncmp(p, "ImsDir", 4) == 0) {
  186. RENEWSTR(conf->userImsDir, valp);
  187. } else if (strncmp(p, "TmpDir", 4) == 0) {
  188. RENEWSTR(conf->userTmpDir, valp);
  189. } else if (strncmp(p, "AltTmpDir", 3) == 0) {
  190. RENEWSTR(conf->userAltDir, valp);
  191. } else
  192. goto _inv;
  193. } else if (strncmp(lp, "Dt", 2) == 0) {
  194. p = lp + 2;
  195. if (!conf->dt) dt = conf->dt = ALLOC(1, DtEnv);
  196. if (strncmp(p, "ConfigDir", 4) == 0) {
  197. RENEWSTR(dt->confDir, valp);
  198. } else if (strncmp(p, "UserDir", 5) == 0) {
  199. RENEWSTR(dt->userDir, valp);
  200. } else if (strncmp(p, "ResourcePath", 4) == 0) {
  201. RENEWSTR(dt->resPath, valp);
  202. } else
  203. goto _inv;
  204. } else if (strncmp(lp, "ImXmod.", 7) == 0) {
  205. p = lp + 7;
  206. if (strncmp(p, "XIM", 3) == 0) {
  207. RENEWSTR(conf->xmod[Proto_XIM], valp);
  208. } else if (strncmp(p, "Ximp", 4) == 0) {
  209. RENEWSTR(conf->xmod[Proto_Ximp], valp);
  210. } else if (strncmp(p, "Xsi", 3) == 0) {
  211. RENEWSTR(conf->xmod[Proto_Xsi], valp);
  212. # ifdef old_hpux
  213. } else if (strncmp(p, "Xhp", 3) == 0) {
  214. RENEWSTR(conf->xmod[Proto_Xhp], valp);
  215. # endif /* old_hpux */
  216. } else if (strncmp(p, "None", 3) == 0) {
  217. RENEWSTR(conf->xmod[Proto_None], valp);
  218. } else
  219. goto _inv;
  220. } else if (strncmp(lp, "ImAtom.", 7) == 0) {
  221. p = lp + 7;
  222. if (strncmp(p, "XIM", 3) == 0) {
  223. RENEWSTR(conf->atom[Proto_XIM], valp);
  224. } else if (strncmp(p, "Ximp", 4) == 0) {
  225. RENEWSTR(conf->atom[Proto_Ximp], valp);
  226. } else if (strncmp(p, "Xsi", 3) == 0) {
  227. RENEWSTR(conf->atom[Proto_Xsi], valp);
  228. # ifdef old_hpux
  229. } else if (strncmp(p, "Xhp", 3) == 0) {
  230. RENEWSTR(conf->atom[Proto_Xhp], valp);
  231. # endif /* old_hpux */
  232. } else if (strncmp(p, "None", 3) == 0) {
  233. RENEWSTR(conf->atom[Proto_None], valp);
  234. } else
  235. goto _inv;
  236. } else if (strncmp(lp, "Action.", 7) == 0) {
  237. p = lp + 7;
  238. if (strncmp(p, "GetRemoteConf", 8) == 0) {
  239. RENEWSTR(conf->action[ACT_GETREMCONF], valp);
  240. } else if (strncmp(p, "RunRemoteIMs", 8) == 0) {
  241. RENEWSTR(conf->action[ACT_RUNREMIMS], valp);
  242. } else
  243. goto _inv;
  244. } else if (strncmp(lp, "Remote", 6) == 0) {
  245. p = lp + 6;
  246. if (strncmp(p, "Disabled", 3) == 0) {
  247. remote->disabled = str_to_bool(valp, False);
  248. } else if (strncmp(p, "UseRemsh", 4) == 0) {
  249. remote->useRemsh = str_to_bool(valp, False);
  250. } else if (strncmp(p, "Timeout", 3) == 0) {
  251. int n = 0;
  252. if (str_to_int(valp, &n) && n >= 0)
  253. remote->timeout = n;
  254. } else if (strncmp(p, "Environment", 3) == 0) {
  255. RENEWSTR(remote->passEnv, valp);
  256. } else
  257. goto _inv;
  258. # ifdef old_hpux
  259. } else if (strncmp(lp, "Vue", 3) == 0) {
  260. p = lp + 3;
  261. if (!conf->vue) vue = conf->vue = ALLOC(1, VueEnv);
  262. if (strncmp(p, "ConfigDir", 4) == 0) {
  263. RENEWSTR(vue->confDir, valp);
  264. } else if (strncmp(p, "UserDir", 5) == 0) {
  265. RENEWSTR(vue->userDir, valp);
  266. } else if (strncmp(p, "UseLiteFile", 5) == 0) {
  267. RENEWSTR(vue->uselite, valp);
  268. } else if (strncmp(p, "LiteResourcePath", 5) == 0) {
  269. RENEWSTR(vue->litePath, valp);
  270. } else if (strncmp(p, "ResourcePath", 5) == 0) {
  271. RENEWSTR(vue->resPath, valp);
  272. } else
  273. goto _inv;
  274. } else if (strncmp(lp, "LocaleAlias", 6) == 0) {
  275. ap = ALLOC(1, LocaleAlias);
  276. p = valp; cut_field(valp);
  277. ap->name = NEWSTR(p);
  278. ap->aliases = NEWSTR(valp);
  279. tmp_alias[num_alias++] = ap;
  280. } else if (strncmp(lp, "XhpLocales", 3) == 0) {
  281. int idx = 0;
  282. p = strrchr(lp, '.');
  283. if (!p) continue; /* invalid */
  284. switch (p[1]) {
  285. case 'J': idx = XHP_JPN; break;
  286. case 'K': idx = XHP_KOR; break;
  287. case 'C': idx = XHP_CHS; break;
  288. case 'T': idx = XHP_CHT; break;
  289. default: goto _inv;
  290. }
  291. if (!conf->xhp)
  292. conf->xhp = ALLOC(XHP_LANG_NUM, XhpLocale);
  293. else if (conf->xhp[idx].locales) {
  294. FREE(conf->xhp[idx].locales);
  295. }
  296. conf->xhp[idx].type = p[1];
  297. conf->xhp[idx].locales = NEWSTR(valp);
  298. # endif /* old_hpux */
  299. } else {
  300. _inv:
  301. DPR(("\t[line=%d] invalid entry '%s'\n", line_num, lp));
  302. }
  303. }
  304. fclose(fp);
  305. # ifdef old_hpux
  306. if (num_alias > 0) {
  307. conf->alias = ALLOC(num_alias + 1, LocaleAlias *);
  308. memcpy((void *)conf->alias, (void *)tmp_alias,
  309. num_alias*sizeof(LocaleAlias *));
  310. conf->alias[num_alias] = (LocaleAlias *)0;
  311. }
  312. # endif /* old_hpux */
  313. /* if (remote->disabled) FREE(remote->passEnv); */
  314. _default:
  315. /* set default value unless set */
  316. if (!conf->imsConfDir) conf->imsConfDir = NEWSTR(conf_dir);
  317. if (!conf->imsAppDir) conf->imsAppDir = NEWSTR(DTIMS_APPDIR);
  318. if (!conf->imsLogDir) conf->imsLogDir = NEWSTR(DTIMS_LOGDIR);
  319. if (!conf->imsLogFile) conf->imsLogFile = NEWSTR(DTIMS_LOGFILE);
  320. if (!conf->imsDir) conf->imsDir = NEWSTR(DTIMS_IMSDIR);
  321. if (!conf->userImsDir) conf->userImsDir = NEWSTR(DTIMS_USRIMSDIR);
  322. if (!conf->userTmpDir) conf->userTmpDir = NEWSTR(DTIMS_USRTMPDIR);
  323. if (!conf->userAltDir) conf->userAltDir = NEWSTR(DTIMS_USRALTDIR);
  324. if (!conf->dt) conf->dt = ALLOC(1, DtEnv);
  325. if (!conf->dt->confDir) conf->dt->confDir = NEWSTR(DT_CONFDIR);
  326. if (!conf->dt->userDir) conf->dt->userDir = NEWSTR(DT_USERDIR);
  327. # ifdef old_hpux
  328. if (!conf->vue) conf->vue = ALLOC(1, VueEnv);
  329. if (!conf->vue->confDir) conf->vue->confDir = NEWSTR(VUE_CONFDIR);
  330. if (!conf->vue->userDir) conf->vue->userDir = NEWSTR(VUE_USERDIR);
  331. # endif /* old_hpux */
  332. if (!conf->xmod[Proto_XIM]) conf->xmod[Proto_XIM] = NEWSTR(IM_XMOD_XIM);
  333. if (!conf->xmod[Proto_Ximp]) conf->xmod[Proto_Ximp] = NEWSTR(IM_XMOD_XIMP);
  334. if (!conf->xmod[Proto_Xsi]) conf->xmod[Proto_Xsi] = NEWSTR(IM_XMOD_XSI);
  335. if (!conf->atom[Proto_XIM]) conf->atom[Proto_XIM] = NEWSTR(IM_ATOM_XIM);
  336. if (!conf->atom[Proto_Ximp]) conf->atom[Proto_Ximp] = NEWSTR(IM_ATOM_XIMP);
  337. if (!conf->atom[Proto_Xsi]) conf->atom[Proto_Xsi] = NEWSTR(IM_ATOM_XSI);
  338. /* default value of {xmod,atom}[Proto_None/Xhp] is NULL */
  339. if (!conf->action[ACT_GETREMCONF])
  340. conf->action[ACT_GETREMCONF] = NEWSTR(NAME_ACT_GETREMCONF);
  341. if (!conf->action[ACT_RUNREMIMS])
  342. conf->action[ACT_RUNREMIMS] = NEWSTR(NAME_ACT_RUNREMIMS);
  343. cmdconf_initialized = True;
  344. return NoError;
  345. }
  346. int expand_cmd_conf(void)
  347. {
  348. char **pp[20 + NUM_ACTIONS], *p, buf[BUFSIZ];
  349. int i, j, n;
  350. CmdConf *conf = &Conf;
  351. #define CHK_ADD(p) if (strchr(p, '%')) pp[n++] = &(p);
  352. #ifdef DEBUG
  353. if (DebugLvl > 1) { pr_CmdConf(); }
  354. #endif
  355. n = 0;
  356. CHK_ADD(conf->imsConfDir);
  357. CHK_ADD(conf->imsAppDir);
  358. CHK_ADD(conf->imsLogDir);
  359. CHK_ADD(conf->imsLogFile);
  360. CHK_ADD(conf->imsDir);
  361. CHK_ADD(conf->userImsDir)
  362. CHK_ADD(conf->userTmpDir)
  363. CHK_ADD(conf->userAltDir)
  364. for (j = 0; j < NUM_ACTIONS; j++) CHK_ADD(conf->action[j])
  365. if (conf->dt) {
  366. CHK_ADD(conf->dt->confDir)
  367. CHK_ADD(conf->dt->userDir)
  368. CHK_ADD(conf->dt->resPath)
  369. }
  370. # ifdef old_hpux
  371. if (conf->vue) {
  372. CHK_ADD(conf->vue->confDir)
  373. CHK_ADD(conf->vue->userDir)
  374. CHK_ADD(conf->vue->uselite)
  375. CHK_ADD(conf->vue->resPath)
  376. CHK_ADD(conf->vue->litePath)
  377. }
  378. # endif /* old_hpux */
  379. /* xmod[] & atom[] must not be expanded, since no ims selected */
  380. /* remote->* should be expanded at preparation of remote exec */
  381. #undef CHK_ADD
  382. for (i = j = 0; i < n; i++) {
  383. p = *(pp[i]);
  384. expand_string(*(pp[i]), buf, BUFSIZ, 0);
  385. #ifdef DEBUG
  386. if (strcmp(p, buf)) j++;
  387. #endif
  388. FREE(p);
  389. *(pp[i]) = NEWSTR(buf);
  390. }
  391. DPR(("expand_cmd_conf(): %d / %d entries modified\n", j, n));
  392. return n;
  393. }
  394. int read_imsconf(ImsConf *conf, char *ims_name, char *ims_fname)
  395. {
  396. int ret = NoError;
  397. char path[MAXPATHLEN];
  398. char *lp, *valp, *p;
  399. int len, n, line_num;
  400. FILE *fp;
  401. if (!ims_fname) ims_fname = ims_name;
  402. len = expand_string("%I/", path, MAXPATHLEN, 0);
  403. strcpyx(path + len, ims_fname);
  404. DPR3(("read_imsconf(%s): path=%s\n", ims_name, path));
  405. CLR(conf, ImsConf);
  406. if ((fp = fopen(path, "r")) == NULL) {
  407. DPR3(("\tcannot open '%s'\n", path));
  408. return ErrNoImsConf;
  409. }
  410. start_tag_line(path);
  411. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  412. if (!valp) {
  413. DPR3(("\t[line=%d] no value for '%s'\n", line_num, lp));
  414. continue;
  415. }
  416. /* valp = trim_line(valp); */
  417. /* TYP_NAME */
  418. if (strcmp(lp, "name") == 0)
  419. ; /* conf->name = NEWSTR(valp); */
  420. else if (strcmp(lp, "server_name") == 0) {
  421. if (p = strchr(valp, ',')) { /* contain secondary names */
  422. conf->servername2 = NEWSTR(valp); /* save full name */
  423. *p = 0;
  424. }
  425. conf->servername = NEWSTR(valp); /* save primary name only */
  426. } else if (strcmp(lp, "class_name") == 0)
  427. conf->classname = NEWSTR(valp);
  428. else if (strcmp(lp, "property") == 0)
  429. conf->property = NEWSTR(valp);
  430. /* TYP_PATH */
  431. else if (strcmp(lp, "cmd_path") == 0)
  432. conf->cmd_path = NEWSTR(valp);
  433. /* TYP_STRING */
  434. else if (strcmp(lp, "cmd_param") == 0)
  435. conf->cmd_param = NEWSTR(valp);
  436. /* TYP_NUMERIC */
  437. else if (strcmp(lp, "chk_timeout") == 0) {
  438. if (str_to_int(valp, &n))
  439. conf->timeout = n;
  440. } else if (strcmp(lp, "chk_interval") == 0) {
  441. if (str_to_int(valp, &n))
  442. conf->interval = n;
  443. }
  444. /* TYP_BOOL */
  445. #define SET_FLAG(f) \
  446. (str_to_bool(valp, False) ? (conf->flags |= (f)) : (conf->flags &= ~(f)))
  447. else if (strcmp(lp, "no_server") == 0)
  448. SET_FLAG(F_NO_SERVER);
  449. else if (strcmp(lp, "no_remote") == 0)
  450. SET_FLAG(F_NO_REMOTE);
  451. else if (strcmp(lp, "no_option") == 0)
  452. SET_FLAG(F_NO_OPTION);
  453. # ifdef old_hpux
  454. else if (strcmp(lp, "try_connect") == 0)
  455. SET_FLAG(F_TRY_CONNECT);
  456. # endif /* old_hpux */
  457. else if (strcmp(lp, "has_window") == 0)
  458. SET_FLAG(F_HAS_WINDOW);
  459. #undef SET_FLAG
  460. /* TYP_NAMELIST */
  461. else if (strcmp(lp, "env_set") == 0)
  462. conf->env_set = NEWSTR(valp);
  463. else if (strcmp(lp, "env_unset") == 0)
  464. conf->env_unset = NEWSTR(valp);
  465. else if (strcmp(lp, "env_pass") == 0)
  466. conf->env_pass = NEWSTR(valp);
  467. else if (strcmp(lp, "protocols") == 0)
  468. conf->protocols = parse_protolist(valp);
  469. else {
  470. DPR3(("\t[line=%d] invalid entry '%s'\n", line_num, lp));
  471. }
  472. }
  473. fclose(fp);
  474. ret = check_ims_conf(conf, ims_name);
  475. if (ret != NoError)
  476. setErrFile(path);
  477. return ret;
  478. }
  479. int check_ims_conf(ImsConf *ims, char *ims_name)
  480. {
  481. int ret = NoError;
  482. char *missing_entry = NULL;
  483. if (strcmp(ims_name, NAME_NONE) == 0) return NoError;
  484. if ((ims->cmd_path) && strcmp(ims->cmd_path, NAME_BUILTIN) == 0) {
  485. ims->flags |= (F_BUILTIN | F_NO_SERVER | F_NO_REMOTE | F_NO_OPTION);
  486. ims->flags &= ~F_TRY_CONNECT;
  487. FREE(ims->cmd_path);
  488. }
  489. /* check indispensable entry */
  490. if (!ims->cmd_path && !(ims->flags & F_BUILTIN)) {
  491. missing_entry = "cmd_path";
  492. DPR(("read_imsconf(%s): no '%s' entry\n", ims_name, missing_entry));
  493. }
  494. if (!ims->servername) {
  495. DPR(("read_imsconf(%s): no '%s' entry\n", ims_name, missing_entry));
  496. missing_entry = "servername";
  497. }
  498. if (!ims->protocols) {
  499. DPR(("read_imsconf(%s): no '%s' entry\n", ims_name, missing_entry));
  500. missing_entry = "protocols";
  501. }
  502. if (missing_entry) {
  503. setErrArg1(missing_entry);
  504. ret = ErrMissEntry;
  505. }
  506. return ret;
  507. }
  508. int read_localeconf(ImsList *list, char *locale_name)
  509. {
  510. char path[MAXPATHLEN];
  511. char *lp, *valp, *pp;
  512. char *def_name;
  513. int sel_mode;
  514. int len, line_num, num_ent;
  515. ImsEnt *ent, *etmp[MAXIMSENT];
  516. FILE *fp;
  517. UserEnv *uenv = &userEnv;
  518. len = expand_string("%I/", path, MAXPATHLEN, 0);
  519. if (!locale_name || !*locale_name) {
  520. locale_name = uenv->real_locale ? uenv->real_locale : uenv->locale;
  521. }
  522. strcpyx(path + len, locale_name);
  523. DPR3(("read_localeconf(%s): path=%s\n", locale_name, path));
  524. CLR(list, ImsList);
  525. list->status = NoError;
  526. list->default_idx = -1;
  527. list->def_selmode = SEL_MODE_NOAUTO;
  528. if ((fp = fopen(path, "r")) == NULL) {
  529. DPR3(("\tcannot open '%s'\n", path));
  530. list->status = ErrNoLocaleConf;
  531. return ErrNoLocaleConf;
  532. }
  533. def_name = NULL;
  534. sel_mode = SEL_MODE_NONE;
  535. num_ent = 0;
  536. start_tag_line(path);
  537. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  538. if (lp[0] == STR_PREFIX_CHAR) {
  539. if (!valp) {
  540. DPR3(("\t[line=%d] no value for '%s'\n", line_num, lp));
  541. continue;
  542. }
  543. if (strncmp(lp + 1, STR_DEFAULTIMS, 3) == 0) {
  544. RENEWSTR(def_name, valp);
  545. } else if (strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
  546. int m = SEL_MODE_NONE;
  547. if (str_to_int(valp, &m) && m >= 0)
  548. sel_mode = m;
  549. } else {
  550. DPR2(("\t[line=%d] invalid entry '%s'\n", line_num, lp));
  551. }
  552. } else { /* ims name entry */
  553. if (num_ent >= MAXIMSENT) {
  554. DPR(("\ttoo many IMS defined: '%s' ignored\n", lp));
  555. break;
  556. }
  557. ent = ALLOC(1, ImsEnt);
  558. if (pp = strchr(lp, STR_PREFIX_CHAR)) {
  559. *pp++ = 0;
  560. if (*pp)
  561. ent->fname = NEWSTR(pp);
  562. else {
  563. DPR(("\tempty file name for '%s' -- ignored\n", lp));
  564. }
  565. }
  566. ent->name = NEWSTR(lp);
  567. if (valp) ent->label = NEWSTR(valp);
  568. etmp[num_ent++] = ent;
  569. }
  570. }
  571. fclose(fp);
  572. if (num_ent) {
  573. list->num_ent = num_ent;
  574. list->elist = ALLOC(num_ent, ImsEnt *);
  575. memcpy((void *)list->elist, (void *)etmp, num_ent*sizeof(ImsEnt *));
  576. list->def_selmode =
  577. (sel_mode != SEL_MODE_NONE) ? sel_mode : SEL_MODE_NOAUTO;
  578. if (def_name) {
  579. int i;
  580. for (i = 0; i < list->num_ent; i++)
  581. if (strcmp(def_name, list->elist[i]->name) == 0) {
  582. list->default_idx = i;
  583. break;
  584. }
  585. FREE(def_name);
  586. }
  587. }
  588. #ifdef DEBUG
  589. if (DebugLvl > 2) pr_ImsList(list);
  590. #endif
  591. return list->status;
  592. }
  593. int read_user_selection(FileSel **fselp, char *locale_name)
  594. {
  595. char path[MAXPATHLEN];
  596. int ret;
  597. int dpy_specific;
  598. FILE *fp;
  599. FileSel *fsel;
  600. dpy_specific = user_selection_fname(path, MAXPATHLEN, -1);
  601. DPR3(("read_user_selection(): path=%s\n", path));
  602. if ((fp = fopen(path, "r")) == NULL) {
  603. DPR3(("\tcannot open '%s'\n", path));
  604. /* *fselp = (FileSel *) 0; */
  605. return ErrNoSelectionFile;
  606. }
  607. fsel = ALLOC(1, FileSel);
  608. start_tag_line(path);
  609. ret = read_selection_file(fsel, fp);
  610. fclose(fp);
  611. fsel->dpy_specific = dpy_specific;
  612. fsel->real_fname = NEWSTR(locale_name);
  613. *fselp = fsel;
  614. return NoError;
  615. }
  616. int read_selection_file(FileSel *fsel, FILE *fp)
  617. {
  618. char *lp, *valp, *vp, *p;
  619. int i, nopts, line_num;
  620. int select_mode, iconic;
  621. char *imsname, *hostname, *com_opt;
  622. ImsOpt *opts[MAXIMSENT], *op;
  623. select_mode = SEL_MODE_NONE;
  624. imsname = hostname = com_opt = NULL;
  625. iconic = -1;
  626. nopts = 0;
  627. opts[0] = (ImsOpt *)NULL;
  628. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  629. if (!valp) {
  630. DPR3(("\t[line=%d] no value for '%s'\n", line_num, lp));
  631. continue;
  632. }
  633. if (lp[0] != STR_PREFIX_CHAR) {
  634. DPR3(("\t[line=%d] invalid name '%s'\n", line_num, lp));
  635. continue;
  636. }
  637. if (strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
  638. if (str_to_int(valp, &i) && i >= 0)
  639. select_mode = i;
  640. } else if (strncmp(lp + 1, STR_IMSNAME, 4) == 0) {
  641. vp = valp; cut_field(valp);
  642. RENEWSTR(imsname, vp);
  643. } else if (strncmp(lp + 1, STR_HOSTNAME, 4) == 0) {
  644. vp = valp; cut_field(valp);
  645. FREE(hostname);
  646. if (strcmp(vp, NAME_LOCAL))
  647. hostname = NEWSTR(vp);
  648. } else if (strncmp(lp + 1, STR_ICONIC, 3) == 0) {
  649. if (*valp)
  650. iconic = str_to_bool(valp, False);
  651. } else if (strncmp(lp + 1, STR_IMSOPTION, 4) == 0) {
  652. if (p = strchr(lp + 1, STR_PREFIX_CHAR)) { /* indiv. opt */
  653. if (nopts >= MAXIMSENT) {
  654. DPR(("\t[line=%d] too many options - '%s' ignored\n",
  655. line_num, lp));
  656. continue;
  657. }
  658. if (!*(++p)) {
  659. DPR(("\t[line=%d] no ims name - '%s' ignored\n",
  660. line_num, lp));
  661. continue;
  662. }
  663. for (op = 0, i = 0; i < nopts; i++)
  664. if (strcmp(p, opts[i]->ims_name) == 0) {
  665. op = opts[i];
  666. FREE(op->ims_name);
  667. FREE(op->opt_str);
  668. break;
  669. }
  670. if (!op) {
  671. op = ALLOC(1, ImsOpt);
  672. opts[nopts++] = op;
  673. }
  674. op->ims_name = NEWSTR(p);
  675. op->opt_str = NEWSTR(valp);
  676. } else { /* common opt */
  677. RENEWSTR(com_opt, valp);
  678. }
  679. } else {
  680. DPR3(("\t[line=%d] unknown name '%s'\n", line_num, lp));
  681. }
  682. }
  683. fsel->name = imsname;
  684. fsel->hostname = hostname;
  685. fsel->com_opt = com_opt;
  686. fsel->select_mode = select_mode;
  687. fsel->iconic = iconic;
  688. if (nopts > 0) {
  689. fsel->opts = ALLOC(nopts + 1, ImsOpt *);
  690. COPY(fsel->opts, opts, nopts, ImsOpt *);
  691. fsel->opts[nopts] = (ImsOpt *)0;
  692. }
  693. return NoError;
  694. }
  695. int save_user_selection(UserSelection *sel, char *locale_name)
  696. {
  697. char path[MAXPATHLEN];
  698. int dpy_specific;
  699. FILE *fp;
  700. FileSel *fsel = sel->fsel;
  701. dpy_specific = user_selection_fname(path, MAXPATHLEN, -1);
  702. if ((fp = fopen(path, "w")) == NULL) {
  703. DPR(("\tcannot create '%s'\n", path));
  704. setErrFile(path);
  705. return ErrFileCreate;
  706. }
  707. put_selection_header(fp);
  708. if (fsel)
  709. put_select_mode(fp, fsel->select_mode);
  710. put_ims_conf(fp, sel);
  711. put_selection_sep(fp);
  712. fclose(fp);
  713. DPR3(("save_user_selection(): '%s' saved on '%s'\n", sel->name, path));
  714. return NoError;
  715. }
  716. #define _SELECTMODE 0
  717. #define _IMSNAME 1
  718. #define _HOSTNAME 2
  719. #define _ICONIC 3
  720. #define _IMSOPTION 4
  721. #define _IMSOPT2 5
  722. static void put_selection_entry(FILE *fp, int ent_type, bool is_valid, char *val, char *val2)
  723. {
  724. char *name = NULL;
  725. switch (ent_type) {
  726. case _SELECTMODE: name = STR_SELECTMODE; break;
  727. case _IMSNAME: name = STR_IMSNAME; break;
  728. case _HOSTNAME: name = STR_HOSTNAME; break;
  729. case _ICONIC: name = STR_ICONIC; break;
  730. case _IMSOPT2:
  731. case _IMSOPTION: name = STR_IMSOPTION; break;
  732. /* default: is_valid = False; */
  733. }
  734. if (!is_valid) putc(COMMENT_CHAR, fp);
  735. if (ent_type == _IMSOPT2)
  736. fprintf(fp, "%c%s%c%s%c\t%s\n", STR_PREFIX_CHAR, name,
  737. STR_PREFIX_CHAR, val2, TAG_END_CHAR, val);
  738. else
  739. fprintf(fp, "%c%s%c\t%s\n", STR_PREFIX_CHAR, name, TAG_END_CHAR, val);
  740. }
  741. static void put_ims_conf(FILE *fp, UserSelection *sel)
  742. {
  743. char *valp, val[20];
  744. if ((valp = sel->name) && *valp)
  745. put_selection_entry(fp, _IMSNAME, True, valp, NULL);
  746. else {
  747. DPR(("put_ims_conf(): no ims name\n"));
  748. if (sel->fsel && (valp = sel->fsel->name) && *valp)
  749. put_selection_entry(fp, _IMSNAME, False, valp, NULL);
  750. }
  751. if ((valp = sel->hostname) && *valp)
  752. put_selection_entry(fp, _HOSTNAME, True, valp, NULL);
  753. else if (sel->fsel && (valp = sel->fsel->hostname) && *valp)
  754. put_selection_entry(fp, _HOSTNAME, False, valp, NULL);
  755. if (sel->iconic != -1) {
  756. sprintf(val, "%ld", (long)sel->iconic);
  757. put_selection_entry(fp, _ICONIC, True, val, NULL);
  758. }
  759. if (sel->fsel && (valp = sel->fsel->com_opt) && *valp) {
  760. bool opt_valid = True;
  761. #if 0
  762. opt_valid = !sel->fsel->name || strcmp(sel->name, sel->fsel->name) == 0;
  763. #endif
  764. put_selection_entry(fp, _IMSOPTION, opt_valid, valp, NULL);
  765. }
  766. if (sel->fsel && sel->fsel->opts) {
  767. ImsOpt **op;
  768. for (op = sel->fsel->opts; *op; op++)
  769. put_selection_entry(fp, _IMSOPT2, True,
  770. (*op)->opt_str, (*op)->ims_name);
  771. }
  772. }
  773. static void put_select_mode(FILE *fp, int select_mode)
  774. {
  775. char val[20];
  776. if (select_mode != SEL_MODE_NOAUTO && select_mode != SEL_MODE_AUTO
  777. #ifdef SelectMode_ONCE
  778. && select_mode != SEL_MODE_ONCE
  779. #endif /* SelectMode_ONCE */
  780. )
  781. select_mode = SEL_MODE_NOAUTO;
  782. sprintf(val, "%ld", (long)select_mode);
  783. put_selection_entry(fp, _SELECTMODE, True, val, NULL);
  784. }
  785. static void put_selection_header(FILE *fp)
  786. {
  787. fprintf(fp, "%s %s\n", COMMENT_CHARS, ProgramRevision);
  788. if (SelectFileFormat)
  789. fprintf(fp, "%s%s\n", COMMENT_CHARS, SelectFileFormat);
  790. }
  791. static void put_selection_sep(FILE *fp)
  792. {
  793. fprintf(fp, "%s\n", COMMENT_CHARS);
  794. }
  795. int get_select_mode(void)
  796. {
  797. char path[MAXPATHLEN];
  798. char *lp, *valp;
  799. int select_mode, dpy_specific;
  800. int n, line_num;
  801. FILE *fp;
  802. select_mode = SEL_MODE_NONE;
  803. dpy_specific = user_selection_fname(path, MAXPATHLEN, -1);
  804. DPR3(("get_select_mode(): path=%s\n", path));
  805. if ((fp = fopen(path, "r")) == NULL) {
  806. DPR3(("\tcannot open '%s'\n", path));
  807. return select_mode;
  808. }
  809. start_tag_line(path);
  810. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  811. if (lp[0] == STR_PREFIX_CHAR
  812. && strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
  813. if (str_to_int(valp, &n))
  814. select_mode = n;
  815. }
  816. }
  817. fclose(fp);
  818. DPR3(("get_select_mode(%s): select_mode=%d\n",
  819. dpy_specific ? "dpy" : NULL, select_mode));
  820. return select_mode;
  821. }
  822. int set_select_mode(int cur_mode, int new_mode)
  823. {
  824. char path[MAXPATHLEN];
  825. int dpy_specific;
  826. FILE *fp;
  827. switch (new_mode) {
  828. case SEL_MODE_NOAUTO: break;
  829. case SEL_MODE_AUTO: break;
  830. #ifdef SelectMode_ONCE
  831. case SEL_MODE_ONCE: break;
  832. #endif /* SelectMode_ONCE */
  833. case SEL_MODE_NONE:
  834. default: new_mode = SEL_MODE_NOAUTO; break;
  835. }
  836. dpy_specific = user_selection_fname(path, MAXPATHLEN, -1);
  837. DPR3(("set_selection_mode(): path=%s\n", path));
  838. #if 0
  839. if (!make_user_dir(dirname(path))) {
  840. setErrFile(dirname(path));
  841. return ErrDirCreate;
  842. }
  843. #endif
  844. if ((fp = fopen(path, "r+")) == NULL) {
  845. DPR3(("\tcannot open '%s'\n", path));
  846. if ((fp = fopen(path, "w")) == NULL) {
  847. setErrFile(path);
  848. return ErrFileCreate;
  849. }
  850. cur_mode = SEL_MODE_NONE;
  851. }
  852. if (cur_mode == SEL_MODE_NONE) { /* append '@SelectMode' line */
  853. fseek(fp, 0, SEEK_END);
  854. put_select_mode(fp, new_mode);
  855. fclose(fp);
  856. } else {
  857. FILE *new_fp;
  858. char new_fname[MAXPATHLEN];
  859. char line_buf[BUFSIZ];
  860. char *lp, *valp;
  861. int n, line_num, mode_line;
  862. sprintf(new_fname, "%s,tmp", path);
  863. if (!(new_fp = fopen(new_fname, "w"))) {
  864. fclose(fp);
  865. DPR(("set_select_mode(): cannot create %s\n", new_fname));
  866. setErrFile(path);
  867. return ErrFileCreate;
  868. }
  869. line_num = mode_line = 0;
  870. while (fgets(lp = line_buf, BUFSIZ, fp)) {
  871. line_num++;
  872. skip_white(lp);
  873. if (*lp == STR_PREFIX_CHAR) {
  874. if (strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
  875. if (mode_line) continue; /* ignore this line */
  876. if (valp = strchr(lp, TAG_END_CHAR)) {
  877. valp++;
  878. skip_white(valp);
  879. if (str_to_int(valp, &n) && n == new_mode)
  880. mode_line = -1;
  881. }
  882. put_select_mode(new_fp, new_mode);
  883. mode_line = line_num;
  884. } else
  885. fputs(line_buf, new_fp);
  886. } else
  887. fputs(line_buf, new_fp);
  888. }
  889. if (!mode_line)
  890. put_select_mode(new_fp, new_mode);
  891. fclose(new_fp);
  892. fclose(fp);
  893. if (mode_line == -1) { /* not changed */
  894. (void) unlink(new_fname);
  895. } else {
  896. if (rename(new_fname, path) == -1) {
  897. setErrFile(path);
  898. return ErrFileCreate;
  899. }
  900. }
  901. (void) unlink(new_fname);
  902. }
  903. DPR2(("set_select_mode(%s): new_mode=%d <- %d\n",
  904. dpy_specific ? "dpy" : NULL, new_mode, cur_mode));
  905. return NoError;
  906. }
  907. static int user_selection_fname(char *buf, int buf_len, int dpy_specific)
  908. {
  909. int len;
  910. UserEnv *uenv = &userEnv;
  911. static bool real_done = False;
  912. if (Opt.UserPath) {
  913. strncpy(buf, Opt.UserPath, buf_len);
  914. buf[buf_len-1] = 0;
  915. dpy_specific = 0;
  916. } else {
  917. if (dpy_specific == -1) {
  918. len = expand_string("%S/%d", buf, buf_len, 0);
  919. dpy_specific = is_directory(buf, False) ? 1 : 0;
  920. }
  921. len = expand_string(dpy_specific ? "%S/%d/" : "%S/", buf, buf_len, 0);
  922. # ifdef old_hpux
  923. if (!real_done && uenv->real_locale) {
  924. real_done = True;
  925. strcpy(buf + len, uenv->real_locale);
  926. if (!is_readable(buf, True)) {
  927. bool rename_done = False;
  928. char buf2[MAXPATHLEN], *bp;
  929. strncpy(buf2, buf, len);
  930. bp = buf2 + len; *bp = 0;
  931. if (strcmp(uenv->locale, uenv->real_locale)) {
  932. strcpy(bp, uenv->locale);
  933. if (is_readable(buf2, False)) {
  934. rename_done = rename(buf2, buf) == 0;
  935. DPR(("user_selection_fname(): rename(%s, %s) %s\n",
  936. uenv->locale, uenv->real_locale,
  937. rename_done ? "OK" : "Failed"));
  938. }
  939. }
  940. if (uenv->locale_aliases) {
  941. char **ap;
  942. for (ap = uenv->locale_aliases; *ap; ap++) {
  943. strcpy(bp, *ap);
  944. if (!is_readable(buf2, False)) continue;
  945. if (rename_done) {
  946. (void) unlink(buf2);
  947. DPR(("user_selection_fname(): unlink(%s) %s\n",
  948. *ap));
  949. } else {
  950. rename_done = rename(buf2, buf) == 0;
  951. DPR(("user_selection_fname(): rename(%s, %s) %s\n",
  952. *ap, uenv->real_locale,
  953. rename_done ? "OK" : "Failed"));
  954. }
  955. }
  956. }
  957. /* real_done = rename_done; */
  958. }
  959. }
  960. # endif /* old_hpux */
  961. /* Add the CDE-generic locale name */
  962. strcpy(buf + len, real_done ? uenv->real_locale : uenv->CDE_locale);
  963. buf[buf_len-1] = 0;
  964. }
  965. return dpy_specific;
  966. }
  967. int parse_protolist(char *valp)
  968. {
  969. int proto_bits = 0;
  970. if (strstr(valp, "XIM")) proto_bits |= ProtoBit(Proto_XIM);
  971. if (strstr(valp, "Ximp")) proto_bits |= ProtoBit(Proto_Ximp);
  972. if (strstr(valp, "Xsi")) proto_bits |= ProtoBit(Proto_Xsi);
  973. # ifdef old_hpux
  974. if (strstr(valp, "Xhp")) proto_bits |= ProtoBit(Proto_Xhp);
  975. # endif /* old_hpux */
  976. if (strstr(valp, "None")) proto_bits |= ProtoBit(Proto_None);
  977. return proto_bits;
  978. }
  979. int default_protocol(ImsConf *conf)
  980. {
  981. if (conf->protocols & ProtoBit(Proto_XIM)) return Proto_XIM;
  982. else if (conf->protocols & ProtoBit(Proto_Ximp)) return Proto_Ximp;
  983. else if (conf->protocols & ProtoBit(Proto_Xsi)) return Proto_Xsi;
  984. # ifdef old_hpux
  985. else if (conf->protocols & ProtoBit(Proto_Xhp)) return Proto_Xhp;
  986. # endif /* old_hpux */
  987. else return Proto_None;
  988. }