static enum cmd_retval cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = self->args; struct client *c; const char *size; u_int w, h; if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); if (args_has(args, 'C')) { if ((size = args_get(args, 'C')) == NULL) { cmdq_error(item, "missing size"); return (CMD_RETURN_ERROR); } if (sscanf(size, "%u,%u", &w, &h) != 2) { cmdq_error(item, "bad size argument"); return (CMD_RETURN_ERROR); } if (w < PANE_MINIMUM || w > 5000 || h < PANE_MINIMUM || h > 5000) { cmdq_error(item, "size too small or too big"); return (CMD_RETURN_ERROR); } if (!(c->flags & CLIENT_CONTROL)) { cmdq_error(item, "not a control client"); return (CMD_RETURN_ERROR); } tty_set_size(&c->tty, w, h); c->flags |= CLIENT_SIZECHANGED; recalculate_sizes(); } else if (args_has(args, 'S')) { c->flags |= CLIENT_STATUSFORCE; server_status_client(c); } else { c->flags |= CLIENT_STATUSFORCE; server_redraw_client(c); } return (CMD_RETURN_NORMAL); }
int tty_resize(struct tty *tty) { struct winsize ws; u_int sx, sy; if (ioctl(tty->fd, TIOCGWINSZ, &ws) != -1) { sx = ws.ws_col; if (sx == 0) sx = 80; sy = ws.ws_row; if (sy == 0) sy = 24; } else { sx = 80; sy = 24; } if (!tty_set_size(tty, sx, sy)) return (0); tty->cx = UINT_MAX; tty->cy = UINT_MAX; tty->rupper = UINT_MAX; tty->rlower = UINT_MAX; /* * If the terminal has been started, reset the actual scroll region and * cursor position, as this may not have happened. */ if (tty->flags & TTY_STARTED) { tty_cursor(tty, 0, 0); tty_region(tty, 0, tty->sy - 1); } return (1); }
/* Changed the argv0 and execlp stuff similar to rxvt-2.18. * Command is ignored as parameter. Matthias */ int run_command(unsigned char *command,unsigned char **argv) { int ptyfd=-1; int uid, gid; int grantpty=1; unsigned char *s3, *s4; int i; int width, height; #ifndef SVR4 static char ptyc3[] = "pqrstuvwxyz"; static char ptyc4[] = "0123456789abcdef"; #endif /* First find a master pty that we can open. */ #if __GLIBC__ - 0 == 2 && __GLIBC_MINOR__ >= 1 ptyfd = getpt(); if (ptyfd < 0) { error("Can't open a pseudo teletype"); return(-1); } if (grantpt(ptyfd) < 0 || unlockpt(ptyfd) < 0) { close(ptyfd); error("Can't grantpt/unlockpt a pseudo teletype"); return(-1); } ttynam = ptsname(ptyfd); if (ttynam == 0) { close(ptyfd); error("Pseudo teletype has no name"); return(-1); } fcntl(ptyfd,F_SETFL,O_NDELAY); grantpty = 0; #else #ifdef TIOCGPTN strcpy(ptynam,"/dev/ptmx"); strcpy(ttynam,"/dev/pts/"); ptyfd = open(ptynam,O_RDWR); if (ptyfd >= 0) // got the master pty { int ptyno; if (ioctl(ptyfd, TIOCGPTN, &ptyno) == 0) { struct stat sbuf; sprintf(ttynam,"/dev/pts/%d",ptyno); if (stat(ttynam,&sbuf) == 0 && S_ISCHR(sbuf.st_mode)) grantpty = 0; else { close(ptyfd); ptyfd = -1; } } else { close(ptyfd); ptyfd = -1; } } #endif if (ptyfd < 0) { #ifdef SVR4 ptyfd = open("/dev/ptmx",O_RDWR); if (ptyfd < 0) { error("Can't open a pseudo teletype"); return(-1); } grantpt(ptyfd); unlockpt(ptyfd); fcntl(ptyfd,F_SETFL,O_NDELAY); ttynam=ptsname(ptyfd); #else strcpy(ptynam, "/dev/ptyxx"); strcpy(ttynam, "/dev/ttyxx"); ptyfd = -1; for (s3 = ptyc3; *s3 != 0; s3++) { for (s4 = ptyc4; *s4 != 0; s4++) { ptynam[8] = ttynam[8] = *s3; ptynam[9] = ttynam[9] = *s4; if ((ptyfd = open(ptynam,O_RDWR)) >= 0) { if (geteuid() == 0 || access(ttynam,R_OK|W_OK) == 0) break; else { close(ptyfd); ptyfd = -1; } } } if (ptyfd >= 0) break; } if (ptyfd < 0) { error("Can't open a pseudo teletype"); return(-1); } fcntl(ptyfd,F_SETFL,O_NDELAY); #endif } #endif /* GLIBC */ for (i = 1; i <= 15; i++) signal(i,catch_sig); signal(SIGCHLD,catch_child); lstat(ttynam,&ttyfd_stat); utime(ttynam,NULL); makeutent(&ttynam[5]); /* stamp /etc/utmp */ comm_pid = fork(); if (comm_pid < 0) { error("Can't fork"); return(-1); } if (comm_pid == 0) { struct group *gr; if ((ttyfd = open(ttynam,O_RDWR)) < 0) { error("could not open slave tty %s",ttynam); clean_exit(1); } #ifdef SVR4 ioctl(ttyfd,I_PUSH,"ptem"); ioctl(ttyfd,I_PUSH,"ldterm"); #endif uid = getuid(); #ifndef SVR4 if ((gr = getgrnam("tty")) != NULL) gid = gr->gr_gid; else gid = -1; if (grantpty) { // regain root privileges seteuid(0); fchown(ttyfd,uid,gid); fchmod(ttyfd,0600); // drop root privileges again seteuid(getuid()); } #endif #ifdef TIOCCONS if (console) { int on = 1; if (ioctl (ttyfd, TIOCCONS, (unsigned char *)&on) == -1) fprintf(stderr, "kvt: cannot open console\n"); } #endif /* TIOCCONS */ #if defined(_HPUX_SOURCE) || defined (__Lynx__) for (i = 0; i < sysconf(_SC_OPEN_MAX); i++) if (i != ttyfd) close(i); #else for (i = 0; i < getdtablesize(); i++) if (i != ttyfd) close(i); #endif dup(ttyfd); dup(ttyfd); dup(ttyfd); if (ttyfd > 2) close(ttyfd); if (setsid() < 0) perror("failed to set process group"); #if defined(TIOCSCTTY) ioctl(0, TIOCSCTTY, 0) ; #endif { int pgrp = getpid(); ioctl(0, TIOCSPGRP, (char *)&pgrp); setpgid(0,0); close(open(ttynam, O_WRONLY, 0)); setpgid(0,0); } /* init of termios structure */ #if defined (__FreeBSD__) || (__NetBSD__) || defined(__bsdi__) ioctl(0,TIOCGETA,(char *)&ttmode); #else # if defined (_HPUX_SOURCE) || defined(__Lynx__) tcgetattr(0, &ttmode); # else ioctl(0,TCGETS,(char *)&ttmode); # endif #endif #if defined(_HPUX_SOURCE) || defined(__Lynx__) ttmode.c_iflag = BRKINT | IGNPAR | ICRNL| IXON; ttmode.c_lflag = ISIG|IEXTEN|ICANON|ECHO|ECHOE|ECHOK; #else ttmode.c_iflag = BRKINT | IGNPAR | ICRNL| IXON | IMAXBEL; ttmode.c_lflag = ISIG|IEXTEN|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE; #endif ttmode.c_oflag = OPOST | ONLCR ; ttmode.c_cflag = B9600 | CS8 | CREAD; ttmode.c_cc[VEOF] = CEOF; #ifdef ALPHA (unsigned) ttmode.c_cc[VEOL] = CEOL; #else ttmode.c_cc[VEOL] = CEOL; #endif ttmode.c_cc[VINTR] = CINTR; ttmode.c_cc[VQUIT] = CQUIT; ttmode.c_cc[VERASE] = CERASE; ttmode.c_cc[VKILL] = CKILL; #if defined(_HPUX_SOURCE) || defined(__Lynx__) ttmode.c_cc[VSUSP] = CSWTCH; #else ttmode.c_cc[VSUSP] = CSUSP; #endif #ifdef VDSUSP ttmode.c_cc[VDSUSP] = CDSUSP; #endif ttmode.c_cc[VSTART] = CSTART; ttmode.c_cc[VSTOP] = CSTOP; #ifdef VREPRINT ttmode.c_cc[VREPRINT] = CRPRNT; #endif #ifdef VDISCARD ttmode.c_cc[VDISCARD] = CFLUSH; #endif #ifdef VWERASE ttmode.c_cc[VWERASE] = CWERASE; #endif #ifdef VLNEXT ttmode.c_cc[VLNEXT] = CLNEXT; #endif #ifdef VSWTC ttmode.c_cc[VSWTC] = 0; #endif #ifdef VSWTCH ttmode.c_cc[VSWTCH] = 0; #endif #if VMIN != VEOF ttmode.c_cc[VMIN] = 1; #endif #if VTIME != VEOL ttmode.c_cc[VTIME] = 0; #endif if(mask == 0x7f) ttmode.c_cflag = B9600 | PARENB | CS7 | CREAD; #if defined (__FreeBSD__) || (__NetBSD__) || defined(__bsdi__) ioctl(0,TIOCSETA,(char *)&ttmode); #else # ifdef _HPUX_SOURCE tcsetattr(0, TCSANOW, &ttmode); # else ioctl(0,TCSETS,(char *)&ttmode); # endif #endif scr_get_size(&width,&height); tty_set_size(0,width,height); /* the stuff inspired from rxvt-2.18: */ /* command interpreter path */ if (argv != NULL) { setgid(getgid()); setuid(uid); execvp (argv [0], (char **) argv); error ("can't execute \"%s\"", argv [0]); clean_exit(1); } else { const char *argv0, *shell; char* base; if ((shell = getenv ("SHELL")) == NULL || *shell == '\0') shell = "/bin/sh"; base = strrchr (shell, '/'); argv0 = (base ? base + 1 : shell); if (login_shell) { char * p = (char*) safemalloc((strlen (argv0)+2)*sizeof(char), argv0); p [0] = '-'; strcpy (&p [1], argv0); argv0 = p; } setgid(getgid()); setuid(uid); execlp (shell, argv0, NULL); error ("can't execute \"%s\"", shell); clean_exit(1); } /* originally rvxt-2.08: (Matthias) */ /* if(login_shell) */ /* { */ /* char *tmp; */ /* strcpy(argv0,"-"); */ /* if ((tmp = strrchr(argv[0], '/')) == NULL) */ /* tmp = argv[0]; */ /* else */ /* tmp++; */ /* strcat(argv0,tmp); */ /* argv[0] = argv0; */ /* } */ /* setgid(getgid()); */ /* setuid(uid); */ /* execvp(command,(char **)argv); */ /* error("Couldn't execute %s",command); */ /* clean_exit(1); */ } return(ptyfd); }
static enum cmd_retval cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = self->args; struct client *c; struct tty *tty; struct window *w; const char *size, *errstr; u_int x, y, adjust; if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL) return (CMD_RETURN_ERROR); tty = &c->tty; if (args_has(args, 'c') || args_has(args, 'L') || args_has(args, 'R') || args_has(args, 'U') || args_has(args, 'D')) { if (args->argc == 0) adjust = 1; else { adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); if (errstr != NULL) { cmdq_error(item, "adjustment %s", errstr); return (CMD_RETURN_ERROR); } } if (args_has(args, 'c')) c->pan_window = NULL; else { w = c->session->curw->window; if (c->pan_window != w) { c->pan_window = w; c->pan_ox = tty->oox; c->pan_oy = tty->ooy; } if (args_has(args, 'L')) { if (c->pan_ox > adjust) c->pan_ox -= adjust; else c->pan_ox = 0; } else if (args_has(args, 'R')) { c->pan_ox += adjust; if (c->pan_ox > w->sx - tty->osx) c->pan_ox = w->sx - tty->osx; } else if (args_has(args, 'U')) { if (c->pan_oy > adjust) c->pan_oy -= adjust; else c->pan_oy = 0; } else if (args_has(args, 'D')) { c->pan_oy += adjust; if (c->pan_oy > w->sy - tty->osy) c->pan_oy = w->sy - tty->osy; } } tty_update_client_offset(c); server_redraw_client(c); return (CMD_RETURN_NORMAL); } if (args_has(args, 'C')) { if ((size = args_get(args, 'C')) == NULL) { cmdq_error(item, "missing size"); return (CMD_RETURN_ERROR); } if (sscanf(size, "%u,%u", &x, &y) != 2 && sscanf(size, "%ux%u", &x, &y)) { cmdq_error(item, "bad size argument"); return (CMD_RETURN_ERROR); } if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM || y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) { cmdq_error(item, "size too small or too big"); return (CMD_RETURN_ERROR); } if (!(c->flags & CLIENT_CONTROL)) { cmdq_error(item, "not a control client"); return (CMD_RETURN_ERROR); } tty_set_size(&c->tty, x, y); c->flags |= CLIENT_SIZECHANGED; recalculate_sizes(); return (CMD_RETURN_NORMAL); } if (args_has(args, 'S')) { c->flags |= CLIENT_STATUSFORCE; server_status_client(c); } else { c->flags |= CLIENT_STATUSFORCE; server_redraw_client(c); } return (CMD_RETURN_NORMAL); }