From e4d021a2232a7df472715e16e81d758131033774 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Wed, 15 Oct 2014 14:19:59 -0700 Subject: [PATCH] node: implement `DEBUG_FD` env variable support Closes #146. --- node.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/node.js b/node.js index db86f647..5dc999fe 100644 --- a/node.js +++ b/node.js @@ -25,6 +25,18 @@ exports.useColors = useColors; exports.colors = [6, 2, 3, 4, 5, 1]; +/** + * The file descriptor to write the `debug()` calls to. + * Set the `DEBUG_FD` env variable to override with another value. i.e.: + * + * $ DEBUG_FD=3 node script.js 3>debug.log + */ + +var fd = parseInt(process.env.DEBUG_FD, 10) || 2; +var stream = 1 === fd ? process.stdout : + 2 === fd ? process.stderr : + createWritableStdioStream(fd); + /** * Is stdout a TTY? Colored output is enabled when `true`. */ @@ -32,7 +44,7 @@ exports.colors = [6, 2, 3, 4, 5, 1]; function useColors() { var debugColors = (process.env.DEBUG_COLORS || '').trim().toLowerCase(); if (0 === debugColors.length) { - return tty.isatty(1); + return tty.isatty(fd); } else { return '0' !== debugColors && 'no' !== debugColors @@ -91,7 +103,7 @@ function formatArgs() { */ function log() { - return console.error.apply(console, arguments); + return stream.write(util.format.apply(this, arguments) + '\n'); } /** @@ -122,6 +134,74 @@ function load() { return process.env.DEBUG; } +/** + * Copied from `node/src/node.js`. + * + * XXX: It's lame that node doesn't expose this API out-of-the-box. It also + * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. + */ + +function createWritableStdioStream (fd) { + var stream; + var tty_wrap = process.binding('tty_wrap'); + + // Note stream._type is used for test-module-load-list.js + + switch (tty_wrap.guessHandleType(fd)) { + case 'TTY': + stream = new tty.WriteStream(fd); + stream._type = 'tty'; + + // Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + case 'FILE': + var fs = require('fs'); + stream = new fs.SyncWriteStream(fd, { autoClose: false }); + stream._type = 'fs'; + break; + + case 'PIPE': + case 'TCP': + var net = require('net'); + stream = new net.Socket({ + fd: fd, + readable: false, + writable: true + }); + + // FIXME Should probably have an option in net.Socket to create a + // stream from an existing fd which is writable only. But for now + // we'll just add this hack and set the `readable` member to false. + // Test: ./node test/fixtures/echo.js < /etc/passwd + stream.readable = false; + stream.read = null; + stream._type = 'pipe'; + + // FIXME Hack to have stream not keep the event loop alive. + // See https://github.com/joyent/node/issues/1726 + if (stream._handle && stream._handle.unref) { + stream._handle.unref(); + } + break; + + default: + // Probably an error on in uv_guess_handle() + throw new Error('Implement me. Unknown stream file type!'); + } + + // For supporting legacy API we put the FD here. + stream.fd = fd; + + stream._isStdio = true; + + return stream; +} + /** * Enable namespaces listed in `process.env.DEBUG` initially. */