Skip to content

Instantly share code, notes, and snippets.

@chjj
Created February 13, 2012 10:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chjj/1815766 to your computer and use it in GitHub Desktop.
Save chjj/1815766 to your computer and use it in GitHub Desktop.
terminal #2:
open("/dev/pts/8", O_RDWR|O_NOCTTY) = 8
ioctl(8, TIOCSWINSZ, {ws_row=30, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb735f738) = 851
close(8) = 0
rt_sigprocmask(SIG_SETMASK, ~[RTMIN RT_1], [], 8) = 0
mmap2(NULL, 266240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xb6a3a000
mprotect(0xb6a3a000, 4096, PROT_NONE) = 0
clone(child_stack=0xb6a7a484, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb6a7abd8, {entry_number:6, base_addr:0xb6a7ab70, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb6a7abd8) = 852
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
write(1, "Starting terminal #2.\n", 22Starting terminal #2.
) = 22
clock_gettime(CLOCK_MONOTONIC, {629544, 678920107}) = 0
epoll_wait(3, {{EPOLLIN, {u32=4, u64=4294967300}}}, 64, 43) = 1
clock_gettime(CLOCK_MONOTONIC, {629544, 680548872}) = 0
read(4, "\1\0\0\0\0\0\0\0", 8) = 8
write(4, "\1\0\0\0\0\0\0\0", 8) = 8
futex(0x919370c, FUTEX_WAKE_PRIVATE, 1) = 1
gettimeofday({1329115610, 235327}, NULL) = 0
gettimeofday({1329115610, 235529}, NULL) = 0
write(1, "#2: data event\n", 15#2: data event
) = 15
futex(0x863c504, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x863c500, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x863c4d4, FUTEX_WAKE_PRIVATE, 1) = 1
clock_gettime(CLOCK_MONOTONIC, {629544, 681224568}) = 0
epoll_wait(3, {{EPOLLIN, {u32=4, u64=4294967300}}}, 64, 41) = 1
clock_gettime(CLOCK_MONOTONIC, {629544, 681322885}) = 0
read(4, "\1\0\0\0\0\0\0\0", 8) = 8
clock_gettime(CLOCK_MONOTONIC, {629544, 681419884}) = 0
epoll_wait(3, {{EPOLLIN, {u32=4, u64=4294967300}}}, 64, 40) = 1
clock_gettime(CLOCK_MONOTONIC, {629544, 681592942}) = 0
read(4, "\1\0\0\0\0\0\0\0", 8) = 8
write(4, "\1\0\0\0\0\0\0\0", 8) = 8
futex(0x919370c, FUTEX_WAKE_PRIVATE, 1) = 1
write(1, "#2: data event\n", 15#2: data event
) = 15
futex(0x863c504, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x863c500, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x863c4d4, FUTEX_WAKE_PRIVATE, 1) = 1
clock_gettime(CLOCK_MONOTONIC, {629544, 682014846}) = 0
epoll_wait(3, {{EPOLLIN, {u32=4, u64=4294967300}}}, 64, 40) = 1
clock_gettime(CLOCK_MONOTONIC, {629544, 682110911}) = 0
read(4, "\1\0\0\0\0\0\0\0", 8) = 8
clock_gettime(CLOCK_MONOTONIC, {629544, 682206471}) = 0
epoll_wait(3, {{EPOLLIN, {u32=4, u64=4294967300}}}, 64, 40) = 1
clock_gettime(CLOCK_MONOTONIC, {629544, 682315014}) = 0
read(4, "\1\0\0\0\0\0\0\0", 8) = 8
write(4, "\1\0\0\0\0\0\0\0", 8) = 8
write(1, "#2: data event\n", 15#2: data event
) = 15
brk(0x9275000) = 0x9275000
futex(0x863c504, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x863c500, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x863c4d4, FUTEX_WAKE_PRIVATE, 1) = 1
clock_gettime(CLOCK_MONOTONIC, {629544, 682733958}) = 0
epoll_wait(3, {{EPOLLIN, {u32=4, u64=4294967300}}}, 64, 39) = 1
clock_gettime(CLOCK_MONOTONIC, {629544, 682820776}) = 0
read(4, "\1\0\0\0\0\0\0\0", 8) = 8
clock_gettime(CLOCK_MONOTONIC, {629544, 682916954}) = 0
epoll_wait(3, {}, 64, 39) = 0
clock_gettime(CLOCK_MONOTONIC, {629544, 722121045}) = 0
clock_gettime(CLOCK_MONOTONIC, {629544, 722205113}) = 0
epoll_wait(3, {}, 64, 4949) = 0
clock_gettime(CLOCK_MONOTONIC, {629549, 672199043}) = 0
gettimeofday({1329115615, 226894}, NULL) = 0
futex(0x919370c, FUTEX_WAKE_PRIVATE, 1) = 1
gettimeofday({1329115615, 227122}, NULL) = 0
gettimeofday({1329115615, 227639}, NULL) = 0
terminal #4:
open("/dev/pts/10", O_RDWR|O_NOCTTY) = 10
ioctl(10, TIOCSWINSZ, {ws_row=30, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb735f738) = 878
close(10) = 0
futex(0x919370c, FUTEX_WAKE_PRIVATE, 1) = 1
write(1, "Starting terminal #4.\n", 22Starting terminal #4.
) = 22
clock_gettime(CLOCK_MONOTONIC, {629554, 678039849}) = 0
epoll_wait(3, {}, 64, 44) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 722253632}) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 722345420}) = 0
epoll_wait(3, {}, 64, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 722465379}) = 0
mmap2(0x4a000000, 524288, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x4a000000
clock_gettime(CLOCK_MONOTONIC, {629554, 722612532}) = 0
epoll_wait(3, {}, 64, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 722700383}) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 722746451}) = 0
epoll_wait(3, {}, 64, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 722833512}) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 722879224}) = 0
epoll_wait(3, {}, 64, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 722964281}) = 0
mmap2(0x4a000000, 524288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4a000000
mmap2(0x5575c000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x5575c000
mmap2(0x53cbb000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x53cbb000
mmap2(0x30c41000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x30c41000
mmap2(0x2ae19000, 36864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ae19000
mmap2(0x2af01000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2af01000
mmap2(0x2ffec000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ffec000
gettimeofday({1329115620, 278506}, NULL) = 0
gettimeofday({1329115620, 278600}, NULL) = 0
mmap2(0x4a800000, 524288, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x4a800000
clock_gettime(CLOCK_MONOTONIC, {629554, 724141537}) = 0
epoll_wait(3, {}, 64, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 724230703}) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 724277715}) = 0
epoll_wait(3, {}, 64, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 724364779}) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 724410705}) = 0
epoll_wait(3, {}, 64, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 724508726}) = 0
mmap2(0x4a800000, 524288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4a800000
gettimeofday({1329115620, 279316}, NULL) = 0
gettimeofday({1329115620, 281210}, NULL) = 0
gettimeofday({1329115620, 281292}, NULL) = 0
gettimeofday({1329115620, 281526}, NULL) = 0
mmap2(0x4a080000, 524288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4a080000
mmap2(0x4a880000, 524288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4a880000
mmap2(0x2ec2e000, 28672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ec2e000
gettimeofday({1329115620, 281847}, NULL) = 0
gettimeofday({1329115620, 281918}, NULL) = 0
gettimeofday({1329115620, 281999}, NULL) = 0
gettimeofday({1329115620, 282047}, NULL) = 0
mmap2(0x4a880000, 524288, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x4a880000
mmap2(0x4a080000, 524288, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x4a080000
mmap2(0x4a000000, 524288, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x4a000000
clock_gettime(CLOCK_MONOTONIC, {629554, 727654122}) = 0
epoll_wait(3, {}, 64, 0) = 0
clock_gettime(CLOCK_MONOTONIC, {629554, 727744003}) = 0
mmap2(0x4a000000, 524288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x4a000000
gettimeofday({1329115620, 282636}, NULL) = 0
gettimeofday({1329115620, 284321}, NULL) = 0
gettimeofday({1329115620, 284395}, NULL) = 0
gettimeofday({1329115620, 288568}, NULL) = 0
gettimeofday({1329115620, 288627}, NULL) = 0
gettimeofday({1329115620, 288673}, NULL) = 0
mmap2(0x4a800000, 524288, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x4a800000
clock_gettime(CLOCK_MONOTONIC, {629554, 734181795}) = 0
epoll_wait(3,
// A synchronous read stream
// Copyright Joyent, Inc. and other Node contributors.
var fs = require('fs');
var util = require('util');
var Stream = require('stream').Stream;
var fs_ = exports;
var kMinPoolSpace = 128;
var kPoolSize = 40 * 1024;
var pool;
function allocNewPool() {
pool = new Buffer(kPoolSize);
pool.used = 0;
}
fs_.createReadStream = function(path, options) {
return new ReadStream(path, options);
};
var ReadStream = fs_.ReadStream = function(path, options) {
if (!(this instanceof ReadStream)) return new ReadStream(path, options);
Stream.call(this);
var self = this;
this.path = path;
this.fd = null;
this.readable = true;
this.paused = false;
this.flags = 'r';
this.mode = 438; /*=0666*/
this.bufferSize = 64 * 1024;
options = options || {};
// Mixin options into this
var keys = Object.keys(options);
for (var index = 0, length = keys.length; index < length; index++) {
var key = keys[index];
this[key] = options[key];
}
if (this.encoding) this.setEncoding(this.encoding);
if (this.start !== undefined) {
if (this.end === undefined) {
this.end = Infinity;
}
if (this.start > this.end) {
throw new Error('start must be <= end');
}
this.pos = this.start;
}
if (this.fd !== null) {
return;
}
fs.open(this.path, this.flags, this.mode, function(err, fd) {
if (err) {
self.emit('error', err);
self.readable = false;
return;
}
self.fd = fd;
self.emit('open', fd);
self._read();
});
};
util.inherits(ReadStream, Stream);
fs_.FileReadStream = fs_.ReadStream; // support the legacy name
ReadStream.prototype.setEncoding = function(encoding) {
var StringDecoder = require('string_decoder').StringDecoder; // lazy load
this._decoder = new StringDecoder(encoding);
};
ReadStream.prototype._read = function() {
var self = this;
if (!this.readable || this.paused || this.reading) return;
this.reading = true;
if (!pool || pool.length - pool.used < kMinPoolSpace) {
// discard the old pool. Can't add to the free list because
// users might have refernces to slices on it.
pool = null;
allocNewPool();
}
// Grab another reference to the pool in the case that while we're in the
// thread pool another read() finishes up the pool, and allocates a new
// one.
var thisPool = pool;
var toRead = Math.min(pool.length - pool.used, ~~this.bufferSize);
var start = pool.used;
if (this.pos !== undefined) {
toRead = Math.min(this.end - this.pos + 1, toRead);
}
var err, bytesRead;
try {
bytesRead = fs.readSync(this.fd, pool, pool.used, toRead, this.pos);
} catch(e) {
err = e;
}
setTimeout(function() {
self.reading = false;
if (err) {
self.emit('error', err);
self.readable = false;
return;
}
if (bytesRead === 0) {
self.emit('end');
self.destroy();
return;
}
var b = thisPool.slice(start, start + bytesRead);
// Possible optimizition here?
// Reclaim some bytes if bytesRead < toRead?
// Would need to ensure that pool === thisPool.
// do not emit events if the stream is paused
if (self.paused) {
self.buffer = b;
return;
}
// do not emit events anymore after we declared the stream unreadable
if (!self.readable) return;
self._emitData(b);
self._read();
}, 100);
if (this.pos !== undefined) {
this.pos += toRead;
}
pool.used += toRead;
};
ReadStream.prototype._emitData = function(d) {
if (this._decoder) {
var string = this._decoder.write(d);
if (string.length) this.emit('data', string);
} else {
this.emit('data', d);
}
};
ReadStream.prototype.destroy = function(cb) {
var self = this;
this.readable = false;
function close() {
fs.close(self.fd, function(err) {
if (err) {
if (cb) cb(err);
self.emit('error', err);
return;
}
if (cb) cb(null);
self.emit('close');
});
}
if (this.fd) {
close();
} else {
this.addListener('open', close);
}
};
ReadStream.prototype.pause = function() {
this.paused = true;
};
ReadStream.prototype.resume = function() {
this.paused = false;
if (this.buffer) {
this._emitData(this.buffer);
this.buffer = null;
}
// hasn't opened yet.
if (null == this.fd) return;
this._read();
};
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
#!/bin/sh
cat hello
while [ true ]; do
sleep 2s
done
/**
* Modules
*/
var fs = require('fs');
var pty = require('./build/Release/pty.node');
// for our sync read stream:
var fs_ = require('./fs');
/**
* Terminal
*/
var Terminal = function(process, name, cols, rows) {
process = process || 'sh';
name = name || 'vt100';
cols = cols || 80;
rows = rows || 30;
var term = pty.fork(process, name, cols, rows);
this.input = fs.createWriteStream(null, { fd: term.fd });
// use our sync read stream, which doesnt go through libeio, for #5
this.output = (i === 6 ? fs_ : fs).createReadStream(null, { fd: term.fd });
this.output.setEncoding('utf8');
this.output._read();
this.pid = term.pid;
this.fd = term.fd;
this.cols = cols;
this.rows = rows;
};
/**
* Test
*/
var i = 0;
var terms = [];
console.log('Starting a terminal every 5 seconds and announcing data events...');
var startTerminal = function() {
var t = i++;
var term = new Terminal(__dirname + '/hello.sh');
console.log('Starting terminal #%d.', t);
term.output.on('data', function(data) {
console.log('#%d: data event', t);
});
terms.push(term);
};
setInterval(function() {
if (i === 5) {
console.log('If you notice, there are no data events from #4.');
console.log('readstream.reading === %s', terms[4].output.reading);
console.log(''
+ 'Let\'s try using a sync read stream, '
+ 'which doesn\'t go through libeio, for #5...');
console.log('');
}
startTerminal();
}, 5000);
/**
* pty.cc
* This file is responsible for starting processes
* with pseudo-terminal file descriptors.
*
* man tty_ioctl
* man tcsetattr
* man forkpty
*/
#include <v8.h>
#include <node.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
/* forkpty */
/* http://www.gnu.org/software/gnulib/manual/html_node/forkpty.html */
#if defined(__GLIBC__) || defined(__CYGWIN__)
#include <pty.h>
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <util.h>
#elif defined(__FreeBSD__)
#include <libutil.h>
#else
#include <pty.h>
#endif
#include <utmp.h> /* login_tty */
#include <termios.h> /* tcgetattr, tty_ioctl */
using namespace std;
using namespace node;
using namespace v8;
static Handle<Value> ForkPty(const Arguments&);
static Handle<Value> ResizePty(const Arguments&);
extern "C" void init(Handle<Object>);
static Handle<Value> ForkPty(const Arguments& args) {
HandleScope scope;
char *argv[] = { "sh", NULL };
if (args.Length() > 0) {
if (!args[0]->IsString()) {
return ThrowException(Exception::Error(
String::New("First argument must be a string.")));
}
String::Utf8Value file(args[0]->ToString());
argv[0] = strdup(*file);
}
struct winsize winp = {};
winp.ws_col = 80;
winp.ws_row = 30;
if (args.Length() == 4) {
if (args[2]->IsNumber() && args[3]->IsNumber()) {
Local<Integer> cols = args[2]->ToInteger();
Local<Integer> rows = args[3]->ToInteger();
winp.ws_col = cols->Value();
winp.ws_row = rows->Value();
} else {
return ThrowException(Exception::Error(
String::New("cols and rows need to be numbers.")));
}
}
int master;
pid_t pid = forkpty(&master, NULL, NULL, &winp);
if (pid == -1) {
return ThrowException(Exception::Error(
String::New("forkpty failed.")));
}
if (pid == 0) {
if (args.Length() > 1 && args[1]->IsString()) {
String::Utf8Value term(args[1]->ToString());
setenv("TERM", strdup(*term), 1);
} else {
setenv("TERM", "vt100", 1);
}
chdir(getenv("HOME"));
execvp(argv[0], argv);
perror("execvp failed");
_exit(1);
}
Local<Object> obj = Object::New();
obj->Set(String::New("fd"), Number::New(master));
obj->Set(String::New("pid"), Number::New(pid));
return scope.Close(obj);
}
/**
* Expose Resize Functionality
*/
static Handle<Value> ResizePty(const Arguments& args) {
HandleScope scope;
if (args.Length() > 0 && !args[0]->IsNumber()) {
return ThrowException(Exception::Error(
String::New("First argument must be a number.")));
}
struct winsize winp = {};
winp.ws_col = 80;
winp.ws_row = 30;
int fd = args[0]->ToInteger()->Value();
if (args.Length() == 3) {
if (args[1]->IsNumber() && args[2]->IsNumber()) {
Local<Integer> cols = args[1]->ToInteger();
Local<Integer> rows = args[2]->ToInteger();
winp.ws_col = cols->Value();
winp.ws_row = rows->Value();
} else {
return ThrowException(Exception::Error(
String::New("cols and rows need to be numbers.")));
}
}
if (ioctl(fd, TIOCSWINSZ, &winp) == -1) {
return ThrowException(Exception::Error(
String::New("ioctl failed.")));
}
return Undefined();
}
extern "C" void init(Handle<Object> target) {
HandleScope scope;
NODE_SET_METHOD(target, "fork", ForkPty);
NODE_SET_METHOD(target, "resize", ResizePty);
}
srcdir = "."
blddir = "build"
VERSION = "0.0.1"
def set_options(opt):
opt.tool_options("compiler_cxx")
def configure(conf):
conf.check_tool("compiler_cxx")
conf.check_tool("node_addon")
def build(bld):
obj = bld.new_task_gen("cxx", "shlib", "node_addon")
obj.cxxflags = ["-Wall"]
obj.linkflags = ["-lutil"]
obj.target = "pty"
obj.source = "pty.cc"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment