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);
}
Example #3
0
/* 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);
}
Example #4
0
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);
}