Exemplo n.º 1
0
static int handle_gotdata(struct handle *h, void *data, int len)
{
    Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);

    if (len < 0) {
	plug_closing(ps->plug, "Read error from handle", 0, 0);
	return 0;
    } else if (len == 0) {
	plug_closing(ps->plug, NULL, 0, 0);
	return 0;
    } else {
        assert(ps->frozen != FROZEN && ps->frozen != THAWING);
        if (ps->frozen == FREEZING) {
            /*
             * If we've received data while this socket is supposed to
             * be frozen (because the read winhandl.c started before
             * sk_set_frozen was called has now returned) then buffer
             * the data for when we unfreeze.
             */
            bufchain_add(&ps->inputdata, data, len);
            ps->frozen = FROZEN;

            /*
             * And return a very large backlog, to prevent further
             * data arriving from winhandl until we unfreeze.
             */
            return INT_MAX;
        } else {
            plug_receive(ps->plug, 0, data, len);
	    return 0;
        }
    }
}
Exemplo n.º 2
0
int handle_write(struct handle *h, const void *data, int len)
{
    assert(h->type == HT_OUTPUT);
    assert(h->u.o.outgoingeof == EOF_NO);
    bufchain_add(&h->u.o.queued_data, data, len);
    handle_try_output(&h->u.o);
    return bufchain_size(&h->u.o.queued_data);
}
Exemplo n.º 3
0
int from_backend(void *frontend_handle, int is_stderr,
                 const char *data, int len)
{
    int osize, esize;

    if (is_stderr) {
        bufchain_add(&stderr_data, data, len);
        try_output(1);
    } else {
        bufchain_add(&stdout_data, data, len);
        try_output(0);
    }

    osize = bufchain_size(&stdout_data);
    esize = bufchain_size(&stderr_data);

    return osize + esize;
}
Exemplo n.º 4
0
static int sk_proxy_write(Socket s, const char *data, int len) {
	Proxy_Socket ps = (Proxy_Socket) s;

	if (ps->state != PROXY_STATE_ACTIVE) {
		bufchain_add(&ps->pending_output_data, data, len);
		return bufchain_size(&ps->pending_output_data);
	}
	return sk_write(ps->sub_socket, data, len);
}
Exemplo n.º 5
0
static int sk_localproxy_write (Socket s, const char *data, int len)
{
    Local_Proxy_Socket ps = (Local_Proxy_Socket) s;

    bufchain_add(&ps->pending_output_data, data, len);

    localproxy_try_send(ps);

    return bufchain_size(&ps->pending_output_data);
}
Exemplo n.º 6
0
Arquivo: proxy.c Projeto: Riatre/PuTTY
static int sk_proxy_write (Socket s, const void *data, int len)
{
    ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt);

    if (ps->state != PROXY_STATE_ACTIVE) {
	bufchain_add(&ps->pending_output_data, data, len);
	return bufchain_size(&ps->pending_output_data);
    }
    return sk_write(ps->sub_socket, data, len);
}
Exemplo n.º 7
0
static size_t sk_proxy_write (Socket *s, const void *data, size_t len)
{
    ProxySocket *ps = container_of(s, ProxySocket, sock);

    if (ps->state != PROXY_STATE_ACTIVE) {
	bufchain_add(&ps->pending_output_data, data, len);
	return bufchain_size(&ps->pending_output_data);
    }
    return sk_write(ps->sub_socket, data, len);
}
Exemplo n.º 8
0
Arquivo: uxser.c Projeto: halcy/PuTTY
/*
 * Called to send data down the serial connection.
 */
