env.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  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: env.c /main/9 1996/10/30 05:57:27 pascale $ */
  24. #include <pwd.h>
  25. #include "xims.h"
  26. typedef enum {
  27. P_Shell, /* posix shell */
  28. K_Shell, /* Korn shell */
  29. C_Shell /* C shell */
  30. } ShellType;
  31. /* local func */
  32. static int shell_type(/* shell */);
  33. int set_cmd_env(void)
  34. {
  35. int ret = NoError;
  36. char **aliases = (char **)0;
  37. char *p;
  38. UserEnv *uenv = &userEnv;
  39. if ((ret = get_user_environ()) != NoError)
  40. return ret;
  41. if ((ret = read_cmd_conf()) != NoError)
  42. return ret;
  43. # ifdef old_hpux
  44. p = get_real_locale(uenv->locale, &aliases);
  45. if (p) {
  46. uenv->real_locale = NEWSTR(p);
  47. uenv->locale_aliases = aliases;
  48. }
  49. # endif /* old_hpux */
  50. expand_cmd_conf();
  51. return ret;
  52. }
  53. int get_user_environ(void)
  54. {
  55. int ret = NoError;
  56. char buf[BUFSIZ], *p;
  57. int n;
  58. UserEnv *uenv = &userEnv;
  59. ret = NoError;
  60. CLR(&userEnv, UserEnv);
  61. if ((p = getenv("LANG")) && *p)
  62. uenv->locale = NEWSTR(p);
  63. else
  64. return ErrNoLocale;
  65. /* find the CDE generic locale name */
  66. if (find_CDE_locale_name() != NoError)
  67. return ErrNoCDELocale;
  68. if ((p = getenv("HOME")) && *p)
  69. uenv->homedir = NEWSTR(p);
  70. else {
  71. if (OpMode != MODE_LIST && OpMode != MODE_REMCONF) {
  72. #ifdef ALLOW_NOHOME
  73. p = "/var/tmp";
  74. uenv->homedir = NEWSTR(p);
  75. #else
  76. ret = ErrNoHome;
  77. #endif /* ALLOW_NOHOME */
  78. }
  79. }
  80. if ((p = Opt.DisplayName) && *p) {
  81. strcpy(buf, "DISPLAY=");
  82. strcat(buf, p);
  83. putenv(XtNewString(buf));
  84. } else
  85. p = getenv("DISPLAY");
  86. if (p && *p)
  87. uenv->displayname = NEWSTR(p);
  88. else {
  89. if (OpMode == MODE_START /* || OpMode == MODE_CURRENT */
  90. || (OpMode == MODE_MODE && (OpFlag & USE_WINDOW_MASK)))
  91. return ErrNoDisplay;
  92. }
  93. if (p = getenv("XMODIFIERS"))
  94. uenv->xmodifiers = NEWSTR(p);
  95. else
  96. uenv->xmodifiers = NULL;
  97. gethostname(buf, BUFSIZ);
  98. uenv->hostname = NEWSTR(buf);
  99. if (!(p = getlogin()))
  100. {
  101. struct passwd *pw;
  102. pw = getpwuid(getuid());
  103. p = pw->pw_name;
  104. }
  105. uenv->username = NEWSTR(p);
  106. n = 0;
  107. if (p = std_dpy_str(uenv->displayname, &n))
  108. uenv->displaydir = p;
  109. else
  110. uenv->displaydir = NEWSTR(uenv->displayname);
  111. uenv->screen_num = n;
  112. return ret;
  113. }
  114. int expand_string(char *in_str, char *out_str, int out_len, ImsConf *ims)
  115. {
  116. char *p, *q, *ep;
  117. char str[20];
  118. int len = 0;
  119. UserEnv *uenv = &userEnv;
  120. CmdConf *conf = &Conf;
  121. p = in_str; q = out_str;
  122. if (*p == '~' && p[1] == '/') {
  123. q = strcpyx(q, uenv->homedir);
  124. *q++ = '/';
  125. p += 2;
  126. out_len -= q - out_str;
  127. }
  128. while (*p && out_len > 0) {
  129. ep = NULL;
  130. if (*p == '%') {
  131. switch(p[1]) {
  132. case 'I': ep = conf->imsConfDir; break;
  133. case 'R': ep = conf->imsAppDir; break;
  134. case 'G': ep = conf->imsLogDir; break;
  135. case 'g': ep = conf->imsLogFile; break;
  136. case 'b': ep = conf->imsDir; break;
  137. case 'S': ep = conf->userImsDir; break;
  138. case 'T': ep = conf->userTmpDir; break;
  139. case 'A': ep = conf->userAltDir; break;
  140. case 'C': ep = conf->dt->confDir; break;
  141. case 'U': ep = conf->dt->userDir; break;
  142. # ifdef old_hpux
  143. case 'V': ep = conf->vue->confDir; break;
  144. case 'X': ep = conf->vue->userDir; break;
  145. # endif /* old_hpux */
  146. case 'L': if (ep = uenv->real_locale) break;
  147. case 'l': ep = uenv->locale; break;
  148. case 'H': ep = uenv->homedir; break;
  149. case 'u': ep = uenv->username; break;
  150. case 'h': ep = uenv->hostname; break;
  151. case 'D': ep = uenv->displayname; break;
  152. case 'd': ep = uenv->displaydir; break;
  153. case 'N': if (ims && (ep = ims->servername2)) break;
  154. case 'n': if (ims) ep = ims->servername; break;
  155. case 'c': if (ims) ep = ims->classname; break;
  156. case 's': sprintf(str, "%ld", (long) uenv->screen_num);
  157. if (str[0] != '\0') ep = str;
  158. break;
  159. case 'r': ep = userSel.hostname; break;
  160. case '%': p++;
  161. default: DPR2(("expand_string: '%%%c' unknown\n"));
  162. ep = 0; break;
  163. }
  164. if (ep) {
  165. if ((out_len -= (int) strlen(ep)) <= 0) break;
  166. q = strcpyx(q, ep);
  167. p += 2;
  168. continue;
  169. }
  170. }
  171. if (--out_len <= 0) break;
  172. *q++ = *p++;
  173. }
  174. *q = 0;
  175. len = q - out_str;
  176. DPR3(("expand_string(\"%s\"):\t\"%s\"\n", in_str, out_str));
  177. if (out_len <= 0) {
  178. DPR(("expand_string(): buffer overflow (len=%d)\n", len));
  179. }
  180. return len;
  181. }
  182. static int shell_type(char *shell)
  183. {
  184. char *p;
  185. int len;
  186. if (!shell || !*shell) {
  187. shell = getenv("SHELL");
  188. if (!shell || !*shell) return P_Shell;
  189. }
  190. if (strchr(p = shell, '/')) {
  191. for (len = strlen(p); len > 1 && p[len - 1] == '/'; len--) ;
  192. shell[len] = 0;
  193. if (p = strrchr(shell, '/')) shell = p + 1;
  194. }
  195. if (strstr(shell, "ksh") != NULL)
  196. return K_Shell;
  197. else if (strstr(shell, "csh") != NULL)
  198. return C_Shell;
  199. return P_Shell;
  200. }
  201. int make_new_environ(OutEnv *oenv, UserSelection *sel)
  202. {
  203. ImsConf *ims;
  204. EnvEnt *ep, *ep2;
  205. int num, i;
  206. int proto;
  207. char *p, **pp;
  208. char buf[BUFSIZ], *bp;
  209. char *xmod, *xinput;
  210. char **setp, **unsetp;
  211. bool xmod_done, xinput_done;
  212. RunEnv *renv;
  213. /* if (!oenv) return ErrInternal; */
  214. if (!sel) sel = &userSel;
  215. CLR(oenv, OutEnv);
  216. renv = sel->renv;
  217. ims = sel->ent->ims;
  218. xmod = ENV_XMODIFIERS;
  219. xmod_done = False;
  220. # ifdef old_hpux
  221. xinput = xhp_xinput_name(NULL);
  222. xinput_done = (xinput) ? False : True;
  223. # else
  224. xinput = NULL;
  225. xinput_done = True;
  226. # endif /* old_hpux */
  227. proto = renv ? renv->proto : default_protocol(ims);
  228. setp = unsetp = 0;
  229. if (ims->env_set) setp = parse_strlist(ims->env_set, ' ');
  230. if (ims->env_unset) unsetp = parse_strlist(ims->env_unset, ' ');
  231. /* set: ims->env_set, XMODIFIERS & X?INPUT */
  232. num = 0;
  233. if (setp) for (pp = setp; *pp; pp++, num++) ;
  234. ep = oenv->set = ALLOC(num + 2 + 1, EnvEnt);
  235. for (i = 0; i < num && (p = setp[i]); i++)
  236. if (strcmp(p, xmod) && (!xinput || strcmp(p, xinput))) {
  237. ep->name = NEWSTR(p);
  238. ep++;
  239. }
  240. if (renv && renv->im_mod) {
  241. ep->name = NEWSTR(xmod);
  242. bp = strcpyx(bp = buf, ENV_MOD_IM); /* "@im=" */
  243. bp = strcpyx(bp, renv->im_mod);
  244. ep->value = NEWSTR(buf);
  245. ep++;
  246. xmod_done = True;
  247. }
  248. # ifdef old_hpux
  249. if (!xinput_done && (proto == Proto_Xhp)) {
  250. #ifdef DEBUG
  251. if (!ims->servername) {
  252. DPR(("make_new_environ(): '%s' servername not defined\n",
  253. sel->name));
  254. }
  255. #endif
  256. ep->name = NEWSTR(xinput);
  257. ep->value = NEWSTR(ims->servername);
  258. ep++;
  259. xinput_done = True;
  260. }
  261. # endif /* old_hpux */
  262. if (ep == oenv->set) {
  263. FREE(oenv->set); oenv->set = (EnvEnt *)0;
  264. } else
  265. ep->name = NULL;
  266. /* unset: XMODIFIERS & X?INPUT, ims->env_unset */
  267. num = 0;
  268. if (unsetp) for (pp = unsetp; *pp; pp++, num++) ;
  269. ep = oenv->unset = ALLOC(num + 2 + 1, EnvEnt);
  270. if (!xmod_done) {
  271. ep->name = NEWSTR(xmod);
  272. ep++;
  273. xmod_done = True;
  274. }
  275. # ifdef old_hpux
  276. if (!xinput_done) {
  277. ep->name = NEWSTR(xinput);
  278. ep++;
  279. xinput_done = True;
  280. }
  281. # endif /* old_hpux */
  282. for (i = 0; i < num && (p = unsetp[i]); i++) {
  283. if (strcmp(p, xmod) == 0 || (xinput && (strcmp(p, xinput) == 0)))
  284. continue;
  285. if (oenv->set) {
  286. for (ep2 = oenv->set; ep2->name; ep2++)
  287. if (strcmp(p, ep2->name) == 0) {
  288. p = NULL;
  289. break;
  290. }
  291. }
  292. if (p) {
  293. ep->name = NEWSTR(p);
  294. ep++;
  295. }
  296. }
  297. if (ep == oenv->unset) {
  298. FREE(oenv->unset); oenv->unset = (EnvEnt *)0;
  299. } else
  300. ep->name = NULL;
  301. FREE_LIST(setp);
  302. FREE_LIST(unsetp);
  303. FREE(xinput);
  304. return NoError;
  305. }
  306. /* print modified environment variables */
  307. int put_new_environ(OutEnv *oenv)
  308. {
  309. EnvEnt *ep;
  310. char tmpbuf[BUFSIZ], *bp, *vp;
  311. int typ = shell_type(Opt.ShellName);
  312. int len;
  313. /* if (!oenv) return ErrInternal; */
  314. #ifdef DEBUG
  315. if (DebugLvl >= 2)
  316. pr_OutEnv(oenv);
  317. #endif
  318. if (!oenv->set && !oenv->unset) return NoError;
  319. tmpbuf[0] = 0;
  320. if (typ == C_Shell) { /* C-Shell format */
  321. bp = strcpyx(tmpbuf, "set noglob;\n");
  322. if (oenv->set) {
  323. for (ep = oenv->set; ep->name; ep++) {
  324. if (!(vp = ep->value) && (vp = strchr(ep->name, '=')))
  325. *vp++ = '\0';
  326. sprintf(bp, "setenv %s '%s';\n", ep->name, vp);
  327. bp += strlen(bp);
  328. }
  329. }
  330. if (oenv->unset) {
  331. bp = strcpyx(bp, "unsetenv ");
  332. for (ep = oenv->unset; ep->name; ep++) {
  333. *bp++= ' ';
  334. bp = strcpyx(bp, ep->name);
  335. }
  336. }
  337. bp = strcpyx(bp, ";\nunset noglob;\n");
  338. } else { /* B-Shell format */
  339. bp = tmpbuf;
  340. if (oenv->set) {
  341. for (ep = oenv->set; ep->name; ep++) {
  342. if (!(vp = ep->value) && (vp = strchr(ep->name, '=')))
  343. *vp++ = '\0';
  344. sprintf(bp, "%s='%s';\n", ep->name, vp);
  345. bp += strlen(bp);
  346. }
  347. bp = strcpyx(bp, "export ");
  348. for (ep = oenv->set; ep->name; ep++) {
  349. *bp++= ' ';
  350. bp = strcpyx(bp, ep->name);
  351. }
  352. bp = strcpyx(bp, ";\n");
  353. }
  354. if (oenv->unset) {
  355. bp = strcpyx(bp, "unset ");
  356. for (ep = oenv->unset; ep->name; ep++) {
  357. *bp++= ' ';
  358. bp = strcpyx(bp, ep->name);
  359. }
  360. bp = strcpyx(bp, ";\n");
  361. }
  362. }
  363. len = bp - tmpbuf;
  364. DPR3(("put_new_environ(len=%d):\t%s\n", len, tmpbuf));
  365. if (len > 0)
  366. write(1, tmpbuf, len);
  367. return NoError;
  368. }
  369. int set_remote_env(char *ptr, char *env_pass)
  370. {
  371. char *bp = ptr, *ep;
  372. char **ls, **ls2, **pp, **pp2;
  373. bool dup_ent;
  374. ls = ls2 = 0;
  375. if (Conf.remote->passEnv
  376. && (ls = parse_strlist(Conf.remote->passEnv, ' '))) {
  377. for (pp = ls; *pp; pp++)
  378. if (ep = getenv(*pp)) {
  379. *bp++ = ' '; bp = strcpyx(bp, *pp); *bp++ = '=';
  380. *bp++ = '"'; bp = strcpyx(bp, ep); *bp++ = '"';
  381. }
  382. }
  383. if (env_pass && (ls2 = parse_strlist(env_pass, ' '))) {
  384. for (pp2 = ls2; *pp2; pp2++) {
  385. dup_ent = False;
  386. if (ls) { /* eliminate duplicate entries */
  387. for (pp = ls; *pp; pp++)
  388. if (strcmp(*pp, *pp2) == 0) {
  389. dup_ent = True;
  390. break;
  391. }
  392. }
  393. if (!dup_ent && (ep = getenv(*pp2))) {
  394. *bp++ = ' '; bp = strcpyx(bp, *pp2); *bp++ = '=';
  395. *bp++ = '"'; bp = strcpyx(bp, ep); *bp++ = '"';
  396. }
  397. }
  398. FREE_LIST(ls2);
  399. ls2 = 0;
  400. }
  401. if (ls) FREE_LIST(ls);
  402. /* if (bp != ptr) *bp++ = ' '; */
  403. *bp = 0;
  404. DPR2(("set_remote_env('%s' & '%s'):\n\t'%s'\n",
  405. Conf.remote->passEnv, env_pass, ptr));
  406. return bp - ptr;
  407. }
  408. # ifdef old_hpux
  409. char *xhp_xinput_name(char *locale)
  410. {
  411. char *xinput_name = "X@INPUT";
  412. char **pp, *p;
  413. int i, len;
  414. XhpLocale *xhp = Conf.xhp;
  415. char **ls;
  416. char typ = 0;
  417. if (!xhp) return NULL;
  418. if (!locale) locale = userEnv.locale;
  419. for (i = 0; !typ && i < XHP_LANG_NUM; i++) {
  420. if (!(ls = parse_strlist(xhp[i].locales, ' '))) continue;
  421. for (pp = ls; *pp; pp++) {
  422. if (locale[0] != (*pp)[0]) continue;
  423. len = strlen(p = *pp);
  424. if ((p[len - 1] == '*' && strncmp(locale, p, len - 1) == 0)
  425. || strcmp(locale, p) == 0) {
  426. typ = xhp[i].type;
  427. break;
  428. }
  429. }
  430. FREE_LIST(ls);
  431. }
  432. if (!typ) {
  433. DPR2(("xhp_xinput_name(%s): unknown locale\n", locale));
  434. return NULL;
  435. }
  436. xinput_name[1] = typ;
  437. return NEWSTR(xinput_name);
  438. }
  439. char *get_real_locale(char *locale, char ***aliases)
  440. {
  441. int i;
  442. int match_idx = -1;
  443. LocaleAlias **alias = Conf.alias, *ap;
  444. char **ls, **pp;
  445. char *real_locale = NULL;
  446. if (!locale || !alias) return NULL;
  447. for (i = 0; match_idx < 0 && (ap = alias[i]); i++) {
  448. if (strcmp(ap->name, locale) == 0) {
  449. match_idx = i;
  450. if (aliases)
  451. ls = parse_strlist(ap->aliases, ' ');
  452. break;
  453. }
  454. if (ls = parse_strlist(ap->aliases, ' ')) {
  455. for (pp = ls; *pp; pp++)
  456. if (strcmp(locale, *pp) == 0) {
  457. match_idx = i;
  458. break;
  459. }
  460. FREE_LIST(ls);
  461. ls = (char **)NULL;
  462. }
  463. }
  464. if (match_idx >= 0) {
  465. real_locale = alias[match_idx]->name;
  466. if (aliases) {
  467. *aliases = ls;
  468. ls = (char **)NULL;
  469. }
  470. } else {
  471. real_locale = NULL;
  472. if (aliases) *aliases = (char **) NULL;
  473. }
  474. if (ls) FREE_LIST(ls);
  475. DPR(("get_real_locale(%s): real_locale=%s aliases=%s\n",
  476. locale, real_locale, aliases ? *aliases : NULL));
  477. return real_locale;
  478. }
  479. # endif /* old_hpux */