connect.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  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. /*
  24. * File: connect.c $TOG: connect.c /main/8 1998/04/09 17:44:33 mgreess $
  25. * Language: C
  26. *
  27. * (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
  28. *
  29. * (c) Copyright 1993, 1994 Hewlett-Packard Company *
  30. * (c) Copyright 1993, 1994 International Business Machines Corp. *
  31. * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
  32. * (c) Copyright 1993, 1994 Novell, Inc. *
  33. */
  34. #include <Dt/UserMsg.h>
  35. #include <bms/sbport.h> /* NOTE: sbport.h must be the first include. */
  36. #include <sys/socket.h> /**** needed by gethostbyname et al *****/
  37. #define X_INCLUDE_NETDB_H
  38. #define XOS_USE_XT_LOCKING
  39. #include <X11/Xos_r.h>
  40. #include <bms/bms.h>
  41. #include <bms/connect.h>
  42. #include <bms/MemoryMgr.h> /* Xe_make_struct, make_str ... */
  43. #include <bms/XeUserMsg.h>
  44. #include <bms/pathwexp.h> /* Xe_shellexp */
  45. #include "DtSvcLock.h"
  46. #include <codelibs/pathutils.h>
  47. /*
  48. * local variables
  49. */
  50. static XeString context_host = NULL;
  51. static XeString FindDomainHost (XeString host_spec);
  52. static void UnParseFileString (XeString host, XeString path);
  53. static int GetDomainName (XeString buffer, unsigned int bufsize);
  54. #define strequal(xxx_str1, xxx_str2) (!strcmp(xxx_str1, xxx_str2))
  55. /*------------------------------------------------------------------------+*/
  56. XeString
  57. XeCreateContextString(XeString host,
  58. XeString directory,
  59. XeString file)
  60. /*------------------------------------------------------------------------+*/
  61. {
  62. XeString context_string;
  63. host = XeFindShortHost(host);
  64. if ((strequal(directory, (XeString)"")) || (directory == NULL)){
  65. if ((strequal(file, (XeString)"")) || (file == NULL)){
  66. Xe_release_str(host);
  67. return((XeString) NULL);
  68. } else {
  69. context_string = XeMalloc (strlen(host) + strlen(file) + 2);
  70. sprintf (context_string, "%s:%s", host, file);
  71. }
  72. } else {
  73. if ((strequal(file, (XeString)"")) || (file == NULL)){
  74. context_string = XeMalloc(strlen(host) + strlen(directory) + 2);
  75. sprintf (context_string, "%s:%s", host, directory);
  76. }
  77. else {
  78. context_string = XeMalloc(strlen(host) + strlen(directory) +
  79. strlen(file) + 3);
  80. sprintf (context_string, "%s:%s/%s", host, directory, file);
  81. }
  82. }
  83. Xe_release_str(host);
  84. return(context_string);
  85. }
  86. /*------------------------------------------------------------------------+*/
  87. XeString
  88. XeFindShortHost(XeString host_spec)
  89. /*------------------------------------------------------------------------+*/
  90. {
  91. XeString host, ptr, ptr2;
  92. XeChar localhost[MAXHOSTNAMELEN];
  93. if (!host_spec || !host_spec[0] || strequal(host_spec, (XeString)"-")) {
  94. _DtSvcProcessLock();
  95. if (!context_host){
  96. context_host = (XeString) XeMalloc (MAXHOSTNAMELEN);
  97. Xegetcwd(context_host, MAXHOSTNAMELEN);
  98. }
  99. _DtSvcProcessUnlock();
  100. host_spec = context_host;
  101. }
  102. host_spec = Xe_shellexp(host_spec);
  103. ptr = strstr(host_spec, (XeString)".");
  104. if (!ptr) /* short name already */
  105. host = strdup(host_spec);
  106. else {
  107. GetDomainName(localhost, MAXHOSTNAMELEN);
  108. ptr2 = strstr(localhost, (XeString)".");
  109. if (ptr2 && strequal(ptr, ptr2)) { /* domains same, can eliminate */
  110. host = Xe_make_ntype(ptr-host_spec+1, XeChar);
  111. strncpy(host, host_spec, ptr-host_spec); /* copy only up to "." */
  112. host[ptr-host_spec] = '\0'; /* NULL terminate copy */
  113. }
  114. else
  115. host = strdup(host_spec);
  116. }
  117. return host;
  118. }
  119. /* temporary without domain comparisons */
  120. /*------------------------------------------------------------------------+*/
  121. XeString
  122. XeFindHost(XeString host_spec)
  123. /*------------------------------------------------------------------------+*/
  124. {
  125. if (!host_spec || !host_spec[0] || strequal(host_spec, (XeString)"-")) {
  126. _DtSvcProcessLock();
  127. if (!context_host){
  128. context_host = (XeString) XeMalloc (MAXHOSTNAMELEN);
  129. Xegetcwd(context_host, MAXHOSTNAMELEN);
  130. }
  131. _DtSvcProcessUnlock();
  132. host_spec = context_host;
  133. }
  134. host_spec = Xe_shellexp(host_spec);
  135. return strdup(host_spec);
  136. }
  137. /* this should be XeFindHost but is called other name for 1.0 operation
  138. using only simple names if in short domain. See defect HZNlp05737 */
  139. /*------------------------------------------------------------------------+*/
  140. static XeString
  141. FindDomainHost(XeString host_spec)
  142. /*------------------------------------------------------------------------+*/
  143. {
  144. XeString host;
  145. XeString ptr;
  146. XeChar localhost[MAXHOSTNAMELEN];
  147. if (!host_spec || !host_spec[0] || strequal(host_spec, (XeString)"-")) {
  148. _DtSvcProcessLock();
  149. if (!context_host){
  150. context_host = (XeString) XeMalloc (MAXHOSTNAMELEN);
  151. Xegetcwd(context_host, MAXHOSTNAMELEN);
  152. }
  153. _DtSvcProcessUnlock();
  154. host_spec = context_host;
  155. }
  156. else if (strequal(host_spec, (XeString)"*")) {
  157. host_spec = strdup((XeString)"*");
  158. return host_spec;
  159. }
  160. host_spec = Xe_shellexp(host_spec);
  161. ptr = strstr(host_spec, (XeString)".");
  162. if (ptr)
  163. host = strdup(host_spec);
  164. else {
  165. GetDomainName(localhost, MAXHOSTNAMELEN);
  166. ptr = strstr(localhost, (XeString)"."); /* points to domain name if one exists */
  167. if (ptr) {
  168. host = Xe_make_ntype(strlen(host_spec)+strlen(ptr)+1, XeChar);
  169. strcpy(host, host_spec);
  170. strcat(host, ptr);
  171. }
  172. else
  173. host = strdup(host_spec);
  174. }
  175. return(host);
  176. }
  177. /****** XeParseFileString and UnParseFileString work together to munge and
  178. unmunge a path into a host path pair. UnParseFileString DOES NOT WORK
  179. FOR ARBITRARY STRINGS. It is not a general functions (it is a hack).
  180. Do not use It as a general function.
  181. ******/
  182. /*------------------------------------------------------------------------+*/
  183. static void
  184. UnParseFileString(XeString host, XeString path)
  185. /*------------------------------------------------------------------------+*/
  186. {
  187. if (host) { /* there was a host in the original string */
  188. *--path = (XeChar) ':';
  189. }
  190. }
  191. /*------------------------------------------------------------------------+*/
  192. int
  193. XeParseFileString(XeString line,
  194. XeString *host_addr,
  195. XeString *path_addr)
  196. /*------------------------------------------------------------------------+*/
  197. {
  198. XeString current_position = line;
  199. if ((XeChar)'/' == *line) {
  200. *host_addr = XeString_NULL;
  201. *path_addr = line;
  202. return(0);
  203. }
  204. while (*current_position && ((XeChar) ':' != *current_position)) {
  205. int len;
  206. if ((len = mblen(current_position, MB_CUR_MAX)) > 1)
  207. current_position += len;
  208. else
  209. current_position++;
  210. }
  211. if (*current_position) { /* host was specified */
  212. *current_position++ = XeChar_NULL; /* ":" goes to NULL */
  213. *host_addr = line;
  214. *path_addr = current_position;
  215. } else {
  216. *host_addr = XeString_NULL;
  217. *path_addr = line;
  218. }
  219. return(0);
  220. }
  221. /***** Xegethostname is a replacement for gethostname which always returns the
  222. canonical (domain) hostname
  223. ******/
  224. static XeString domainname = XeString_NULL;
  225. /* this should be Xegethostname but is called other name for 1.0 operation
  226. using only simple names if in short domain. See defect HZNlp05737 */
  227. /*------------------------------------------------------------------------+*/
  228. static int
  229. GetDomainName(XeString buffer, unsigned int bufsize)
  230. /*------------------------------------------------------------------------+*/
  231. {
  232. XeString tmpbuf = Xe_make_buffer(bufsize);
  233. XeString ptr;
  234. struct hostent *host_ret;
  235. _Xgethostbynameparams host_buf;
  236. static Boolean firstPass = TRUE;
  237. int status;
  238. /* try to get domain name from hostname */
  239. if ((status = gethostname(tmpbuf, bufsize))) {
  240. XeFree(tmpbuf);
  241. return status; /* failed gethostname */
  242. }
  243. ptr = strstr(tmpbuf, (XeString)".");
  244. _DtSvcProcessLock();
  245. if (domainname && ptr && strcmp(domainname, ptr)) /* domains are different */
  246. _DtSimpleError(XeProgName, XeWarning, NULL, (XeString) "><Domain configured in hostname and domain server are different: '%s', '%s'", domainname, ptr);
  247. if (!domainname && ptr)
  248. domainname = strdup(ptr);
  249. if (ptr) { /* "." in hostname */
  250. strncpy(buffer, tmpbuf, bufsize);
  251. XeFree(tmpbuf);
  252. _DtSvcProcessUnlock();
  253. return 0;
  254. }
  255. /* look up domain name in domain server */
  256. if (!domainname && (firstPass)) {
  257. firstPass = FALSE;
  258. host_ret = _XGethostbyname(tmpbuf, host_buf);
  259. if (host_ret == NULL) {
  260. _DtSimpleError(XeProgName, XeWarning, NULL, (XeString) "><%s not found in hosts database", tmpbuf);
  261. _DtSvcProcessUnlock();
  262. return -1;
  263. }
  264. if ((ptr = strstr(host_ret->h_name, (XeString)"."))) /* if dot in canonical name */
  265. domainname = strdup(ptr);
  266. }
  267. /* construct full domain name for return */
  268. strncpy(buffer, tmpbuf, bufsize);
  269. if (domainname)
  270. strncat(buffer, domainname, bufsize - strlen(tmpbuf));
  271. XeFree(tmpbuf);
  272. _DtSvcProcessUnlock();
  273. return 0;
  274. }
  275. /*------------------------------------------------------------------------+*/
  276. int
  277. Xegetshorthostname(XeString buffer, unsigned int bufsize)
  278. /*------------------------------------------------------------------------+*/
  279. {
  280. XeString ptr;
  281. int status;
  282. if ((status = gethostname(buffer, bufsize)))
  283. return status; /* failed gethostname */
  284. if ((ptr = strstr(buffer, (XeString)".")))
  285. *ptr = '\0'; /* delete domain name if there is one */
  286. return 0;
  287. }
  288. /*------------------------------------------------------------------------+*/
  289. int
  290. Xegethostname(XeString buffer, unsigned int bufsize)
  291. /*------------------------------------------------------------------------+*/
  292. {
  293. return Xegetshorthostname(buffer, bufsize);
  294. }
  295. /*------------------------------------------------------------------------+*/
  296. Boolean
  297. XeIsLocalHostP(XeString hostname)
  298. /*------------------------------------------------------------------------+*/
  299. {
  300. XeChar localhost[MAXHOSTNAMELEN];
  301. XeString found_host = FindDomainHost(hostname);
  302. int status;
  303. GetDomainName(localhost, MAXHOSTNAMELEN);
  304. status = strcmp(localhost, found_host)==0;
  305. XeFree(found_host);
  306. return status;
  307. }
  308. /*------------------------------------------------------------------------+*/
  309. Boolean
  310. XeIsSameHostP(XeString host1, XeString host2)
  311. /*------------------------------------------------------------------------+*/
  312. {
  313. XeString long_host1 = FindDomainHost(host1);
  314. XeString long_host2 = FindDomainHost(host2);
  315. int status = strcmp(long_host1, long_host2) == 0;
  316. if (!host1 || !host1[0] || !strcmp(host1,(XeString)"-")
  317. || !host2 || !host2[0] || !strcmp(host2,(XeString)"-"))
  318. status = strcmp(host1, host2) == 0;
  319. XeFree(long_host1);
  320. XeFree(long_host2);
  321. return status;
  322. }
  323. /* note the following functions use char not Xechar because they are
  324. plug replacements for the Unix functions */
  325. static char *last_env_string = NULL; /* save env so it can be freed later */
  326. /* Note: only use this function for $PWD as it assumes it can free the
  327. env variable when a new one is assigned -- this will only be true if
  328. the same variable is used for all calls to copying_putenv */
  329. static void
  330. copying_putenv(char *env)
  331. {
  332. char *env_copy = XeCopyStringM(env);
  333. putenv(env_copy);
  334. _DtSvcProcessLock();
  335. if (last_env_string)
  336. XeFree(last_env_string);
  337. last_env_string = env_copy;
  338. _DtSvcProcessUnlock();
  339. }
  340. /*------------------------------------------------------------------------+*/
  341. char *
  342. Xegetcwd(char *buf, int size)
  343. /*------------------------------------------------------------------------+*/
  344. {
  345. Boolean pwd_ok = FALSE;
  346. char *env, *current_dir;
  347. if ((current_dir = getenv("PWD"))) { /* use PWD instead of slow call */
  348. int s1, s2;
  349. struct stat sb1, sb2;
  350. /* The code used to copy size-1 bytes. This is a waste most of */
  351. /* the time. All we need to copy is strlen($PWD) bytes unless */
  352. /* there are more bytes that fit into the array passed in. */
  353. int len=strlen(current_dir);
  354. if (len > size-1)
  355. len = size-1;
  356. strncpy(buf, current_dir, len);
  357. buf[len] = '\0';
  358. /* Make sure $PWD is the same as "." before we trust it. */
  359. /* All this is still much faster the getcwd() esp. on UX discless. */
  360. s1 = stat(buf, &sb1);
  361. s2 = stat(".", &sb2);
  362. /* If device and inode are the same, we have a match */
  363. pwd_ok = ((s1 == 0 && s2 == 0) &&
  364. (sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino) );
  365. }
  366. if (!pwd_ok) {
  367. current_dir = getcwd(buf, size);
  368. env = XeMalloc(MAXPATHLEN+10);
  369. sprintf(env, "PWD=%s", buf);
  370. copying_putenv(env); /* set PWD if necessary for later cache use */
  371. XeFree(env);
  372. }
  373. return current_dir;
  374. }
  375. /*------------------------------------------------------------------------+*/
  376. int
  377. Xechdir (const char *path)
  378. /*------------------------------------------------------------------------+*/
  379. {
  380. int status;
  381. char *simple_path = NULL;
  382. char *env;
  383. char buf[MAXPATHLEN+10];
  384. if ((status = chdir(path))==0) {
  385. env = XeMalloc(MAXPATHLEN+10);
  386. if (path[0] != '/') { /* relative path */
  387. path = getcwd(buf, sizeof buf);
  388. sprintf(env, "PWD=%s", path);
  389. }
  390. else {
  391. char *canon_path = pathcollapse(path, NULL, FALSE);
  392. /* absolute path */
  393. sprintf(env, "PWD=%s", canon_path);
  394. /* note XeFree() not appropriate if Xemalloc not used */
  395. free(canon_path);
  396. }
  397. copying_putenv(env); /* update PWD if directory changed */
  398. XeFree(env);
  399. }
  400. return status;
  401. }