static int serial_send(void *handle, const char *buf, int len)
{
    Serial serial = (Serial) handle;

    if (serial->fd < 0)
	return 0;

    bufchain_add(&serial->output_data, buf, len);
    serial_try_write(serial);

    return bufchain_size(&serial->output_data);
}
Exemplo n.º 9
0
static int plug_proxy_receive(Plug p, int urgent, byte *data, int len) {
	Proxy_Plug pp = (Proxy_Plug) p;
	Proxy_Socket ps = pp->proxy_socket;

	if (ps->state != PROXY_STATE_ACTIVE) {
		/* we will lose the urgentness of this data, but since most,
		 * if not all, of this data will be consumed by the negotiation
		 * process, hopefully it won't affect the protocol above us
		 */
		bufchain_add(&ps->pending_input_data, data, len);
		ps->receive_urgent = urgent;
		ps->receive_data = data;
		ps->receive_len = len;
		return ps->negotiate(ps, PROXY_CHANGE_RECEIVE);
	}
	return plug_receive(ps->plug, urgent, data, len);
}
Exemplo n.º 10
0
/*
 * Internal wrapper function which must be called for _all_ output
 * to the log file. It takes care of opening the log file if it
 * isn't open, buffering data if it's in the process of being
 * opened asynchronously, etc.
 */
static void logwrite(struct LogContext *ctx, void *data, int len)
{
    /*
     * In state L_CLOSED, we call logfopen, which will set the state
     * to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of
     * those three _after_ processing L_CLOSED.
     */
    if (ctx->state == L_CLOSED)
	logfopen(ctx);

    if (ctx->state == L_OPENING) {
	bufchain_add(&ctx->queue, data, len);
    } else if (ctx->state == L_OPEN) {
	assert(ctx->lgfp);
	fwrite(data, 1, len, ctx->lgfp);
    }				       /* else L_ERROR, so ignore the write */
}
Exemplo n.º 11
0
Arquivo: proxy.c Projeto: Riatre/PuTTY
static void plug_proxy_receive (Plug p, int urgent, char *data, int len)
{
    ProxySocket *ps = FROMFIELD(p, ProxySocket, plugvt);

    if (ps->state != PROXY_STATE_ACTIVE) {
	/* we will lose the urgentness of this data, but since most,
	 * if not all, of this data will be consumed by the negotiation
	 * process, hopefully it won't affect the protocol above us
	 */
	bufchain_add(&ps->pending_input_data, data, len);
	ps->receive_urgent = urgent;
	ps->receive_data = data;
	ps->receive_len = len;
	ps->negotiate(ps, PROXY_CHANGE_RECEIVE);
    } else {
        plug_receive(ps->plug, urgent, data, len);
    }
}
Exemplo n.º 12
0
/*
 * Internal wrapper function which must be called for _all_ output
 * to the log file. It takes care of opening the log file if it
 * isn't open, buffering data if it's in the process of being
 * opened asynchronously, etc.
 */
static void logwrite(struct LogContext *ctx, void *data, int len)
{
    /*
     * In state L_CLOSED, we call logfopen, which will set the state
     * to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of
     * those three _after_ processing L_CLOSED.
     */
#ifdef PERSOPORT
    if( timestamp_newfile ) {
        if (ctx->state == L_OPEN) {
            logfclose(ctx);
        }
        timestamp_newfile = 0 ;
    }
#endif

    if (ctx->state == L_CLOSED)
        logfopen(ctx);

    if (ctx->state == L_OPENING) {
        bufchain_add(&ctx->queue, data, len);
    } else if (ctx->state == L_OPEN) {
        assert(ctx->lgfp);
#ifdef PERSOPORT
        if( !get_param("PUTTY") ) {
            if( timestamp_newline ) {
                log_writetimestamp( ctx ) ;
                timestamp_newline = 0 ;
            }
            char * c = (char*)(data+len-1) ;
            if( c[0]=='\n' ) timestamp_newline = 1 ;
        }
#endif
        if (fwrite(data, 1, len, ctx->lgfp) < (size_t)len) {
            logfclose(ctx);
            ctx->state = L_ERROR;
            /* Log state is L_ERROR so this won't cause a loop */
            logevent(ctx->frontend,
                     "Disabled writing session log due to error while writing");
        }
    }				       /* else L_ERROR, so ignore the write */
}
Exemplo n.º 13
0
/*
 * Internal wrapper function which must be called for _all_ output
 * to the log file. It takes care of opening the log file if it
 * isn't open, buffering data if it's in the process of being
 * opened asynchronously, etc.
 */
