file.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  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 = NULL;
  133. RemoteEnv *remote;
  134. FILE *fp;
  135. conf_dir = DTIMS_CONFDIR;
  136. if (!(path = Opt.ConfPath) || !*path) {
  137. if (!(path = getenv("DTIMS_STARTCONF")) || !*path) {
  138. if ((p = getenv("DTIMS_CONFDIR")) && *p)
  139. conf_dir = p;
  140. snprintf(path = buf, sizeof(buf), "%s/%s", conf_dir, DTIMS_CONFFILE);
  141. }
  142. }
  143. DPR3(("read_cmd_conf(): path=%s\n", path));
  144. if ((fp = fopen(path, "r")) == NULL) {
  145. DPR3(("\tcannot open '%s'\n", path));
  146. #ifdef DEBUG2
  147. DPR(("cannot open '%s' -- continue with default config\n", path));
  148. goto _default;
  149. #else
  150. setErrFile(path);
  151. return ErrFileOpen;
  152. #endif
  153. }
  154. remote = conf->remote = ALLOC(1, RemoteEnv);
  155. remote->disabled = remote->useRemsh = False;
  156. remote->timeout = REMOTE_TIMEOUT;
  157. remote->passEnv = NULL;
  158. num_alias = 0;
  159. start_tag_line(path);
  160. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  161. if (!valp) {
  162. DPR3(("\t[line=%d] no value for '%s'\n", line_num, lp));
  163. continue;
  164. }
  165. if (strncmp(lp, "Ims", 3) == 0) {
  166. p = lp + 3;
  167. if (strncmp(p, "ConfigDir", 4) == 0) {
  168. RENEWSTR(conf->imsConfDir, valp);
  169. } else if (strncmp(p, "AppDefDir", 4) == 0) {
  170. RENEWSTR(conf->imsAppDir, valp);
  171. } else if (strncmp(p, "LogDir", 4) == 0) {
  172. RENEWSTR(conf->imsLogDir, valp);
  173. } else if (strncmp(p, "LogFile", 4) == 0) {
  174. RENEWSTR(conf->imsLogFile, valp);
  175. } else if (strncmp(p, "DirName", 3) == 0) {
  176. RENEWSTR(conf->imsDir, valp);
  177. } else
  178. goto _inv;
  179. } else if (strncmp(lp, "User", 4) == 0) {
  180. p = lp + 4;
  181. if (strncmp(p, "ImsDir", 4) == 0) {
  182. RENEWSTR(conf->userImsDir, valp);
  183. } else if (strncmp(p, "TmpDir", 4) == 0) {
  184. RENEWSTR(conf->userTmpDir, valp);
  185. } else if (strncmp(p, "AltTmpDir", 3) == 0) {
  186. RENEWSTR(conf->userAltDir, valp);
  187. } else
  188. goto _inv;
  189. } else if (strncmp(lp, "Dt", 2) == 0) {
  190. p = lp + 2;
  191. if (!conf->dt) dt = conf->dt = ALLOC(1, DtEnv);
  192. if (strncmp(p, "ConfigDir", 4) == 0) {
  193. RENEWSTR(dt->confDir, valp);
  194. } else if (strncmp(p, "UserDir", 5) == 0) {
  195. RENEWSTR(dt->userDir, valp);
  196. } else if (strncmp(p, "ResourcePath", 4) == 0) {
  197. RENEWSTR(dt->resPath, valp);
  198. } else
  199. goto _inv;
  200. } else if (strncmp(lp, "ImXmod.", 7) == 0) {
  201. p = lp + 7;
  202. if (strncmp(p, "XIM", 3) == 0) {
  203. RENEWSTR(conf->xmod[Proto_XIM], valp);
  204. } else if (strncmp(p, "Ximp", 4) == 0) {
  205. RENEWSTR(conf->xmod[Proto_Ximp], valp);
  206. } else if (strncmp(p, "Xsi", 3) == 0) {
  207. RENEWSTR(conf->xmod[Proto_Xsi], valp);
  208. } else if (strncmp(p, "None", 3) == 0) {
  209. RENEWSTR(conf->xmod[Proto_None], valp);
  210. } else
  211. goto _inv;
  212. } else if (strncmp(lp, "ImAtom.", 7) == 0) {
  213. p = lp + 7;
  214. if (strncmp(p, "XIM", 3) == 0) {
  215. RENEWSTR(conf->atom[Proto_XIM], valp);
  216. } else if (strncmp(p, "Ximp", 4) == 0) {
  217. RENEWSTR(conf->atom[Proto_Ximp], valp);
  218. } else if (strncmp(p, "Xsi", 3) == 0) {
  219. RENEWSTR(conf->atom[Proto_Xsi], valp);
  220. } else if (strncmp(p, "None", 3) == 0) {
  221. RENEWSTR(conf->atom[Proto_None], valp);
  222. } else
  223. goto _inv;
  224. } else if (strncmp(lp, "Action.", 7) == 0) {
  225. p = lp + 7;
  226. if (strncmp(p, "GetRemoteConf", 8) == 0) {
  227. RENEWSTR(conf->action[ACT_GETREMCONF], valp);
  228. } else if (strncmp(p, "RunRemoteIMs", 8) == 0) {
  229. RENEWSTR(conf->action[ACT_RUNREMIMS], valp);
  230. } else
  231. goto _inv;
  232. } else if (strncmp(lp, "Remote", 6) == 0) {
  233. p = lp + 6;
  234. if (strncmp(p, "Disabled", 3) == 0) {
  235. remote->disabled = str_to_bool(valp, False);
  236. } else if (strncmp(p, "UseRemsh", 4) == 0) {
  237. remote->useRemsh = str_to_bool(valp, False);
  238. } else if (strncmp(p, "Timeout", 3) == 0) {
  239. int n = 0;
  240. if (str_to_int(valp, &n) && n >= 0)
  241. remote->timeout = n;
  242. } else if (strncmp(p, "Environment", 3) == 0) {
  243. RENEWSTR(remote->passEnv, valp);
  244. } else
  245. goto _inv;
  246. } else {
  247. _inv:
  248. DPR(("\t[line=%d] invalid entry '%s'\n", line_num, lp));
  249. }
  250. }
  251. fclose(fp);
  252. /* if (remote->disabled) FREE(remote->passEnv); */
  253. _default:
  254. /* set default value unless set */
  255. if (!conf->imsConfDir) conf->imsConfDir = NEWSTR(conf_dir);
  256. if (!conf->imsAppDir) conf->imsAppDir = NEWSTR(DTIMS_APPDIR);
  257. if (!conf->imsLogDir) conf->imsLogDir = NEWSTR(DTIMS_LOGDIR);
  258. if (!conf->imsLogFile) conf->imsLogFile = NEWSTR(DTIMS_LOGFILE);
  259. if (!conf->imsDir) conf->imsDir = NEWSTR(DTIMS_IMSDIR);
  260. if (!conf->userImsDir) conf->userImsDir = NEWSTR(DTIMS_USRIMSDIR);
  261. if (!conf->userTmpDir) conf->userTmpDir = NEWSTR(DTIMS_USRTMPDIR);
  262. if (!conf->userAltDir) conf->userAltDir = NEWSTR(DTIMS_USRALTDIR);
  263. if (!conf->dt) conf->dt = ALLOC(1, DtEnv);
  264. if (!conf->dt->confDir) conf->dt->confDir = NEWSTR(DT_CONFDIR);
  265. if (!conf->dt->userDir) conf->dt->userDir = NEWSTR(DT_USERDIR);
  266. if (!conf->xmod[Proto_XIM]) conf->xmod[Proto_XIM] = NEWSTR(IM_XMOD_XIM);
  267. if (!conf->xmod[Proto_Ximp]) conf->xmod[Proto_Ximp] = NEWSTR(IM_XMOD_XIMP);
  268. if (!conf->xmod[Proto_Xsi]) conf->xmod[Proto_Xsi] = NEWSTR(IM_XMOD_XSI);
  269. if (!conf->atom[Proto_XIM]) conf->atom[Proto_XIM] = NEWSTR(IM_ATOM_XIM);
  270. if (!conf->atom[Proto_Ximp]) conf->atom[Proto_Ximp] = NEWSTR(IM_ATOM_XIMP);
  271. if (!conf->atom[Proto_Xsi]) conf->atom[Proto_Xsi] = NEWSTR(IM_ATOM_XSI);
  272. /* default value of {xmod,atom}[Proto_None/Xhp] is NULL */
  273. if (!conf->action[ACT_GETREMCONF])
  274. conf->action[ACT_GETREMCONF] = NEWSTR(NAME_ACT_GETREMCONF);
  275. if (!conf->action[ACT_RUNREMIMS])
  276. conf->action[ACT_RUNREMIMS] = NEWSTR(NAME_ACT_RUNREMIMS);
  277. cmdconf_initialized = True;
  278. return NoError;
  279. }
  280. int expand_cmd_conf(void)
  281. {
  282. char **pp[20 + NUM_ACTIONS], *p, buf[BUFSIZ];
  283. int i, j, n;
  284. CmdConf *conf = &Conf;
  285. #define CHK_ADD(p) if (strchr(p, '%')) pp[n++] = &(p);
  286. #ifdef DEBUG
  287. if (DebugLvl > 1) { pr_CmdConf(); }
  288. #endif
  289. n = 0;
  290. CHK_ADD(conf->imsConfDir);
  291. CHK_ADD(conf->imsAppDir);
  292. CHK_ADD(conf->imsLogDir);
  293. CHK_ADD(conf->imsLogFile);
  294. CHK_ADD(conf->imsDir);
  295. CHK_ADD(conf->userImsDir)
  296. CHK_ADD(conf->userTmpDir)
  297. CHK_ADD(conf->userAltDir)
  298. for (j = 0; j < NUM_ACTIONS; j++) CHK_ADD(conf->action[j])
  299. if (conf->dt) {
  300. CHK_ADD(conf->dt->confDir)
  301. CHK_ADD(conf->dt->userDir)
  302. CHK_ADD(conf->dt->resPath)
  303. }
  304. /* xmod[] & atom[] must not be expanded, since no ims selected */
  305. /* remote->* should be expanded at preparation of remote exec */
  306. #undef CHK_ADD
  307. for (i = j = 0; i < n; i++) {
  308. p = *(pp[i]);
  309. expand_string(*(pp[i]), buf, BUFSIZ, 0);
  310. #ifdef DEBUG
  311. if (strcmp(p, buf)) j++;
  312. #endif
  313. FREE(p);
  314. *(pp[i]) = NEWSTR(buf);
  315. }
  316. DPR(("expand_cmd_conf(): %d / %d entries modified\n", j, n));
  317. return n;
  318. }
  319. int read_imsconf(ImsConf *conf, char *ims_name, char *ims_fname)
  320. {
  321. int ret = NoError;
  322. char path[MAXPATHLEN];
  323. char *lp, *valp, *p;
  324. int len, n, line_num;
  325. FILE *fp;
  326. if (!ims_fname) ims_fname = ims_name;
  327. len = expand_string("%I/", path, MAXPATHLEN, 0);
  328. strcpyx(path + len, ims_fname);
  329. DPR3(("read_imsconf(%s): path=%s\n", ims_name, path));
  330. CLR(conf, ImsConf);
  331. if ((fp = fopen(path, "r")) == NULL) {
  332. DPR3(("\tcannot open '%s'\n", path));
  333. return ErrNoImsConf;
  334. }
  335. start_tag_line(path);
  336. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  337. if (!valp) {
  338. DPR3(("\t[line=%d] no value for '%s'\n", line_num, lp));
  339. continue;
  340. }
  341. /* valp = trim_line(valp); */
  342. /* TYP_NAME */
  343. if (strcmp(lp, "name") == 0)
  344. ; /* conf->name = NEWSTR(valp); */
  345. else if (strcmp(lp, "server_name") == 0) {
  346. if (p = strchr(valp, ',')) { /* contain secondary names */
  347. conf->servername2 = NEWSTR(valp); /* save full name */
  348. *p = 0;
  349. }
  350. conf->servername = NEWSTR(valp); /* save primary name only */
  351. } else if (strcmp(lp, "class_name") == 0)
  352. conf->classname = NEWSTR(valp);
  353. else if (strcmp(lp, "property") == 0)
  354. conf->property = NEWSTR(valp);
  355. /* TYP_PATH */
  356. else if (strcmp(lp, "cmd_path") == 0)
  357. conf->cmd_path = NEWSTR(valp);
  358. /* TYP_STRING */
  359. else if (strcmp(lp, "cmd_param") == 0)
  360. conf->cmd_param = NEWSTR(valp);
  361. /* TYP_NUMERIC */
  362. else if (strcmp(lp, "chk_timeout") == 0) {
  363. if (str_to_int(valp, &n))
  364. conf->timeout = n;
  365. } else if (strcmp(lp, "chk_interval") == 0) {
  366. if (str_to_int(valp, &n))
  367. conf->interval = n;
  368. }
  369. /* TYP_BOOL */
  370. #define SET_FLAG(f) \
  371. (str_to_bool(valp, False) ? (conf->flags |= (f)) : (conf->flags &= ~(f)))
  372. else if (strcmp(lp, "no_server") == 0)
  373. SET_FLAG(F_NO_SERVER);
  374. else if (strcmp(lp, "no_remote") == 0)
  375. SET_FLAG(F_NO_REMOTE);
  376. else if (strcmp(lp, "no_option") == 0)
  377. SET_FLAG(F_NO_OPTION);
  378. else if (strcmp(lp, "has_window") == 0)
  379. SET_FLAG(F_HAS_WINDOW);
  380. #undef SET_FLAG
  381. /* TYP_NAMELIST */
  382. else if (strcmp(lp, "env_set") == 0)
  383. conf->env_set = NEWSTR(valp);
  384. else if (strcmp(lp, "env_unset") == 0)
  385. conf->env_unset = NEWSTR(valp);
  386. else if (strcmp(lp, "env_pass") == 0)
  387. conf->env_pass = NEWSTR(valp);
  388. else if (strcmp(lp, "protocols") == 0)
  389. conf->protocols = parse_protolist(valp);
  390. else {
  391. DPR3(("\t[line=%d] invalid entry '%s'\n", line_num, lp));
  392. }
  393. }
  394. fclose(fp);
  395. ret = check_ims_conf(conf, ims_name);
  396. if (ret != NoError)
  397. setErrFile(path);
  398. return ret;
  399. }
  400. int check_ims_conf(ImsConf *ims, char *ims_name)
  401. {
  402. int ret = NoError;
  403. char *missing_entry = NULL;
  404. if (strcmp(ims_name, NAME_NONE) == 0) return NoError;
  405. if ((ims->cmd_path) && strcmp(ims->cmd_path, NAME_BUILTIN) == 0) {
  406. ims->flags |= (F_BUILTIN | F_NO_SERVER | F_NO_REMOTE | F_NO_OPTION);
  407. ims->flags &= ~F_TRY_CONNECT;
  408. FREE(ims->cmd_path);
  409. }
  410. /* check indispensable entry */
  411. if (!ims->cmd_path && !(ims->flags & F_BUILTIN)) {
  412. missing_entry = "cmd_path";
  413. DPR(("read_imsconf(%s): no '%s' entry\n", ims_name, missing_entry));
  414. }
  415. if (!ims->servername) {
  416. DPR(("read_imsconf(%s): no '%s' entry\n", ims_name, missing_entry));
  417. missing_entry = "servername";
  418. }
  419. if (!ims->protocols) {
  420. DPR(("read_imsconf(%s): no '%s' entry\n", ims_name, missing_entry));
  421. missing_entry = "protocols";
  422. }
  423. if (missing_entry) {
  424. setErrArg1(missing_entry);
  425. ret = ErrMissEntry;
  426. }
  427. return ret;
  428. }
  429. int read_localeconf(ImsList *list, char *locale_name)
  430. {
  431. char path[MAXPATHLEN];
  432. char *lp, *valp, *pp;
  433. char *def_name;
  434. int sel_mode;
  435. int len, line_num, num_ent;
  436. ImsEnt *ent, *etmp[MAXIMSENT];
  437. FILE *fp;
  438. UserEnv *uenv = &userEnv;
  439. len = expand_string("%I/", path, MAXPATHLEN, 0);
  440. if (!locale_name || !*locale_name) {
  441. locale_name = uenv->real_locale ? uenv->real_locale : uenv->locale;
  442. }
  443. strcpyx(path + len, locale_name);
  444. DPR3(("read_localeconf(%s): path=%s\n", locale_name, path));
  445. CLR(list, ImsList);
  446. list->status = NoError;
  447. list->default_idx = -1;
  448. list->def_selmode = SEL_MODE_NOAUTO;
  449. if ((fp = fopen(path, "r")) == NULL) {
  450. DPR3(("\tcannot open '%s'\n", path));
  451. list->status = ErrNoLocaleConf;
  452. return ErrNoLocaleConf;
  453. }
  454. def_name = NULL;
  455. sel_mode = SEL_MODE_NONE;
  456. num_ent = 0;
  457. start_tag_line(path);
  458. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  459. if (lp[0] == STR_PREFIX_CHAR) {
  460. if (!valp) {
  461. DPR3(("\t[line=%d] no value for '%s'\n", line_num, lp));
  462. continue;
  463. }
  464. if (strncmp(lp + 1, STR_DEFAULTIMS, 3) == 0) {
  465. RENEWSTR(def_name, valp);
  466. } else if (strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
  467. int m = SEL_MODE_NONE;
  468. if (str_to_int(valp, &m) && m >= 0)
  469. sel_mode = m;
  470. } else {
  471. DPR2(("\t[line=%d] invalid entry '%s'\n", line_num, lp));
  472. }
  473. } else { /* ims name entry */
  474. if (num_ent >= MAXIMSENT) {
  475. DPR(("\ttoo many IMS defined: '%s' ignored\n", lp));
  476. break;
  477. }
  478. ent = ALLOC(1, ImsEnt);
  479. if (pp = strchr(lp, STR_PREFIX_CHAR)) {
  480. *pp++ = 0;
  481. if (*pp)
  482. ent->fname = NEWSTR(pp);
  483. else {
  484. DPR(("\tempty file name for '%s' -- ignored\n", lp));
  485. }
  486. }
  487. ent->name = NEWSTR(lp);
  488. if (valp) ent->label = NEWSTR(valp);
  489. etmp[num_ent++] = ent;
  490. }
  491. }
  492. fclose(fp);
  493. if (num_ent) {
  494. list->num_ent = num_ent;
  495. list->elist = ALLOC(num_ent, ImsEnt *);
  496. memcpy((void *)list->elist, (void *)etmp, num_ent*sizeof(ImsEnt *));
  497. list->def_selmode =
  498. (sel_mode != SEL_MODE_NONE) ? sel_mode : SEL_MODE_NOAUTO;
  499. if (def_name) {
  500. int i;
  501. for (i = 0; i < list->num_ent; i++)
  502. if (strcmp(def_name, list->elist[i]->name) == 0) {
  503. list->default_idx = i;
  504. break;
  505. }
  506. FREE(def_name);
  507. }
  508. }
  509. #ifdef DEBUG
  510. if (DebugLvl > 2) pr_ImsList(list);
  511. #endif
  512. return list->status;
  513. }
  514. int read_user_selection(FileSel **fselp, char *locale_name)
  515. {
  516. char path[MAXPATHLEN];
  517. int ret;
  518. int dpy_specific;
  519. FILE *fp;
  520. FileSel *fsel;
  521. dpy_specific = user_selection_fname(path, MAXPATHLEN, -1);
  522. DPR3(("read_user_selection(): path=%s\n", path));
  523. if ((fp = fopen(path, "r")) == NULL) {
  524. DPR3(("\tcannot open '%s'\n", path));
  525. /* *fselp = (FileSel *) 0; */
  526. return ErrNoSelectionFile;
  527. }
  528. fsel = ALLOC(1, FileSel);
  529. start_tag_line(path);
  530. ret = read_selection_file(fsel, fp);
  531. fclose(fp);
  532. fsel->dpy_specific = dpy_specific;
  533. fsel->real_fname = NEWSTR(locale_name);
  534. *fselp = fsel;
  535. return NoError;
  536. }
  537. int read_selection_file(FileSel *fsel, FILE *fp)
  538. {
  539. char *lp, *valp, *vp, *p;
  540. int i, nopts, line_num;
  541. int select_mode, iconic;
  542. char *imsname, *hostname, *com_opt;
  543. ImsOpt *opts[MAXIMSENT], *op;
  544. select_mode = SEL_MODE_NONE;
  545. imsname = hostname = com_opt = NULL;
  546. iconic = -1;
  547. nopts = 0;
  548. opts[0] = (ImsOpt *)NULL;
  549. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  550. if (!valp) {
  551. DPR3(("\t[line=%d] no value for '%s'\n", line_num, lp));
  552. continue;
  553. }
  554. if (lp[0] != STR_PREFIX_CHAR) {
  555. DPR3(("\t[line=%d] invalid name '%s'\n", line_num, lp));
  556. continue;
  557. }
  558. if (strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
  559. if (str_to_int(valp, &i) && i >= 0)
  560. select_mode = i;
  561. } else if (strncmp(lp + 1, STR_IMSNAME, 4) == 0) {
  562. vp = valp; cut_field(valp);
  563. RENEWSTR(imsname, vp);
  564. } else if (strncmp(lp + 1, STR_HOSTNAME, 4) == 0) {
  565. vp = valp; cut_field(valp);
  566. FREE(hostname);
  567. if (strcmp(vp, NAME_LOCAL))
  568. hostname = NEWSTR(vp);
  569. } else if (strncmp(lp + 1, STR_ICONIC, 3) == 0) {
  570. if (*valp)
  571. iconic = str_to_bool(valp, False);
  572. } else if (strncmp(lp + 1, STR_IMSOPTION, 4) == 0) {
  573. if (p = strchr(lp + 1, STR_PREFIX_CHAR)) { /* indiv. opt */
  574. if (nopts >= MAXIMSENT) {
  575. DPR(("\t[line=%d] too many options - '%s' ignored\n",
  576. line_num, lp));
  577. continue;
  578. }
  579. if (!*(++p)) {
  580. DPR(("\t[line=%d] no ims name - '%s' ignored\n",
  581. line_num, lp));
  582. continue;
  583. }
  584. for (op = 0, i = 0; i < nopts; i++)
  585. if (strcmp(p, opts[i]->ims_name) == 0) {
  586. op = opts[i];
  587. FREE(op->ims_name);
  588. FREE(op->opt_str);
  589. break;
  590. }
  591. if (!op) {
  592. op = ALLOC(1, ImsOpt);
  593. opts[nopts++] = op;
  594. }
  595. op->ims_name = NEWSTR(p);
  596. op->opt_str = NEWSTR(valp);
  597. } else { /* common opt */
  598. RENEWSTR(com_opt, valp);
  599. }
  600. } else {
  601. DPR3(("\t[line=%d] unknown name '%s'\n", line_num, lp));
  602. }
  603. }
  604. fsel->name = imsname;
  605. fsel->hostname = hostname;
  606. fsel->com_opt = com_opt;
  607. fsel->select_mode = select_mode;
  608. fsel->iconic = iconic;
  609. if (nopts > 0) {
  610. fsel->opts = ALLOC(nopts + 1, ImsOpt *);
  611. COPY(fsel->opts, opts, nopts, ImsOpt *);
  612. fsel->opts[nopts] = (ImsOpt *)0;
  613. }
  614. return NoError;
  615. }
  616. int save_user_selection(UserSelection *sel, char *locale_name)
  617. {
  618. char path[MAXPATHLEN];
  619. int dpy_specific;
  620. FILE *fp;
  621. FileSel *fsel = sel->fsel;
  622. dpy_specific = user_selection_fname(path, MAXPATHLEN, -1);
  623. if ((fp = fopen(path, "w")) == NULL) {
  624. DPR(("\tcannot create '%s'\n", path));
  625. setErrFile(path);
  626. return ErrFileCreate;
  627. }
  628. put_selection_header(fp);
  629. if (fsel)
  630. put_select_mode(fp, fsel->select_mode);
  631. put_ims_conf(fp, sel);
  632. put_selection_sep(fp);
  633. fclose(fp);
  634. DPR3(("save_user_selection(): '%s' saved on '%s'\n", sel->name, path));
  635. return NoError;
  636. }
  637. #define _SELECTMODE 0
  638. #define _IMSNAME 1
  639. #define _HOSTNAME 2
  640. #define _ICONIC 3
  641. #define _IMSOPTION 4
  642. #define _IMSOPT2 5
  643. static void put_selection_entry(FILE *fp, int ent_type, bool is_valid, char *val, char *val2)
  644. {
  645. char *name = NULL;
  646. switch (ent_type) {
  647. case _SELECTMODE: name = STR_SELECTMODE; break;
  648. case _IMSNAME: name = STR_IMSNAME; break;
  649. case _HOSTNAME: name = STR_HOSTNAME; break;
  650. case _ICONIC: name = STR_ICONIC; break;
  651. case _IMSOPT2:
  652. case _IMSOPTION: name = STR_IMSOPTION; break;
  653. /* default: is_valid = False; */
  654. }
  655. if (!is_valid) putc(COMMENT_CHAR, fp);
  656. if (ent_type == _IMSOPT2)
  657. fprintf(fp, "%c%s%c%s%c\t%s\n", STR_PREFIX_CHAR, name,
  658. STR_PREFIX_CHAR, val2, TAG_END_CHAR, val);
  659. else
  660. fprintf(fp, "%c%s%c\t%s\n", STR_PREFIX_CHAR, name, TAG_END_CHAR, val);
  661. }
  662. static void put_ims_conf(FILE *fp, UserSelection *sel)
  663. {
  664. char *valp, val[20];
  665. if ((valp = sel->name) && *valp)
  666. put_selection_entry(fp, _IMSNAME, True, valp, NULL);
  667. else {
  668. DPR(("put_ims_conf(): no ims name\n"));
  669. if (sel->fsel && (valp = sel->fsel->name) && *valp)
  670. put_selection_entry(fp, _IMSNAME, False, valp, NULL);
  671. }
  672. if ((valp = sel->hostname) && *valp)
  673. put_selection_entry(fp, _HOSTNAME, True, valp, NULL);
  674. else if (sel->fsel && (valp = sel->fsel->hostname) && *valp)
  675. put_selection_entry(fp, _HOSTNAME, False, valp, NULL);
  676. if (sel->iconic != -1) {
  677. sprintf(val, "%ld", (long)sel->iconic);
  678. put_selection_entry(fp, _ICONIC, True, val, NULL);
  679. }
  680. if (sel->fsel && (valp = sel->fsel->com_opt) && *valp) {
  681. bool opt_valid = True;
  682. #if 0
  683. opt_valid = !sel->fsel->name || strcmp(sel->name, sel->fsel->name) == 0;
  684. #endif
  685. put_selection_entry(fp, _IMSOPTION, opt_valid, valp, NULL);
  686. }
  687. if (sel->fsel && sel->fsel->opts) {
  688. ImsOpt **op;
  689. for (op = sel->fsel->opts; *op; op++)
  690. put_selection_entry(fp, _IMSOPT2, True,
  691. (*op)->opt_str, (*op)->ims_name);
  692. }
  693. }
  694. static void put_select_mode(FILE *fp, int select_mode)
  695. {
  696. char val[20];
  697. if (select_mode != SEL_MODE_NOAUTO && select_mode != SEL_MODE_AUTO
  698. #ifdef SelectMode_ONCE
  699. && select_mode != SEL_MODE_ONCE
  700. #endif /* SelectMode_ONCE */
  701. )
  702. select_mode = SEL_MODE_NOAUTO;
  703. sprintf(val, "%ld", (long)select_mode);
  704. put_selection_entry(fp, _SELECTMODE, True, val, NULL);
  705. }
  706. static void put_selection_header(FILE *fp)
  707. {
  708. fprintf(fp, "%s %s\n", COMMENT_CHARS, ProgramRevision);
  709. if (SelectFileFormat)
  710. fprintf(fp, "%s%s\n", COMMENT_CHARS, SelectFileFormat);
  711. }
  712. static void put_selection_sep(FILE *fp)
  713. {
  714. fprintf(fp, "%s\n", COMMENT_CHARS);
  715. }
  716. int get_select_mode(void)
  717. {
  718. char path[MAXPATHLEN];
  719. char *lp, *valp;
  720. int select_mode, dpy_specific;
  721. int n, line_num;
  722. FILE *fp;
  723. select_mode = SEL_MODE_NONE;
  724. dpy_specific = user_selection_fname(path, MAXPATHLEN, -1);
  725. DPR3(("get_select_mode(): path=%s\n", path));
  726. if ((fp = fopen(path, "r")) == NULL) {
  727. DPR3(("\tcannot open '%s'\n", path));
  728. return select_mode;
  729. }
  730. start_tag_line(path);
  731. while ((line_num = read_tag_line(fp, &lp, &valp)) > 0) {
  732. if (lp[0] == STR_PREFIX_CHAR
  733. && strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
  734. if (str_to_int(valp, &n))
  735. select_mode = n;
  736. }
  737. }
  738. fclose(fp);
  739. DPR3(("get_select_mode(%s): select_mode=%d\n",
  740. dpy_specific ? "dpy" : NULL, select_mode));
  741. return select_mode;
  742. }
  743. int set_select_mode(int cur_mode, int new_mode)
  744. {
  745. char path[MAXPATHLEN];
  746. int dpy_specific;
  747. FILE *fp;
  748. switch (new_mode) {
  749. case SEL_MODE_NOAUTO: break;
  750. case SEL_MODE_AUTO: break;
  751. #ifdef SelectMode_ONCE
  752. case SEL_MODE_ONCE: break;
  753. #endif /* SelectMode_ONCE */
  754. case SEL_MODE_NONE:
  755. default: new_mode = SEL_MODE_NOAUTO; break;
  756. }
  757. dpy_specific = user_selection_fname(path, MAXPATHLEN, -1);
  758. DPR3(("set_selection_mode(): path=%s\n", path));
  759. #if 0
  760. if (!make_user_dir(dirname(path))) {
  761. setErrFile(dirname(path));
  762. return ErrDirCreate;
  763. }
  764. #endif
  765. if ((fp = fopen(path, "r+")) == NULL) {
  766. DPR3(("\tcannot open '%s'\n", path));
  767. if ((fp = fopen(path, "w")) == NULL) {
  768. setErrFile(path);
  769. return ErrFileCreate;
  770. }
  771. cur_mode = SEL_MODE_NONE;
  772. }
  773. if (cur_mode == SEL_MODE_NONE) { /* append '@SelectMode' line */
  774. fseek(fp, 0, SEEK_END);
  775. put_select_mode(fp, new_mode);
  776. fclose(fp);
  777. } else {
  778. FILE *new_fp;
  779. char new_fname[MAXPATHLEN];
  780. char line_buf[BUFSIZ];
  781. char *lp, *valp;
  782. int n, line_num, mode_line;
  783. snprintf(new_fname, sizeof(new_fname), "%s,tmp", path);
  784. if (!(new_fp = fopen(new_fname, "w"))) {
  785. fclose(fp);
  786. DPR(("set_select_mode(): cannot create %s\n", new_fname));
  787. setErrFile(path);
  788. return ErrFileCreate;
  789. }
  790. line_num = mode_line = 0;
  791. while (fgets(lp = line_buf, BUFSIZ, fp)) {
  792. line_num++;
  793. skip_white(lp);
  794. if (*lp == STR_PREFIX_CHAR) {
  795. if (strncmp(lp + 1, STR_SELECTMODE, 3) == 0) {
  796. if (mode_line) continue; /* ignore this line */
  797. if (valp = strchr(lp, TAG_END_CHAR)) {
  798. valp++;
  799. skip_white(valp);
  800. if (str_to_int(valp, &n) && n == new_mode)
  801. mode_line = -1;
  802. }
  803. put_select_mode(new_fp, new_mode);
  804. mode_line = line_num;
  805. } else
  806. fputs(line_buf, new_fp);
  807. } else
  808. fputs(line_buf, new_fp);
  809. }
  810. if (!mode_line)
  811. put_select_mode(new_fp, new_mode);
  812. fclose(new_fp);
  813. fclose(fp);
  814. if (mode_line == -1) { /* not changed */
  815. (void) unlink(new_fname);
  816. } else {
  817. if (rename(new_fname, path) == -1) {
  818. setErrFile(path);
  819. return ErrFileCreate;
  820. }
  821. }
  822. (void) unlink(new_fname);
  823. }
  824. DPR2(("set_select_mode(%s): new_mode=%d <- %d\n",
  825. dpy_specific ? "dpy" : NULL, new_mode, cur_mode));
  826. return NoError;
  827. }
  828. static int user_selection_fname(char *buf, int buf_len, int dpy_specific)
  829. {
  830. int len;
  831. UserEnv *uenv = &userEnv;
  832. static bool real_done = False;
  833. if (Opt.UserPath) {
  834. strncpy(buf, Opt.UserPath, buf_len);
  835. buf[buf_len-1] = 0;
  836. dpy_specific = 0;
  837. } else {
  838. if (dpy_specific == -1) {
  839. len = expand_string("%S/%d", buf, buf_len, 0);
  840. dpy_specific = is_directory(buf, False) ? 1 : 0;
  841. }
  842. len = expand_string(dpy_specific ? "%S/%d/" : "%S/", buf, buf_len, 0);
  843. /* Add the CDE-generic locale name */
  844. strcpy(buf + len, real_done ? uenv->real_locale : uenv->CDE_locale);
  845. buf[buf_len-1] = 0;
  846. }
  847. return dpy_specific;
  848. }
  849. int parse_protolist(char *valp)
  850. {
  851. int proto_bits = 0;
  852. if (strstr(valp, "XIM")) proto_bits |= ProtoBit(Proto_XIM);
  853. if (strstr(valp, "Ximp")) proto_bits |= ProtoBit(Proto_Ximp);
  854. if (strstr(valp, "Xsi")) proto_bits |= ProtoBit(Proto_Xsi);
  855. if (strstr(valp, "None")) proto_bits |= ProtoBit(Proto_None);
  856. return proto_bits;
  857. }
  858. int default_protocol(ImsConf *conf)
  859. {
  860. if (conf->protocols & ProtoBit(Proto_XIM)) return Proto_XIM;
  861. else if (conf->protocols & ProtoBit(Proto_Ximp)) return Proto_Ximp;
  862. else if (conf->protocols & ProtoBit(Proto_Xsi)) return Proto_Xsi;
  863. else return Proto_None;
  864. }