PageRenderTime 63ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/socket.c

https://github.com/niha/nihascreen
C | 1778 lines | 1523 code | 108 blank | 147 comment | 423 complexity | 33c1817c159647cce5537f3767d2b4ea 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. * http://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 <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <fcntl.h>
  32. #if !defined(NAMEDPIPE)
  33. #include <sys/socket.h>
  34. #include <sys/un.h>
  35. #endif
  36. #ifndef SIGINT
  37. # include <signal.h>
  38. #endif
  39. #include "screen.h"
  40. #ifdef HAVE_DIRENT_H
  41. # include <dirent.h>
  42. #else
  43. # include <sys/dir.h>
  44. # define dirent direct
  45. #endif
  46. #include "extern.h"
  47. #include "list_generic.h"
  48. static int CheckPid __P((int));
  49. static void ExecCreate __P((struct msg *));
  50. static void DoCommandMsg __P((struct msg *));
  51. #if defined(_SEQUENT_) && !defined(NAMEDPIPE)
  52. # define connect sconnect /* _SEQUENT_ has braindamaged connect */
  53. static int sconnect __P((int, struct sockaddr *, int));
  54. #endif
  55. static void FinishAttach __P((struct msg *));
  56. static void FinishDetach __P((struct msg *));
  57. static void AskPassword __P((struct msg *));
  58. extern char *RcFileName, *extra_incap, *extra_outcap;
  59. extern int ServerSocket, real_uid, real_gid, eff_uid, eff_gid;
  60. extern int dflag, iflag, rflag, lsflag, quietflag, wipeflag, xflag;
  61. extern int queryflag;
  62. extern char *attach_tty, *LoginName, HostName[];
  63. extern struct display *display, *displays;
  64. extern struct win *fore, **wtab, *console_window, *windows;
  65. extern struct layer *flayer;
  66. extern struct layout *layout_attach, *layout_last, layout_last_marker;
  67. extern struct NewWindow nwin_undef;
  68. #ifdef MULTIUSER
  69. extern char *multi;
  70. #endif
  71. extern int maxwin;
  72. extern char *getenv();
  73. extern char SockPath[];
  74. extern struct event serv_read;
  75. extern char *rc_name;
  76. extern struct comm comms[];
  77. #ifdef MULTIUSER
  78. # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0) | (multi ? 1 : 0))
  79. #else
  80. # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0))
  81. #endif
  82. /*
  83. * Socket directory manager
  84. *
  85. * fdp: pointer to store the first good socket.
  86. * nfoundp: pointer to store the number of sockets found matching.
  87. * notherp: pointer to store the number of sockets not matching.
  88. * match: string to match socket name.
  89. *
  90. * The socket directory must be in SockPath!
  91. * The global variables LoginName, multi, rflag, xflag, dflag,
  92. * quietflag, SockPath are used.
  93. *
  94. * The first good socket is stored in fdp and its name is
  95. * appended to SockPath.
  96. * If none exists or fdp is NULL SockPath is not changed.
  97. *
  98. * Returns: number of good sockets.
  99. *
  100. */
  101. int
  102. FindSocket(fdp, nfoundp, notherp, match)
  103. int *fdp;
  104. int *nfoundp, *notherp;
  105. char *match;
  106. {
  107. DIR *dirp;
  108. struct dirent *dp;
  109. struct stat st;
  110. int mode;
  111. int sdirlen;
  112. int matchlen = 0;
  113. char *name, *n;
  114. int firsts = -1, sockfd;
  115. char *firstn = NULL;
  116. int nfound = 0, ngood = 0, ndead = 0, nwipe = 0, npriv = 0;
  117. int nperfect = 0;
  118. struct sent
  119. {
  120. struct sent *next;
  121. int mode;
  122. char *name;
  123. } *slist, **slisttail, *sent, *nsent;
  124. if (match)
  125. {
  126. matchlen = strlen(match);
  127. #ifdef NAME_MAX
  128. if (matchlen > NAME_MAX)
  129. matchlen = NAME_MAX;
  130. #endif
  131. }
  132. /*
  133. * SockPath contains the socket directory.
  134. * At the end of FindSocket the socket name will be appended to it.
  135. * Thus FindSocket() can only be called once!
  136. */
  137. sdirlen = strlen(SockPath);
  138. #ifdef USE_SETEUID
  139. xseteuid(real_uid);
  140. xsetegid(real_gid);
  141. #endif
  142. if ((dirp = opendir(SockPath)) == 0)
  143. Panic(errno, "Cannot opendir %s", SockPath);
  144. slist = 0;
  145. slisttail = &slist;
  146. while ((dp = readdir(dirp)))
  147. {
  148. int cmatch = 0;
  149. name = dp->d_name;
  150. debug1("- %s\n", name);
  151. if (*name == 0 || *name == '.' || strlen(name) > 2*MAXSTR)
  152. continue;
  153. if (matchlen)
  154. {
  155. n = name;
  156. /* if we don't want to match digits. Skip them */
  157. if ((*match <= '0' || *match > '9') && (*n > '0' && *n <= '9'))
  158. {
  159. while (*n >= '0' && *n <= '9')
  160. n++;
  161. if (*n == '.')
  162. n++;
  163. }
  164. /* the tty prefix is optional */
  165. if (strncmp(match, "tty", 3) && strncmp(n, "tty", 3) == 0)
  166. n += 3;
  167. if (strncmp(match, n, matchlen))
  168. {
  169. if (n == name && *match > '0' && *match <= '9')
  170. {
  171. while (*n >= '0' && *n <= '9')
  172. n++;
  173. if (*n == '.')
  174. n++;
  175. if (strncmp(match, n, matchlen))
  176. continue;
  177. }
  178. else
  179. continue;
  180. }
  181. else
  182. cmatch = (*(n + matchlen) == 0);
  183. debug1(" -> matched %s\n", match);
  184. }
  185. sprintf(SockPath + sdirlen, "/%s", name);
  186. debug1("stat %s\n", SockPath);
  187. errno = 0;
  188. debug2("uid = %d, gid = %d\n", getuid(), getgid());
  189. debug2("euid = %d, egid = %d\n", geteuid(), getegid());
  190. if (stat(SockPath, &st))
  191. {
  192. debug1("errno = %d\n", errno);
  193. continue;
  194. }
  195. #ifndef SOCK_NOT_IN_FS
  196. # ifdef NAMEDPIPE
  197. # ifdef S_ISFIFO
  198. debug("S_ISFIFO?\n");
  199. if (!S_ISFIFO(st.st_mode))
  200. continue;
  201. # endif
  202. # else
  203. # ifdef S_ISSOCK
  204. debug("S_ISSOCK?\n");
  205. if (!S_ISSOCK(st.st_mode))
  206. continue;
  207. # endif
  208. # endif
  209. #endif
  210. debug2("st.st_uid = %d, real_uid = %d\n", st.st_uid, real_uid);
  211. if ((int)st.st_uid != real_uid)
  212. continue;
  213. mode = (int)st.st_mode & 0777;
  214. debug1(" has mode 0%03o\n", mode);
  215. #ifdef MULTIUSER
  216. if (multi && ((mode & 0677) != 0601))
  217. {
  218. debug(" is not a MULTI-USER session");
  219. if (strcmp(multi, LoginName))
  220. {
  221. debug(" and we are in a foreign directory.\n");
  222. mode = -4;
  223. }
  224. else
  225. {
  226. debug(", but it is our own session.\n");
  227. }
  228. }
  229. #endif
  230. debug(" store it.\n");
  231. if ((sent = (struct sent *)malloc(sizeof(struct sent))) == 0)
  232. continue;
  233. sent->next = 0;
  234. sent->name = SaveStr(name);
  235. sent->mode = mode;
  236. *slisttail = sent;
  237. slisttail = &sent->next;
  238. nfound++;
  239. sockfd = MakeClientSocket(0);
  240. #ifdef USE_SETEUID
  241. /* MakeClientSocket sets ids back to eff */
  242. xseteuid(real_uid);
  243. xsetegid(real_gid);
  244. #endif
  245. if (sockfd == -1)
  246. {
  247. debug2(" MakeClientSocket failed, unreachable? %d %d\n",
  248. matchlen, wipeflag);
  249. sent->mode = -3;
  250. #ifndef SOCKDIR_IS_LOCAL_TO_HOST
  251. /* Unreachable - it is dead if we detect that it's local
  252. * or we specified a match
  253. */
  254. n = name + strlen(name) - 1;
  255. while (n != name && *n != '.')
  256. n--;
  257. if (matchlen == 0 && !(*n == '.' && n[1] && strncmp(HostName, n + 1, strlen(n + 1)) == 0))
  258. {
  259. npriv++; /* a good socket that was not for us */
  260. continue;
  261. }
  262. #endif
  263. ndead++;
  264. sent->mode = -1;
  265. if (wipeflag)
  266. {
  267. if (unlink(SockPath) == 0)
  268. {
  269. sent->mode = -2;
  270. nwipe++;
  271. }
  272. }
  273. continue;
  274. }
  275. mode &= 0776;
  276. /* Shall we connect ? */
  277. debug2(" connecting: mode=%03o, rflag=%d, ", mode, rflag);
  278. debug2("xflag=%d, dflag=%d ?\n", xflag, dflag);
  279. /*
  280. * mode 600: socket is detached.
  281. * mode 700: socket is attached.
  282. * xflag implies rflag here.
  283. *
  284. * fail, when socket mode mode is not 600 or 700
  285. * fail, when we want to detach w/o reattach, but it already is detached.
  286. * fail, when we only want to attach, but mode 700 and not xflag.
  287. * fail, if none of dflag, rflag, xflag is set.
  288. */
  289. if ((mode != 0700 && mode != 0600) ||
  290. (dflag && !rflag && !xflag && mode == 0600) ||
  291. (!dflag && rflag && mode == 0700 && !xflag) ||
  292. (!dflag && !rflag && !xflag))
  293. {
  294. close(sockfd);
  295. debug(" no!\n");
  296. npriv++; /* a good socket that was not for us */
  297. continue;
  298. }
  299. ngood++;
  300. if (cmatch)
  301. nperfect++;
  302. if (fdp && (firsts == -1 || (cmatch && nperfect == 1)))
  303. {
  304. if (firsts != -1)
  305. close(firsts);
  306. firsts = sockfd;
  307. firstn = sent->name;
  308. debug(" taken.\n");
  309. }
  310. else
  311. {
  312. debug(" discarded.\n");
  313. close(sockfd);
  314. }
  315. }
  316. (void)closedir(dirp);
  317. if (!lsflag && nperfect == 1)
  318. ngood = nperfect;
  319. if (nfound && (lsflag || ngood != 1) && !quietflag)
  320. {
  321. switch(ngood)
  322. {
  323. case 0:
  324. Msg(0, nfound > 1 ? "There are screens on:" : "There is a screen on:");
  325. break;
  326. case 1:
  327. Msg(0, nfound > 1 ? "There are several screens on:" : "There is a suitable screen on:");
  328. break;
  329. default:
  330. Msg(0, "There are several suitable screens on:");
  331. break;
  332. }
  333. for (sent = slist; sent; sent = sent->next)
  334. {
  335. switch (sent->mode)
  336. {
  337. case 0700:
  338. printf("\t%s\t(Attached)\n", sent->name);
  339. break;
  340. case 0600:
  341. printf("\t%s\t(Detached)\n", sent->name);
  342. break;
  343. #ifdef MULTIUSER
  344. case 0701:
  345. printf("\t%s\t(Multi, attached)\n", sent->name);
  346. break;
  347. case 0601:
  348. printf("\t%s\t(Multi, detached)\n", sent->name);
  349. break;
  350. #endif
  351. case -1:
  352. /* No trigraphs here! */
  353. printf("\t%s\t(Dead ?%c?)\n", sent->name, '?');
  354. break;
  355. case -2:
  356. printf("\t%s\t(Removed)\n", sent->name);
  357. break;
  358. case -3:
  359. printf("\t%s\t(Remote or dead)\n", sent->name);
  360. break;
  361. case -4:
  362. printf("\t%s\t(Private)\n", sent->name);
  363. break;
  364. }
  365. }
  366. }
  367. if (ndead && !quietflag)
  368. {
  369. char *m = "Remove dead screens with 'screen -wipe'.";
  370. if (wipeflag)
  371. Msg(0, "%d socket%s wiped out.", nwipe, nwipe > 1 ? "s" : "");
  372. else
  373. Msg(0, m, ndead > 1 ? "s" : "", ndead > 1 ? "" : "es"); /* other args for nethack */
  374. }
  375. if (firsts != -1)
  376. {
  377. sprintf(SockPath + sdirlen, "/%s", firstn);
  378. *fdp = firsts;
  379. }
  380. else
  381. SockPath[sdirlen] = 0;
  382. for (sent = slist; sent; sent = nsent)
  383. {
  384. nsent = sent->next;
  385. free(sent->name);
  386. free((char *)sent);
  387. }
  388. #ifdef USE_SETEUID
  389. xseteuid(eff_uid);
  390. xsetegid(eff_gid);
  391. #endif
  392. if (notherp)
  393. *notherp = npriv;
  394. if (nfoundp)
  395. *nfoundp = nfound - nwipe;
  396. return ngood;
  397. }
  398. /*
  399. **
  400. ** Socket/pipe create routines
  401. **
  402. */
  403. #ifdef NAMEDPIPE
  404. int
  405. MakeServerSocket()
  406. {
  407. register int s;
  408. struct stat st;
  409. # ifdef USE_SETEUID
  410. xseteuid(real_uid);
  411. xsetegid(real_gid);
  412. # endif
  413. if ((s = open(SockPath, O_WRONLY | O_NONBLOCK)) >= 0)
  414. {
  415. debug("huii, my fifo already exists??\n");
  416. if (quietflag)
  417. {
  418. Kill(D_userpid, SIG_BYE);
  419. eexit(11);
  420. }
  421. Msg(0, "There is already a screen running on %s.", Filename(SockPath));
  422. if (stat(SockPath, &st) == -1)
  423. Panic(errno, "stat");
  424. if ((int)st.st_uid != real_uid)
  425. Panic(0, "Unfortunately you are not its owner.");
  426. if ((st.st_mode & 0700) == 0600)
  427. Panic(0, "To resume it, use \"screen -r\"");
  428. else
  429. Panic(0, "It is not detached.");
  430. /* NOTREACHED */
  431. }
  432. # ifdef USE_SETEUID
  433. (void) unlink(SockPath);
  434. if (mkfifo(SockPath, SOCKMODE))
  435. Panic(0, "mkfifo %s failed", SockPath);
  436. # ifdef BROKEN_PIPE
  437. if ((s = open(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0)
  438. # else
  439. if ((s = open(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0)
  440. # endif
  441. Panic(errno, "open fifo %s", SockPath);
  442. xseteuid(eff_uid);
  443. xsetegid(eff_gid);
  444. return s;
  445. # else /* !USE_SETEUID */
  446. if (UserContext() > 0)
  447. {
  448. (void) unlink(SockPath);
  449. UserReturn(mkfifo(SockPath, SOCKMODE));
  450. }
  451. if (UserStatus())
  452. Panic(0, "mkfifo %s failed", SockPath);
  453. # ifdef BROKEN_PIPE
  454. if ((s = secopen(SockPath, O_RDWR | O_NONBLOCK, 0)) < 0)
  455. # else
  456. if ((s = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0)
  457. # endif
  458. Panic(errno, "open fifo %s", SockPath);
  459. return s;
  460. # endif /* !USE_SETEUID */
  461. }
  462. int
  463. MakeClientSocket(err)
  464. int err;
  465. {
  466. register int s = 0;
  467. if ((s = secopen(SockPath, O_WRONLY | O_NONBLOCK, 0)) >= 0)
  468. {
  469. (void) fcntl(s, F_SETFL, 0);
  470. return s;
  471. }
  472. if (err)
  473. Msg(errno, "%s", SockPath);
  474. debug2("MakeClientSocket() open %s failed (%d)\n", SockPath, errno);
  475. return -1;
  476. }
  477. #else /* NAMEDPIPE */
  478. int
  479. MakeServerSocket()
  480. {
  481. register int s;
  482. struct sockaddr_un a;
  483. struct stat st;
  484. if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  485. Panic(errno, "socket");
  486. a.sun_family = AF_UNIX;
  487. strncpy(a.sun_path, SockPath, sizeof(a.sun_path));
  488. a.sun_path[sizeof(a.sun_path) - 1] = 0;
  489. # ifdef USE_SETEUID
  490. xseteuid(real_uid);
  491. xsetegid(real_gid);
  492. # endif
  493. if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) != -1)
  494. {
  495. debug("oooooh! socket already is alive!\n");
  496. if (quietflag)
  497. {
  498. Kill(D_userpid, SIG_BYE);
  499. /*
  500. * oh, well. nobody receives that return code. papa
  501. * dies by signal.
  502. */
  503. eexit(11);
  504. }
  505. Msg(0, "There is already a screen running on %s.", Filename(SockPath));
  506. if (stat(SockPath, &st) == -1)
  507. Panic(errno, "stat");
  508. if (st.st_uid != real_uid)
  509. Panic(0, "Unfortunately you are not its owner.");
  510. if ((st.st_mode & 0700) == 0600)
  511. Panic(0, "To resume it, use \"screen -r\"");
  512. else
  513. Panic(0, "It is not detached.");
  514. /* NOTREACHED */
  515. }
  516. #if defined(m88k) || defined(sysV68)
  517. close(s); /* we get bind: Invalid argument if this is not done */
  518. if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  519. Panic(errno, "reopen socket");
  520. #endif
  521. (void) unlink(SockPath);
  522. if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
  523. Panic(errno, "bind (%s)", SockPath);
  524. #ifdef SOCK_NOT_IN_FS
  525. {
  526. int f;
  527. if ((f = secopen(SockPath, O_RDWR | O_CREAT, SOCKMODE)) < 0)
  528. Panic(errno, "shadow socket open");
  529. close(f);
  530. }
  531. #else
  532. chmod(SockPath, SOCKMODE);
  533. # ifndef USE_SETEUID
  534. chown(SockPath, real_uid, real_gid);
  535. # endif
  536. #endif /* SOCK_NOT_IN_FS */
  537. if (listen(s, 5) == -1)
  538. Panic(errno, "listen");
  539. # ifdef F_SETOWN
  540. fcntl(s, F_SETOWN, getpid());
  541. debug1("Serversocket owned by %d\n", fcntl(s, F_GETOWN, 0));
  542. # endif /* F_SETOWN */
  543. # ifdef USE_SETEUID
  544. xseteuid(eff_uid);
  545. xsetegid(eff_gid);
  546. # endif
  547. return s;
  548. }
  549. int
  550. MakeClientSocket(err)
  551. int err;
  552. {
  553. register int s;
  554. struct sockaddr_un a;
  555. if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  556. Panic(errno, "socket");
  557. a.sun_family = AF_UNIX;
  558. strncpy(a.sun_path, SockPath, sizeof(a.sun_path));
  559. a.sun_path[sizeof(a.sun_path) - 1] = 0;
  560. # ifdef USE_SETEUID
  561. xseteuid(real_uid);
  562. xsetegid(real_gid);
  563. # else
  564. if (access(SockPath, W_OK))
  565. {
  566. if (err)
  567. Msg(errno, "%s", SockPath);
  568. debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno);
  569. close(s);
  570. return -1;
  571. }
  572. # endif
  573. if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) == -1)
  574. {
  575. if (err)
  576. Msg(errno, "%s: connect", SockPath);
  577. debug("MakeClientSocket: connect failed.\n");
  578. close(s);
  579. s = -1;
  580. }
  581. # ifdef USE_SETEUID
  582. xseteuid(eff_uid);
  583. xsetegid(eff_gid);
  584. # endif
  585. return s;
  586. }
  587. #endif /* NAMEDPIPE */
  588. /*
  589. **
  590. ** Message send and receive routines
  591. **
  592. */
  593. void
  594. SendCreateMsg(sty, nwin)
  595. char *sty;
  596. struct NewWindow *nwin;
  597. {
  598. int s;
  599. struct msg m;
  600. register char *p;
  601. register int len, n;
  602. char **av = nwin->args;
  603. #ifdef NAME_MAX
  604. if (strlen(sty) > NAME_MAX)
  605. sty[NAME_MAX] = 0;
  606. #endif
  607. if (strlen(sty) > 2 * MAXSTR - 1)
  608. sty[2 * MAXSTR - 1] = 0;
  609. sprintf(SockPath + strlen(SockPath), "/%s", sty);
  610. if ((s = MakeClientSocket(1)) == -1)
  611. exit(1);
  612. debug1("SendCreateMsg() to '%s'\n", SockPath);
  613. bzero((char *)&m, sizeof(m));
  614. m.type = MSG_CREATE;
  615. strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1);
  616. m.m_tty[sizeof(m.m_tty) - 1] = 0;
  617. p = m.m.create.line;
  618. n = 0;
  619. if (nwin->args != nwin_undef.args)
  620. for (av = nwin->args; *av && n < MAXARGS - 1; ++av, ++n)
  621. {
  622. len = strlen(*av) + 1;
  623. if (p + len >= m.m.create.line + sizeof(m.m.create.line) - 1)
  624. break;
  625. strcpy(p, *av);
  626. p += len;
  627. }
  628. if (nwin->aka != nwin_undef.aka && p + strlen(nwin->aka) + 1 < m.m.create.line + sizeof(m.m.create.line))
  629. strcpy(p, nwin->aka);
  630. else
  631. *p = '\0';
  632. m.m.create.nargs = n;
  633. m.m.create.aflag = nwin->aflag;
  634. m.m.create.flowflag = nwin->flowflag;
  635. m.m.create.lflag = nwin->lflag;
  636. m.m.create.hheight = nwin->histheight;
  637. if (getcwd(m.m.create.dir, sizeof(m.m.create.dir)) == 0)
  638. {
  639. Msg(errno, "getcwd");
  640. return;
  641. }
  642. if (nwin->term != nwin_undef.term)
  643. strncpy(m.m.create.screenterm, nwin->term, 19);
  644. m.m.create.screenterm[19] = '\0';
  645. m.protocol_revision = MSG_REVISION;
  646. debug1("SendCreateMsg writing '%s'\n", m.m.create.line);
  647. if (write(s, (char *) &m, sizeof m) != sizeof m)
  648. Msg(errno, "write");
  649. close(s);
  650. }
  651. int
  652. SendErrorMsg(tty, buf)
  653. char *tty, *buf;
  654. {
  655. int s;
  656. struct msg m;
  657. strncpy(m.m.message, buf, sizeof(m.m.message) - 1);
  658. m.m.message[sizeof(m.m.message) - 1] = 0;
  659. s = MakeClientSocket(0);
  660. if (s < 0)
  661. return -1;
  662. m.type = MSG_ERROR;
  663. strncpy(m.m_tty, tty, sizeof(m.m_tty) - 1);
  664. m.m_tty[sizeof(m.m_tty) - 1] = 0;
  665. m.protocol_revision = MSG_REVISION;
  666. debug1("SendErrorMsg(): writing to '%s'\n", SockPath);
  667. (void) write(s, (char *) &m, sizeof m);
  668. close(s);
  669. return 0;
  670. }
  671. static void
  672. ExecCreate(mp)
  673. struct msg *mp;
  674. {
  675. struct NewWindow nwin;
  676. char *args[MAXARGS];
  677. register int n;
  678. register char **pp = args, *p = mp->m.create.line;
  679. nwin = nwin_undef;
  680. n = mp->m.create.nargs;
  681. if (n > MAXARGS - 1)
  682. n = MAXARGS - 1;
  683. /* ugly hack alert... should be done by the frontend! */
  684. if (n)
  685. {
  686. int l, num;
  687. char buf[20];
  688. l = strlen(p);
  689. if (IsNumColon(p, 10, buf, sizeof(buf)))
  690. {
  691. if (*buf)
  692. nwin.aka = buf;
  693. num = atoi(p);
  694. if (num < 0 || num > maxwin - 1)
  695. num = 0;
  696. nwin.StartAt = num;
  697. p += l + 1;
  698. n--;
  699. }
  700. }
  701. for (; n > 0; n--)
  702. {
  703. *pp++ = p;
  704. p += strlen(p) + 1;
  705. }
  706. *pp = 0;
  707. if (*p)
  708. nwin.aka = p;
  709. if (*args)
  710. nwin.args = args;
  711. nwin.aflag = mp->m.create.aflag;
  712. nwin.flowflag = mp->m.create.flowflag;
  713. if (*mp->m.create.dir)
  714. nwin.dir = mp->m.create.dir;
  715. nwin.lflag = mp->m.create.lflag;
  716. nwin.histheight = mp->m.create.hheight;
  717. if (*mp->m.create.screenterm)
  718. nwin.term = mp->m.create.screenterm;
  719. MakeWindow(&nwin);
  720. }
  721. static int
  722. CheckPid(pid)
  723. int pid;
  724. {
  725. debug1("Checking pid %d\n", pid);
  726. if (pid < 2)
  727. return -1;
  728. if (eff_uid == real_uid)
  729. return kill(pid, 0);
  730. if (UserContext() > 0)
  731. UserReturn(kill(pid, 0));
  732. return UserStatus();
  733. }
  734. #ifdef hpux
  735. /*
  736. * From: "F. K. Bruner" <napalm@ugcs.caltech.edu>
  737. * From: "Dan Egnor" <egnor@oracorp.com> Tue Aug 10 06:56:45 1993
  738. * The problem is that under HPUX (and possibly other systems too) there are
  739. * two equivalent device files for each pty/tty device:
  740. * /dev/ttyxx == /dev/pty/ttyxx
  741. * /dev/ptyxx == /dev/ptym/ptyxx
  742. * I didn't look into the exact specifics, but I've run across this problem
  743. * before: Even if you open /dev/ttyxx as fds 0 1 & 2 for a process, if that
  744. * process calls the system to determine its tty, it'll get /dev/pty/ttyxx.
  745. *
  746. * Earlier versions seemed to work -- wonder what they did.
  747. */
  748. static int
  749. ttycmp(s1, s2)
  750. char *s1, *s2;
  751. {
  752. if (strlen(s1) > 5) s1 += strlen(s1) - 5;
  753. if (strlen(s2) > 5) s2 += strlen(s2) - 5;
  754. return strcmp(s1, s2);
  755. }
  756. # define TTYCMP(a, b) ttycmp(a, b)
  757. #else
  758. # define TTYCMP(a, b) strcmp(a, b)
  759. #endif
  760. static int
  761. CreateTempDisplay(m, recvfd, wi)
  762. struct msg *m;
  763. int recvfd;
  764. struct win *wi;
  765. {
  766. int pid;
  767. int attach;
  768. char *user;
  769. int i;
  770. struct mode Mode;
  771. struct display *olddisplays = displays;
  772. switch (m->type)
  773. {
  774. case MSG_CONT:
  775. case MSG_ATTACH:
  776. pid = m->m.attach.apid;
  777. user = m->m.attach.auser;
  778. attach = 1;
  779. break;
  780. #ifdef REMOTE_DETACH
  781. case MSG_DETACH:
  782. # ifdef POW_DETACH
  783. case MSG_POW_DETACH:
  784. # endif /* POW_DETACH */
  785. pid = m->m.detach.dpid;
  786. user = m->m.detach.duser;
  787. attach = 0;
  788. break;
  789. #endif
  790. default:
  791. return -1;
  792. }
  793. if (CheckPid(pid))
  794. {
  795. Msg(0, "Attach attempt with bad pid(%d)!", pid);
  796. return -1;
  797. }
  798. if (recvfd != -1)
  799. {
  800. char *myttyname;
  801. i = recvfd;
  802. recvfd = -1;
  803. myttyname = ttyname(i);
  804. if (myttyname == 0 || strcmp(myttyname, m->m_tty))
  805. {
  806. Msg(errno, "Attach: passed fd does not match tty: %s - %s!", m->m_tty, myttyname ? myttyname : "NULL");
  807. close(i);
  808. Kill(pid, SIG_BYE);
  809. return -1;
  810. }
  811. }
  812. else if ((i = secopen(m->m_tty, O_RDWR | O_NONBLOCK, 0)) < 0)
  813. {
  814. Msg(errno, "Attach: Could not open %s!", m->m_tty);
  815. Kill(pid, SIG_BYE);
  816. return -1;
  817. }
  818. #ifdef MULTIUSER
  819. if (attach)
  820. Kill(pid, SIGCONT);
  821. #endif
  822. #if defined(ultrix) || defined(pyr) || defined(NeXT)
  823. brktty(i); /* for some strange reason this must be done */
  824. #endif
  825. if (attach)
  826. {
  827. if (display || wi)
  828. {
  829. write(i, "Attaching from inside of screen?\n", 33);
  830. close(i);
  831. Kill(pid, SIG_BYE);
  832. Msg(0, "Attach msg ignored: coming from inside.");
  833. return -1;
  834. }
  835. #ifdef MULTIUSER
  836. if (strcmp(user, LoginName))
  837. if (*FindUserPtr(user) == 0)
  838. {
  839. write(i, "Access to session denied.\n", 26);
  840. close(i);
  841. Kill(pid, SIG_BYE);
  842. Msg(0, "Attach: access denied for user %s.", user);
  843. return -1;
  844. }
  845. #endif
  846. debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", pid, m->m_tty);
  847. #ifndef MULTI
  848. if (displays)
  849. {
  850. write(i, "Screen session in use.\n", 23);
  851. close(i);
  852. Kill(pid, SIG_BYE);
  853. return -1;
  854. }
  855. #endif
  856. }
  857. /* create new display */
  858. GetTTY(i, &Mode);
  859. if (MakeDisplay(user, m->m_tty, attach ? m->m.attach.envterm : "", i, pid, &Mode) == 0)
  860. {
  861. write(i, "Could not make display.\n", 24);
  862. close(i);
  863. Msg(0, "Attach: could not make display for user %s", user);
  864. Kill(pid, SIG_BYE);
  865. return -1;
  866. }
  867. #ifdef ENCODINGS
  868. if (attach)
  869. {
  870. # ifdef UTF8
  871. D_encoding = m->m.attach.encoding == 1 ? UTF8 : m->m.attach.encoding ? m->m.attach.encoding - 1 : 0;
  872. # else
  873. D_encoding = m->m.attach.encoding ? m->m.attach.encoding - 1 : 0;
  874. # endif
  875. if (D_encoding < 0 || !EncodingName(D_encoding))
  876. D_encoding = 0;
  877. }
  878. #endif
  879. if (iflag && olddisplays)
  880. {
  881. iflag = 0;
  882. #if defined(TERMIO) || defined(POSIX)
  883. olddisplays->d_NewMode.tio.c_cc[VINTR] = VDISABLE;
  884. olddisplays->d_NewMode.tio.c_lflag &= ~ISIG;
  885. #else /* TERMIO || POSIX */
  886. olddisplays->d_NewMode.m_tchars.t_intrc = -1;
  887. #endif /* TERMIO || POSIX */
  888. SetTTY(olddisplays->d_userfd, &olddisplays->d_NewMode);
  889. }
  890. SetMode(&D_OldMode, &D_NewMode, D_flow, iflag);
  891. SetTTY(D_userfd, &D_NewMode);
  892. if (fcntl(D_userfd, F_SETFL, FNBLOCK))
  893. Msg(errno, "Warning: NBLOCK fcntl failed");
  894. return 0;
  895. }
  896. void
  897. ReceiveMsg()
  898. {
  899. int left, len;
  900. static struct msg m;
  901. char *p;
  902. int ns = ServerSocket;
  903. struct win *wi;
  904. int recvfd = -1;
  905. struct acluser *user;
  906. #ifdef NAMEDPIPE
  907. debug("Ha, there was someone knocking on my fifo??\n");
  908. if (fcntl(ServerSocket, F_SETFL, 0) == -1)
  909. Panic(errno, "BLOCK fcntl");
  910. p = (char *) &m;
  911. left = sizeof(m);
  912. #else
  913. struct sockaddr_un a;
  914. struct msghdr msg;
  915. struct iovec iov;
  916. char control[1024];
  917. len = sizeof(a);
  918. debug("Ha, there was someone knocking on my socket??\n");
  919. if ((ns = accept(ns, (struct sockaddr *) &a, (void *)&len)) < 0)
  920. {
  921. Msg(errno, "accept");
  922. return;
  923. }
  924. p = (char *) &m;
  925. left = sizeof(m);
  926. bzero(&msg, sizeof(msg));
  927. iov.iov_base = &m;
  928. iov.iov_len = left;
  929. msg.msg_iov = &iov;
  930. msg.msg_iovlen = 1;
  931. msg.msg_controllen = sizeof(control);
  932. msg.msg_control = &control;
  933. while (left > 0)
  934. {
  935. len = recvmsg(ns, &msg, 0);
  936. if (len < 0 && errno == EINTR)
  937. continue;
  938. if (len < 0)
  939. {
  940. close(ns);
  941. Msg(errno, "read");
  942. return;
  943. }
  944. if (msg.msg_controllen)
  945. {
  946. struct cmsghdr *cmsg;
  947. for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
  948. {
  949. int cl;
  950. char *cp;
  951. if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
  952. continue;
  953. cp = (char *)CMSG_DATA(cmsg);
  954. cl = cmsg->cmsg_len;
  955. while(cl >= CMSG_LEN(sizeof(int)))
  956. {
  957. int passedfd;
  958. bcopy(cp, &passedfd, sizeof(int));
  959. if (recvfd >= 0 && passedfd != recvfd)
  960. close(recvfd);
  961. recvfd = passedfd;
  962. cl -= CMSG_LEN(sizeof(int));
  963. }
  964. }
  965. }
  966. p += len;
  967. left -= len;
  968. break;
  969. }
  970. #endif
  971. while (left > 0)
  972. {
  973. len = read(ns, p, left);
  974. if (len < 0 && errno == EINTR)
  975. continue;
  976. if (len <= 0)
  977. break;
  978. p += len;
  979. left -= len;
  980. }
  981. #ifdef NAMEDPIPE
  982. # ifndef BROKEN_PIPE
  983. /* Reopen pipe to prevent EOFs at the select() call */
  984. close(ServerSocket);
  985. if ((ServerSocket = secopen(SockPath, O_RDONLY | O_NONBLOCK, 0)) < 0)
  986. Panic(errno, "reopen fifo %s", SockPath);
  987. evdeq(&serv_read);
  988. serv_read.fd = ServerSocket;
  989. evenq(&serv_read);
  990. # endif
  991. #else
  992. close(ns);
  993. #endif
  994. if (len < 0)
  995. {
  996. Msg(errno, "read");
  997. if (recvfd != -1)
  998. close(recvfd);
  999. return;
  1000. }
  1001. if (left > 0)
  1002. {
  1003. if (left != sizeof(m))
  1004. Msg(0, "Message %d of %d bytes too small", left, (int)sizeof(m));
  1005. else
  1006. debug("No data on socket.\n");
  1007. return;
  1008. }
  1009. if (m.protocol_revision != MSG_REVISION)
  1010. {
  1011. if (recvfd != -1)
  1012. close(recvfd);
  1013. Msg(0, "Invalid message (magic 0x%08x).", m.protocol_revision);
  1014. return;
  1015. }
  1016. debug2("*** RecMsg: type %d tty %s\n", m.type, m.m_tty);
  1017. if (m.type != MSG_ATTACH && recvfd != -1)
  1018. {
  1019. close(recvfd);
  1020. recvfd = -1;
  1021. }
  1022. for (display = displays; display; display = display->d_next)
  1023. if (TTYCMP(D_usertty, m.m_tty) == 0)
  1024. break;
  1025. debug2("display: %s display %sfound\n", m.m_tty, display ? "" : "not ");
  1026. wi = 0;
  1027. if (!display)
  1028. {
  1029. for (wi = windows; wi; wi = wi->w_next)
  1030. if (!TTYCMP(m.m_tty, wi->w_tty))
  1031. {
  1032. /* XXX: hmmm, rework this? */
  1033. display = wi->w_layer.l_cvlist ? wi->w_layer.l_cvlist->c_display : 0;
  1034. debug2("but window %s %sfound.\n", m.m_tty, display ? "" :
  1035. "(backfacing)");
  1036. break;
  1037. }
  1038. }
  1039. /* Remove the status to prevent garbage on the screen */
  1040. if (display && D_status)
  1041. RemoveStatus();
  1042. if (display && !D_tcinited && m.type != MSG_HANGUP)
  1043. {
  1044. if (recvfd != -1)
  1045. close(recvfd);
  1046. return; /* ignore messages for bad displays */
  1047. }
  1048. switch (m.type)
  1049. {
  1050. case MSG_WINCH:
  1051. if (display)
  1052. CheckScreenSize(1); /* Change fore */
  1053. break;
  1054. case MSG_CREATE:
  1055. /*
  1056. * the window that issued the create message need not be an active
  1057. * window. Then we create the window without having a display.
  1058. * Resulting in another inactive window.
  1059. */
  1060. ExecCreate(&m);
  1061. break;
  1062. case MSG_CONT:
  1063. if (display && D_userpid != 0 && kill(D_userpid, 0) == 0)
  1064. break; /* Intruder Alert */
  1065. debug2("RecMsg: apid=%d,was %d\n", m.m.attach.apid, display ? D_userpid : 0);
  1066. /* FALLTHROUGH */
  1067. case MSG_ATTACH:
  1068. if (CreateTempDisplay(&m, recvfd, wi))
  1069. break;
  1070. #ifdef PASSWORD
  1071. if (D_user->u_password && *D_user->u_password)
  1072. AskPassword(&m);
  1073. else
  1074. #endif
  1075. FinishAttach(&m);
  1076. break;
  1077. case MSG_ERROR:
  1078. Msg(0, "%s", m.m.message);
  1079. break;
  1080. case MSG_HANGUP:
  1081. if (!wi) /* ignore hangups from inside */
  1082. Hangup();
  1083. break;
  1084. #ifdef REMOTE_DETACH
  1085. case MSG_DETACH:
  1086. # ifdef POW_DETACH
  1087. case MSG_POW_DETACH:
  1088. # endif /* POW_DETACH */
  1089. #ifdef PASSWORD
  1090. user = *FindUserPtr(m.m.detach.duser);
  1091. if (user && user->u_password && *user->u_password)
  1092. {
  1093. if (CreateTempDisplay(&m, recvfd, 0))
  1094. break;
  1095. AskPassword(&m);
  1096. }
  1097. else
  1098. #endif /* PASSWORD */
  1099. FinishDetach(&m);
  1100. break;
  1101. #endif
  1102. case MSG_QUERY:
  1103. {
  1104. char *oldSockPath = SaveStr(SockPath);
  1105. strcpy(SockPath, m.m.command.writeback);
  1106. int s = MakeClientSocket(0);
  1107. strcpy(SockPath, oldSockPath);
  1108. Free(oldSockPath);
  1109. if (s >= 0)
  1110. {
  1111. queryflag = s;
  1112. DoCommandMsg(&m);
  1113. close(s);
  1114. }
  1115. else
  1116. queryflag = -1;
  1117. Kill(m.m.command.apid, (queryflag >= 0) ? SIGCONT : SIG_BYE); /* Send SIG_BYE if an error happened */
  1118. queryflag = -1;
  1119. }
  1120. break;
  1121. case MSG_COMMAND:
  1122. DoCommandMsg(&m);
  1123. break;
  1124. default:
  1125. Msg(0, "Invalid message (type %d).", m.type);
  1126. }
  1127. }
  1128. void
  1129. ReceiveRaw(s)
  1130. int s;
  1131. {
  1132. char rd[256];
  1133. int len = 0;
  1134. #ifdef NAMEDPIPE
  1135. if (fcntl(s, F_SETFL, 0) == -1)
  1136. Panic(errno, "BLOCK fcntl");
  1137. #else
  1138. struct sockaddr_un a;
  1139. len = sizeof(a);
  1140. if ((s = accept(s, (struct sockaddr *) &a, (void *)&len)) < 0)
  1141. {
  1142. Msg(errno, "accept");
  1143. return;
  1144. }
  1145. #endif
  1146. while ((len = read(s, rd, 255)) > 0)
  1147. {
  1148. rd[len] = 0;
  1149. printf("%s", rd);
  1150. }
  1151. close(s);
  1152. }
  1153. #if defined(_SEQUENT_) && !defined(NAMEDPIPE)
  1154. #undef connect
  1155. /*
  1156. * sequent_ptx socket emulation must have mode 000 on the socket!
  1157. */
  1158. static int
  1159. sconnect(s, sapp, len)
  1160. int s, len;
  1161. struct sockaddr *sapp;
  1162. {
  1163. register struct sockaddr_un *sap;
  1164. struct stat st;
  1165. int x;
  1166. sap = (struct sockaddr_un *)sapp;
  1167. if (stat(sap->sun_path, &st))
  1168. return -1;
  1169. chmod(sap->sun_path, 0);
  1170. x = connect(s, (struct sockaddr *) sap, len);
  1171. chmod(sap->sun_path, st.st_mode);
  1172. return x;
  1173. }
  1174. #endif
  1175. /*
  1176. * Set the mode bits of the socket to the current status
  1177. */
  1178. int
  1179. chsock()
  1180. {
  1181. int r, euid = geteuid();
  1182. if (euid != real_uid)
  1183. {
  1184. if (UserContext() <= 0)
  1185. return UserStatus();
  1186. }
  1187. r = chmod(SockPath, SOCKMODE);
  1188. /*
  1189. * Sockets usually reside in the /tmp/ area, where sysadmin scripts
  1190. * may be happy to remove old files. We manually prevent the socket
  1191. * from becoming old. (chmod does not touch mtime).
  1192. */
  1193. (void)utimes(SockPath, NULL);
  1194. if (euid != real_uid)
  1195. UserReturn(r);
  1196. return r;
  1197. }
  1198. /*
  1199. * Try to recreate the socket/pipe
  1200. */
  1201. int
  1202. RecoverSocket()
  1203. {
  1204. close(ServerSocket);
  1205. if ((int)geteuid() != real_uid)
  1206. {
  1207. if (UserContext() > 0)
  1208. UserReturn(unlink(SockPath));
  1209. (void)UserStatus();
  1210. }
  1211. else
  1212. (void) unlink(SockPath);
  1213. if ((ServerSocket = MakeServerSocket()) < 0)
  1214. return 0;
  1215. evdeq(&serv_read);
  1216. serv_read.fd = ServerSocket;
  1217. evenq(&serv_read);
  1218. return 1;
  1219. }
  1220. static void
  1221. FinishAttach(m)
  1222. struct msg *m;
  1223. {
  1224. char *p;
  1225. int pid;
  1226. int noshowwin;
  1227. struct win *wi;
  1228. ASSERT(display);
  1229. pid = D_userpid;
  1230. #ifdef REMOTE_DETACH
  1231. if (m->m.attach.detachfirst == MSG_DETACH
  1232. # ifdef POW_DETACH
  1233. || m->m.attach.detachfirst == MSG_POW_DETACH
  1234. # endif
  1235. )
  1236. FinishDetach(m);
  1237. #endif
  1238. #if defined(pyr) || defined(xelos) || defined(sequent)
  1239. /*
  1240. * Kludge for systems with braindamaged termcap routines,
  1241. * which evaluate $TERMCAP, regardless weather it describes
  1242. * the correct terminal type or not.
  1243. */
  1244. debug("unsetenv(TERMCAP) in case of a different terminal");
  1245. unsetenv("TERMCAP");
  1246. #endif
  1247. /*
  1248. * We reboot our Terminal Emulator. Forget all we knew about
  1249. * the old terminal, reread the termcap entries in .screenrc
  1250. * (and nothing more from .screenrc is read. Mainly because
  1251. * I did not check, weather a full reinit is safe. jw)
  1252. * and /etc/screenrc, and initialise anew.
  1253. */
  1254. if (extra_outcap)
  1255. free(extra_outcap);
  1256. if (extra_incap)
  1257. free(extra_incap);
  1258. extra_incap = extra_outcap = 0;
  1259. debug2("Message says size (%dx%d)\n", m->m.attach.columns, m->m.attach.lines);
  1260. #ifdef ETCSCREENRC
  1261. # ifdef ALLOW_SYSSCREENRC
  1262. if ((p = getenv("SYSSCREENRC")))
  1263. StartRc(p, 1);
  1264. else
  1265. # endif
  1266. StartRc(ETCSCREENRC, 1);
  1267. #endif
  1268. StartRc(RcFileName, 1);
  1269. if (InitTermcap(m->m.attach.columns, m->m.attach.lines))
  1270. {
  1271. FreeDisplay();
  1272. Kill(pid, SIG_BYE);
  1273. return;
  1274. }
  1275. MakeDefaultCanvas();
  1276. InitTerm(m->m.attach.adaptflag); /* write init string on fd */
  1277. if (displays->d_next == 0)
  1278. (void) chsock();
  1279. signal(SIGHUP, SigHup);
  1280. if (m->m.attach.esc != -1 && m->m.attach.meta_esc != -1)
  1281. {
  1282. D_user->u_Esc = m->m.attach.esc;
  1283. D_user->u_MetaEsc = m->m.attach.meta_esc;
  1284. }
  1285. #ifdef UTMPOK
  1286. /*
  1287. * we set the Utmp slots again, if we were detached normally
  1288. * and if we were detached by ^Z.
  1289. * don't log zomies back in!
  1290. */
  1291. RemoveLoginSlot();
  1292. if (displays->d_next == 0)
  1293. for (wi = windows; wi; wi = wi->w_next)
  1294. if (wi->w_ptyfd >= 0 && wi->w_slot != (slot_t) -1)
  1295. SetUtmp(wi);
  1296. #endif
  1297. D_fore = NULL;
  1298. if (layout_attach)
  1299. {
  1300. struct layout *lay = layout_attach;
  1301. if (lay == &layout_last_marker)
  1302. lay = layout_last;
  1303. if (lay)
  1304. {
  1305. LoadLayout(lay, &D_canvas);
  1306. SetCanvasWindow(D_forecv, 0);
  1307. }
  1308. }
  1309. /*
  1310. * there may be a window that we remember from last detach:
  1311. */
  1312. debug1("D_user->u_detachwin = %d\n", D_user->u_detachwin);
  1313. if (D_user->u_detachwin >= 0)
  1314. fore = wtab[D_user->u_detachwin];
  1315. else
  1316. fore = 0;
  1317. /* Wayne wants us to restore the other window too. */
  1318. if (D_user->u_detachotherwin >= 0)
  1319. D_other = wtab[D_user->u_detachotherwin];
  1320. noshowwin = 0;
  1321. if (*m->m.attach.preselect)
  1322. {
  1323. if (!strcmp(m->m.attach.preselect, "="))
  1324. fore = 0;
  1325. else if (!strcmp(m->m.attach.preselect, "-"))
  1326. {
  1327. fore = 0;
  1328. noshowwin = 1;
  1329. }
  1330. else if (!strcmp(m->m.attach.preselect, "+"))
  1331. {
  1332. struct action newscreen;
  1333. char *na = 0;
  1334. newscreen.nr = RC_SCREEN;
  1335. newscreen.args = &na;
  1336. newscreen.quiet = 0;
  1337. DoAction(&newscreen, -1);
  1338. }
  1339. else
  1340. fore = FindNiceWindow(fore, m->m.attach.preselect);
  1341. }
  1342. else
  1343. fore = FindNiceWindow(fore, 0);
  1344. if (fore)
  1345. SetForeWindow(fore);
  1346. else if (!noshowwin)
  1347. {
  1348. #ifdef MULTIUSER
  1349. if (!AclCheckPermCmd(D_user, ACL_EXEC, &comms[RC_WINDOWLIST]))
  1350. #endif
  1351. {
  1352. struct display *olddisplay = display;
  1353. flayer = D_forecv->c_layer;
  1354. display_windows(1, WLIST_NUM, (struct win *)0);
  1355. noshowwin = 1;
  1356. display = olddisplay; /* display_windows can change display */
  1357. }
  1358. }
  1359. Activate(0);
  1360. ResetIdle();
  1361. if (!D_fore && !noshowwin)
  1362. ShowWindows(-1);
  1363. if (displays->d_next == 0 && console_window)
  1364. {
  1365. if (TtyGrabConsole(console_window->w_ptyfd, 1, "reattach") == 0)
  1366. Msg(0, "console %s is on window %d", HostName, console_window->w_number);
  1367. }
  1368. debug("activated...\n");
  1369. # if defined(DEBUG) && defined(SIG_NODEBUG)
  1370. if (!dfp)
  1371. {
  1372. sleep(1);
  1373. debug1("Attacher %d must not debug, as we have debug off.\n", pid);
  1374. kill(pid, SIG_NODEBUG);
  1375. }
  1376. # endif /* SIG_NODEBUG */
  1377. }
  1378. static void
  1379. FinishDetach(m)
  1380. struct msg *m;
  1381. {
  1382. struct display *next, **d, *det;
  1383. int pid;
  1384. if (m->type == MSG_ATTACH)
  1385. pid = D_userpid;
  1386. else
  1387. pid = m->m.detach.dpid;
  1388. /* Remove the temporary display prompting for the password from the list */
  1389. for (d = &displays; (det = *d); d = &det->d_next)
  1390. {
  1391. if (det->d_userpid == pid)
  1392. break;
  1393. }
  1394. if (det)
  1395. {
  1396. *d = det->d_next;
  1397. det->d_next = 0;
  1398. }
  1399. for (display = displays; display; display = next)
  1400. {
  1401. next = display->d_next;
  1402. # ifdef POW_DETACH
  1403. if (m->type == MSG_POW_DETACH)
  1404. Detach(D_REMOTE_POWER);
  1405. else
  1406. # endif /* POW_DETACH */
  1407. if (m->type == MSG_DETACH)
  1408. Detach(D_REMOTE);
  1409. else if (m->type == MSG_ATTACH)
  1410. {
  1411. #ifdef POW_DETACH
  1412. if (m->m.attach.detachfirst == MSG_POW_DETACH)
  1413. Detach(D_REMOTE_POWER);
  1414. else
  1415. #endif
  1416. if (m->m.attach.detachfirst == MSG_DETACH)
  1417. Detach(D_REMOTE);
  1418. }
  1419. }
  1420. display = displays = det;
  1421. if (m->type != MSG_ATTACH)
  1422. {
  1423. if (display)
  1424. FreeDisplay();
  1425. Kill(pid, SIGCONT);
  1426. }
  1427. }
  1428. #ifdef PASSWORD
  1429. static void PasswordProcessInput __P((char *, int));
  1430. struct pwdata {
  1431. int l;
  1432. char buf[20 + 1];
  1433. struct msg m;
  1434. };
  1435. static void
  1436. AskPassword(m)
  1437. struct msg *m;
  1438. {
  1439. struct pwdata *pwdata;
  1440. ASSERT(display);
  1441. pwdata = (struct pwdata *)malloc(sizeof(struct pwdata));
  1442. if (!pwdata)
  1443. Panic(0, "%s", strnomem);
  1444. pwdata->l = 0;
  1445. pwdata->m = *m;
  1446. D_processinputdata = (char *)pwdata;
  1447. D_processinput = PasswordProcessInput;
  1448. AddStr("Screen password: ");
  1449. }
  1450. static void
  1451. PasswordProcessInput(ibuf, ilen)
  1452. char *ibuf;
  1453. int ilen;
  1454. {
  1455. struct pwdata *pwdata;
  1456. int c, l;
  1457. char *up;
  1458. int pid = D_userpid;
  1459. pwdata = (struct pwdata *)D_processinputdata;
  1460. l = pwdata->l;
  1461. while (ilen-- > 0)
  1462. {
  1463. c = *(unsigned char *)ibuf++;
  1464. if (c == '\r' || c == '\n')
  1465. {
  1466. up = D_user->u_password;
  1467. pwdata->buf[l] = 0;
  1468. if (strncmp(crypt(pwdata->buf, up), up, strlen(up)))
  1469. {
  1470. /* uh oh, user failed */
  1471. bzero(pwdata->buf, sizeof(pwdata->buf));
  1472. AddStr("\r\nPassword incorrect.\r\n");
  1473. D_processinputdata = 0; /* otherwise freed by FreeDis */
  1474. FreeDisplay();
  1475. Msg(0, "Illegal reattach attempt from terminal %s.", pwdata->m.m_tty);
  1476. free(pwdata);
  1477. Kill(pid, SIG_BYE);
  1478. return;
  1479. }
  1480. /* great, pw matched, all is fine */
  1481. bzero(pwdata->buf, sizeof(pwdata->buf));
  1482. AddStr("\r\n");
  1483. D_processinputdata = 0;
  1484. D_processinput = ProcessInput;
  1485. #ifdef REMOTE_DETACH
  1486. if (pwdata->m.type == MSG_DETACH
  1487. # ifdef POW_DETACH
  1488. || pwdata->m.type == MSG_POW_DETACH
  1489. # endif
  1490. )
  1491. FinishDetach(&pwdata->m);
  1492. else
  1493. #endif
  1494. FinishAttach(&pwdata->m);
  1495. free(pwdata);
  1496. return;
  1497. }
  1498. if (c == Ctrl('c'))
  1499. {
  1500. AddStr("\r\n");
  1501. FreeDisplay();
  1502. Kill(pid, SIG_BYE);
  1503. return;
  1504. }
  1505. if (c == '\b' || c == 0177)
  1506. {
  1507. if (l > 0)
  1508. l--;
  1509. continue;
  1510. }
  1511. if (c == Ctrl('u'))
  1512. {
  1513. l = 0;
  1514. continue;
  1515. }
  1516. if (l < (int)sizeof(pwdata->buf) - 1)
  1517. pwdata->buf[l++] = c;
  1518. }
  1519. pwdata->l = l;
  1520. }
  1521. #endif
  1522. static void
  1523. DoCommandMsg(mp)
  1524. struct msg *mp;
  1525. {
  1526. char *args[MAXARGS];
  1527. int argl[MAXARGS];
  1528. char fullcmd[MAXSTR];
  1529. register char *fc;
  1530. int n;
  1531. register char *p = mp->m.command.cmd;
  1532. struct acluser *user;
  1533. #ifdef MULTIUSER
  1534. extern struct acluser *EffectiveAclUser; /* acls.c */
  1535. #else
  1536. extern struct acluser *users; /* acls.c */
  1537. #endif
  1538. n = mp->m.command.nargs;
  1539. if (n > MAXARGS - 1)
  1540. n = MAXARGS - 1;
  1541. for (fc = fullcmd; n > 0; n--)
  1542. {
  1543. int len = strlen(p);
  1544. strncpy(fc, p, fullcmd + sizeof(fullcmd) - fc - 1);
  1545. p += len + 1;
  1546. fc += len;
  1547. *fc++ = ' ';
  1548. }
  1549. if (fc != fullcmd)
  1550. *--fc = 0;
  1551. if (Parse(fullcmd, sizeof fullcmd, args, argl) <= 0)
  1552. {
  1553. queryflag = -1;
  1554. return;
  1555. }
  1556. #ifdef MULTIUSER
  1557. user = *FindUserPtr(mp->m.attach.auser);
  1558. if (user == 0)
  1559. {
  1560. Msg(0, "Unknown user %s tried to send a command!", mp->m.attach.auser);
  1561. queryflag = -1;
  1562. return;
  1563. }
  1564. #else
  1565. user = users;
  1566. #endif
  1567. #ifdef PASSWORD
  1568. if (user->u_password && *user->u_password)
  1569. {
  1570. Msg(0, "User %s has a password, cannot use remote commands (using -Q or -X option).", mp->m.attach.auser);
  1571. queryflag = -1;
  1572. return;
  1573. }
  1574. #endif
  1575. if (!display)
  1576. for (display = displays; display; display = display->d_next)
  1577. if (D_user == user)
  1578. break;
  1579. for (fore = windows; fore; fore = fore->w_next)
  1580. if (!TTYCMP(mp->m_tty, fore->w_tty))
  1581. {
  1582. if (!display)
  1583. display = fore->w_layer.l_cvlist ? fore->w_layer.l_cvlist->c_display : 0;
  1584. break;
  1585. }
  1586. if (!display)
  1587. display = displays; /* sigh */
  1588. if (*mp->m.command.preselect)
  1589. {
  1590. int i = -1;
  1591. if (strcmp(mp->m.command.preselect, "-"))
  1592. {
  1593. i = WindowByNoN(mp->m.command.preselect);
  1594. if (i < 0 || !wtab[i])
  1595. {
  1596. Msg(0, "Could not find pre-select window.");
  1597. queryflag = -1;
  1598. return;
  1599. }
  1600. }
  1601. fore = i >= 0 ? wtab[i] : 0;
  1602. }
  1603. else if (!fore)
  1604. {
  1605. if (display && D_user == user)
  1606. fore = Layer2Window(display->d_forecv->c_layer);
  1607. if (!fore)
  1608. {
  1609. fore = user->u_detachwin >= 0 ? wtab[user->u_detachwin] : 0;
  1610. fore = FindNiceWindow(fore, 0);
  1611. }
  1612. }
  1613. if (!fore)
  1614. fore = windows; /* sigh */
  1615. #ifdef MULTIUSER
  1616. EffectiveAclUser = user;
  1617. #endif
  1618. if (*args)
  1619. {
  1620. char *oldrcname = rc_name;
  1621. rc_name = "-X";
  1622. debug3("Running command on display %x window %x (%d)\n", display, fore, fore ? fore->w_number : -1);
  1623. flayer = fore ? &fore->w_layer : 0;
  1624. if (fore && fore->w_savelayer && (fore->w_blocked || fore->w_savelayer->l_cvlist == 0))
  1625. flayer = fore->w_savelayer;
  1626. DoCommand(args, argl);
  1627. rc_name = oldrcname;
  1628. }
  1629. #ifdef MULTIUSER
  1630. EffectiveAclUser = 0;
  1631. #endif
  1632. }
  1633. #ifndef NAMEDPIPE
  1634. int
  1635. SendAttachMsg(s, m, fd)
  1636. int s;
  1637. struct msg *m;
  1638. int fd;
  1639. {
  1640. int r;
  1641. struct msghdr msg;
  1642. struct iovec iov;
  1643. char buf[CMSG_SPACE(sizeof(int))];
  1644. struct cmsghdr *cmsg;
  1645. iov.iov_base = (char *)m;
  1646. iov.iov_len = sizeof(*m);
  1647. bzero(&msg, sizeof(msg));
  1648. msg.msg_name = 0;
  1649. msg.msg_namelen = 0;
  1650. msg.msg_iov = &iov;
  1651. msg.msg_iovlen = 1;
  1652. msg.msg_control = buf;
  1653. msg.msg_controllen = sizeof(buf);
  1654. cmsg = CMSG_FIRSTHDR(&msg);
  1655. cmsg->cmsg_level = SOL_SOCKET;
  1656. cmsg->cmsg_type = SCM_RIGHTS;
  1657. cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  1658. bcopy(&fd, CMSG_DATA(cmsg), sizeof(int));
  1659. msg.msg_controllen = cmsg->cmsg_len;
  1660. while(1)
  1661. {
  1662. r = sendmsg(s, &msg, 0);
  1663. if (r == -1 && errno == EINTR)
  1664. continue;
  1665. if (r == -1)
  1666. return -1;
  1667. return 0;
  1668. }
  1669. }
  1670. #endif