static void logwrite(struct LogContext *ctx, void *data, int len)
{
    /*
     * In state L_CLOSED, we call logfopen, which will set the state
     * to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of
     * those three _after_ processing L_CLOSED.
     */
    if (ctx->state == L_CLOSED)
        logfopen(ctx);

    if (ctx->state == L_OPENING) {
        bufchain_add(&ctx->queue, data, len);
    } else if (ctx->state == L_OPEN) {
        assert(ctx->lgfp);
        if (fwrite(data, 1, len, ctx->lgfp) < len) {
            logfclose(ctx);
            ctx->state = L_ERROR;
            /* Log state is L_ERROR so this won't cause a loop */
            logevent(ctx->frontend,
                     "Disabled writing session log due to error while writing");
        }
    }				       /* else L_ERROR, so ignore the write */
}
Exemplo n.º 14
0
Arquivo: main.c Projeto: actility/ong
int main(int argc, char **argv)
{
  int masterr, masterw, slaver, slavew, pid;
  char ptyname[FILENAME_MAX];
  bufchain tochild, tostdout;
  int tochild_active, tostdout_active, fromstdin_active, fromchild_active;
  int exitcode = -1;
  pid_t childpid = -1;

        --argc, ++argv;         /* point at argument after "--" */

  /*
   * Allocate the pipe for transmitting signals back to the
   * top-level select loop.
   */
  if (pipe(signalpipe) < 0) {
    perror("pipe");
    return 1;
  }

  /*
   * Now that pipe exists, we can set up the SIGCHLD handler to
   * write to one end of it. We needn't already know details like
   * which child pid we're waiting for, because we don't need that
   * until we respond to reading the far end of the pipe in the
   * main select loop.
   */
  signal(SIGCHLD, sigchld);

  /*
   * Allocate the pty or pipes.
   */
  masterr = pty_get(ptyname);
  masterw = dup(masterr);
  slaver = open(ptyname, O_RDWR);
  slavew = dup(slaver);
  if (slaver < 0) {
    perror("slave pty: open");
    return 1;
  }

  bufchain_init(&tochild);
  bufchain_init(&tostdout);
  tochild_active = tostdout_active = TRUE;
  fromchild_active = fromstdin_active = TRUE;

  /*
   * Fork and execute the command.
   */
  pid = fork();
  if (pid < 0) {
    perror("fork");
    return 1;
  }

  if (pid == 0) {
    int i;
    /*
     * We are the child.
     */
    close(masterr);
    close(masterw);

    fcntl(slaver, F_SETFD, 0);    /* don't close on exec */
    fcntl(slavew, F_SETFD, 0);    /* don't close on exec */
    close(0);
    dup2(slaver, 0);
    close(1);
    dup2(slavew, 1);
    int fd;
    close(2);
    dup2(slavew, 2);
    setsid();
    setpgid(0, 0);
    tcsetpgrp(0, getpgrp());
    if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
      ioctl(fd, TIOCNOTTY);
      close(fd);
    }
    ioctl(slavew, TIOCSCTTY);
    
    /* Close everything _else_, for tidiness. */
    for (i = 3; i < 1024; i++)
      close(i);
    if (argc > 0) {
      execvp(argv[0], argv);     /* assumes argv has trailing NULL */
    } else {
      execl(getenv("SHELL"), getenv("SHELL"), NULL);
    }
    /*
     * If we're here, exec has gone badly foom.
     */
    perror("exec");
    exit(127);
  }

  /*
   * Now we're the parent. Close the slave fds and start copying
   * stuff back and forth.
   */
  close(slaver);
  close(slavew);
  childpid = pid;

  tcgetattr(0, &oldattrs);
  newattrs = oldattrs;
  newattrs.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR);
  newattrs.c_oflag &= ~(ONLCR | OCRNL);
  newattrs.c_lflag &= ~(ISIG | ICANON | ECHO);
  atexit(attrsonexit);
  tcsetattr(0, TCSADRAIN, &newattrs);
  

  while (1) {
    fd_set rset, wset;
    char buf[65536];
    int maxfd, ret;

    FD_ZERO(&rset);
    FD_ZERO(&wset);
    maxfd = 0;

    FD_SET(signalpipe[0], &rset);
    maxfd = max(signalpipe[0]+1, maxfd);

    if (tochild_active && bufchain_size(&tochild)) {
      FD_SET(masterw, &wset);
      maxfd = max(masterw+1, maxfd);
    }
    if (tostdout_active && bufchain_size(&tostdout)) {
      FD_SET(1, &wset);
      maxfd = max(1+1, maxfd);
    }
    if (fromstdin_active && bufchain_size(&tochild) < LOCALBUF_LIMIT) {
      FD_SET(0, &rset);
      maxfd = max(0+1, maxfd);
    }
    if (fromchild_active && bufchain_size(&tostdout) < LOCALBUF_LIMIT) {
      FD_SET(masterr, &rset);
      maxfd = max(masterr+1, maxfd);
    }

    do {
      ret = select(maxfd, &rset, &wset, NULL, NULL);
    } while (ret < 0 && (errno == EINTR || errno == EAGAIN));

    if (ret < 0) {
      perror("select");
      return 1;
    }

    if (FD_ISSET(masterr, &rset)) {

      if (FD_ISSET(masterr, &rset)) {
        ret = read(masterr, buf, sizeof(buf));
        if (ret <= 0) {
          /*
           * EIO from a pty master just means end of
           * file, annoyingly. Why can't it report
           * ordinary EOF?
           */
          if (errno == EIO)
            ret = 0;
          if (ret < 0) {
            perror("child process: read");
          }
          close(masterr);
          fromchild_active = FALSE;
          ret = 0;
        }
      } else
        ret = 0;

      if (ret) {
        bufchain_add(&tostdout, buf, ret);
      }
    }
    if (FD_ISSET(0, &rset)) {

      if (FD_ISSET(0, &rset)) {
        ret = read(0, buf, sizeof(buf));
        if (ret <= 0) {
          if (ret < 0) {
            perror("stdin: read");
          }
          close(0);
          fromstdin_active = FALSE;
          ret = 0;
        }
      } else
        ret = 0;

      if (ret) {
        bufchain_add(&tochild, buf, ret);
      }
    }
    if (FD_ISSET(1, &wset)) {
      void *data;
      int len, ret;
      bufchain_prefix(&tostdout, &data, &len);
      if ((ret = write(1, data, len)) < 0) {
        perror("stdout: write");
        close(1);
        close(masterr);
        tostdout_active = fromchild_active = FALSE;
      } else
        bufchain_consume(&tostdout, ret);
    }
    if (FD_ISSET(masterw, &wset)) {
      void *data;
      int len;
      bufchain_prefix(&tochild, &data, &len);
      if ((ret = write(masterw, data, len)) < 0) {
        perror("child process: write");
        close(0);
        close(masterw);
        tochild_active = fromstdin_active = FALSE;
      } else
        bufchain_consume(&tochild, ret);
    }
    if (FD_ISSET(signalpipe[0], &rset)) {
      ret = read(signalpipe[0], buf, 1);
      if (ret == 1 && buf[0] == 'C') {
        int pid, code;
        pid = wait(&code);     /* reap the exit code */
        if (pid == childpid)
          exitcode = code;
      }
    }

    /*
     * If there can be no further data from a direction (the
     * input fd has been closed and the buffered data is used
     * up) but its output fd is still open, close it.
     */
    if (!fromstdin_active && !bufchain_size(&tochild) && tochild_active) {
      tochild_active = FALSE;
      close(masterw);
    }
    if (!fromchild_active && !bufchain_size(&tostdout) && tostdout_active){
      tostdout_active = FALSE;
      close(1);
    }

    /*
     * Termination condition with pipes is that there's still
     * data flowing in at least one direction.
     * 
     * Termination condition for a pty-based run is that the
     * child process hasn't yet terminated and/or there is
     * still buffered data to send.
     */
    if (exitcode < 0)
      /* process is still active */;
    else if (tochild_active && bufchain_size(&tochild))
      /* data still to be sent to child's children */;
    else if (tostdout_active && bufchain_size(&tostdout))
      /* data still to be sent to stdout */;
    else
      break;           /* terminate */
  }

  close(masterw);
  close(masterr);

  if (exitcode < 0) {
    int pid, code;
    pid = wait(&code);
    exitcode = code;
  }

  return (WIFEXITED(exitcode) ? WEXITSTATUS(exitcode) :
      128 | WTERMSIG(exitcode));
}