uxpty.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256
  1. /*
  2. * Pseudo-tty backend for pterm.
  3. */
  4. #define _GNU_SOURCE
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <signal.h>
  10. #include <assert.h>
  11. #include <fcntl.h>
  12. #include <termios.h>
  13. #include <grp.h>
  14. #include <utmp.h>
  15. #include <pwd.h>
  16. #include <time.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <sys/wait.h>
  20. #include <sys/ioctl.h>
  21. #include <errno.h>
  22. #include "putty.h"
  23. #include "tree234.h"
  24. #ifndef OMIT_UTMP
  25. #include <utmpx.h>
  26. #endif
  27. #ifndef FALSE
  28. #define FALSE 0
  29. #endif
  30. #ifndef TRUE
  31. #define TRUE 1
  32. #endif
  33. /* updwtmpx() needs the name of the wtmp file. Try to find it. */
  34. #ifndef WTMPX_FILE
  35. #ifdef _PATH_WTMPX
  36. #define WTMPX_FILE _PATH_WTMPX
  37. #else
  38. #define WTMPX_FILE "/var/log/wtmpx"
  39. #endif
  40. #endif
  41. #ifndef LASTLOG_FILE
  42. #ifdef _PATH_LASTLOG
  43. #define LASTLOG_FILE _PATH_LASTLOG
  44. #else
  45. #define LASTLOG_FILE "/var/log/lastlog"
  46. #endif
  47. #endif
  48. /*
  49. * Set up a default for vaguely sane systems. The idea is that if
  50. * OMIT_UTMP is not defined, then at least one of the symbols which
  51. * enable particular forms of utmp processing should be, if only so
  52. * that a link error can warn you that you should have defined
  53. * OMIT_UTMP if you didn't want any. Currently HAVE_PUTUTLINE is
  54. * the only such symbol.
  55. */
  56. #ifndef OMIT_UTMP
  57. #if !defined HAVE_PUTUTLINE
  58. #define HAVE_PUTUTLINE
  59. #endif
  60. #endif
  61. typedef struct pty_tag *Pty;
  62. /*
  63. * The pty_signal_pipe, along with the SIGCHLD handler, must be
  64. * process-global rather than session-specific.
  65. */
  66. static int pty_signal_pipe[2] = { -1, -1 }; /* obviously bogus initial val */
  67. struct pty_tag {
  68. Conf *conf;
  69. int master_fd, slave_fd;
  70. void *frontend;
  71. char name[FILENAME_MAX];
  72. pid_t child_pid;
  73. int term_width, term_height;
  74. int child_dead, finished;
  75. int exit_code;
  76. bufchain output_data;
  77. };
  78. /*
  79. * We store our pty backends in a tree sorted by master fd, so that
  80. * when we get an uxsel notification we know which backend instance
  81. * is the owner of the pty that caused it.
  82. */
  83. static int pty_compare_by_fd(void *av, void *bv)
  84. {
  85. Pty a = (Pty)av;
  86. Pty b = (Pty)bv;
  87. if (a->master_fd < b->master_fd)
  88. return -1;
  89. else if (a->master_fd > b->master_fd)
  90. return +1;
  91. return 0;
  92. }
  93. static int pty_find_by_fd(void *av, void *bv)
  94. {
  95. int a = *(int *)av;
  96. Pty b = (Pty)bv;
  97. if (a < b->master_fd)
  98. return -1;
  99. else if (a > b->master_fd)
  100. return +1;
  101. return 0;
  102. }
  103. static tree234 *ptys_by_fd = NULL;
  104. /*
  105. * We also have a tree sorted by child pid, so that when we wait()
  106. * in response to the signal we know which backend instance is the
  107. * owner of the process that caused the signal.
  108. */
  109. static int pty_compare_by_pid(void *av, void *bv)
  110. {
  111. Pty a = (Pty)av;
  112. Pty b = (Pty)bv;
  113. if (a->child_pid < b->child_pid)
  114. return -1;
  115. else if (a->child_pid > b->child_pid)
  116. return +1;
  117. return 0;
  118. }
  119. static int pty_find_by_pid(void *av, void *bv)
  120. {
  121. pid_t a = *(pid_t *)av;
  122. Pty b = (Pty)bv;
  123. if (a < b->child_pid)
  124. return -1;
  125. else if (a > b->child_pid)
  126. return +1;
  127. return 0;
  128. }
  129. static tree234 *ptys_by_pid = NULL;
  130. /*
  131. * If we are using pty_pre_init(), it will need to have already
  132. * allocated a pty structure, which we must then return from
  133. * pty_init() rather than allocating a new one. Here we store that
  134. * structure between allocation and use.
  135. *
  136. * Note that although most of this module is entirely capable of
  137. * handling multiple ptys in a single process, pty_pre_init() is
  138. * fundamentally _dependent_ on there being at most one pty per
  139. * process, so the normal static-data constraints don't apply.
  140. *
  141. * Likewise, since utmp is only used via pty_pre_init, it too must
  142. * be single-instance, so we can declare utmp-related variables
  143. * here.
  144. */
  145. static Pty single_pty = NULL;
  146. #ifndef OMIT_UTMP
  147. static pid_t pty_utmp_helper_pid = -1;
  148. static int pty_utmp_helper_pipe = -1;
  149. static int pty_stamped_utmp;
  150. static struct utmpx utmp_entry;
  151. #endif
  152. /*
  153. * pty_argv is a grievous hack to allow a proper argv to be passed
  154. * through from the Unix command line. Again, it doesn't really
  155. * make sense outside a one-pty-per-process setup.
  156. */
  157. char **pty_argv;
  158. char *pty_osx_envrestore_prefix;
  159. static void pty_close(Pty pty);
  160. static void pty_try_write(Pty pty);
  161. #ifndef OMIT_UTMP
  162. static void setup_utmp(char *ttyname, char *location)
  163. {
  164. #ifdef HAVE_LASTLOG
  165. struct lastlog lastlog_entry;
  166. FILE *lastlog;
  167. #endif
  168. struct passwd *pw;
  169. struct timeval tv;
  170. pw = getpwuid(getuid());
  171. memset(&utmp_entry, 0, sizeof(utmp_entry));
  172. utmp_entry.ut_type = USER_PROCESS;
  173. utmp_entry.ut_pid = getpid();
  174. strncpy(utmp_entry.ut_line, ttyname+5, lenof(utmp_entry.ut_line));
  175. strncpy(utmp_entry.ut_id, ttyname+8, lenof(utmp_entry.ut_id));
  176. strncpy(utmp_entry.ut_user, pw->pw_name, lenof(utmp_entry.ut_user));
  177. strncpy(utmp_entry.ut_host, location, lenof(utmp_entry.ut_host));
  178. /*
  179. * Apparently there are some architectures where (struct
  180. * utmpx).ut_tv is not essentially struct timeval (e.g. Linux
  181. * amd64). Hence the temporary.
  182. */
  183. gettimeofday(&tv, NULL);
  184. utmp_entry.ut_tv.tv_sec = tv.tv_sec;
  185. utmp_entry.ut_tv.tv_usec = tv.tv_usec;
  186. setutxent();
  187. pututxline(&utmp_entry);
  188. endutxent();
  189. updwtmpx(WTMPX_FILE, &utmp_entry);
  190. #ifdef HAVE_LASTLOG
  191. memset(&lastlog_entry, 0, sizeof(lastlog_entry));
  192. strncpy(lastlog_entry.ll_line, ttyname+5, lenof(lastlog_entry.ll_line));
  193. strncpy(lastlog_entry.ll_host, location, lenof(lastlog_entry.ll_host));
  194. time(&lastlog_entry.ll_time);
  195. if ((lastlog = fopen(LASTLOG_FILE, "r+")) != NULL) {
  196. fseek(lastlog, sizeof(lastlog_entry) * getuid(), SEEK_SET);
  197. fwrite(&lastlog_entry, 1, sizeof(lastlog_entry), lastlog);
  198. fclose(lastlog);
  199. }
  200. #endif
  201. pty_stamped_utmp = 1;
  202. }
  203. static void cleanup_utmp(void)
  204. {
  205. struct timeval tv;
  206. if (!pty_stamped_utmp)
  207. return;
  208. utmp_entry.ut_type = DEAD_PROCESS;
  209. memset(utmp_entry.ut_user, 0, lenof(utmp_entry.ut_user));
  210. gettimeofday(&tv, NULL);
  211. utmp_entry.ut_tv.tv_sec = tv.tv_sec;
  212. utmp_entry.ut_tv.tv_usec = tv.tv_usec;
  213. updwtmpx(WTMPX_FILE, &utmp_entry);
  214. memset(utmp_entry.ut_line, 0, lenof(utmp_entry.ut_line));
  215. utmp_entry.ut_tv.tv_sec = 0;
  216. utmp_entry.ut_tv.tv_usec = 0;
  217. setutxent();
  218. pututxline(&utmp_entry);
  219. endutxent();
  220. pty_stamped_utmp = 0; /* ensure we never double-cleanup */
  221. }
  222. #endif
  223. #ifndef NO_PTY_PRE_INIT
  224. static void sigchld_handler(int signum)
  225. {
  226. if (write(pty_signal_pipe[1], "x", 1) <= 0)
  227. /* not much we can do about it */;
  228. }
  229. #endif
  230. #ifndef OMIT_UTMP
  231. static void fatal_sig_handler(int signum)
  232. {
  233. putty_signal(signum, SIG_DFL);
  234. cleanup_utmp();
  235. raise(signum);
  236. }
  237. #endif
  238. static int pty_open_slave(Pty pty)
  239. {
  240. if (pty->slave_fd < 0) {
  241. pty->slave_fd = open(pty->name, O_RDWR);
  242. cloexec(pty->slave_fd);
  243. }
  244. return pty->slave_fd;
  245. }
  246. static void pty_open_master(Pty pty)
  247. {
  248. #ifdef BSD_PTYS
  249. const char chars1[] = "pqrstuvwxyz";
  250. const char chars2[] = "0123456789abcdef";
  251. const char *p1, *p2;
  252. char master_name[20];
  253. struct group *gp;
  254. for (p1 = chars1; *p1; p1++)
  255. for (p2 = chars2; *p2; p2++) {
  256. sprintf(master_name, "/dev/pty%c%c", *p1, *p2);
  257. pty->master_fd = open(master_name, O_RDWR);
  258. if (pty->master_fd >= 0) {
  259. if (geteuid() == 0 ||
  260. access(master_name, R_OK | W_OK) == 0) {
  261. /*
  262. * We must also check at this point that we are
  263. * able to open the slave side of the pty. We
  264. * wouldn't want to allocate the wrong master,
  265. * get all the way down to forking, and _then_
  266. * find we're unable to open the slave.
  267. */
  268. strcpy(pty->name, master_name);
  269. pty->name[5] = 't'; /* /dev/ptyXX -> /dev/ttyXX */
  270. cloexec(pty->master_fd);
  271. if (pty_open_slave(pty) >= 0 &&
  272. access(pty->name, R_OK | W_OK) == 0)
  273. goto got_one;
  274. if (pty->slave_fd > 0)
  275. close(pty->slave_fd);
  276. pty->slave_fd = -1;
  277. }
  278. close(pty->master_fd);
  279. }
  280. }
  281. /* If we get here, we couldn't get a tty at all. */
  282. fprintf(stderr, "pterm: unable to open a pseudo-terminal device\n");
  283. exit(1);
  284. got_one:
  285. /* We need to chown/chmod the /dev/ttyXX device. */
  286. gp = getgrnam("tty");
  287. chown(pty->name, getuid(), gp ? gp->gr_gid : -1);
  288. chmod(pty->name, 0600);
  289. #else
  290. const int flags = O_RDWR
  291. #ifdef O_NOCTTY
  292. | O_NOCTTY
  293. #endif
  294. ;
  295. #ifdef HAVE_POSIX_OPENPT
  296. #ifdef SET_NONBLOCK_VIA_OPENPT
  297. /*
  298. * OS X, as of 10.10 at least, doesn't permit me to set O_NONBLOCK
  299. * on pty master fds via the usual fcntl mechanism. Fortunately,
  300. * it does let me work around this by adding O_NONBLOCK to the
  301. * posix_openpt flags parameter, which isn't a documented use of
  302. * the API but seems to work. So we'll do that for now.
  303. */
  304. pty->master_fd = posix_openpt(flags | O_NONBLOCK);
  305. #else
  306. pty->master_fd = posix_openpt(flags);
  307. #endif
  308. if (pty->master_fd < 0) {
  309. perror("posix_openpt");
  310. exit(1);
  311. }
  312. #else
  313. pty->master_fd = open("/dev/ptmx", flags);
  314. if (pty->master_fd < 0) {
  315. perror("/dev/ptmx: open");
  316. exit(1);
  317. }
  318. #endif
  319. if (grantpt(pty->master_fd) < 0) {
  320. perror("grantpt");
  321. exit(1);
  322. }
  323. if (unlockpt(pty->master_fd) < 0) {
  324. perror("unlockpt");
  325. exit(1);
  326. }
  327. cloexec(pty->master_fd);
  328. pty->name[FILENAME_MAX-1] = '\0';
  329. strncpy(pty->name, ptsname(pty->master_fd), FILENAME_MAX-1);
  330. #endif
  331. #ifndef SET_NONBLOCK_VIA_OPENPT
  332. nonblock(pty->master_fd);
  333. #endif
  334. if (!ptys_by_fd)
  335. ptys_by_fd = newtree234(pty_compare_by_fd);
  336. add234(ptys_by_fd, pty);
  337. }
  338. static Pty new_pty_struct(void)
  339. {
  340. Pty pty = snew(struct pty_tag);
  341. pty->conf = NULL;
  342. bufchain_init(&pty->output_data);
  343. return pty;
  344. }
  345. /*
  346. * Pre-initialisation. This is here to get around the fact that GTK
  347. * doesn't like being run in setuid/setgid programs (probably
  348. * sensibly). So before we initialise GTK - and therefore before we
  349. * even process the command line - we check to see if we're running
  350. * set[ug]id. If so, we open our pty master _now_, chown it as
  351. * necessary, and drop privileges. We can always close it again
  352. * later. If we're potentially going to be doing utmp as well, we
  353. * also fork off a utmp helper process and communicate with it by
  354. * means of a pipe; the utmp helper will keep privileges in order
  355. * to clean up utmp when we exit (i.e. when its end of our pipe
  356. * closes).
  357. */
  358. void pty_pre_init(void)
  359. {
  360. #ifndef NO_PTY_PRE_INIT
  361. Pty pty;
  362. #ifndef OMIT_UTMP
  363. pid_t pid;
  364. int pipefd[2];
  365. #endif
  366. pty = single_pty = new_pty_struct();
  367. /* set the child signal handler straight away; it needs to be set
  368. * before we ever fork. */
  369. putty_signal(SIGCHLD, sigchld_handler);
  370. pty->master_fd = pty->slave_fd = -1;
  371. #ifndef OMIT_UTMP
  372. pty_stamped_utmp = FALSE;
  373. #endif
  374. if (geteuid() != getuid() || getegid() != getgid()) {
  375. pty_open_master(pty);
  376. #ifndef OMIT_UTMP
  377. /*
  378. * Fork off the utmp helper.
  379. */
  380. if (pipe(pipefd) < 0) {
  381. perror("pterm: pipe");
  382. exit(1);
  383. }
  384. cloexec(pipefd[0]);
  385. cloexec(pipefd[1]);
  386. pid = fork();
  387. if (pid < 0) {
  388. perror("pterm: fork");
  389. exit(1);
  390. } else if (pid == 0) {
  391. char display[128], buffer[128];
  392. int dlen, ret;
  393. close(pipefd[1]);
  394. /*
  395. * Now sit here until we receive a display name from the
  396. * other end of the pipe, and then stamp utmp. Unstamp utmp
  397. * again, and exit, when the pipe closes.
  398. */
  399. dlen = 0;
  400. while (1) {
  401. ret = read(pipefd[0], buffer, lenof(buffer));
  402. if (ret <= 0) {
  403. cleanup_utmp();
  404. _exit(0);
  405. } else if (!pty_stamped_utmp) {
  406. if (dlen < lenof(display))
  407. memcpy(display+dlen, buffer,
  408. min(ret, lenof(display)-dlen));
  409. if (buffer[ret-1] == '\0') {
  410. /*
  411. * Now we have a display name. NUL-terminate
  412. * it, and stamp utmp.
  413. */
  414. display[lenof(display)-1] = '\0';
  415. /*
  416. * Trap as many fatal signals as we can in the
  417. * hope of having the best possible chance to
  418. * clean up utmp before termination. We are
  419. * unfortunately unprotected against SIGKILL,
  420. * but that's life.
  421. */
  422. putty_signal(SIGHUP, fatal_sig_handler);
  423. putty_signal(SIGINT, fatal_sig_handler);
  424. putty_signal(SIGQUIT, fatal_sig_handler);
  425. putty_signal(SIGILL, fatal_sig_handler);
  426. putty_signal(SIGABRT, fatal_sig_handler);
  427. putty_signal(SIGFPE, fatal_sig_handler);
  428. putty_signal(SIGPIPE, fatal_sig_handler);
  429. putty_signal(SIGALRM, fatal_sig_handler);
  430. putty_signal(SIGTERM, fatal_sig_handler);
  431. putty_signal(SIGSEGV, fatal_sig_handler);
  432. putty_signal(SIGUSR1, fatal_sig_handler);
  433. putty_signal(SIGUSR2, fatal_sig_handler);
  434. #ifdef SIGBUS
  435. putty_signal(SIGBUS, fatal_sig_handler);
  436. #endif
  437. #ifdef SIGPOLL
  438. putty_signal(SIGPOLL, fatal_sig_handler);
  439. #endif
  440. #ifdef SIGPROF
  441. putty_signal(SIGPROF, fatal_sig_handler);
  442. #endif
  443. #ifdef SIGSYS
  444. putty_signal(SIGSYS, fatal_sig_handler);
  445. #endif
  446. #ifdef SIGTRAP
  447. putty_signal(SIGTRAP, fatal_sig_handler);
  448. #endif
  449. #ifdef SIGVTALRM
  450. putty_signal(SIGVTALRM, fatal_sig_handler);
  451. #endif
  452. #ifdef SIGXCPU
  453. putty_signal(SIGXCPU, fatal_sig_handler);
  454. #endif
  455. #ifdef SIGXFSZ
  456. putty_signal(SIGXFSZ, fatal_sig_handler);
  457. #endif
  458. #ifdef SIGIO
  459. putty_signal(SIGIO, fatal_sig_handler);
  460. #endif
  461. setup_utmp(pty->name, display);
  462. }
  463. }
  464. }
  465. } else {
  466. close(pipefd[0]);
  467. pty_utmp_helper_pid = pid;
  468. pty_utmp_helper_pipe = pipefd[1];
  469. }
  470. #endif
  471. }
  472. /* Drop privs. */
  473. {
  474. #ifndef HAVE_NO_SETRESUID
  475. int gid = getgid(), uid = getuid();
  476. int setresgid(gid_t, gid_t, gid_t);
  477. int setresuid(uid_t, uid_t, uid_t);
  478. if (setresgid(gid, gid, gid) < 0) {
  479. perror("setresgid");
  480. exit(1);
  481. }
  482. if (setresuid(uid, uid, uid) < 0) {
  483. perror("setresuid");
  484. exit(1);
  485. }
  486. #else
  487. if (setgid(getgid()) < 0) {
  488. perror("setgid");
  489. exit(1);
  490. }
  491. if (setuid(getuid()) < 0) {
  492. perror("setuid");
  493. exit(1);
  494. }
  495. #endif
  496. }
  497. #endif /* NO_PTY_PRE_INIT */
  498. }
  499. int pty_real_select_result(Pty pty, int event, int status)
  500. {
  501. char buf[4096];
  502. int ret;
  503. int finished = FALSE;
  504. if (event < 0) {
  505. /*
  506. * We've been called because our child process did
  507. * something. `status' tells us what.
  508. */
  509. if ((WIFEXITED(status) || WIFSIGNALED(status))) {
  510. /*
  511. * The primary child process died. We could keep
  512. * the terminal open for remaining subprocesses to
  513. * output to, but conventional wisdom seems to feel
  514. * that that's the Wrong Thing for an xterm-alike,
  515. * so we bail out now (though we don't necessarily
  516. * _close_ the window, depending on the state of
  517. * Close On Exit). This would be easy enough to
  518. * change or make configurable if necessary.
  519. */
  520. pty->exit_code = status;
  521. pty->child_dead = TRUE;
  522. del234(ptys_by_pid, pty);
  523. finished = TRUE;
  524. }
  525. } else {
  526. if (event == 1) {
  527. ret = read(pty->master_fd, buf, sizeof(buf));
  528. /*
  529. * Clean termination condition is that either ret == 0, or ret
  530. * < 0 and errno == EIO. Not sure why the latter, but it seems
  531. * to happen. Boo.
  532. */
  533. if (ret == 0 || (ret < 0 && errno == EIO)) {
  534. /*
  535. * We assume a clean exit if the pty has closed but the
  536. * actual child process hasn't. The only way I can
  537. * imagine this happening is if it detaches itself from
  538. * the pty and goes daemonic - in which case the
  539. * expected usage model would precisely _not_ be for
  540. * the pterm window to hang around!
  541. */
  542. finished = TRUE;
  543. if (!pty->child_dead)
  544. pty->exit_code = 0;
  545. } else if (ret < 0) {
  546. perror("read pty master");
  547. exit(1);
  548. } else if (ret > 0) {
  549. from_backend(pty->frontend, 0, buf, ret);
  550. }
  551. } else if (event == 2) {
  552. /*
  553. * Attempt to send data down the pty.
  554. */
  555. pty_try_write(pty);
  556. }
  557. }
  558. if (finished && !pty->finished) {
  559. int close_on_exit;
  560. uxsel_del(pty->master_fd);
  561. pty_close(pty);
  562. pty->master_fd = -1;
  563. pty->finished = TRUE;
  564. /*
  565. * This is a slight layering-violation sort of hack: only
  566. * if we're not closing on exit (COE is set to Never, or to
  567. * Only On Clean and it wasn't a clean exit) do we output a
  568. * `terminated' message.
  569. */
  570. close_on_exit = conf_get_int(pty->conf, CONF_close_on_exit);
  571. if (close_on_exit == FORCE_OFF ||
  572. (close_on_exit == AUTO && pty->exit_code != 0)) {
  573. char message[512];
  574. message[0] = '\0';
  575. if (WIFEXITED(pty->exit_code))
  576. sprintf(message, "\r\n[pterm: process terminated with exit"
  577. " code %d]\r\n", WEXITSTATUS(pty->exit_code));
  578. else if (WIFSIGNALED(pty->exit_code))
  579. #ifdef HAVE_NO_STRSIGNAL
  580. sprintf(message, "\r\n[pterm: process terminated on signal"
  581. " %d]\r\n", WTERMSIG(pty->exit_code));
  582. #else
  583. sprintf(message, "\r\n[pterm: process terminated on signal"
  584. " %d (%.400s)]\r\n", WTERMSIG(pty->exit_code),
  585. strsignal(WTERMSIG(pty->exit_code)));
  586. #endif
  587. from_backend(pty->frontend, 0, message, strlen(message));
  588. }
  589. notify_remote_exit(pty->frontend);
  590. }
  591. return !finished;
  592. }
  593. int pty_select_result(int fd, int event)
  594. {
  595. int ret = TRUE;
  596. Pty pty;
  597. if (fd == pty_signal_pipe[0]) {
  598. pid_t pid;
  599. int status;
  600. char c[1];
  601. if (read(pty_signal_pipe[0], c, 1) <= 0)
  602. /* ignore error */;
  603. /* ignore its value; it'll be `x' */
  604. do {
  605. pid = waitpid(-1, &status, WNOHANG);
  606. pty = find234(ptys_by_pid, &pid, pty_find_by_pid);
  607. if (pty)
  608. ret = ret && pty_real_select_result(pty, -1, status);
  609. } while (pid > 0);
  610. } else {
  611. pty = find234(ptys_by_fd, &fd, pty_find_by_fd);
  612. if (pty)
  613. ret = ret && pty_real_select_result(pty, event, 0);
  614. }
  615. return ret;
  616. }
  617. static void pty_uxsel_setup(Pty pty)
  618. {
  619. int rwx;
  620. rwx = 1; /* always want to read from pty */
  621. if (bufchain_size(&pty->output_data))
  622. rwx |= 2; /* might also want to write to it */
  623. uxsel_set(pty->master_fd, rwx, pty_select_result);
  624. /*
  625. * In principle this only needs calling once for all pty
  626. * backend instances, but it's simplest just to call it every
  627. * time; uxsel won't mind.
  628. */
  629. uxsel_set(pty_signal_pipe[0], 1, pty_select_result);
  630. }
  631. /*
  632. * Called to set up the pty.
  633. *
  634. * Returns an error message, or NULL on success.
  635. *
  636. * Also places the canonical host name into `realhost'. It must be
  637. * freed by the caller.
  638. */
  639. static const char *pty_init(void *frontend, void **backend_handle, Conf *conf,
  640. const char *host, int port, char **realhost,
  641. int nodelay, int keepalive)
  642. {
  643. int slavefd;
  644. pid_t pid, pgrp;
  645. #ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */
  646. long windowid;
  647. #endif
  648. Pty pty;
  649. if (single_pty) {
  650. pty = single_pty;
  651. assert(pty->conf == NULL);
  652. } else {
  653. pty = new_pty_struct();
  654. pty->master_fd = pty->slave_fd = -1;
  655. #ifndef OMIT_UTMP
  656. pty_stamped_utmp = FALSE;
  657. #endif
  658. }
  659. pty->frontend = frontend;
  660. *backend_handle = NULL; /* we can't sensibly use this, sadly */
  661. pty->conf = conf_copy(conf);
  662. pty->term_width = conf_get_int(conf, CONF_width);
  663. pty->term_height = conf_get_int(conf, CONF_height);
  664. if (pty->master_fd < 0)
  665. pty_open_master(pty);
  666. #ifndef OMIT_UTMP
  667. /*
  668. * Stamp utmp (that is, tell the utmp helper process to do so),
  669. * or not.
  670. */
  671. if (pty_utmp_helper_pipe >= 0) { /* if it's < 0, we can't anyway */
  672. if (!conf_get_int(conf, CONF_stamp_utmp)) {
  673. close(pty_utmp_helper_pipe); /* just let the child process die */
  674. pty_utmp_helper_pipe = -1;
  675. } else {
  676. const char *location = get_x_display(pty->frontend);
  677. int len = strlen(location)+1, pos = 0; /* +1 to include NUL */
  678. while (pos < len) {
  679. int ret = write(pty_utmp_helper_pipe, location+pos, len - pos);
  680. if (ret < 0) {
  681. perror("pterm: writing to utmp helper process");
  682. close(pty_utmp_helper_pipe); /* arrgh, just give up */
  683. pty_utmp_helper_pipe = -1;
  684. break;
  685. }
  686. pos += ret;
  687. }
  688. }
  689. }
  690. #endif
  691. #ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */
  692. windowid = get_windowid(pty->frontend);
  693. #endif
  694. /*
  695. * Fork and execute the command.
  696. */
  697. pid = fork();
  698. if (pid < 0) {
  699. perror("fork");
  700. exit(1);
  701. }
  702. if (pid == 0) {
  703. struct termios attrs;
  704. /*
  705. * We are the child.
  706. */
  707. if (pty_osx_envrestore_prefix) {
  708. int plen = strlen(pty_osx_envrestore_prefix);
  709. extern char **environ;
  710. char **ep;
  711. restart_osx_env_restore:
  712. for (ep = environ; *ep; ep++) {
  713. char *e = *ep;
  714. if (!strncmp(e, pty_osx_envrestore_prefix, plen)) {
  715. int unset = (e[plen] == 'u');
  716. char *pname = dupprintf("%.*s", (int)strcspn(e, "="), e);
  717. char *name = pname + plen + 1;
  718. char *value = e + strcspn(e, "=");
  719. if (*value) value++;
  720. value = dupstr(value);
  721. if (unset)
  722. unsetenv(name);
  723. else
  724. setenv(name, value, 1);
  725. unsetenv(pname);
  726. sfree(pname);
  727. sfree(value);
  728. goto restart_osx_env_restore;
  729. }
  730. }
  731. }
  732. slavefd = pty_open_slave(pty);
  733. if (slavefd < 0) {
  734. perror("slave pty: open");
  735. _exit(1);
  736. }
  737. close(pty->master_fd);
  738. noncloexec(slavefd);
  739. dup2(slavefd, 0);
  740. dup2(slavefd, 1);
  741. dup2(slavefd, 2);
  742. close(slavefd);
  743. setsid();
  744. #ifdef TIOCSCTTY
  745. ioctl(0, TIOCSCTTY, 1);
  746. #endif
  747. pgrp = getpid();
  748. tcsetpgrp(0, pgrp);
  749. /*
  750. * Set up configuration-dependent termios settings on the new
  751. * pty. Linux would have let us do this on the pty master
  752. * before we forked, but that fails on OS X, so we do it here
  753. * instead.
  754. */
  755. if (tcgetattr(0, &attrs) == 0) {
  756. /*
  757. * Set the backspace character to be whichever of ^H and
  758. * ^? is specified by bksp_is_delete.
  759. */
  760. attrs.c_cc[VERASE] = conf_get_int(conf, CONF_bksp_is_delete)
  761. ? '\177' : '\010';
  762. /*
  763. * Set the IUTF8 bit iff the character set is UTF-8.
  764. */
  765. #ifdef IUTF8
  766. if (frontend_is_utf8(frontend))
  767. attrs.c_iflag |= IUTF8;
  768. else
  769. attrs.c_iflag &= ~IUTF8;
  770. #endif
  771. tcsetattr(0, TCSANOW, &attrs);
  772. }
  773. setpgid(pgrp, pgrp);
  774. {
  775. int ptyfd = open(pty->name, O_WRONLY, 0);
  776. if (ptyfd >= 0)
  777. close(ptyfd);
  778. }
  779. setpgid(pgrp, pgrp);
  780. {
  781. char *term_env_var = dupprintf("TERM=%s",
  782. conf_get_str(conf, CONF_termtype));
  783. putenv(term_env_var);
  784. /* We mustn't free term_env_var, as putenv links it into the
  785. * environment in place.
  786. */
  787. }
  788. #ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */
  789. {
  790. char *windowid_env_var = dupprintf("WINDOWID=%ld", windowid);
  791. putenv(windowid_env_var);
  792. /* We mustn't free windowid_env_var, as putenv links it into the
  793. * environment in place.
  794. */
  795. }
  796. {
  797. /*
  798. * In case we were invoked with a --display argument that
  799. * doesn't match DISPLAY in our actual environment, we
  800. * should set DISPLAY for processes running inside the
  801. * terminal to match the display the terminal itself is
  802. * on.
  803. */
  804. const char *x_display = get_x_display(pty->frontend);
  805. char *x_display_env_var = dupprintf("DISPLAY=%s", x_display);
  806. putenv(x_display_env_var);
  807. /* As above, we don't free this. */
  808. }
  809. #endif
  810. {
  811. char *key, *val;
  812. for (val = conf_get_str_strs(conf, CONF_environmt, NULL, &key);
  813. val != NULL;
  814. val = conf_get_str_strs(conf, CONF_environmt, key, &key)) {
  815. char *varval = dupcat(key, "=", val, NULL);
  816. putenv(varval);
  817. /*
  818. * We must not free varval, since putenv links it
  819. * into the environment _in place_. Weird, but
  820. * there we go. Memory usage will be rationalised
  821. * as soon as we exec anyway.
  822. */
  823. }
  824. }
  825. /*
  826. * SIGINT, SIGQUIT and SIGPIPE may have been set to ignored by
  827. * our parent, particularly by things like sh -c 'pterm &' and
  828. * some window or session managers. SIGPIPE was also
  829. * (potentially) blocked by us during startup. Reverse all
  830. * this for our child process.
  831. */
  832. putty_signal(SIGINT, SIG_DFL);
  833. putty_signal(SIGQUIT, SIG_DFL);
  834. putty_signal(SIGPIPE, SIG_DFL);
  835. block_signal(SIGPIPE, 0);
  836. if (pty_argv) {
  837. /*
  838. * Exec the exact argument list we were given.
  839. */
  840. execvp(pty_argv[0], pty_argv);
  841. /*
  842. * If that fails, and if we had exactly one argument, pass
  843. * that argument to $SHELL -c.
  844. *
  845. * This arranges that we can _either_ follow 'pterm -e'
  846. * with a list of argv elements to be fed directly to
  847. * exec, _or_ with a single argument containing a command
  848. * to be parsed by a shell (but, in cases of doubt, the
  849. * former is more reliable).
  850. *
  851. * A quick survey of other terminal emulators' -e options
  852. * (as of Debian squeeze) suggests that:
  853. *
  854. * - xterm supports both modes, more or less like this
  855. * - gnome-terminal will only accept a one-string shell command
  856. * - Eterm, kterm and rxvt will only accept a list of
  857. * argv elements (as did older versions of pterm).
  858. *
  859. * It therefore seems important to support both usage
  860. * modes in order to be a drop-in replacement for either
  861. * xterm or gnome-terminal, and hence for anyone's
  862. * plausible uses of the Debian-style alias
  863. * 'x-terminal-emulator'...
  864. */
  865. if (pty_argv[1] == NULL) {
  866. char *shell = getenv("SHELL");
  867. if (shell)
  868. execl(shell, shell, "-c", pty_argv[0], (void *)NULL);
  869. }
  870. } else {
  871. char *shell = getenv("SHELL");
  872. char *shellname;
  873. if (conf_get_int(conf, CONF_login_shell)) {
  874. char *p = strrchr(shell, '/');
  875. shellname = snewn(2+strlen(shell), char);
  876. p = p ? p+1 : shell;
  877. sprintf(shellname, "-%s", p);
  878. } else
  879. shellname = shell;
  880. execl(getenv("SHELL"), shellname, (void *)NULL);
  881. }
  882. /*
  883. * If we're here, exec has gone badly foom.
  884. */
  885. perror("exec");
  886. _exit(127);
  887. } else {
  888. pty->child_pid = pid;
  889. pty->child_dead = FALSE;
  890. pty->finished = FALSE;
  891. if (pty->slave_fd > 0)
  892. close(pty->slave_fd);
  893. if (!ptys_by_pid)
  894. ptys_by_pid = newtree234(pty_compare_by_pid);
  895. add234(ptys_by_pid, pty);
  896. }
  897. if (pty_signal_pipe[0] < 0) {
  898. if (pipe(pty_signal_pipe) < 0) {
  899. perror("pipe");
  900. exit(1);
  901. }
  902. cloexec(pty_signal_pipe[0]);
  903. cloexec(pty_signal_pipe[1]);
  904. }
  905. pty_uxsel_setup(pty);
  906. *backend_handle = pty;
  907. *realhost = dupstr("");
  908. return NULL;
  909. }
  910. static void pty_reconfig(void *handle, Conf *conf)
  911. {
  912. Pty pty = (Pty)handle;
  913. /*
  914. * We don't have much need to reconfigure this backend, but
  915. * unfortunately we do need to pick up the setting of Close On
  916. * Exit so we know whether to give a `terminated' message.
  917. */
  918. conf_copy_into(pty->conf, conf);
  919. }
  920. /*
  921. * Stub routine (never called in pterm).
  922. */
  923. static void pty_free(void *handle)
  924. {
  925. Pty pty = (Pty)handle;
  926. /* Either of these may fail `not found'. That's fine with us. */
  927. del234(ptys_by_pid, pty);
  928. del234(ptys_by_fd, pty);
  929. bufchain_clear(&pty->output_data);
  930. conf_free(pty->conf);
  931. pty->conf = NULL;
  932. if (pty == single_pty) {
  933. /*
  934. * Leave this structure around in case we need to Restart
  935. * Session.
  936. */
  937. } else {
  938. sfree(pty);
  939. }
  940. }
  941. static void pty_try_write(Pty pty)
  942. {
  943. void *data;
  944. int len, ret;
  945. assert(pty->master_fd >= 0);
  946. while (bufchain_size(&pty->output_data) > 0) {
  947. bufchain_prefix(&pty->output_data, &data, &len);
  948. ret = write(pty->master_fd, data, len);
  949. if (ret < 0 && (errno == EWOULDBLOCK)) {
  950. /*
  951. * We've sent all we can for the moment.
  952. */
  953. break;
  954. }
  955. if (ret < 0) {
  956. perror("write pty master");
  957. exit(1);
  958. }
  959. bufchain_consume(&pty->output_data, ret);
  960. }
  961. pty_uxsel_setup(pty);
  962. }
  963. /*
  964. * Called to send data down the pty.
  965. */
  966. static int pty_send(void *handle, const char *buf, int len)
  967. {
  968. Pty pty = (Pty)handle;
  969. if (pty->master_fd < 0)
  970. return 0; /* ignore all writes if fd closed */
  971. bufchain_add(&pty->output_data, buf, len);
  972. pty_try_write(pty);
  973. return bufchain_size(&pty->output_data);
  974. }
  975. static void pty_close(Pty pty)
  976. {
  977. if (pty->master_fd >= 0) {
  978. close(pty->master_fd);
  979. pty->master_fd = -1;
  980. }
  981. #ifndef OMIT_UTMP
  982. if (pty_utmp_helper_pipe >= 0) {
  983. close(pty_utmp_helper_pipe); /* this causes utmp to be cleaned up */
  984. pty_utmp_helper_pipe = -1;
  985. }
  986. #endif
  987. }
  988. /*
  989. * Called to query the current socket sendability status.
  990. */
  991. static int pty_sendbuffer(void *handle)
  992. {
  993. /* Pty pty = (Pty)handle; */
  994. return 0;
  995. }
  996. /*
  997. * Called to set the size of the window
  998. */
  999. static void pty_size(void *handle, int width, int height)
  1000. {
  1001. Pty pty = (Pty)handle;
  1002. struct winsize size;
  1003. pty->term_width = width;
  1004. pty->term_height = height;
  1005. size.ws_row = (unsigned short)pty->term_height;
  1006. size.ws_col = (unsigned short)pty->term_width;
  1007. size.ws_xpixel = (unsigned short) pty->term_width *
  1008. font_dimension(pty->frontend, 0);
  1009. size.ws_ypixel = (unsigned short) pty->term_height *
  1010. font_dimension(pty->frontend, 1);
  1011. ioctl(pty->master_fd, TIOCSWINSZ, (void *)&size);
  1012. return;
  1013. }
  1014. /*
  1015. * Send special codes.
  1016. */
  1017. static void pty_special(void *handle, Telnet_Special code)
  1018. {
  1019. /* Pty pty = (Pty)handle; */
  1020. /* Do nothing! */
  1021. return;
  1022. }
  1023. /*
  1024. * Return a list of the special codes that make sense in this
  1025. * protocol.
  1026. */
  1027. static const struct telnet_special *pty_get_specials(void *handle)
  1028. {
  1029. /* Pty pty = (Pty)handle; */
  1030. /*
  1031. * Hmm. When I get round to having this actually usable, it
  1032. * might be quite nice to have the ability to deliver a few
  1033. * well chosen signals to the child process - SIGINT, SIGTERM,
  1034. * SIGKILL at least.
  1035. */
  1036. return NULL;
  1037. }
  1038. static int pty_connected(void *handle)
  1039. {
  1040. /* Pty pty = (Pty)handle; */
  1041. return TRUE;
  1042. }
  1043. static int pty_sendok(void *handle)
  1044. {
  1045. /* Pty pty = (Pty)handle; */
  1046. return 1;
  1047. }
  1048. static void pty_unthrottle(void *handle, int backlog)
  1049. {
  1050. /* Pty pty = (Pty)handle; */
  1051. /* do nothing */
  1052. }
  1053. static int pty_ldisc(void *handle, int option)
  1054. {
  1055. /* Pty pty = (Pty)handle; */
  1056. return 0; /* neither editing nor echoing */
  1057. }
  1058. static void pty_provide_ldisc(void *handle, void *ldisc)
  1059. {
  1060. /* Pty pty = (Pty)handle; */
  1061. /* This is a stub. */
  1062. }
  1063. static void pty_provide_logctx(void *handle, void *logctx)
  1064. {
  1065. /* Pty pty = (Pty)handle; */
  1066. /* This is a stub. */
  1067. }
  1068. static int pty_exitcode(void *handle)
  1069. {
  1070. Pty pty = (Pty)handle;
  1071. if (!pty->finished)
  1072. return -1; /* not dead yet */
  1073. else
  1074. return pty->exit_code;
  1075. }
  1076. static int pty_cfg_info(void *handle)
  1077. {
  1078. /* Pty pty = (Pty)handle; */
  1079. return 0;
  1080. }
  1081. Backend pty_backend = {
  1082. pty_init,
  1083. pty_free,
  1084. pty_reconfig,
  1085. pty_send,
  1086. pty_sendbuffer,
  1087. pty_size,
  1088. pty_special,
  1089. pty_get_specials,
  1090. pty_connected,
  1091. pty_exitcode,
  1092. pty_sendok,
  1093. pty_ldisc,
  1094. pty_provide_ldisc,
  1095. pty_provide_logctx,
  1096. pty_unthrottle,
  1097. pty_cfg_info,
  1098. NULL /* test_for_upstream */,
  1099. "pty",
  1100. -1,
  1101. 0
  1102. };