PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/socket.c

https://github.com/amade/screen
C | 1428 lines | 1186 code | 106 blank | 136 comment | 379 complexity | dffef785003871c1a8e83d08ae9c38ef MD5 | raw file
Possible License(s): GPL-3.0
  1. /* Copyright (c) 2008, 2009
  2. * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3. * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4. * Micah Cowan (micah@cowan.name)
  5. * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
  6. * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
  7. * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  8. * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  9. * Copyright (c) 1987 Oliver Laumann
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 3, or (at your option)
  14. * any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program (see the file COPYING); if not, see
  23. * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
  24. * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
  25. *
  26. ****************************************************************
  27. */
  28. #include "config.h"
  29. #include "socket.h"
  30. #include <pwd.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <fcntl.h>
  34. #include <sys/socket.h>
  35. #ifdef _OpenBSD_
  36. #include <sys/uio.h>
  37. #endif
  38. #include <sys/un.h>
  39. #include <utime.h>
  40. #include <stdint.h>
  41. #include <stdbool.h>
  42. #include <string.h>
  43. #include <unistd.h>
  44. #include <signal.h>
  45. #if ENABLE_PAM
  46. #include <security/pam_appl.h>
  47. #else
  48. #include <shadow.h>
  49. #endif
  50. #include "screen.h"
  51. #ifdef HAVE_DIRENT_H
  52. #include <dirent.h>
  53. #else
  54. #include <sys/dir.h>
  55. #define dirent direct
  56. #endif
  57. #ifndef CMSG_LEN
  58. #define CMSG_LEN(length) ((_CMSG_DATA_ALIGN(sizeof(struct cmsghdr))) + (length))
  59. #endif
  60. #ifndef CMSG_SPACE
  61. #define CMSG_SPACE(length) ((_CMSG_DATA_ALIGN(sizeof(struct cmsghdr))) + (_CMSG_DATA_ALIGN(length)))
  62. #endif
  63. #include "encoding.h"
  64. #include "fileio.h"
  65. #include "list_generic.h"
  66. #include "misc.h"
  67. #include "process.h"
  68. #include "resize.h"
  69. #include "termcap.h"
  70. #include "tty.h"
  71. #include "utmp.h"
  72. static int CheckPid(pid_t);
  73. static void ExecCreate(Message *);
  74. static void DoCommandMsg(Message *);
  75. static void FinishAttach(Message *);
  76. static void FinishDetach(Message *);
  77. static void AskPassword(Message *);
  78. static bool CheckPassword(const char *password);
  79. static void PasswordProcessInput(char *, size_t);
  80. #define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0) | (multi ? 1 : 0))
  81. /*
  82. * Socket directory manager
  83. *
  84. * fdp: pointer to store the first good socket.
  85. * nfoundp: pointer to store the number of sockets found matching.
  86. * notherp: pointer to store the number of sockets not matching.
  87. * match: string to match socket name.
  88. *
  89. * The socket directory must be in SocketPath!
  90. * The global variables LoginName, multi, rflag, xflag, dflag,
  91. * quietflag, SocketPath are used.
  92. *
  93. * The first good socket is stored in fdp and its name is
  94. * appended to SocketPath.
  95. * If none exists or fdp is NULL SocketPath is not changed.
  96. *
  97. * Returns: number of good sockets.
  98. *
  99. */
  100. int FindSocket(int *fdp, int *nfoundp, int *notherp, char *match)
  101. {
  102. DIR *dirp;
  103. struct dirent *dp;
  104. struct stat st;
  105. int mode;
  106. int sdirlen;
  107. int matchlen = 0;
  108. char *name, *n;
  109. int firsts = -1, sockfd;
  110. char *firstn = NULL;
  111. int nfound = 0, ngood = 0, ndead = 0, nwipe = 0, npriv = 0;
  112. int nperfect = 0;
  113. struct sent {
  114. struct sent *next;
  115. int mode;
  116. char *name;
  117. } *slist, **slisttail, *sent, *nsent;
  118. if (match) {
  119. matchlen = strlen(match);
  120. if (matchlen > FILENAME_MAX)
  121. matchlen = FILENAME_MAX;
  122. }
  123. /*
  124. * SocketPath contains the socket directory.
  125. * At the end of FindSocket the socket name will be appended to it.
  126. * Thus FindSocket() can only be called once!
  127. */
  128. sdirlen = strlen(SocketPath);
  129. xseteuid(real_uid);
  130. xsetegid(real_gid);
  131. if ((dirp = opendir(SocketPath)) == NULL)
  132. Panic(errno, "Cannot opendir %s", SocketPath);
  133. slist = NULL;
  134. slisttail = &slist;
  135. while ((dp = readdir(dirp))) {
  136. int cmatch = 0;
  137. name = dp->d_name;
  138. if (*name == 0 || *name == '.' || strlen(name) > 2 * MAXSTR)
  139. continue;
  140. if (matchlen) {
  141. n = name;
  142. /* if we don't want to match digits. Skip them */
  143. if ((*match <= '0' || *match > '9') && (*n > '0' && *n <= '9')) {
  144. while (*n >= '0' && *n <= '9')
  145. n++;
  146. if (*n == '.')
  147. n++;
  148. }
  149. /* the tty prefix is optional */
  150. if (strncmp(match, "tty", 3) && strncmp(n, "tty", 3) == 0)
  151. n += 3;
  152. if (strncmp(match, n, matchlen)) {
  153. if (n == name && *match > '0' && *match <= '9') {
  154. while (*n >= '0' && *n <= '9')
  155. n++;
  156. if (*n == '.')
  157. n++;
  158. if (strncmp(match, n, matchlen))
  159. continue;
  160. } else
  161. continue;
  162. } else
  163. cmatch = (*(n + matchlen) == 0);
  164. }
  165. sprintf(SocketPath + sdirlen, "/%s", name);
  166. errno = 0;
  167. if (stat(SocketPath, &st)) {
  168. continue;
  169. }
  170. #ifdef SOCKET_DIR /* if SOCKET_DIR is not defined, the socket is in $HOME.
  171. in that case it does not make sense to compare uids. */
  172. if (st.st_uid != real_uid)
  173. continue;
  174. #endif
  175. mode = (int)st.st_mode & 0777;
  176. if (multi && ((mode & 0677) != 0601)) {
  177. if (strcmp(multi, LoginName)) {
  178. mode = -4;
  179. } else {
  180. }
  181. }
  182. if ((sent = malloc(sizeof(struct sent))) == NULL)
  183. continue;
  184. sent->next = NULL;
  185. sent->name = SaveStr(name);
  186. sent->mode = mode;
  187. *slisttail = sent;
  188. slisttail = &sent->next;
  189. nfound++;
  190. sockfd = MakeClientSocket(0);
  191. /* MakeClientSocket sets ids back to eff */
  192. xseteuid(real_uid);
  193. xsetegid(real_gid);
  194. if (sockfd == -1) {
  195. sent->mode = -3;
  196. #ifndef SOCKDIR_IS_LOCAL_TO_HOST
  197. /* Unreachable - it is dead if we detect that it's local
  198. * or we specified a match
  199. */
  200. n = name + strlen(name) - 1;
  201. while (n != name && *n != '.')
  202. n--;
  203. if (matchlen == 0 && !(*n == '.' && n[1] && strncmp(HostName, n + 1, strlen(n + 1)) == 0)) {
  204. npriv++; /* a good socket that was not for us */
  205. continue;
  206. }
  207. #endif
  208. ndead++;
  209. sent->mode = -1;
  210. if (wipeflag) {
  211. if (unlink(SocketPath) == 0) {
  212. sent->mode = -2;
  213. nwipe++;
  214. }
  215. }
  216. continue;
  217. }
  218. mode &= 0776;
  219. /* Shall we connect ? */
  220. /*
  221. * mode 600: socket is detached.
  222. * mode 700: socket is attached.
  223. * xflag implies rflag here.
  224. *
  225. * fail, when socket mode mode is not 600 or 700
  226. * fail, when we want to detach w/o reattach, but it already is detached.
  227. * fail, when we only want to attach, but mode 700 and not xflag.
  228. * fail, if none of dflag, rflag, xflag is set.
  229. */
  230. if ((mode != 0700 && mode != 0600) ||
  231. (dflag && !rflag && !xflag && mode == 0600) ||
  232. (!dflag && rflag && mode == 0700 && !xflag) || (!dflag && !rflag && !xflag)) {
  233. close(sockfd);
  234. npriv++; /* a good socket that was not for us */
  235. continue;
  236. }
  237. ngood++;
  238. if (cmatch)
  239. nperfect++;
  240. if (fdp && (firsts == -1 || (cmatch && nperfect == 1))) {
  241. if (firsts != -1)
  242. close(firsts);
  243. firsts = sockfd;
  244. firstn = sent->name;
  245. } else {
  246. close(sockfd);
  247. }
  248. }
  249. (void)closedir(dirp);
  250. if (!lsflag && nperfect == 1)
  251. ngood = nperfect;
  252. if (nfound && (lsflag || ngood != 1) && !quietflag) {
  253. switch (ngood) {
  254. case 0:
  255. Msg(0, nfound > 1 ? "There are screens on:" : "There is a screen on:");
  256. break;
  257. case 1:
  258. Msg(0, nfound > 1 ? "There are several screens on:" : "There is a suitable screen on:");
  259. break;
  260. default:
  261. Msg(0, "There are several suitable screens on:");
  262. break;
  263. }
  264. for (sent = slist; sent; sent = sent->next) {
  265. switch (sent->mode) {
  266. case 0700:
  267. printf("\t%s\t(Attached)\n", sent->name);
  268. break;
  269. case 0600:
  270. printf("\t%s\t(Detached)\n", sent->name);
  271. break;
  272. case 0701:
  273. printf("\t%s\t(Multi, attached)\n", sent->name);
  274. break;
  275. case 0601:
  276. printf("\t%s\t(Multi, detached)\n", sent->name);
  277. break;
  278. case -1:
  279. /* No trigraphs here! */
  280. printf("\t%s\t(Dead ?%c?)\n", sent->name, '?');
  281. break;
  282. case -2:
  283. printf("\t%s\t(Removed)\n", sent->name);
  284. break;
  285. case -3:
  286. printf("\t%s\t(Remote or dead)\n", sent->name);
  287. break;
  288. case -4:
  289. printf("\t%s\t(Private)\n", sent->name);
  290. break;
  291. }
  292. }
  293. }
  294. if (ndead && !quietflag) {
  295. char *m = "Remove dead screens with 'screen -wipe'.";
  296. if (wipeflag)
  297. Msg(0, "%d socket%s wiped out.", nwipe, nwipe > 1 ? "s" : "");
  298. else
  299. Msg(0, m, ndead > 1 ? "s" : "", ndead > 1 ? "" : "es");
  300. }
  301. if (firsts != -1) {
  302. sprintf(SocketPath + sdirlen, "/%s", firstn);
  303. *fdp = firsts;
  304. } else
  305. SocketPath[sdirlen] = 0;
  306. for (sent = slist; sent; sent = nsent) {
  307. nsent = sent->next;
  308. free(sent->name);
  309. free((char *)sent);
  310. }
  311. xseteuid(eff_uid);
  312. xsetegid(eff_gid);
  313. if (notherp)
  314. *notherp = npriv;
  315. if (nfoundp)
  316. *nfoundp = nfound - nwipe;
  317. return ngood;
  318. }
  319. /*
  320. **
  321. ** Socket/pipe create routines
  322. **
  323. */
  324. int MakeServerSocket(void)
  325. {
  326. int s;
  327. struct sockaddr_un a;
  328. struct stat st;
  329. if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  330. Panic(errno, "socket");
  331. a.sun_family = AF_UNIX;
  332. strncpy(a.sun_path, SocketPath, ARRAY_SIZE(a.sun_path));
  333. a.sun_path[ARRAY_SIZE(a.sun_path) - 1] = 0;
  334. xseteuid(real_uid);
  335. xsetegid(real_gid);
  336. if (connect(s, (struct sockaddr *)&a, strlen(SocketPath) + 2) != -1) {
  337. if (quietflag) {
  338. Kill(D_userpid, SIG_BYE);
  339. /*
  340. * oh, well. nobody receives that return code. papa
  341. * dies by signal.
  342. */
  343. eexit(11);
  344. }
  345. Msg(0, "There is already a screen running on %s.", Filename(SocketPath));
  346. if (stat(SocketPath, &st) == -1)
  347. Panic(errno, "stat");
  348. #ifdef SOCKET_DIR /* if SOCKET_DIR is not defined, the socket is in $HOME.
  349. in that case it does not make sense to compare uids. */
  350. if (st.st_uid != real_uid)
  351. Panic(0, "Unfortunately you are not its owner.");
  352. #endif
  353. if ((st.st_mode & 0700) == 0600)
  354. Panic(0, "To resume it, use \"screen -r\"");
  355. else
  356. Panic(0, "It is not detached.");
  357. /* NOTREACHED */
  358. }
  359. (void)unlink(SocketPath);
  360. if (bind(s, (struct sockaddr *)&a, strlen(SocketPath) + 2) == -1)
  361. Panic(errno, "bind (%s)", SocketPath);
  362. chmod(SocketPath, SOCKMODE);
  363. if (chown(SocketPath, real_uid, real_gid))
  364. Panic(errno, "chown");
  365. if (listen(s, 5) == -1)
  366. Panic(errno, "listen");
  367. #ifdef F_SETOWN
  368. fcntl(s, F_SETOWN, getpid());
  369. #endif /* F_SETOWN */
  370. xseteuid(eff_uid);
  371. xsetegid(eff_gid);
  372. return s;
  373. }
  374. int MakeClientSocket(int err)
  375. {
  376. int s;
  377. struct sockaddr_un a;
  378. if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  379. Panic(errno, "socket");
  380. a.sun_family = AF_UNIX;
  381. strncpy(a.sun_path, SocketPath, ARRAY_SIZE(a.sun_path));
  382. a.sun_path[ARRAY_SIZE(a.sun_path) - 1] = 0;
  383. xseteuid(real_uid);
  384. xsetegid(real_gid);
  385. if (connect(s, (struct sockaddr *)&a, strlen(SocketPath) + 2) == -1) {
  386. if (err)
  387. Msg(errno, "%s: connect", SocketPath);
  388. close(s);
  389. s = -1;
  390. }
  391. xseteuid(eff_uid);
  392. xsetegid(eff_gid);
  393. return s;
  394. }
  395. /*
  396. **
  397. ** Message send and receive routines
  398. **
  399. */
  400. void SendCreateMsg(char *sty, struct NewWindow *nwin)
  401. {
  402. int s;
  403. Message m;
  404. char *p;
  405. size_t len, n;
  406. char **av;
  407. if (strlen(sty) > FILENAME_MAX)
  408. sty[FILENAME_MAX] = 0;
  409. if (strlen(sty) > 2 * MAXSTR - 1)
  410. sty[2 * MAXSTR - 1] = 0;
  411. sprintf(SocketPath + strlen(SocketPath), "/%s", sty);
  412. if ((s = MakeClientSocket(1)) == -1)
  413. exit(1);
  414. memset((char *)&m, 0, sizeof(Message));
  415. m.type = MSG_CREATE;
  416. strncpy(m.m_tty, attach_tty, ARRAY_SIZE(m.m_tty) - 1);
  417. m.m_tty[ARRAY_SIZE(m.m_tty) - 1] = 0;
  418. p = m.m.create.line;
  419. n = 0;
  420. if (nwin->args != nwin_undef.args)
  421. for (av = nwin->args; *av && n < MAXARGS - 1; ++av, ++n) {
  422. len = strlen(*av) + 1;
  423. if (p + len >= m.m.create.line + ARRAY_SIZE(m.m.create.line) - 1)
  424. break;
  425. strcpy(p, *av);
  426. p += len;
  427. }
  428. if (nwin->aka != nwin_undef.aka && p + strlen(nwin->aka) + 1 < m.m.create.line + ARRAY_SIZE(m.m.create.line))
  429. strcpy(p, nwin->aka);
  430. else
  431. *p = '\0';
  432. m.m.create.nargs = n;
  433. m.m.create.aflag = nwin->aflag;
  434. m.m.create.flowflag = nwin->flowflag;
  435. m.m.create.lflag = nwin->lflag;
  436. m.m.create.Lflag = nwin->Lflag;
  437. m.m.create.hheight = nwin->histheight;
  438. if (getcwd(m.m.create.dir, ARRAY_SIZE(m.m.create.dir)) == NULL) {
  439. Msg(errno, "getcwd");
  440. goto end;
  441. }
  442. if (nwin->term != nwin_undef.term)
  443. strncpy(m.m.create.screenterm, nwin->term, MAXTERMLEN);
  444. m.m.create.screenterm[MAXTERMLEN] = '\0';
  445. m.protocol_revision = MSG_REVISION;
  446. if (write(s, (char *)&m, sizeof(Message)) != sizeof(Message))
  447. Msg(errno, "write");
  448. end:
  449. close(s);
  450. }
  451. int SendErrorMsg(char *tty, char *buf)
  452. {
  453. int s;
  454. int ret = 0;
  455. Message m;
  456. strncpy(m.m.message, buf, ARRAY_SIZE(m.m.message) - 1);
  457. m.m.message[ARRAY_SIZE(m.m.message) - 1] = 0;
  458. s = MakeClientSocket(0);
  459. if (s < 0)
  460. return -1;
  461. m.type = MSG_ERROR;
  462. strncpy(m.m_tty, tty, ARRAY_SIZE(m.m_tty) - 1);
  463. m.m_tty[ARRAY_SIZE(m.m_tty) - 1] = 0;
  464. m.protocol_revision = MSG_REVISION;
  465. if (write(s, (char *)&m, sizeof(Message)))
  466. ret = -2;
  467. close(s);
  468. return ret;
  469. }
  470. static void ExecCreate(Message *mp)
  471. {
  472. struct NewWindow nwin;
  473. char *args[MAXARGS];
  474. int n;
  475. char **pp = args, *p = mp->m.create.line;
  476. char buf[20];
  477. nwin = nwin_undef;
  478. n = mp->m.create.nargs;
  479. if (n > MAXARGS - 1)
  480. n = MAXARGS - 1;
  481. /* ugly hack alert... should be done by the frontend! */
  482. if (n) {
  483. int l, num;
  484. l = strlen(p);
  485. if (IsNumColon(p, buf, ARRAY_SIZE(buf))) {
  486. if (*buf)
  487. nwin.aka = buf;
  488. num = atoi(p);
  489. if (num < 0 || num > last_window->w_number)
  490. num = 0;
  491. nwin.StartAt = num;
  492. p += l + 1;
  493. n--;
  494. }
  495. }
  496. for (; n > 0; n--) {
  497. *pp++ = p;
  498. p += strlen(p) + 1;
  499. }
  500. *pp = NULL;
  501. if (*p)
  502. nwin.aka = p;
  503. if (*args)
  504. nwin.args = args;
  505. nwin.aflag = mp->m.create.aflag;
  506. nwin.flowflag = mp->m.create.flowflag;
  507. if (*mp->m.create.dir)
  508. nwin.dir = mp->m.create.dir;
  509. nwin.lflag = mp->m.create.lflag;
  510. nwin.Lflag = mp->m.create.Lflag;
  511. nwin.histheight = mp->m.create.hheight;
  512. if (*mp->m.create.screenterm)
  513. nwin.term = mp->m.create.screenterm;
  514. MakeWindow(&nwin);
  515. }
  516. static int CheckPid(pid_t pid)
  517. {
  518. if (pid < 2)
  519. return -1;
  520. if (eff_uid == real_uid)
  521. return kill(pid, 0);
  522. if (UserContext() > 0)
  523. UserReturn(kill(pid, 0));
  524. return UserStatus();
  525. }
  526. static int CreateTempDisplay(Message *m, int recvfd, Window *win)
  527. {
  528. pid_t pid;
  529. int attach;
  530. char *user;
  531. int i;
  532. struct mode Mode;
  533. Display *olddisplays = displays;
  534. switch (m->type) {
  535. case MSG_CONT:
  536. case MSG_ATTACH:
  537. pid = m->m.attach.apid;
  538. user = m->m.attach.auser;
  539. attach = 1;
  540. break;
  541. case MSG_DETACH:
  542. case MSG_POW_DETACH:
  543. pid = m->m.detach.dpid;
  544. user = m->m.detach.duser;
  545. attach = 0;
  546. break;
  547. default:
  548. return -1;
  549. }
  550. if (CheckPid(pid)) {
  551. Msg(0, "Attach attempt with bad pid(%d)!", pid);
  552. return -1;
  553. }
  554. if (recvfd != -1) {
  555. char ttyname_in_ns[MAXPATHLEN] = {0};
  556. char *myttyname;
  557. i = recvfd;
  558. errno = 0;
  559. myttyname = GetPtsPathOrSymlink(i);
  560. if (myttyname && errno == ENODEV) {
  561. ssize_t ret = readlink(myttyname, ttyname_in_ns,
  562. ARRAY_SIZE(ttyname_in_ns));
  563. if (ret < 0 || (size_t)ret >= ARRAY_SIZE(ttyname_in_ns)) {
  564. Msg(errno, "Could not perform necessary sanity "
  565. "checks on pts device.");
  566. close(i);
  567. Kill(pid, SIG_BYE);
  568. return -1;
  569. }
  570. if (strcmp(ttyname_in_ns, m->m_tty)) {
  571. Msg(errno, "Attach: passed fd does not match "
  572. "tty: %s - %s!",
  573. ttyname_in_ns,
  574. m->m_tty[0] != '\0' ? m->m_tty : "(null)");
  575. close(i);
  576. Kill(pid, SIG_BYE);
  577. return -1;
  578. }
  579. /* m->m_tty so far contains the actual name of the pts
  580. * device in its namespace (e.g. /dev/pts/0). This name
  581. * however is not valid in the current namespace. So
  582. * after we verified that the symlink returned by
  583. * GetPtsPathOrSymlink() refers to the same pts device
  584. * in this namespace we need to update m->m_tty to use
  585. * that symlink for all future operations.
  586. */
  587. strncpy(m->m_tty, myttyname, ARRAY_SIZE(m->m_tty) - 1);
  588. m->m_tty[ARRAY_SIZE(m->m_tty) - 1] = 0;
  589. } else if (myttyname == NULL || strcmp(myttyname, m->m_tty)) {
  590. Msg(errno,
  591. "Attach: passed fd does not match tty: %s - %s!",
  592. m->m_tty, myttyname ? myttyname : "NULL");
  593. close(i);
  594. Kill(pid, SIG_BYE);
  595. return -1;
  596. }
  597. } else if ((i = secopen(m->m_tty, O_RDWR | O_NONBLOCK, 0)) < 0) {
  598. Msg(errno, "Attach: Could not open %s!", m->m_tty);
  599. Kill(pid, SIG_BYE);
  600. return -1;
  601. }
  602. if (attach)
  603. Kill(pid, SIGCONT);
  604. if (attach) {
  605. if (display || win) {
  606. int unused_result = write(i, "Attaching from inside of screen?\n", 33);
  607. (void)unused_result; /* unused */
  608. close(i);
  609. Kill(pid, SIG_BYE);
  610. Msg(0, "Attach msg ignored: coming from inside.");
  611. return -1;
  612. }
  613. if (strcmp(user, LoginName))
  614. if (*FindUserPtr(user) == NULL) {
  615. int unused_result = write(i, "Access to session denied.\n", 26);
  616. (void)unused_result; /* unused */
  617. close(i);
  618. Kill(pid, SIG_BYE);
  619. Msg(0, "Attach: access denied for user %s.", user);
  620. return -1;
  621. }
  622. }
  623. /* create new display */
  624. GetTTY(i, &Mode);
  625. if (MakeDisplay(user, m->m_tty, attach ? m->m.attach.envterm : "", i, pid, &Mode) == NULL) {
  626. int unused_result = write(i, "Could not make display.\n", 24);
  627. (void)unused_result; /* unused */
  628. close(i);
  629. Msg(0, "Attach: could not make display for user %s", user);
  630. Kill(pid, SIG_BYE);
  631. return -1;
  632. }
  633. if (attach) {
  634. D_encoding = m->m.attach.encoding == 1 ? UTF8 : m->m.attach.encoding ? m->m.attach.encoding - 1 : 0;
  635. if (D_encoding < 0 || !EncodingName(D_encoding))
  636. D_encoding = 0;
  637. }
  638. if (iflag && olddisplays) {
  639. iflag = false;
  640. olddisplays->d_NewMode.tio.c_cc[VINTR] = VDISABLE;
  641. olddisplays->d_NewMode.tio.c_lflag &= ~ISIG;
  642. SetTTY(olddisplays->d_userfd, &olddisplays->d_NewMode);
  643. }
  644. SetMode(&D_OldMode, &D_NewMode, D_flow, iflag);
  645. SetTTY(D_userfd, &D_NewMode);
  646. if (fcntl(D_userfd, F_SETFL, FNBLOCK))
  647. Msg(errno, "Warning: NBLOCK fcntl failed");
  648. return 0;
  649. }
  650. void ReceiveMsg(void)
  651. {
  652. int left, len;
  653. static Message m;
  654. char *p;
  655. int ns = ServerSocket;
  656. Window *win = NULL;
  657. int recvfd = -1;
  658. struct sockaddr_un a;
  659. struct msghdr msg;
  660. struct iovec iov;
  661. char control[1024];
  662. len = sizeof(a);
  663. if ((ns = accept(ns, (struct sockaddr *)&a, (socklen_t *) &len)) < 0) {
  664. Msg(errno, "accept");
  665. return;
  666. }
  667. p = (char *)&m;
  668. left = sizeof(Message);
  669. memset(&msg, 0, sizeof(struct msghdr));
  670. iov.iov_base = &m;
  671. iov.iov_len = left;
  672. msg.msg_iov = &iov;
  673. msg.msg_iovlen = 1;
  674. msg.msg_controllen = ARRAY_SIZE(control);
  675. msg.msg_control = &control;
  676. while (left > 0) {
  677. len = recvmsg(ns, &msg, 0);
  678. if (len < 0 && errno == EINTR)
  679. continue;
  680. if (len < 0) {
  681. close(ns);
  682. Msg(errno, "read");
  683. return;
  684. }
  685. if (msg.msg_controllen) {
  686. struct cmsghdr *cmsg;
  687. for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
  688. size_t cl;
  689. char *cp;
  690. if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
  691. continue;
  692. cp = (char *)CMSG_DATA(cmsg);
  693. cl = cmsg->cmsg_len;
  694. while (cl >= CMSG_LEN(sizeof(int))) {
  695. int passedfd;
  696. memmove(&passedfd, cp, sizeof(int));
  697. if (recvfd >= 0 && passedfd != recvfd)
  698. close(recvfd);
  699. recvfd = passedfd;
  700. cl -= CMSG_LEN(sizeof(int));
  701. }
  702. }
  703. }
  704. p += len;
  705. left -= len;
  706. break;
  707. }
  708. while (left > 0) {
  709. len = read(ns, p, left);
  710. if (len < 0 && errno == EINTR)
  711. continue;
  712. if (len <= 0)
  713. break;
  714. p += len;
  715. left -= len;
  716. }
  717. close(ns);
  718. if (len < 0) {
  719. Msg(errno, "read");
  720. if (recvfd != -1)
  721. close(recvfd);
  722. return;
  723. }
  724. if (left > 0) {
  725. if (left != sizeof(Message))
  726. Msg(0, "Message %d of %d bytes too small", left, (int)sizeof(Message));
  727. return;
  728. }
  729. if (m.protocol_revision != MSG_REVISION) {
  730. if (recvfd != -1)
  731. close(recvfd);
  732. Msg(0, "Invalid message (magic 0x%08x).", m.protocol_revision);
  733. return;
  734. }
  735. if (m.type != MSG_ATTACH && recvfd != -1) {
  736. close(recvfd);
  737. recvfd = -1;
  738. }
  739. for (display = displays; display; display = display->d_next)
  740. if (strcmp(D_usertty, m.m_tty) == 0)
  741. break;
  742. if (!display) {
  743. for (win = mru_window; win; win = win->w_prev_mru)
  744. if (!strcmp(m.m_tty, win->w_tty)) {
  745. /* XXX: hmmm, rework this? */
  746. display = win->w_layer.l_cvlist ? win->w_layer.l_cvlist->c_display : NULL;
  747. break;
  748. }
  749. }
  750. /* Remove the status to prevent garbage on the screen */
  751. if (display && D_status)
  752. RemoveStatus();
  753. if (display && !D_tcinited && m.type != MSG_HANGUP) {
  754. if (recvfd != -1)
  755. close(recvfd);
  756. return; /* ignore messages for bad displays */
  757. }
  758. switch (m.type) {
  759. case MSG_WINCH:
  760. if (display)
  761. CheckScreenSize(1); /* Change fore */
  762. break;
  763. case MSG_CREATE:
  764. /*
  765. * the window that issued the create message need not be an active
  766. * window. Then we create the window without having a display.
  767. * Resulting in another inactive window.
  768. */
  769. ExecCreate(&m);
  770. break;
  771. case MSG_CONT:
  772. if (display && D_userpid != 0 && kill(D_userpid, 0) == 0)
  773. break; /* Intruder Alert */
  774. /* FALLTHROUGH */
  775. case MSG_ATTACH:
  776. if (CreateTempDisplay(&m, recvfd, win))
  777. break;
  778. AskPassword(&m);
  779. break;
  780. case MSG_ERROR:
  781. {
  782. int blocked = D_blocked;
  783. if (D_blocked == 4) /* allow error messages while in blanker mode */
  784. D_blocked = 0; /* likely they're from failed blanker */
  785. Msg(0, "%s", m.m.message);
  786. D_blocked = blocked;
  787. }
  788. break;
  789. case MSG_HANGUP:
  790. if (!win) /* ignore hangups from inside */
  791. Hangup();
  792. break;
  793. case MSG_DETACH:
  794. case MSG_POW_DETACH:
  795. if (CreateTempDisplay(&m, recvfd, NULL))
  796. break;
  797. AskPassword(&m);
  798. break;
  799. case MSG_QUERY:
  800. {
  801. char *oldSocketPath = SaveStr(SocketPath);
  802. strncpy(SocketPath, m.m.command.writeback, ARRAY_SIZE(SocketPath));
  803. int s = MakeClientSocket(0);
  804. strncpy(SocketPath, oldSocketPath, ARRAY_SIZE(SocketPath));
  805. Free(oldSocketPath);
  806. if (s >= 0) {
  807. queryflag = s;
  808. DoCommandMsg(&m);
  809. close(s);
  810. } else
  811. queryflag = -1;
  812. Kill(m.m.command.apid, (queryflag >= 0) ? SIGCONT : SIG_BYE); /* Send SIG_BYE if an error happened */
  813. queryflag = -1;
  814. }
  815. break;
  816. case MSG_COMMAND:
  817. DoCommandMsg(&m);
  818. break;
  819. default:
  820. Msg(0, "Invalid message (type %d).", m.type);
  821. }
  822. }
  823. void ReceiveRaw(int s)
  824. {
  825. char rd[256];
  826. ssize_t len = 0;
  827. struct sockaddr_un a;
  828. len = sizeof(a);
  829. if ((s = accept(s, (struct sockaddr *)&a, (socklen_t *)&len)) < 0) {
  830. Msg(errno, "accept");
  831. return;
  832. }
  833. while ((len = read(s, rd, 255)) > 0) {
  834. rd[len] = 0;
  835. printf("%s", rd);
  836. }
  837. close(s);
  838. }
  839. /*
  840. * Set the mode bits of the socket to the current status
  841. */
  842. int chsock(void)
  843. {
  844. int ret;
  845. uid_t euid = geteuid();
  846. if (euid != real_uid) {
  847. if (UserContext() <= 0)
  848. return UserStatus();
  849. }
  850. ret = chmod(SocketPath, SOCKMODE);
  851. /*
  852. * Sockets usually reside in the /tmp/ area, where sysadmin scripts
  853. * may be happy to remove old files. We manually prevent the socket
  854. * from becoming old. (chmod does not touch mtime).
  855. */
  856. (void)utimes(SocketPath, NULL);
  857. if (euid != real_uid)
  858. UserReturn(ret);
  859. return ret;
  860. }
  861. /*
  862. * Try to recreate the socket/pipe
  863. */
  864. int RecoverSocket(void)
  865. {
  866. close(ServerSocket);
  867. if (geteuid() != real_uid) {
  868. if (UserContext() > 0)
  869. UserReturn(unlink(SocketPath));
  870. (void)UserStatus();
  871. } else
  872. (void)unlink(SocketPath);
  873. if ((ServerSocket = MakeServerSocket()) < 0)
  874. return 0;
  875. evdeq(&serv_read);
  876. serv_read.fd = ServerSocket;
  877. evenq(&serv_read);
  878. return 1;
  879. }
  880. static void FinishAttach(Message *m)
  881. {
  882. pid_t pid;
  883. int noshowwin;
  884. pid = D_userpid;
  885. if (m->m.attach.detachfirst == MSG_DETACH || m->m.attach.detachfirst == MSG_POW_DETACH)
  886. FinishDetach(m);
  887. /*
  888. * We reboot our Terminal Emulator. Forget all we knew about
  889. * the old terminal, reread the termcap entries in .screenrc
  890. * (and nothing more from .screenrc is read. Mainly because
  891. * I did not check, whether a full reinit is safe. jw)
  892. * and /etc/screenrc, and initialise anew.
  893. */
  894. if (extra_outcap)
  895. free(extra_outcap);
  896. if (extra_incap)
  897. free(extra_incap);
  898. extra_incap = extra_outcap = NULL;
  899. StartRc(SYSTEM_SCREENRC, 1);
  900. StartRc(RcFileName, 1);
  901. if (InitTermcap(m->m.attach.columns, m->m.attach.lines)) {
  902. FreeDisplay();
  903. Kill(pid, SIG_BYE);
  904. return;
  905. }
  906. MakeDefaultCanvas();
  907. InitTerm(m->m.attach.adaptflag); /* write init string on fd */
  908. if (displays->d_next == NULL)
  909. (void)chsock();
  910. xsignal(SIGHUP, SigHup);
  911. if (m->m.attach.esc != -1 && m->m.attach.meta_esc != -1) {
  912. D_user->u_Esc = m->m.attach.esc;
  913. D_user->u_MetaEsc = m->m.attach.meta_esc;
  914. }
  915. #ifdef ENABLE_UTMP
  916. /*
  917. * we set the Utmp slots again, if we were detached normally
  918. * and if we were detached by ^Z.
  919. * don't log zomies back in!
  920. */
  921. RemoveLoginSlot();
  922. if (displays->d_next == NULL)
  923. for (Window *win = mru_window; win; win = win->w_prev_mru)
  924. if (win->w_ptyfd >= 0 && win->w_slot != (slot_t) - 1)
  925. SetUtmp(win);
  926. #endif
  927. D_fore = NULL;
  928. if (layout_attach) {
  929. Layout *lay = layout_attach;
  930. if (lay == &layout_last_marker)
  931. lay = layout_last;
  932. if (lay) {
  933. LoadLayout(lay);
  934. SetCanvasWindow(D_forecv, NULL);
  935. }
  936. }
  937. /*
  938. * there may be a window that we remember from last detach:
  939. */
  940. if (D_user->u_detachwin >= 0)
  941. fore = GetWindowByNumber(D_user->u_detachwin);
  942. else
  943. fore = NULL;
  944. /* Wayne wants us to restore the other window too. */
  945. if (D_user->u_detachotherwin >= 0)
  946. D_other = GetWindowByNumber(D_user->u_detachotherwin);
  947. noshowwin = 0;
  948. if (*m->m.attach.preselect) {
  949. if (!strcmp(m->m.attach.preselect, "="))
  950. fore = NULL;
  951. else if (!strcmp(m->m.attach.preselect, "-")) {
  952. fore = NULL;
  953. noshowwin = 1;
  954. } else if (!strcmp(m->m.attach.preselect, "+")) {
  955. struct action newscreen;
  956. char *na = NULL;
  957. newscreen.nr = RC_SCREEN;
  958. newscreen.args = &na;
  959. newscreen.quiet = 0;
  960. DoAction(&newscreen);
  961. } else
  962. fore = FindNiceWindow(fore, m->m.attach.preselect);
  963. } else
  964. fore = FindNiceWindow(fore, NULL);
  965. if (fore)
  966. SetForeWindow(fore);
  967. else if (!noshowwin) {
  968. if (!AclCheckPermCmd(D_user, ACL_EXEC, &comms[RC_WINDOWLIST])) {
  969. Display *olddisplay = display;
  970. flayer = D_forecv->c_layer;
  971. display_windows(1, WLIST_NUM, NULL);
  972. noshowwin = 1;
  973. display = olddisplay; /* display_windows can change display */
  974. }
  975. }
  976. Activate(0);
  977. ResetIdle();
  978. if (!D_fore && !noshowwin)
  979. ShowWindows(-1);
  980. if (displays->d_next == NULL && console_window) {
  981. if (TtyGrabConsole(console_window->w_ptyfd, true, "reattach") == 0)
  982. Msg(0, "console %s is on window %d", HostName, console_window->w_number);
  983. }
  984. }
  985. static void FinishDetach(Message *m)
  986. {
  987. Display *next, **d, *det;
  988. pid_t pid;
  989. if (m->type == MSG_ATTACH)
  990. pid = D_userpid;
  991. else
  992. pid = m->m.detach.dpid;
  993. /* Remove the temporary display prompting for the password from the list */
  994. for (d = &displays; (det = *d); d = &det->d_next) {
  995. if (det->d_userpid == pid)
  996. break;
  997. }
  998. if (det) {
  999. *d = det->d_next;
  1000. det->d_next = NULL;
  1001. }
  1002. for (display = displays; display; display = next) {
  1003. next = display->d_next;
  1004. if (m->type == MSG_POW_DETACH)
  1005. Detach(D_REMOTE_POWER);
  1006. else if (m->type == MSG_DETACH)
  1007. Detach(D_REMOTE);
  1008. else if (m->type == MSG_ATTACH) {
  1009. if (m->m.attach.detachfirst == MSG_POW_DETACH)
  1010. Detach(D_REMOTE_POWER);
  1011. else if (m->m.attach.detachfirst == MSG_DETACH)
  1012. Detach(D_REMOTE);
  1013. }
  1014. }
  1015. display = displays = det;
  1016. if (m->type != MSG_ATTACH) {
  1017. if (display)
  1018. FreeDisplay();
  1019. Kill(pid, SIGCONT);
  1020. }
  1021. }
  1022. struct pwdata {
  1023. size_t len;
  1024. char buf[MAXLOGINLEN + 1];
  1025. Message m;
  1026. };
  1027. static void AskPassword(Message *m)
  1028. {
  1029. struct pwdata *pwdata;
  1030. char prompt[MAXSTR];
  1031. char *gecos_comma;
  1032. char *realname = NULL;
  1033. pwdata = calloc(1, sizeof(struct pwdata));
  1034. if (!pwdata)
  1035. Panic(0, "%s", strnomem);
  1036. pwdata->len = 0;
  1037. pwdata->m = *m;
  1038. D_processinputdata = pwdata;
  1039. D_processinput = PasswordProcessInput;
  1040. /* if GECOS data is CSV, we only want the text before the first comma */
  1041. if ((gecos_comma = strchr(ppp->pw_gecos, ',')))
  1042. if (!(realname = strndup(ppp->pw_gecos, gecos_comma - ppp->pw_gecos)))
  1043. gecos_comma = NULL; /* well, it was worth a shot. */
  1044. snprintf(prompt, sizeof(prompt), "\ascreen used by %s%s<%s> on %s.\r\nPassword: ",
  1045. gecos_comma ? realname : ppp->pw_gecos,
  1046. ppp->pw_gecos[0] ? " " : "", ppp->pw_name, HostName);
  1047. free(realname);
  1048. AddStr(prompt);
  1049. }
  1050. #if ENABLE_PAM
  1051. static int screen_conv(int num_msg, const struct pam_message **msg,
  1052. struct pam_response **resp, void *data)
  1053. {
  1054. (void)num_msg; /* unused */
  1055. (void)msg; /* unused */
  1056. *resp = (struct pam_response *)data;
  1057. return PAM_SUCCESS;
  1058. }
  1059. static bool CheckPassword(const char *password) {
  1060. bool ret = false;
  1061. struct pam_response *reply;
  1062. pam_handle_t *pamh = NULL;
  1063. struct pam_conv pamc;
  1064. int pam_ret;
  1065. char *tty_name;
  1066. reply = (struct pam_response *)malloc(sizeof(struct pam_response));
  1067. reply[0].resp = strdup(password);
  1068. reply[0].resp_retcode = 0;
  1069. pamc.conv = &screen_conv;
  1070. pamc.appdata_ptr = (void *)reply;
  1071. pam_ret= pam_start("screen", ppp->pw_name, &pamc, &pamh);
  1072. if (pam_ret!= PAM_SUCCESS) {
  1073. return false;
  1074. }
  1075. if (strncmp(attach_tty, "/dev/", 5) == 0) {
  1076. tty_name = attach_tty + 5;
  1077. } else {
  1078. tty_name = attach_tty;
  1079. }
  1080. pam_ret = pam_set_item(pamh, PAM_TTY, tty_name);
  1081. if (pam_ret != PAM_SUCCESS) {
  1082. return false;
  1083. }
  1084. pam_ret = pam_authenticate(pamh, 0);
  1085. pam_end(pamh, pam_ret);
  1086. if (pam_ret == PAM_MAXTRIES) {
  1087. AddStr("\r\nmaximum number of tries exceeded\r\n");
  1088. return false;
  1089. } else if (pam_ret == PAM_ABORT) {
  1090. AddStr("\r\nabort requested by PAM\r\n");
  1091. return false;
  1092. } else if (pam_ret == PAM_SUCCESS) {
  1093. ret = true;
  1094. }
  1095. return ret;
  1096. }
  1097. #else /* ENABLE_PAM */
  1098. static bool CheckPassword(const char *password) {
  1099. bool ret = false;
  1100. char *passwd = 0;
  1101. struct spwd *p;
  1102. gid_t gid = getegid();
  1103. uid_t uid = geteuid();
  1104. if (seteuid(0) || setegid(0))
  1105. Panic(0, "\r\ncan't get root uid/gid\r\n");
  1106. p = getspnam(ppp->pw_name);
  1107. if (seteuid(uid) || setegid(gid))
  1108. Panic(0, "\r\ncan't restore uid/gid\r\n");
  1109. if (p == NULL) {
  1110. AddStr("\r\ncan't open passwd file\r\n");
  1111. return false;
  1112. }
  1113. passwd = crypt(password, p->sp_pwdp);
  1114. ret = (strcmp(passwd, p->sp_pwdp) == 0);
  1115. return ret;
  1116. }
  1117. #endif /* ENABLE_PAM */
  1118. static void PasswordProcessInput(char *ibuf, size_t ilen)
  1119. {
  1120. struct pwdata *pwdata;
  1121. int c;
  1122. size_t len;
  1123. int pid = D_userpid;
  1124. pwdata = D_processinputdata;
  1125. len = pwdata->len;
  1126. while (ilen-- > 0) {
  1127. c = *(unsigned char *)ibuf++;
  1128. if (c == '\r' || c == '\n') {
  1129. pwdata->buf[len] = 0;
  1130. if (!CheckPassword(pwdata->buf)) {
  1131. /* uh oh, user failed */
  1132. memset(pwdata->buf, 0, sizeof(pwdata->buf));
  1133. AddStr("\r\nPassword incorrect.\r\n");
  1134. D_processinputdata = NULL; /* otherwise freed by FreeDis */
  1135. FreeDisplay();
  1136. Msg(0, "Illegal reattach attempt from terminal %s.", pwdata->m.m_tty);
  1137. free(pwdata);
  1138. Kill(pid, SIG_BYE);
  1139. return;
  1140. }
  1141. /* great, pw matched, all is fine */
  1142. memset(pwdata->buf, 0, sizeof(pwdata->buf));
  1143. AddStr("\r\n");
  1144. D_processinputdata = NULL;
  1145. D_processinput = ProcessInput;
  1146. if (pwdata->m.type == MSG_DETACH || pwdata->m.type == MSG_POW_DETACH)
  1147. FinishDetach(&pwdata->m);
  1148. else
  1149. FinishAttach(&pwdata->m);
  1150. free(pwdata);
  1151. return;
  1152. }
  1153. if (c == Ctrl('c')) {
  1154. memset(pwdata->buf, 0, sizeof(pwdata->buf));
  1155. AddStr("\r\n");
  1156. FreeDisplay();
  1157. Kill(pid, SIG_BYE);
  1158. return;
  1159. }
  1160. if (c == '\b' || c == 0177) {
  1161. if (len > 0) {
  1162. pwdata->buf[len] = 0;
  1163. len--;
  1164. }
  1165. continue;
  1166. }
  1167. if (c == Ctrl('u')) {
  1168. memset(pwdata->buf, 0, sizeof(pwdata->buf));
  1169. len = 0;
  1170. continue;
  1171. }
  1172. if (len < sizeof(pwdata->buf) - 1)
  1173. pwdata->buf[len++] = c;
  1174. }
  1175. pwdata->len = len;
  1176. }
  1177. /* 'end' is exclusive, i.e. you should *not* write in *end */
  1178. static char *strncpy_escape_quote(char *dst, const char *src, const char *end)
  1179. {
  1180. while (*src && dst < end) {
  1181. if (*src == '"') {
  1182. if (dst + 2 < end) /* \\ \" \0 */
  1183. *dst++ = '\\';
  1184. else
  1185. return NULL;
  1186. }
  1187. *dst++ = *src++;
  1188. }
  1189. if (dst >= end)
  1190. return NULL;
  1191. *dst = '\0';
  1192. return dst;
  1193. }
  1194. static void DoCommandMsg(Message *mp)
  1195. {
  1196. char *args[MAXARGS];
  1197. int argl[MAXARGS];
  1198. char fullcmd[MAXSTR];
  1199. char *fc;
  1200. int n;
  1201. char *p = mp->m.command.cmd;
  1202. struct acluser *user;
  1203. n = mp->m.command.nargs;
  1204. if (n > MAXARGS - 1)
  1205. n = MAXARGS - 1;
  1206. for (fc = fullcmd; n > 0; n--) {
  1207. size_t len = strlen(p);
  1208. *fc++ = '"';
  1209. if (!(fc = strncpy_escape_quote(fc, p, fullcmd + ARRAY_SIZE(fullcmd) - 2))) { /* '"' ' ' */
  1210. Msg(0, "Remote command too long.");
  1211. queryflag = -1;
  1212. return;
  1213. }
  1214. p += len + 1;
  1215. *fc++ = '"';
  1216. *fc++ = ' ';
  1217. }
  1218. if (fc != fullcmd)
  1219. *--fc = 0;
  1220. if (Parse(fullcmd, ARRAY_SIZE(fullcmd), args, argl) <= 0) {
  1221. queryflag = -1;
  1222. return;
  1223. }
  1224. user = *FindUserPtr(mp->m.attach.auser);
  1225. if (user == NULL) {
  1226. Msg(0, "Unknown user %s tried to send a command!", mp->m.attach.auser);
  1227. queryflag = -1;
  1228. return;
  1229. }
  1230. /*if (user->u_password && *user->u_password) {
  1231. Msg(0, "User %s has a password, cannot use remote commands (using -Q or -X option).",
  1232. mp->m.attach.auser);
  1233. queryflag = -1;
  1234. return;
  1235. }*/
  1236. if (!display)
  1237. for (display = displays; display; display = display->d_next)
  1238. if (D_user == user)
  1239. break;
  1240. for (fore = mru_window; fore; fore = fore->w_prev_mru)
  1241. if (!strcmp(mp->m_tty, fore->w_tty)) {
  1242. if (!display)
  1243. display = fore->w_layer.l_cvlist ? fore->w_layer.l_cvlist->c_display : NULL;
  1244. /* If the window is not visibile in any display, then do not use the originating window as
  1245. * the foreground window for the command. This way, if there is an existing display, then
  1246. * the command will execute from the foreground window of that display. This is necessary so
  1247. * that commands that are relative to the window (e.g. 'next' etc.) do the right thing. */
  1248. if (!fore->w_layer.l_cvlist || !fore->w_layer.l_cvlist->c_display)
  1249. fore = NULL;
  1250. break;
  1251. }
  1252. if (!display)
  1253. display = displays; /* sigh */
  1254. if (*mp->m.command.preselect) {
  1255. int i = -1;
  1256. if (strcmp(mp->m.command.preselect, "-")) {
  1257. i = WindowByNoN(mp->m.command.preselect);
  1258. if (i < 0 || !GetWindowByNumber(i)) {
  1259. Msg(0, "Could not find pre-select window.");
  1260. queryflag = -1;
  1261. return;
  1262. }
  1263. }
  1264. fore = i >= 0 ? GetWindowByNumber(i) : NULL;
  1265. } else if (!fore) {
  1266. if (display && D_user == user)
  1267. fore = Layer2Window(display->d_forecv->c_layer);
  1268. if (!fore) {
  1269. fore = user->u_detachwin >= 0 ? GetWindowByNumber(user->u_detachwin) : NULL;
  1270. fore = FindNiceWindow(fore, NULL);
  1271. }
  1272. }
  1273. if (!fore)
  1274. fore = mru_window; /* sigh */
  1275. EffectiveAclUser = user;
  1276. if (*args) {
  1277. char *oldrcname = rc_name;
  1278. rc_name = "-X";
  1279. flayer = fore ? &fore->w_layer : NULL;
  1280. if (fore && fore->w_savelayer && (fore->w_blocked || fore->w_savelayer->l_cvlist == NULL))
  1281. flayer = fore->w_savelayer;
  1282. DoCommand(args, argl);
  1283. rc_name = oldrcname;
  1284. }
  1285. EffectiveAclUser = NULL;
  1286. }
  1287. int SendAttachMsg(int s, Message *m, int fd)
  1288. {
  1289. struct msghdr msg;
  1290. struct iovec iov;
  1291. char buf[CMSG_SPACE(sizeof(int))];
  1292. struct cmsghdr *cmsg;
  1293. iov.iov_base = (char *)m;
  1294. iov.iov_len = sizeof(Message);
  1295. memset(&msg, 0, sizeof(struct msghdr));
  1296. msg.msg_name = NULL;
  1297. msg.msg_namelen = 0;
  1298. msg.msg_iov = &iov;
  1299. msg.msg_iovlen = 1;
  1300. msg.msg_control = buf;
  1301. msg.msg_controllen = ARRAY_SIZE(buf);
  1302. cmsg = CMSG_FIRSTHDR(&msg);
  1303. cmsg->cmsg_level = SOL_SOCKET;
  1304. cmsg->cmsg_type = SCM_RIGHTS;
  1305. cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  1306. memmove(CMSG_DATA(cmsg), &fd, sizeof(int));
  1307. msg.msg_controllen = cmsg->cmsg_len;
  1308. while (1) {
  1309. int ret = sendmsg(s, &msg, 0);
  1310. if (ret == -1 && errno == EINTR)
  1311. continue;
  1312. if (ret == -1)
  1313. return -1;
  1314. return 0;
  1315. }
  1316. }