docs: function Terminal(file, args, opt) {
    if (!(this instanceof Terminal)) {
      return new Terminal(file, args, opt);
    }
  
    var self = this
      , env
      , cwd
      , name
      , cols
      , rows
      , uid
      , gid
      , term;
  
    // backward compatibility
    if (typeof args === 'string') {
      opt = {
        name: arguments[1],
        cols: arguments[2],
        rows: arguments[3],
        cwd: process.env.HOME
      };
      args = [];
    }
  
    // for 'close'
    this._internalee = new EventEmitter;
  
    // arguments
    args = args || [];
    file = file || 'sh';
    opt = opt || {};
  
    cols = opt.cols || 80;
    rows = opt.rows || 24;
  
    uid = opt.uid != null ? opt.uid : -1;
    gid = opt.gid != null ? opt.gid : -1;
  
    opt.env = opt.env || process.env;
    env = extend({}, opt.env);
  
    if (opt.env === process.env) {
      // Make sure we didn't start our
      // server from inside tmux.
      delete env.TMUX;
      delete env.TMUX_PANE;
  
      // Make sure we didn't start
      // our server from inside screen.
      // http://web.mit.edu/gnu/doc/html/screen_20.html
      delete env.STY;
      delete env.WINDOW;
  
      // Delete some variables that
      // might confuse our terminal.
      delete env.WINDOWID;
      delete env.TERMCAP;
      delete env.COLUMNS;
      delete env.LINES;
    }
  
    // Could set some basic env vars
    // here, if they do not exist:
    // USER, SHELL, HOME, LOGNAME, WINDOWID
  
    cwd = opt.cwd || process.cwd();
    name = opt.name || env.TERM || 'xterm';
    env.TERM = name;
    // XXX Shouldn't be necessary:
    // env.LINES = rows + '';
    // env.COLUMNS = cols + '';
  
    env = environ(env);
  
    function onexit(code, signal) {
      // XXX Sometimes a data event is emitted
      // after exit. Wait til socket is destroyed.
      if (!self._emittedClose) {
        if (self._boundClose) return;
        self._boundClose = true;
        self.once('close', function() {
          self.emit('exit', code, signal);
        });
        return;
      }
      self.emit('exit', code, signal);
    }
  
    // fork
    term = pty.fork(file, args, env, cwd, cols, rows, uid, gid, onexit);
  
    this.socket = TTYStream(term.fd);
    this.socket.setEncoding('utf8');
  
    if (opt.resume !== false) {
      this.socket.resume();
    }
  
    // setup
    this.socket.on('error', function(err) {
      // NOTE: fs.ReadStream gets EAGAIN twice at first:
      if (err.code) {
        if (~err.code.indexOf('EAGAIN')) return;
      }
  
      // close
      self._close();
      // EIO on exit from fs.ReadStream:
      if (!self._emittedClose) {
        self._emittedClose = true;
        Terminal.total--;
        self.emit('close');
      }
  
      // EIO, happens when someone closes our child
      // process: the only process in the terminal.
      // node < 0.6.14: errno 5
      // node >= 0.6.14: read EIO
      if (err.code) {
        if (~err.code.indexOf('errno 5')
            || ~err.code.indexOf('EIO')) return;
      }
  
      // throw anything else
      if (self.listeners('error').length < 2) {
        throw err;
      }
    });
  
    this.pid = term.pid;
    this.fd = term.fd;
    this.pty = term.pty;
  
    this.file = file;
    this.name = name;
    this.cols = cols;
    this.rows = rows;
  
    this.readable = true;
    this.writable = true;
  
    Terminal.total++;
  
    this.socket.on('close', function() {
      if (self._emittedClose) return;
      self._emittedClose = true;
      Terminal.total--;
      self._close();
      self.emit('close');
    });
  
    env = null;
  }