Context get_ctx(void *frontend) { #ifdef Q_OS_WIN return get_windowid(0)?GetDC(get_windowid(0)):0; #else struct gui_data *inst = (struct gui_data *)frontend; struct draw_ctx *dctx; dctx = snew(struct draw_ctx); dctx->inst = inst; return dctx; #endif }
void free_ctx(Context ctx) { #ifdef Q_OS_WIN ReleaseDC(get_windowid(0),ctx); #else struct draw_ctx *dctx = (struct draw_ctx *)ctx; sfree(dctx); #endif }
/* * Called to set up the pty. * * Returns an error message, or NULL on success. * * Also places the canonical host name into `realhost'. It must be * freed by the caller. */ static const char *pty_init(void *frontend, void **backend_handle, Conf *conf, char *host, int port, char **realhost, int nodelay, int keepalive) { int slavefd; pid_t pid, pgrp; #ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */ long windowid; #endif Pty pty; if (single_pty) { pty = single_pty; assert(pty->conf == NULL); } else { pty = snew(struct pty_tag); pty->master_fd = pty->slave_fd = -1; #ifndef OMIT_UTMP pty_stamped_utmp = FALSE; #endif } pty->frontend = frontend; *backend_handle = NULL; /* we can't sensibly use this, sadly */ pty->conf = conf_copy(conf); pty->term_width = conf_get_int(conf, CONF_width); pty->term_height = conf_get_int(conf, CONF_height); if (pty->master_fd < 0) pty_open_master(pty); /* * Set the backspace character to be whichever of ^H and ^? is * specified by bksp_is_delete. */ { struct termios attrs; tcgetattr(pty->master_fd, &attrs); attrs.c_cc[VERASE] = conf_get_int(conf, CONF_bksp_is_delete) ? '\177' : '\010'; tcsetattr(pty->master_fd, TCSANOW, &attrs); } #ifndef OMIT_UTMP /* * Stamp utmp (that is, tell the utmp helper process to do so), * or not. */ if (pty_utmp_helper_pipe >= 0) { /* if it's < 0, we can't anyway */ if (!conf_get_int(conf, CONF_stamp_utmp)) { close(pty_utmp_helper_pipe); /* just let the child process die */ pty_utmp_helper_pipe = -1; } else { char *location = get_x_display(pty->frontend); int len = strlen(location)+1, pos = 0; /* +1 to include NUL */ while (pos < len) { int ret = write(pty_utmp_helper_pipe, location+pos, len - pos); if (ret < 0) { perror("pterm: writing to utmp helper process"); close(pty_utmp_helper_pipe); /* arrgh, just give up */ pty_utmp_helper_pipe = -1; break; } pos += ret; } } } #endif #ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */ windowid = get_windowid(pty->frontend); #endif /* * Fork and execute the command. */ pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (pid == 0) { /* * We are the child. */ slavefd = pty_open_slave(pty); if (slavefd < 0) { perror("slave pty: open"); _exit(1); } close(pty->master_fd); noncloexec(slavefd); dup2(slavefd, 0); dup2(slavefd, 1); dup2(slavefd, 2); close(slavefd); setsid(); #ifdef TIOCSCTTY ioctl(0, TIOCSCTTY, 1); #endif pgrp = getpid(); tcsetpgrp(0, pgrp); setpgid(pgrp, pgrp); { int ptyfd = open(pty->name, O_WRONLY, 0); if (ptyfd >= 0) close(ptyfd); } setpgid(pgrp, pgrp); { char *term_env_var = dupprintf("TERM=%s", conf_get_str(conf, CONF_termtype)); putenv(term_env_var); /* We mustn't free term_env_var, as putenv links it into the * environment in place. */ } #ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */ { char *windowid_env_var = dupprintf("WINDOWID=%ld", windowid); putenv(windowid_env_var); /* We mustn't free windowid_env_var, as putenv links it into the * environment in place. */ } #endif { char *key, *val; for (val = conf_get_str_strs(conf, CONF_environmt, NULL, &key); val != NULL; val = conf_get_str_strs(conf, CONF_environmt, key, &key)) { char *varval = dupcat(key, "=", val, NULL); putenv(varval); /* * We must not free varval, since putenv links it * into the environment _in place_. Weird, but * there we go. Memory usage will be rationalised * as soon as we exec anyway. */ } } /* * SIGINT, SIGQUIT and SIGPIPE may have been set to ignored by * our parent, particularly by things like sh -c 'pterm &' and * some window or session managers. SIGCHLD, meanwhile, was * blocked during pt_main() startup. Reverse all this for our * child process. */ putty_signal(SIGINT, SIG_DFL); putty_signal(SIGQUIT, SIG_DFL); putty_signal(SIGPIPE, SIG_DFL); block_signal(SIGCHLD, 0); if (pty_argv) { /* * Exec the exact argument list we were given. */ execvp(pty_argv[0], pty_argv); /* * If that fails, and if we had exactly one argument, pass * that argument to $SHELL -c. * * This arranges that we can _either_ follow 'pterm -e' * with a list of argv elements to be fed directly to * exec, _or_ with a single argument containing a command * to be parsed by a shell (but, in cases of doubt, the * former is more reliable). * * A quick survey of other terminal emulators' -e options * (as of Debian squeeze) suggests that: * * - xterm supports both modes, more or less like this * - gnome-terminal will only accept a one-string shell command * - Eterm, kterm and rxvt will only accept a list of * argv elements (as did older versions of pterm). * * It therefore seems important to support both usage * modes in order to be a drop-in replacement for either * xterm or gnome-terminal, and hence for anyone's * plausible uses of the Debian-style alias * 'x-terminal-emulator'... */ if (pty_argv[1] == NULL) { char *shell = getenv("SHELL"); if (shell) execl(shell, shell, "-c", pty_argv[0], (void *)NULL); } } else { char *shell = getenv("SHELL"); char *shellname; if (conf_get_int(conf, CONF_login_shell)) { char *p = strrchr(shell, '/'); shellname = snewn(2+strlen(shell), char); p = p ? p+1 : shell; sprintf(shellname, "-%s", p); } else shellname = shell; execl(getenv("SHELL"), shellname, (void *)NULL); }
/* * Called to set up the pty. * * Returns an error message, or NULL on success. * * Also places the canonical host name into `realhost'. It must be * freed by the caller. */ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg, char *host, int port, char **realhost, int nodelay, int keepalive) { int slavefd; pid_t pid, pgrp; #ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */ long windowid; #endif Pty pty; if (single_pty) { pty = single_pty; } else { pty = snew(struct pty_tag); pty->master_fd = pty->slave_fd = -1; #ifndef OMIT_UTMP pty_stamped_utmp = FALSE; #endif } pty->frontend = frontend; *backend_handle = NULL; /* we can't sensibly use this, sadly */ pty->cfg = *cfg; /* structure copy */ pty->term_width = cfg->width; pty->term_height = cfg->height; if (pty->master_fd < 0) pty_open_master(pty); /* * Set the backspace character to be whichever of ^H and ^? is * specified by bksp_is_delete. */ { struct termios attrs; tcgetattr(pty->master_fd, &attrs); attrs.c_cc[VERASE] = cfg->bksp_is_delete ? '\177' : '\010'; tcsetattr(pty->master_fd, TCSANOW, &attrs); } #ifndef OMIT_UTMP /* * Stamp utmp (that is, tell the utmp helper process to do so), * or not. */ if (!cfg->stamp_utmp) { close(pty_utmp_helper_pipe); /* just let the child process die */ pty_utmp_helper_pipe = -1; } else { char *location = get_x_display(pty->frontend); int len = strlen(location)+1, pos = 0; /* +1 to include NUL */ while (pos < len) { int ret = write(pty_utmp_helper_pipe, location+pos, len - pos); if (ret < 0) { perror("pterm: writing to utmp helper process"); close(pty_utmp_helper_pipe); /* arrgh, just give up */ pty_utmp_helper_pipe = -1; break; } pos += ret; } } #endif #ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */ windowid = get_windowid(pty->frontend); #endif /* * Fork and execute the command. */ pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (pid == 0) { /* * We are the child. */ slavefd = pty_open_slave(pty); if (slavefd < 0) { perror("slave pty: open"); _exit(1); } close(pty->master_fd); fcntl(slavefd, F_SETFD, 0); /* don't close on exec */ dup2(slavefd, 0); dup2(slavefd, 1); dup2(slavefd, 2); close(slavefd); setsid(); #ifdef TIOCSCTTY ioctl(0, TIOCSCTTY, 1); #endif pgrp = getpid(); tcsetpgrp(0, pgrp); setpgid(pgrp, pgrp); close(open(pty->name, O_WRONLY, 0)); setpgid(pgrp, pgrp); { char *term_env_var = dupprintf("TERM=%s", cfg->termtype); putenv(term_env_var); /* We mustn't free term_env_var, as putenv links it into the * environment in place. */ } #ifndef NOT_X_WINDOWS /* for Mac OS X native compilation */ { char *windowid_env_var = dupprintf("WINDOWID=%ld", windowid); putenv(windowid_env_var); /* We mustn't free windowid_env_var, as putenv links it into the * environment in place. */ } #endif { char *e = cfg->environmt; char *var, *varend, *val, *varval; while (*e) { var = e; while (*e && *e != '\t') e++; varend = e; if (*e == '\t') e++; val = e; while (*e) e++; e++; varval = dupprintf("%.*s=%s", varend-var, var, val); putenv(varval); /* * We must not free varval, since putenv links it * into the environment _in place_. Weird, but * there we go. Memory usage will be rationalised * as soon as we exec anyway. */ } } /* * SIGINT, SIGQUIT and SIGPIPE may have been set to ignored by * our parent, particularly by things like sh -c 'pterm &' and * some window or session managers. SIGCHLD, meanwhile, was * blocked during pt_main() startup. Reverse all this for our * child process. */ putty_signal(SIGINT, SIG_DFL); putty_signal(SIGQUIT, SIG_DFL); putty_signal(SIGPIPE, SIG_DFL); block_signal(SIGCHLD, 0); if (pty_argv) execvp(pty_argv[0], pty_argv); else { char *shell = getenv("SHELL"); char *shellname; if (cfg->login_shell) { char *p = strrchr(shell, '/'); shellname = snewn(2+strlen(shell), char); p = p ? p+1 : shell; sprintf(shellname, "-%s", p); } else
/* * Called to set up the pty. * * Returns an error message, or NULL on success. * * Also places the canonical host name into `realhost'. It must be * freed by the caller. */ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg, char *host, int port, char **realhost, int nodelay, int keepalive) { int slavefd; pid_t pid, pgrp; long windowid; pty_frontend = frontend; *backend_handle = NULL; /* we can't sensibly use this, sadly */ pty_cfg = *cfg; /* structure copy */ pty_term_width = cfg->width; pty_term_height = cfg->height; if (pty_master_fd < 0) pty_open_master(); /* * Set the backspace character to be whichever of ^H and ^? is * specified by bksp_is_delete. */ { struct termios attrs; tcgetattr(pty_master_fd, &attrs); attrs.c_cc[VERASE] = cfg->bksp_is_delete ? '\177' : '\010'; tcsetattr(pty_master_fd, TCSANOW, &attrs); } /* * Stamp utmp (that is, tell the utmp helper process to do so), * or not. */ if (!cfg->stamp_utmp) { close(pty_utmp_helper_pipe); /* just let the child process die */ pty_utmp_helper_pipe = -1; } else { char *location = get_x_display(pty_frontend); int len = strlen(location)+1, pos = 0; /* +1 to include NUL */ while (pos < len) { int ret = write(pty_utmp_helper_pipe, location+pos, len - pos); if (ret < 0) { perror("pterm: writing to utmp helper process"); close(pty_utmp_helper_pipe); /* arrgh, just give up */ pty_utmp_helper_pipe = -1; break; } pos += ret; } } windowid = get_windowid(pty_frontend); /* * Fork and execute the command. */ pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (pid == 0) { int i; /* * We are the child. */ slavefd = open(pty_name, O_RDWR); if (slavefd < 0) { perror("slave pty: open"); _exit(1); } close(pty_master_fd); fcntl(slavefd, F_SETFD, 0); /* don't close on exec */ dup2(slavefd, 0); dup2(slavefd, 1); dup2(slavefd, 2); setsid(); ioctl(slavefd, TIOCSCTTY, 1); pgrp = getpid(); tcsetpgrp(slavefd, pgrp); setpgrp(); close(open(pty_name, O_WRONLY, 0)); setpgrp(); /* Close everything _else_, for tidiness. */ for (i = 3; i < 1024; i++) close(i); { char term_env_var[10 + sizeof(cfg->termtype)]; sprintf(term_env_var, "TERM=%s", cfg->termtype); putenv(term_env_var); } { char windowid_env_var[40]; sprintf(windowid_env_var, "WINDOWID=%ld", windowid); putenv(windowid_env_var); } { char *e = cfg->environmt; char *var, *varend, *val, *varval; while (*e) { var = e; while (*e && *e != '\t') e++; varend = e; if (*e == '\t') e++; val = e; while (*e) e++; e++; varval = dupprintf("%.*s=%s", varend-var, var, val); putenv(varval); /* * We must not free varval, since putenv links it * into the environment _in place_. Weird, but * there we go. Memory usage will be rationalised * as soon as we exec anyway. */ } } /* * SIGINT and SIGQUIT may have been set to ignored by our * parent, particularly by things like sh -c 'pterm &' and * some window managers. Reverse this for our child process. */ putty_signal(SIGINT, SIG_DFL); putty_signal(SIGQUIT, SIG_DFL); if (pty_argv) execvp(pty_argv[0], pty_argv); else { char *shell = getenv("SHELL"); char *shellname; if (cfg->login_shell) { char *p = strrchr(shell, '/'); shellname = snewn(2+strlen(shell), char); p = p ? p+1 : shell; sprintf(shellname, "-%s", p); } else