initial commit
This commit is contained in:
commit
55ebab1701
8 changed files with 66230 additions and 0 deletions
25
README.md
Normal file
25
README.md
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
`script` and `scriptreplay` are part of the `bsdutils` package in Debian and
|
||||||
|
Ubuntu, `util-linux-ng` in Fedora and `util-linux` in SUSE. They allow to
|
||||||
|
capture a terminal or script output and replay it, respectively.
|
||||||
|
|
||||||
|
This page uses the vt100 emulator by Frank Bi and adds code of my own to read
|
||||||
|
typescript and timing files to make it possible to replay captured scripts a
|
||||||
|
web browser.
|
||||||
|
|
||||||
|
By adding an upload facility to this it would be possible to have a youtube or
|
||||||
|
pastebin for terminal sessions. Due to laziness this remains a proof of concept
|
||||||
|
for now though.
|
||||||
|
|
||||||
|
- This javascript terminal window is 80x24 characters, so it might be
|
||||||
|
best to adjust your terminal window to that size as well using the
|
||||||
|
following to check:
|
||||||
|
$ watch "tput cols; tput lines"
|
||||||
|
- Start recording:
|
||||||
|
$ SHELL=/bin/sh TERM=vt100 script -t typescript 2> timingfile
|
||||||
|
- Do your stuff and when done exit script with `exit`, `logout` or
|
||||||
|
ctrl-d.
|
||||||
|
- To test how your recorded session looks like, use:
|
||||||
|
$ scriptreplay timingfile typescript
|
||||||
|
- Enter `timingfile` and `typescript` into form above and hit the play
|
||||||
|
button.
|
||||||
|
|
649
VT100.js
Normal file
649
VT100.js
Normal file
|
@ -0,0 +1,649 @@
|
||||||
|
// VT100.js -- a text terminal emulator in JavaScript with a ncurses-like
|
||||||
|
// interface and a POSIX-like interface. (The POSIX-like calls are
|
||||||
|
// implemented on top of the ncurses-like calls, not the other way round.)
|
||||||
|
//
|
||||||
|
// Released under the GNU LGPL v2.1, by Frank Bi <bi@zompower.tk>
|
||||||
|
//
|
||||||
|
// 2007-08-12 - refresh():
|
||||||
|
// - factor out colour code to html_colours_()
|
||||||
|
// - fix handling of A_REVERSE | A_DIM
|
||||||
|
// - simplify initial <br> output code
|
||||||
|
// - fix underlining colour
|
||||||
|
// - fix attron() not to turn off attributes
|
||||||
|
// - decouple A_STANDOUT and A_BOLD
|
||||||
|
// 2007-08-11 - getch() now calls refresh()
|
||||||
|
// 2007-08-06 - Safari compat fix -- turn '\r' into '\n' for onkeypress
|
||||||
|
// 2007-08-05 - Opera compat fixes for onkeypress
|
||||||
|
// 2007-07-30 - IE compat fixes:
|
||||||
|
// - change key handling code
|
||||||
|
// - add <br>...<br> so that 1st and last lines align
|
||||||
|
// 2007-07-28 - change wrapping behaviour -- writing at the right edge no
|
||||||
|
// longer causes the cursor to immediately wrap around
|
||||||
|
// - add <b>...</b> to output to make A_STANDOUT stand out more
|
||||||
|
// - add handling of backspace, tab, return keys
|
||||||
|
// - fix doc. of VT100() constructor
|
||||||
|
// - change from GPL to LGPL
|
||||||
|
// 2007-07-09 - initial release
|
||||||
|
//
|
||||||
|
// class VT100
|
||||||
|
// A_NORMAL, A_UNDERLINE, A_REVERSE, A_BLINK, A_DIM, A_BOLD, A_STANDOUT
|
||||||
|
// =class constants=
|
||||||
|
// Attribute constants.
|
||||||
|
// VT100(wd, ht, scr_id) =constructor=
|
||||||
|
// Creates a virtual terminal with width `wd', and
|
||||||
|
// height `ht'. The terminal will be displayed between
|
||||||
|
// <pre>...</pre> tags which have element ID `scr_id'.
|
||||||
|
// addch(ch [, attr])
|
||||||
|
// Writes out the character `ch'. If `attr' is given,
|
||||||
|
// it specifies the attributes for the character,
|
||||||
|
// otherwise the current attributes are used.
|
||||||
|
// addstr(stuff) Writes out the string `stuff' using the current
|
||||||
|
// attributes.
|
||||||
|
// attroff(a) Turns off any current attributes given in `a'.
|
||||||
|
// attron(a) Turns on any attributes given in `a'.
|
||||||
|
// attrset(a) Sets the current attributes to `a'.
|
||||||
|
// bkgdset(a) Sets the background attributes to `a'.
|
||||||
|
// clear() Clears the terminal using the background attributes,
|
||||||
|
// and homes the cursor.
|
||||||
|
// clrtobol() Clears the portion of the terminal from the cursor
|
||||||
|
// to the bottom.
|
||||||
|
// clrtoeol() Clears the portion of the current line after the
|
||||||
|
// cursor.
|
||||||
|
// COLOR_PAIR(pn) Converts a colour pair number `pn' into an
|
||||||
|
// attribute.
|
||||||
|
// curs_set(vis [, grab])
|
||||||
|
// If `vis' is 0, makes the cursor invisible; otherwise
|
||||||
|
// make it visible. If `grab' is given and true, starts
|
||||||
|
// capturing keyboard events (for `getch()'); if given
|
||||||
|
// and false, stops capturing events.
|
||||||
|
// echo() Causes key strokes to be automatically echoed on the
|
||||||
|
// terminal.
|
||||||
|
// erase() Same as `clear()'.
|
||||||
|
// getch(isr) Arranges to call `isr' when a key stroke is
|
||||||
|
// received. The received character and the terminal
|
||||||
|
// object are passed as arguments to `isr'.
|
||||||
|
// getmaxyx() Returns an associative array with the maximum row
|
||||||
|
// (`y') and column (`x') numbers for the terminal.
|
||||||
|
// getyx() Returns an associative array with the current row
|
||||||
|
// (`y') and column (`x') of the cursor.
|
||||||
|
// move(r, c) Moves the cursor to row `r', column `c'.
|
||||||
|
// noecho() Stops automatically echoing key strokes.
|
||||||
|
// pair_content(pn)
|
||||||
|
// Returns an associative array with the foreground
|
||||||
|
// (`f') and background (`b') colour numbers for the
|
||||||
|
// colour pair `pn'.
|
||||||
|
// PAIR_NUMBER(a) Returns the colour pair number in the attributes
|
||||||
|
// `a'.
|
||||||
|
// refresh() Updates the display.
|
||||||
|
// scroll() Scrolls the terminal up one line.
|
||||||
|
// standend() Same as `attrset(VT100.A_NORMAL)'.
|
||||||
|
// standout() Same as `attron(VT100.A_STANDOUT)'.
|
||||||
|
// write(stuff) Writes `stuff' to the terminal and immediately
|
||||||
|
// updates the display; (some) escape sequences are
|
||||||
|
// interpreted and acted on.
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
function VT100(wd, ht, scr_id)
|
||||||
|
{
|
||||||
|
var r;
|
||||||
|
var c;
|
||||||
|
var scr = document.getElementById(scr_id);
|
||||||
|
this.wd_ = wd;
|
||||||
|
this.ht_ = ht;
|
||||||
|
this.c_attr_ = this.bkgd_ = this.COLOR_PAIR(0) | VT100.A_NORMAL;
|
||||||
|
this.color_pair_ = new Array(VT100.COLOR_PAIRS);
|
||||||
|
this.color_pair_[0] = { f: VT100.COLOR_WHITE, b: VT100.COLOR_BLACK };
|
||||||
|
this.text_ = new Array(ht);
|
||||||
|
this.attr_ = new Array(ht);
|
||||||
|
for (r = 0; r < ht; ++r) {
|
||||||
|
this.text_[r] = new Array(wd);
|
||||||
|
this.attr_[r] = new Array(wd);
|
||||||
|
}
|
||||||
|
this.scr_ = scr;
|
||||||
|
this.cursor_vis_ = true;
|
||||||
|
this.grab_events_ = false;
|
||||||
|
this.getch_isr_ = undefined;
|
||||||
|
this.key_buf_ = [];
|
||||||
|
this.echo_ = true;
|
||||||
|
this.esc_state_ = 0;
|
||||||
|
this.clear();
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// public constants -- colours and colour pairs
|
||||||
|
VT100.COLOR_BLACK = 0;
|
||||||
|
VT100.COLOR_BLUE = 1;
|
||||||
|
VT100.COLOR_GREEN = 2;
|
||||||
|
VT100.COLOR_CYAN = 3;
|
||||||
|
VT100.COLOR_RED = 4;
|
||||||
|
VT100.COLOR_MAGENTA = 5;
|
||||||
|
VT100.COLOR_YELLOW = 6;
|
||||||
|
VT100.COLOR_WHITE = 7;
|
||||||
|
VT100.COLOR_PAIRS = 256;
|
||||||
|
VT100.COLORS = 8;
|
||||||
|
// public constants -- attributes
|
||||||
|
VT100.A_NORMAL = 0;
|
||||||
|
VT100.A_UNDERLINE = 1;
|
||||||
|
VT100.A_REVERSE = 2;
|
||||||
|
VT100.A_BLINK = 4;
|
||||||
|
VT100.A_DIM = 8;
|
||||||
|
VT100.A_BOLD = 16;
|
||||||
|
VT100.A_STANDOUT = 32;
|
||||||
|
VT100.A_PROTECT = VT100.A_INVIS = 0; // ?
|
||||||
|
// other public constants
|
||||||
|
VT100.TABSIZE = 8;
|
||||||
|
// private constants
|
||||||
|
VT100.ATTR_FLAGS_ = VT100.A_UNDERLINE | VT100.A_REVERSE | VT100.A_BLINK |
|
||||||
|
VT100.A_DIM | VT100.A_BOLD | VT100.A_STANDOUT |
|
||||||
|
VT100.A_PROTECT | VT100.A_INVIS;
|
||||||
|
VT100.COLOR_SHIFT_ = 6;
|
||||||
|
VT100.browser_ie_ = (navigator.appName.indexOf("Microsoft") != -1);
|
||||||
|
VT100.browser_opera_ = (navigator.appName.indexOf("Opera") != -1);
|
||||||
|
// class variables
|
||||||
|
VT100.the_vt_ = undefined;
|
||||||
|
|
||||||
|
// class methods
|
||||||
|
|
||||||
|
// this is actually an event handler
|
||||||
|
VT100.handle_onkeypress_ = function(e)
|
||||||
|
{
|
||||||
|
var vt = VT100.the_vt_, ch;
|
||||||
|
if (vt === undefined)
|
||||||
|
return true;
|
||||||
|
if (VT100.browser_ie_ || VT100.browser_opera_) {
|
||||||
|
ch = event.keyCode;
|
||||||
|
if (ch == 13)
|
||||||
|
ch = 10;
|
||||||
|
else if (ch > 255 || (ch < 32 && ch != 8))
|
||||||
|
return true;
|
||||||
|
ch = String.fromCharCode(ch);
|
||||||
|
} else {
|
||||||
|
ch = e.charCode;
|
||||||
|
if (ch) {
|
||||||
|
if (ch > 255)
|
||||||
|
return true;
|
||||||
|
ch = String.fromCharCode(ch);
|
||||||
|
if (ch == '\r')
|
||||||
|
ch = '\n';
|
||||||
|
} else
|
||||||
|
switch (e.keyCode) {
|
||||||
|
case e.DOM_VK_BACK_SPACE:
|
||||||
|
ch = '\b'; break;
|
||||||
|
case e.DOM_VK_TAB:
|
||||||
|
ch = '\t'; break;
|
||||||
|
case e.DOM_VK_RETURN:
|
||||||
|
case e.DOM_VK_ENTER:
|
||||||
|
ch = '\n'; break;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vt.key_buf_.push(ch);
|
||||||
|
setTimeout(VT100.go_getch_, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is actually an event handler
|
||||||
|
VT100.handle_onkeydown_ = function()
|
||||||
|
{
|
||||||
|
var vt = VT100.the_vt_, ch;
|
||||||
|
switch (event.keyCode) {
|
||||||
|
case 8:
|
||||||
|
ch = '\b'; break;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
vt.key_buf_.push(ch);
|
||||||
|
setTimeout(VT100.go_getch_, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.go_getch_ = function()
|
||||||
|
{
|
||||||
|
var vt = VT100.the_vt_;
|
||||||
|
if (vt === undefined)
|
||||||
|
return;
|
||||||
|
var isr = vt.getch_isr_;
|
||||||
|
vt.getch_isr_ = undefined;
|
||||||
|
if (isr === undefined)
|
||||||
|
return;
|
||||||
|
var ch = vt.key_buf_.shift();
|
||||||
|
if (ch === undefined) {
|
||||||
|
vt.getch_isr_ = isr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (vt.echo_)
|
||||||
|
vt.addch(ch);
|
||||||
|
isr(ch, vt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// object methods
|
||||||
|
|
||||||
|
VT100.prototype.may_scroll_ = function()
|
||||||
|
{
|
||||||
|
var ht = this.ht_, cr = this.row_;
|
||||||
|
while (cr >= ht) {
|
||||||
|
this.scroll();
|
||||||
|
--cr;
|
||||||
|
}
|
||||||
|
this.row_ = cr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.html_colours_ = function(attr)
|
||||||
|
{
|
||||||
|
var pair, fg, bg, co0, co1;
|
||||||
|
pair = this.pair_content(this.PAIR_NUMBER(attr));
|
||||||
|
fg = pair.f;
|
||||||
|
bg = pair.b;
|
||||||
|
switch (attr & (VT100.A_REVERSE | VT100.A_DIM | VT100.A_BOLD)) {
|
||||||
|
case 0:
|
||||||
|
case VT100.A_DIM | VT100.A_BOLD:
|
||||||
|
co0 = '00'; co1 = 'c0'; break;
|
||||||
|
case VT100.A_BOLD:
|
||||||
|
co0 = '00'; co1 = 'ff'; break;
|
||||||
|
case VT100.A_DIM:
|
||||||
|
if (fg == VT100.COLOR_BLACK)
|
||||||
|
co0 = '40';
|
||||||
|
else
|
||||||
|
co0 = '00';
|
||||||
|
co1 = '40';
|
||||||
|
break;
|
||||||
|
case VT100.A_REVERSE:
|
||||||
|
case VT100.A_REVERSE | VT100.A_DIM | VT100.A_BOLD:
|
||||||
|
co0 = 'c0'; co1 = '40'; break;
|
||||||
|
case VT100.A_REVERSE | VT100.A_BOLD:
|
||||||
|
co0 = 'c0'; co1 = '00'; break;
|
||||||
|
default:
|
||||||
|
if (fg == VT100.COLOR_BLACK)
|
||||||
|
co0 = '80';
|
||||||
|
else
|
||||||
|
co0 = 'c0';
|
||||||
|
co1 = 'c0';
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
f: '#' + (fg & 4 ? co1 : co0) +
|
||||||
|
(fg & 2 ? co1 : co0) +
|
||||||
|
(fg & 1 ? co1 : co0),
|
||||||
|
b: '#' + (bg & 4 ? co1 : co0) +
|
||||||
|
(bg & 2 ? co1 : co0) +
|
||||||
|
(bg & 1 ? co1 : co0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.addch = function(ch, attr)
|
||||||
|
{
|
||||||
|
var cc = this.col_;
|
||||||
|
switch (ch) {
|
||||||
|
case '\b':
|
||||||
|
if (cc != 0)
|
||||||
|
--cc;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
++this.row_;
|
||||||
|
cc = 0;
|
||||||
|
this.clrtoeol();
|
||||||
|
this.may_scroll_();
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
this.may_scroll_();
|
||||||
|
cc = 0;
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
this.may_scroll_();
|
||||||
|
cc += VT100.TABSIZE - cc % VT100.TABSIZE;
|
||||||
|
if (cc >= this.wd_) {
|
||||||
|
++this.row_;
|
||||||
|
cc -= this.wd_;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (attr === undefined)
|
||||||
|
attr = this.c_attr_;
|
||||||
|
if (cc >= this.wd_) {
|
||||||
|
++this.row_;
|
||||||
|
cc = 0;
|
||||||
|
}
|
||||||
|
this.may_scroll_();
|
||||||
|
this.text_[this.row_][cc] = ch;
|
||||||
|
this.attr_[this.row_][cc] = attr;
|
||||||
|
++cc;
|
||||||
|
}
|
||||||
|
this.col_ = cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.addstr = function(stuff)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < stuff.length; ++i)
|
||||||
|
this.addch(stuff.charAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.attroff = function(a)
|
||||||
|
{
|
||||||
|
a &= VT100.ATTR_FLAGS_;
|
||||||
|
this.c_attr_ &= ~a;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.attron = function(a)
|
||||||
|
{
|
||||||
|
a &= VT100.ATTR_FLAGS_;
|
||||||
|
this.c_attr_ |= a;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.attrset = function(a)
|
||||||
|
{
|
||||||
|
this.c_attr_ = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.bkgdset = function(a)
|
||||||
|
{
|
||||||
|
this.bkgd_ = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.clear = function()
|
||||||
|
{
|
||||||
|
this.row_ = this.col_ = 0;
|
||||||
|
for (r = 0; r < this.ht_; ++r) {
|
||||||
|
for (c = 0; c < this.wd_; ++c) {
|
||||||
|
this.text_[r][c] = ' ';
|
||||||
|
this.attr_[r][c] = this.bkgd_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.clrtobot = function()
|
||||||
|
{
|
||||||
|
var ht = this.ht_;
|
||||||
|
var wd = this.wd_;
|
||||||
|
this.clrtoeol();
|
||||||
|
for (var r = this.row_ + 1; r < ht; ++r) {
|
||||||
|
for (var c = 0; c < wd; ++c) {
|
||||||
|
this.text_[r][c] = ' ';
|
||||||
|
this.attr_[r][c] = this.bkgd_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.clrtoeol = function()
|
||||||
|
{
|
||||||
|
var r = this.row_;
|
||||||
|
if (r >= this.ht_)
|
||||||
|
return;
|
||||||
|
for (var c = this.col_; c < this.wd_; ++c) {
|
||||||
|
this.text_[r][c] = ' ';
|
||||||
|
this.attr_[r][c] = this.bkgd_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.COLOR_PAIR = function(pn)
|
||||||
|
{
|
||||||
|
return pn << VT100.COLOR_SHIFT_;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.curs_set = function(vis, grab)
|
||||||
|
{
|
||||||
|
if (vis !== undefined)
|
||||||
|
this.cursor_vis_ = (vis > 0);
|
||||||
|
if (grab === true || grab === false) {
|
||||||
|
if (grab === this.grab_events_)
|
||||||
|
return;
|
||||||
|
if (grab) {
|
||||||
|
this.grab_events_ = true;
|
||||||
|
VT100.the_vt_ = this;
|
||||||
|
document.onkeypress = VT100.handle_onkeypress_;
|
||||||
|
if (VT100.browser_ie_)
|
||||||
|
document.onkeydown = VT100.handle_onkeydown_;
|
||||||
|
} else {
|
||||||
|
document.onkeypress = undefined;
|
||||||
|
if (VT100.browser_ie_)
|
||||||
|
document.onkeydown = VT100.handle_onkeydown_;
|
||||||
|
this.grab_events_ = false;
|
||||||
|
VT100.the_vt_ = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.echo = function()
|
||||||
|
{
|
||||||
|
this.echo_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.erase = VT100.prototype.clear;
|
||||||
|
|
||||||
|
VT100.prototype.getch = function(isr)
|
||||||
|
{
|
||||||
|
this.refresh();
|
||||||
|
this.getch_isr_ = isr;
|
||||||
|
setTimeout(VT100.go_getch_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.getmaxyx = function()
|
||||||
|
{
|
||||||
|
return { y: this.ht_ - 1, x: this.wd_ - 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.getyx = function()
|
||||||
|
{
|
||||||
|
return { y: this.row_, x: this.col_ };
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.move = function(r, c)
|
||||||
|
{
|
||||||
|
if (r < 0)
|
||||||
|
r = 0;
|
||||||
|
else if (r >= this.ht_)
|
||||||
|
r = this.ht_ - 1;
|
||||||
|
if (c < 0)
|
||||||
|
c = 0;
|
||||||
|
else if (c >= this.wd_)
|
||||||
|
c = this.wd_ - 1;
|
||||||
|
this.row_ = r;
|
||||||
|
this.col_ = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.noecho = function()
|
||||||
|
{
|
||||||
|
this.echo_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.pair_content = function(pn)
|
||||||
|
{
|
||||||
|
return this.color_pair_[pn];
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.PAIR_NUMBER = function(at)
|
||||||
|
{
|
||||||
|
return at >> VT100.COLOR_SHIFT_;
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.refresh = function()
|
||||||
|
{
|
||||||
|
var r, c, stuff = "", end_tag = "", at = -1, n_at, ch,
|
||||||
|
pair, cr, cc, ht, wd, cv;
|
||||||
|
ht = this.ht_;
|
||||||
|
wd = this.wd_;
|
||||||
|
cr = this.row_;
|
||||||
|
cc = this.col_;
|
||||||
|
cv = this.cursor_vis_;
|
||||||
|
if (cc >= wd)
|
||||||
|
cc = wd - 1;
|
||||||
|
for (r = 0; r < ht; ++r) {
|
||||||
|
stuff += '<br>';
|
||||||
|
for (c = 0; c < wd; ++c) {
|
||||||
|
n_at = this.attr_[r][c];
|
||||||
|
if (cv && r == cr && c == cc)
|
||||||
|
n_at ^= VT100.A_REVERSE;
|
||||||
|
if (n_at != at) {
|
||||||
|
stuff += end_tag;
|
||||||
|
end_tag = "";
|
||||||
|
if (n_at & VT100.A_BLINK) {
|
||||||
|
stuff += "<blink>";
|
||||||
|
end_tag = "</blink>" + end_tag;
|
||||||
|
}
|
||||||
|
if (n_at & VT100.A_STANDOUT)
|
||||||
|
n_at |= VT100.A_BOLD;
|
||||||
|
pair = this.html_colours_(n_at);
|
||||||
|
stuff += '<span style="color:' + pair.f +
|
||||||
|
';background-color:' + pair.b;
|
||||||
|
if (n_at & VT100.A_UNDERLINE)
|
||||||
|
stuff += ';text-decoration:underline';
|
||||||
|
stuff += ';">';
|
||||||
|
end_tag = "</span>" + end_tag;
|
||||||
|
at = n_at;
|
||||||
|
}
|
||||||
|
ch = this.text_[r][c];
|
||||||
|
switch (ch) {
|
||||||
|
case '&':
|
||||||
|
stuff += '&'; break;
|
||||||
|
case '<':
|
||||||
|
stuff += '<'; break;
|
||||||
|
case '>':
|
||||||
|
stuff += '>'; break;
|
||||||
|
case ' ':
|
||||||
|
stuff += ' '; break;
|
||||||
|
default:
|
||||||
|
stuff += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.scr_.innerHTML = " <b>" + stuff + end_tag + "</b><br> ";
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.scroll = function()
|
||||||
|
{
|
||||||
|
var n_text = this.text_[0], n_attr = this.attr_[0],
|
||||||
|
ht = this.ht_, wd = this.wd_;
|
||||||
|
for (var r = 1; r < ht; ++r) {
|
||||||
|
this.text_[r - 1] = this.text_[r];
|
||||||
|
this.attr_[r - 1] = this.attr_[r];
|
||||||
|
}
|
||||||
|
this.text_[ht - 1] = n_text;
|
||||||
|
this.attr_[ht - 1] = n_attr;
|
||||||
|
for (var c = 0; c < wd; ++c) {
|
||||||
|
n_text[c] = ' ';
|
||||||
|
n_attr[c] = this.bkgd_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.standend = function()
|
||||||
|
{
|
||||||
|
this.attrset(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.standout = function()
|
||||||
|
{
|
||||||
|
this.attron(VT100.A_STANDOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
VT100.prototype.write = function(stuff)
|
||||||
|
{
|
||||||
|
var ch, x, r, c, i, j, yx, myx;
|
||||||
|
for (i = 0; i < stuff.length; ++i) {
|
||||||
|
ch = stuff.charAt(i);
|
||||||
|
switch (ch) {
|
||||||
|
case '\x00':
|
||||||
|
case '\x7f':
|
||||||
|
continue;
|
||||||
|
case '\a':
|
||||||
|
case '\b':
|
||||||
|
case '\t':
|
||||||
|
case '\r':
|
||||||
|
this.addch(ch);
|
||||||
|
continue;
|
||||||
|
case '\n':
|
||||||
|
case '\v':
|
||||||
|
case '\f': // what a mess
|
||||||
|
yx = this.getyx();
|
||||||
|
myx = this.getmaxyx();
|
||||||
|
if (yx.y >= myx.y) {
|
||||||
|
this.scroll();
|
||||||
|
this.move(myx.y, 0);
|
||||||
|
} else
|
||||||
|
this.move(yx.y + 1, 0);
|
||||||
|
continue;
|
||||||
|
case '\x18':
|
||||||
|
case '\x1a':
|
||||||
|
this.esc_state_ = 0;
|
||||||
|
continue;
|
||||||
|
case '\x1b':
|
||||||
|
this.esc_state_ = 1;
|
||||||
|
continue;
|
||||||
|
case '\x9b':
|
||||||
|
this.esc_state_ = 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// not a recognized control character
|
||||||
|
switch (this.esc_state_) {
|
||||||
|
case 0: // not in escape sequence
|
||||||
|
this.addch(ch);
|
||||||
|
break;
|
||||||
|
case 1: // just saw ESC
|
||||||
|
switch (ch) {
|
||||||
|
case '[':
|
||||||
|
this.esc_state_ = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // just saw CSI
|
||||||
|
this.csi_parms_ = [0];
|
||||||
|
this.esc_state_ = 3;
|
||||||
|
case 3: // saw CSI and parameters
|
||||||
|
switch (ch) {
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
|
x = this.csi_parms_.pop();
|
||||||
|
this.csi_parms_.push(x * 10 + ch * 1);
|
||||||
|
continue;
|
||||||
|
case ';':
|
||||||
|
if (this.csi_parms_.length < 17)
|
||||||
|
this.csi_parms_.push(0);
|
||||||
|
case '?': // ?!?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.esc_state_ = 0;
|
||||||
|
switch (ch) {
|
||||||
|
case 'H':
|
||||||
|
this.esc_state_ = 0;
|
||||||
|
this.csi_parms_.push(0);
|
||||||
|
this.move(this.csi_parms_[0] - 1,
|
||||||
|
this.csi_parms_[1] - 1);
|
||||||
|
break;
|
||||||
|
case 'J':
|
||||||
|
switch (this.csi_parms_[0]) {
|
||||||
|
case 0:
|
||||||
|
this.clrtobot();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
this.clear();
|
||||||
|
this.move(0, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
for (j=0; j<this.csi_parms_.length; ++j) {
|
||||||
|
x = this.csi_parms_[j];
|
||||||
|
switch (x) {
|
||||||
|
case 0:
|
||||||
|
this.standend();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
this.attron(VT100.A_BOLD);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case '[':
|
||||||
|
this.esc_state_ = 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4: // saw CSI [
|
||||||
|
this.esc_state_ = 0; // gobble char.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.refresh();
|
||||||
|
}
|
105
index.html
Normal file
105
index.html
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>scriptreplay in javascript</title>
|
||||||
|
<script type="text/javascript" src="./VT100.js" ></script>
|
||||||
|
<script type="text/javascript" src="./scriptreplay.js" ></script>
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
window.addEventListener("load", function(evt) {
|
||||||
|
vt = new VT100(80, 24, "term");
|
||||||
|
vt.clear();
|
||||||
|
vt.refresh();
|
||||||
|
vt.write(
|
||||||
|
"\n\n\n" +
|
||||||
|
" * This javascript terminal window is 80x24 characters, so it might be\n" +
|
||||||
|
" best to adjust your terminal window to that size as well using the\n" +
|
||||||
|
" following to check:\n" +
|
||||||
|
" $ watch \"tput cols; tput lines\"\n" +
|
||||||
|
" * Start recording:\n" +
|
||||||
|
" $ SHELL=/bin/sh TERM=vt100 script -t typescript 2> timingfile\n" +
|
||||||
|
" * Do your stuff and when done exit script with `exit`, `logout` or\n" +
|
||||||
|
" ctrl-d.\n" +
|
||||||
|
" * To test how your recorded session looks like, use:\n" +
|
||||||
|
" $ scriptreplay timingfile typescript\n" +
|
||||||
|
" * Enter `timingfile` and `typescript` into form above and hit the play\n" +
|
||||||
|
" button.\n");
|
||||||
|
document.getElementById("stop").addEventListener("click", stop, false);
|
||||||
|
document.getElementById("speed").addEventListener('change', set_speed, false);
|
||||||
|
document.getElementById("fontsize").addEventListener('change', set_fontsize, false);
|
||||||
|
document.getElementById("play").addEventListener("click", play, false);
|
||||||
|
|
||||||
|
var samples = document.querySelectorAll("ul#sample>li>a[id^=\"sample_\"]");
|
||||||
|
for (var i = 0; i < samples.length; i++) {
|
||||||
|
samples[i].addEventListener('click', function(evt) {
|
||||||
|
play_file(evt.target.id.substr(7));
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
--></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h2>scriptreplay in javascript</h2>
|
||||||
|
|
||||||
|
<p><tt>script</tt> and <tt>scriptreplay</tt> are part of the <tt>bsdutils</tt>
|
||||||
|
package in debian and ubuntu, <tt>util-linux-ng</tt> in fedora and
|
||||||
|
<tt>util-linux</tt> in suse. They allow to capture a terminal or script output
|
||||||
|
and replay it.</p>
|
||||||
|
|
||||||
|
<p>This page uses the <a href="./VT100.js">vt100 emulator</a> by
|
||||||
|
<a href="http://fzort.org/bi/o.php#vt100_js">frank bi</a> and adds
|
||||||
|
<a href="./scriptreplay.js">code of my own</a> to read typescript and timing
|
||||||
|
files to make it possible to replay captured scripts a web browser.</p>
|
||||||
|
|
||||||
|
<p>By adding an upload facility to this it would be possible to have a youtube
|
||||||
|
or pastebin for terminal sessions. Due to laziness this remains a proof of
|
||||||
|
concept for now though.</p>
|
||||||
|
|
||||||
|
<p>(C) 2011 Johannes 'josch' Schauer <j [dot] schauer [at] email [dot] de></p>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>file input</legend>
|
||||||
|
typescript: <input type="file" id="typescript" name="typescript" /><br />
|
||||||
|
timingfile: <input type="file" id="timingfile" name="typescript" /><br />
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>samples</legend>
|
||||||
|
<ul id="sample">
|
||||||
|
<li><a href="javascript:void()" id="sample_qemu">qemu boot</a></li>
|
||||||
|
<li><a href="javascript:void()" id="sample_starwars">star wars</a></li>
|
||||||
|
</ul>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<tt><pre id=term></pre></tt>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>play control</legend>
|
||||||
|
<button id="play">play</button>
|
||||||
|
<button id="stop">stop</button>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>output properties</legend>
|
||||||
|
Font size
|
||||||
|
<select id="fontsize">
|
||||||
|
<option value="8">8</option>
|
||||||
|
<option value="10">10</option>
|
||||||
|
<option value="12" selected="selected">12</option>
|
||||||
|
<option value="14">14</option>
|
||||||
|
<option value="16">16</option>
|
||||||
|
<option value="18">18</option>
|
||||||
|
</select>
|
||||||
|
Speed
|
||||||
|
<select id="speed">
|
||||||
|
<option value="0.25">slowest</option>
|
||||||
|
<option value="0.5">slower</option>
|
||||||
|
<option value="0.75">slow</option>
|
||||||
|
<option value="1.0" selected="selected">normal</option>
|
||||||
|
<option value="1.5">fast</option>
|
||||||
|
<option value="2.0">faster</option>
|
||||||
|
<option value="4.0">fastest</option>
|
||||||
|
</select>
|
||||||
|
</fieldset>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
262
qemu.script
Normal file
262
qemu.script
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
Script started on Mon 04 Jul 2011 10:53:10 AM CEST
|
||||||
|
$ qemu-system-mipsel -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda hda.img -append "root=/dev/sda1 console=ttyS0" -nographic
|
||||||
|
[ 0.000000] Initializing cgroup subsys cpuset
|
||||||
|
[ 0.000000] Initializing cgroup subsys cpu
|
||||||
|
[ 0.000000] Linux version 2.6.32-5-4kc-malta (Debian 2.6.32-35) (dannf@debian.org) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 Tue Jun 14 18:46:39 UTC 2011
|
||||||
|
[ 0.000000]
|
||||||
|
[ 0.000000] LINUX started...
|
||||||
|
[ 0.000000] bootconsole [early0] enabled
|
||||||
|
[ 0.000000] CPU revision is: 00019300 (MIPS 24Kc)
|
||||||
|
[ 0.000000] FPU revision is: 00000000
|
||||||
|
[ 0.000000] Determined physical RAM map:
|
||||||
|
[ 0.000000] memory: 00001000 @ 00000000 (reserved)
|
||||||
|
[ 0.000000] memory: 000ef000 @ 00001000 (ROM data)
|
||||||
|
[ 0.000000] memory: 005b2000 @ 000f0000 (reserved)
|
||||||
|
[ 0.000000] memory: 0795e000 @ 006a2000 (usable)
|
||||||
|
[ 0.000000] Wasting 54336 bytes for tracking 1698 unused pages
|
||||||
|
[ 0.000000] Initrd not found or empty - disabling initrd
|
||||||
|
[ 0.000000] Zone PFN ranges:
|
||||||
|
[ 0.000000] DMA 0x00000000 -> 0x00001000
|
||||||
|
[ 0.000000] Normal 0x00001000 -> 0x00008000
|
||||||
|
[ 0.000000] Movable zone start PFN for each node
|
||||||
|
[ 0.000000] early_node_map[1] active PFN ranges
|
||||||
|
[ 0.000000] 0: 0x00000000 -> 0x00008000
|
||||||
|
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512
|
||||||
|
[ 0.000000] Kernel command line: root=/dev/sda1 console=ttyS0
|
||||||
|
[ 0.000000] PID hash table entries: 512 (order: -1, 2048 bytes)
|
||||||
|
[ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
|
||||||
|
[ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
|
||||||
|
[ 0.000000] Primary instruction cache 2kB, VIPT, 2-way, linesize 16 bytes.
|
||||||
|
[ 0.000000] Primary data cache 2kB, 2-way, VIPT, no aliases, linesize 16 bytes
|
||||||
|
[ 0.000000] Writing ErrCtl register=00000000
|
||||||
|
[ 0.000000] Readback ErrCtl register=00000000
|
||||||
|
[ 0.000000] Memory: 122972k/124280k available (3979k kernel code, 1128k reserved, 1088k data, 208k init, 0k highmem)
|
||||||
|
[ 0.000000] SLUB: Genslabs=7, HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
|
||||||
|
[ 0.000000] Hierarchical RCU implementation.
|
||||||
|
[ 0.000000] NR_IRQS:256
|
||||||
|
[ 0.000000] CPU frequency 200.00 MHz
|
||||||
|
[ 0.000000] Console: colour dummy device 80x25
|
||||||
|
[ 0.008000] Calibrating delay loop... 784.38 BogoMIPS (lpj=1568768)
|
||||||
|
[ 0.088000] Security Framework initialized
|
||||||
|
[ 0.088000] SELinux: Disabled at boot.
|
||||||
|
[ 0.088000] Mount-cache hash table entries: 512
|
||||||
|
[ 0.096000] Initializing cgroup subsys ns
|
||||||
|
[ 0.096000] Initializing cgroup subsys cpuacct
|
||||||
|
[ 0.096000] Initializing cgroup subsys devices
|
||||||
|
[ 0.096000] Initializing cgroup subsys freezer
|
||||||
|
[ 0.096000] Initializing cgroup subsys net_cls
|
||||||
|
[ 0.108000] devtmpfs: initialized
|
||||||
|
[ 0.120000] regulator: core version 0.5
|
||||||
|
[ 0.120000] NET: Registered protocol family 16
|
||||||
|
[ 0.136000] bio: create slab <bio-0> at 0
|
||||||
|
[ 0.140000] vgaarb: loaded
|
||||||
|
[ 0.140000] SCSI subsystem initialized
|
||||||
|
[ 0.144000] pci 0000:00:0a.3: BAR 14: address space collision on of bridge [0x1100-0x110f]
|
||||||
|
[ 0.144000] pci 0000:00:0a.3: quirk: region 1100-110f claimed by PIIX4 SMB
|
||||||
|
[ 0.148000] vgaarb: device added: PCI:0000:00:12.0,decodes=io+mem,owns=none,locks=none
|
||||||
|
[ 0.148000] pci 0000:00:0a.3: BAR 14: bogus alignment [0x1100-0x110f] flags 0x100
|
||||||
|
[ 0.156000] Switching to clocksource MIPS
|
||||||
|
[ 0.180000] NET: Registered protocol family 2
|
||||||
|
[ 0.180000] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
|
||||||
|
[ 0.184000] TCP established hash table entries: 4096 (order: 3, 32768 bytes)
|
||||||
|
[ 0.184000] TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
|
||||||
|
[ 0.184000] TCP: Hash tables configured (established 4096 bind 4096)
|
||||||
|
[ 0.184000] TCP reno registered
|
||||||
|
[ 0.184000] NET: Registered protocol family 1
|
||||||
|
[ 0.188000] RPC: Registered udp transport module.
|
||||||
|
[ 0.188000] RPC: Registered tcp transport module.
|
||||||
|
[ 0.188000] RPC: Registered tcp NFSv4.1 backchannel transport module.
|
||||||
|
[ 0.196000] audit: initializing netlink socket (disabled)
|
||||||
|
[ 0.200000] type=2000 audit(1309769597.200:1): initialized
|
||||||
|
[ 0.212000] VFS: Disk quotas dquot_6.5.2
|
||||||
|
[ 0.212000] Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
|
||||||
|
[ 0.220000] msgmni has been set to 240
|
||||||
|
[ 0.228000] alg: No test for stdrng (krng)
|
||||||
|
[ 0.228000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
|
||||||
|
[ 0.228000] io scheduler noop registered
|
||||||
|
[ 0.232000] io scheduler anticipatory registered
|
||||||
|
[ 0.232000] io scheduler deadline registered
|
||||||
|
[ 0.232000] io scheduler cfq registered (default)
|
||||||
|
[ 0.232000] PCI: Enabling device 0000:00:12.0 (0000 -> 0002)
|
||||||
|
[ 0.232000] cirrusfb 0000:00:12.0: Cirrus Logic chipset on PCI bus, RAM (4096 kB) at 0x10000000
|
||||||
|
[ 0.448000] Console: switching to colour frame buffer device 80x30
|
||||||
|
[ 0.468000] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
|
||||||
|
[ 0.472000] serial8250.0: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
|
||||||
|
[ 0.472000] console [ttyS0] enabled, bootconsole disabled
|
||||||
|
[ 0.472000] console [ttyS0] enabled, bootconsole disabled
|
||||||
|
[ 0.476000] serial8250.0: ttyS1 at I/O 0x2f8 (irq = 3) is a 16550A
|
||||||
|
[ 0.476000] serial8250.0: ttyS2 at MMIO 0x1f000900 (irq = 18) is a 16550A
|
||||||
|
[ 0.484000] brd: module loaded
|
||||||
|
[ 0.488000] PCI: Enabling device 0000:00:0a.1 (0000 -> 0001)
|
||||||
|
[ 0.492000] scsi0 : ata_piix
|
||||||
|
[ 0.492000] scsi1 : ata_piix
|
||||||
|
[ 0.492000] ata1: PATA max UDMA/33 cmd 0x1f0 ctl 0x3f6 bmdma 0x1040 irq 14
|
||||||
|
[ 0.492000] ata2: PATA max UDMA/33 cmd 0x170 ctl 0x376 bmdma 0x1048 irq 15
|
||||||
|
[ 0.496000] pcnet32.c:v1.35 21.Apr.2008 tsbogend@alpha.franken.de
|
||||||
|
[ 0.500000] PCI: Enabling device 0000:00:0b.0 (0000 -> 0003)
|
||||||
|
[ 0.500000] pcnet32: PCnet/PCI II 79C970A at 0x1020, 52:54:00:12:34:56 assigned IRQ 10.
|
||||||
|
[ 0.500000] eth0: registered as PCnet/PCI II 79C970A
|
||||||
|
[ 0.500000] pcnet32: 1 cards_found.
|
||||||
|
[ 0.504000] serio: i8042 KBD port at 0x60,0x64 irq 1
|
||||||
|
[ 0.504000] serio: i8042 AUX port at 0x60,0x64 irq 12
|
||||||
|
[ 0.508000] mice: PS/2 mouse device common for all mice
|
||||||
|
[ 0.508000] rtc_cmos rtc_cmos: rtc core: registered rtc_cmos as rtc0
|
||||||
|
[ 0.508000] rtc0: alarms up to one day, 242 bytes nvram
|
||||||
|
[ 0.512000] TCP cubic registered
|
||||||
|
[ 0.512000] NET: Registered protocol family 17
|
||||||
|
[ 0.512000] registered taskstats version 1
|
||||||
|
[ 0.516000] rtc_cmos rtc_cmos: setting system clock to 2011-07-04 08:35:13 UTC (1309768513)
|
||||||
|
[ 0.516000] Initalizing network drop monitor service
|
||||||
|
[ 0.612000] input: AT Raw Set 2 keyboard as /devices/platform/i8042/serio0/input/input0
|
||||||
|
[ 0.660000] ata2.00: ATAPI: QEMU DVD-ROM, 0.12.5, max UDMA/100
|
||||||
|
[ 0.664000] ata1.00: ATA-7: QEMU HARDDISK, 0.12.5, max UDMA/100
|
||||||
|
[ 0.664000] ata1.00: 8192000 sectors, multi 16: LBA48
|
||||||
|
[ 0.664000] ata1.00: configured for UDMA/33
|
||||||
|
[ 0.672000] ata2.00: configured for UDMA/33
|
||||||
|
[ 0.676000] scsi 0:0:0:0: Direct-Access ATA QEMU HARDDISK 0.12 PQ: 0 ANSI: 5
|
||||||
|
[ 0.680000] sd 0:0:0:0: [sda] 8192000 512-byte logical blocks: (4.19 GB/3.90 GiB)
|
||||||
|
[ 0.680000] sd 0:0:0:0: [sda] Write Protect is off
|
||||||
|
[ 0.684000] scsi 1:0:0:0: CD-ROM QEMU QEMU DVD-ROM 0.12 PQ: 0 ANSI: 5
|
||||||
|
[ 0.684000] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
|
||||||
|
[ 0.688000] sda: sda1 sda2 < sda5 >
|
||||||
|
[ 0.704000] sd 0:0:0:0: [sda] Attached SCSI disk
|
||||||
|
[ 0.712000] kjournald starting. Commit interval 5 seconds
|
||||||
|
[ 0.716000] EXT3-fs: mounted filesystem with ordered data mode.
|
||||||
|
[ 0.716000] VFS: Mounted root (ext3 filesystem) readonly on device 8:1.
|
||||||
|
[ 0.720000] Freeing prom memory: 956k freed
|
||||||
|
[ 0.732000] Freeing unused kernel memory: 208k freed
|
||||||
|
INIT: version 2.88 booting
|
||||||
|
Using makefile-style concurrent boot in runlevel S.
|
||||||
|
.udev/ already exists on the static /dev! ... [33m(warning).[39;49m
|
||||||
|
Starting the hotplug events dispatcher: udevd.
|
||||||
|
Synthesizing the initial hotplug events...done.
|
||||||
|
Waiting for /dev to be fully populated...[ 5.612000] usbcore: registered new interface driver usbfs
|
||||||
|
[ 5.612000] usbcore: registered new interface driver hub
|
||||||
|
[ 5.664000] piix4_smbus 0000:00:0a.3: SMBus Host Controller at 0x1100, revision 0
|
||||||
|
[ 5.664000] usbcore: registered new device driver usb
|
||||||
|
[ 5.864000] sr0: scsi3-mmc drive: 4x/4x xa/form2 tray
|
||||||
|
[ 5.864000] Uniform CD-ROM driver Revision: 3.20
|
||||||
|
[ 5.976000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
|
||||||
|
[ 6.060000] physmap platform flash device: 00400000 at 1e000000
|
||||||
|
[ 6.108000] uhci_hcd: USB Universal Host Controller Interface driver
|
||||||
|
[ 6.108000] PCI: Enabling device 0000:00:0a.2 (0000 -> 0001)
|
||||||
|
[ 6.108000] uhci_hcd 0000:00:0a.2: UHCI Host Controller
|
||||||
|
[ 6.112000] uhci_hcd 0000:00:0a.2: new USB bus registered, assigned bus number 1
|
||||||
|
[ 6.128000] uhci_hcd 0000:00:0a.2: irq 11, io base 0x00001000
|
||||||
|
[ 6.160000] usb usb1: New USB device found, idVendor=1d6b, idProduct=0001
|
||||||
|
[ 6.160000] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
|
||||||
|
[ 6.160000] usb usb1: Product: UHCI Host Controller
|
||||||
|
[ 6.160000] usb usb1: Manufacturer: Linux 2.6.32-5-4kc-malta uhci_hcd
|
||||||
|
[ 6.160000] usb usb1: SerialNumber: 0000:00:0a.2
|
||||||
|
[ 6.216000] usb usb1: configuration #1 chosen from 1 choice
|
||||||
|
[ 6.220000] hub 1-0:1.0: USB hub found
|
||||||
|
[ 6.220000] hub 1-0:1.0: 2 ports detected
|
||||||
|
[ 6.236000] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input1
|
||||||
|
[ 6.308000] sd 0:0:0:0: Attached scsi generic sg0 type 0
|
||||||
|
[ 6.312000] sr 1:0:0:0: Attached scsi generic sg1 type 5
|
||||||
|
[ 6.976000] physmap-flash.0: PFOW string at 0x0 is not found
|
||||||
|
[ 7.056000] cmdlinepart partition parsing not available
|
||||||
|
[ 7.084000] RedBoot partition parsing not available
|
||||||
|
[ 7.084000] Using physmap partition information
|
||||||
|
[ 7.084000] Creating 3 MTD partitions on "physmap-flash.0":
|
||||||
|
[ 7.084000] 0x000000000000-0x000000100000 : "YAMON"
|
||||||
|
[ 7.092000] 0x000000100000-0x0000003e0000 : "User FS"
|
||||||
|
[ 7.096000] 0x0000003e0000-0x000000400000 : "Board Config"
|
||||||
|
done.
|
||||||
|
Activating swap...[ 8.312000] Adding 219128k swap on /dev/sda5. Priority:-1 extents:1 across:219128k
|
||||||
|
done.
|
||||||
|
Checking root file system...fsck from util-linux-ng 2.17.2
|
||||||
|
/dev/sda1: clean, 41254/242400 files, 285212/968448 blocks
|
||||||
|
done.
|
||||||
|
[ 8.988000] EXT3 FS on sda1, internal journal
|
||||||
|
Cleaning up ifupdown....
|
||||||
|
Setting up networking....
|
||||||
|
Loading kernel modules...[ 9.980000] loop: module loaded
|
||||||
|
done.
|
||||||
|
Activating lvm and md swap...done.
|
||||||
|
Checking file systems...fsck from util-linux-ng 2.17.2
|
||||||
|
done.
|
||||||
|
Mounting local filesystems...done.
|
||||||
|
Activating swapfile swap...done.
|
||||||
|
Cleaning up temporary files....
|
||||||
|
Configuring network interfaces...done.
|
||||||
|
Starting portmap daemon....
|
||||||
|
Starting NFS common utilities: statd.
|
||||||
|
Cleaning up temporary files...[ 14.824000] eth0: link up
|
||||||
|
.
|
||||||
|
Setting kernel variables ...done.
|
||||||
|
INIT: Entering runlevel: 2
|
||||||
|
Using makefile-style concurrent boot in runlevel 2.
|
||||||
|
Starting NFS common utilities: statd.
|
||||||
|
Starting portmap daemon...Already running..
|
||||||
|
Starting enhanced syslogd: rsyslogd.
|
||||||
|
Starting deferred execution scheduler: atd.
|
||||||
|
Starting periodic command scheduler: cron.
|
||||||
|
Starting system message bus: dbus.
|
||||||
|
Starting MTA: exim4.
|
||||||
|
[ 28.976000] NET: Registered protocol family 10
|
||||||
|
|
||||||
|
Debian GNU/Linux 6.0 debian ttyS0
|
||||||
|
|
||||||
|
debian login: root
|
||||||
|
Password:
|
||||||
|
Last login: Mon Jul 4 09:33:06 CEST 2011 on ttyS0
|
||||||
|
Linux debian 2.6.32-5-4kc-malta #1 Tue Jun 14 18:46:39 UTC 2011 mips
|
||||||
|
|
||||||
|
The programs included with the Debian GNU/Linux system are free software;
|
||||||
|
the exact distribution terms for each program are described in the
|
||||||
|
individual files in /usr/share/doc/*/copyright.
|
||||||
|
|
||||||
|
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||||
|
permitted by applicable law.
|
||||||
|
root@debian:~# uname -a
|
||||||
|
Linux debian 2.6.32-5-4kc-malta #1 Tue Jun 14 18:46:39 UTC 2011 mips GNU/Linux
|
||||||
|
root@debian:~# cat /proc/cpuinfo
|
||||||
|
system type : MIPS Malta
|
||||||
|
processor : 0
|
||||||
|
cpu model : MIPS 24Kc V0.0 FPU V0.0
|
||||||
|
BogoMIPS : 784.38
|
||||||
|
wait instruction : yes
|
||||||
|
microsecond timers : yes
|
||||||
|
tlb_entries : 16
|
||||||
|
extra interrupt vector : yes
|
||||||
|
hardware watchpoint : yes, count: 1, address/irw mask: [0x0ff8]
|
||||||
|
ASEs implemented :
|
||||||
|
shadow register sets : 1
|
||||||
|
core : 0
|
||||||
|
VCED exceptions : not available
|
||||||
|
VCEI exceptions : not available
|
||||||
|
|
||||||
|
root@debian:~# halt
|
||||||
|
|
||||||
|
Broadcast message from root@debian (ttyS0) (Mon Jul 4 10:36:14 2011):
|
||||||
|
|
||||||
|
The system is going down for system halt NOW!
|
||||||
|
INIT: Switching to runlevel: 0
|
||||||
|
root@debian:~#
INIT: Sending processes the TERM signal
|
||||||
|
Using makefile-style concurrent boot in runlevel 0.
|
||||||
|
Stopping deferred execution scheduler: atd.
|
||||||
|
Stopping MTA: exim4_listener.
|
||||||
|
Asking all remaining processes to terminate...done.
|
||||||
|
All processes ended within 2 seconds....done.
|
||||||
|
Stopping enhanced syslogd: rsyslogd.
|
||||||
|
Stopping portmap daemon....
|
||||||
|
Stopping NFS common utilities: statd.
|
||||||
|
Bad SWSTYLE=0x04
|
||||||
|
Deconfiguring network interfaces...Internet Systems Consortium DHCP Client 4.1.1-P1
|
||||||
|
Copyright 2004-2010 Internet Systems Consortium.
|
||||||
|
All rights reserved.
|
||||||
|
For info, please visit https://www.isc.org/software/dhcp/
|
||||||
|
|
||||||
|
Listening on LPF/eth0/52:54:00:12:34:56
|
||||||
|
Sending on LPF/eth0/52:54:00:12:34:56
|
||||||
|
Sending on Socket/fallback
|
||||||
|
DHCPRELEASE on eth0 to 10.0.2.2 port 67
|
||||||
|
done.
|
||||||
|
Cleaning up ifupdown....
|
||||||
|
Saving the system clock.
|
||||||
|
Deactivating swap...done.
|
||||||
|
Will now halt.
|
||||||
|
$ exit
|
||||||
|
|
||||||
|
Script done on Mon 04 Jul 2011 10:54:33 AM CEST
|
198
qemu.time
Normal file
198
qemu.time
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
0.596415 2
|
||||||
|
0.015173 125
|
||||||
|
5.780041 2
|
||||||
|
1.039932 793
|
||||||
|
0.049982 358
|
||||||
|
0.010029 651
|
||||||
|
0.009955 289
|
||||||
|
0.010026 94
|
||||||
|
2.939978 41
|
||||||
|
0.009958 32
|
||||||
|
0.070038 401
|
||||||
|
0.010057 39
|
||||||
|
0.019968 97
|
||||||
|
0.009996 47
|
||||||
|
0.010002 252
|
||||||
|
0.010000 226
|
||||||
|
0.009973 399
|
||||||
|
0.030011 236
|
||||||
|
0.010025 127
|
||||||
|
0.009969 122
|
||||||
|
0.009994 44
|
||||||
|
0.010029 506
|
||||||
|
0.009990 72
|
||||||
|
0.219995 271
|
||||||
|
0.019997 151
|
||||||
|
0.010009 330
|
||||||
|
0.009992 359
|
||||||
|
0.010024 23
|
||||||
|
0.000017 5
|
||||||
|
0.000012 393
|
||||||
|
0.009949 155
|
||||||
|
0.010019 93
|
||||||
|
0.090023 197
|
||||||
|
0.049982 98
|
||||||
|
0.009962 437
|
||||||
|
0.010017 37
|
||||||
|
0.009987 59
|
||||||
|
0.010005 133
|
||||||
|
0.010040 126
|
||||||
|
0.009964 58
|
||||||
|
0.009994 27
|
||||||
|
0.180012 4
|
||||||
|
0.010035 51
|
||||||
|
0.129993 3
|
||||||
|
0.045599 45
|
||||||
|
0.424369 27
|
||||||
|
0.140006 45
|
||||||
|
0.270003 4
|
||||||
|
0.290000 42
|
||||||
|
0.130012 8
|
||||||
|
0.479987 41
|
||||||
|
0.380031 126
|
||||||
|
2.399973 87
|
||||||
|
0.049983 59
|
||||||
|
0.010009 113
|
||||||
|
0.190004 76
|
||||||
|
0.120004 69
|
||||||
|
0.080005 287
|
||||||
|
0.067802 67
|
||||||
|
0.000037 349
|
||||||
|
0.032161 156
|
||||||
|
0.059996 103
|
||||||
|
0.019999 124
|
||||||
|
0.070005 67
|
||||||
|
0.669997 61
|
||||||
|
0.079992 32
|
||||||
|
0.019996 14
|
||||||
|
0.000019 5
|
||||||
|
0.000013 4
|
||||||
|
0.000016 2
|
||||||
|
0.000012 234
|
||||||
|
0.009944 64
|
||||||
|
0.010001 8
|
||||||
|
0.370023 18
|
||||||
|
0.779984 90
|
||||||
|
0.059988 8
|
||||||
|
0.010016 28
|
||||||
|
0.129994 33
|
||||||
|
0.200000 58
|
||||||
|
0.119996 3
|
||||||
|
0.010008 8
|
||||||
|
0.039999 51
|
||||||
|
0.170013 23
|
||||||
|
0.370015 4
|
||||||
|
0.159999 24
|
||||||
|
0.069972 4
|
||||||
|
0.159990 25
|
||||||
|
0.100006 37
|
||||||
|
0.130004 8
|
||||||
|
0.300000 29
|
||||||
|
1.310011 8
|
||||||
|
0.039991 24
|
||||||
|
0.039991 30
|
||||||
|
0.130006 3
|
||||||
|
0.000021 8
|
||||||
|
0.039982 29
|
||||||
|
0.089997 8
|
||||||
|
0.059996 27
|
||||||
|
0.019991 8
|
||||||
|
0.040015 30
|
||||||
|
0.099998 4
|
||||||
|
0.459992 33
|
||||||
|
0.180006 8
|
||||||
|
0.240004 26
|
||||||
|
0.049996 4
|
||||||
|
0.210005 36
|
||||||
|
0.219998 4
|
||||||
|
0.620003 30
|
||||||
|
0.350055 28
|
||||||
|
0.339933 3
|
||||||
|
0.000033 4
|
||||||
|
0.300007 28
|
||||||
|
0.269964 8
|
||||||
|
0.060055 7
|
||||||
|
0.879942 24
|
||||||
|
0.010045 54
|
||||||
|
0.109966 40
|
||||||
|
1.599991 46
|
||||||
|
0.030000 39
|
||||||
|
1.170010 46
|
||||||
|
1.279981 41
|
||||||
|
0.020009 4
|
||||||
|
0.460008 37
|
||||||
|
1.040004 13
|
||||||
|
0.019993 6
|
||||||
|
6.320004 4
|
||||||
|
0.279992 52
|
||||||
|
0.299999 3
|
||||||
|
1.230074 39
|
||||||
|
0.009964 14
|
||||||
|
0.009961 1
|
||||||
|
5.940003 1
|
||||||
|
0.129993 1
|
||||||
|
0.160008 1
|
||||||
|
0.110012 3
|
||||||
|
0.240002 10
|
||||||
|
0.189996 3
|
||||||
|
1.370004 424
|
||||||
|
0.359983 15
|
||||||
|
8.180054 1
|
||||||
|
1.659965 1
|
||||||
|
0.119988 1
|
||||||
|
0.160018 1
|
||||||
|
0.059981 1
|
||||||
|
0.400005 1
|
||||||
|
0.190007 1
|
||||||
|
0.149992 1
|
||||||
|
0.179992 3
|
||||||
|
0.180015 81
|
||||||
|
0.050017 15
|
||||||
|
0.010008 1
|
||||||
|
1.520035 1
|
||||||
|
0.099976 1
|
||||||
|
0.039946 1
|
||||||
|
0.100034 1
|
||||||
|
0.220008 1
|
||||||
|
0.189971 1
|
||||||
|
0.110026 1
|
||||||
|
0.100004 2
|
||||||
|
0.389977 1
|
||||||
|
0.020018 1
|
||||||
|
0.470004 1
|
||||||
|
0.099966 5
|
||||||
|
0.440017 3
|
||||||
|
0.620020 409
|
||||||
|
0.039985 15
|
||||||
|
0.009990 1
|
||||||
|
6.040066 1
|
||||||
|
0.049927 1
|
||||||
|
0.130006 1
|
||||||
|
0.120011 3
|
||||||
|
0.310013 133
|
||||||
|
0.119961 50
|
||||||
|
0.600002 44
|
||||||
|
0.009997 54
|
||||||
|
1.170033 46
|
||||||
|
0.899968 28
|
||||||
|
0.010002 4
|
||||||
|
0.100023 46
|
||||||
|
0.579972 8
|
||||||
|
0.159989 48
|
||||||
|
1.310007 35
|
||||||
|
0.039996 4
|
||||||
|
0.220008 30
|
||||||
|
0.619996 40
|
||||||
|
0.050000 18
|
||||||
|
0.940034 388
|
||||||
|
0.130012 27
|
||||||
|
0.449955 27
|
||||||
|
0.020000 20
|
||||||
|
0.389991 8
|
||||||
|
0.090015 17
|
||||||
|
0.840000 2
|
||||||
|
0.970052 1
|
||||||
|
1.709937 1
|
||||||
|
0.080006 1
|
||||||
|
0.089997 1
|
||||||
|
0.160021 2
|
133
scriptreplay.js
Normal file
133
scriptreplay.js
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
var vt, timer;
|
||||||
|
var speed = 1.0;
|
||||||
|
|
||||||
|
function Timer(callback, delay) {
|
||||||
|
var timerId, start, remaining = delay;
|
||||||
|
|
||||||
|
this.pause = function() {
|
||||||
|
window.clearTimeout(timerId);
|
||||||
|
remaining -= new Date() - start;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.resume = function() {
|
||||||
|
start = new Date();
|
||||||
|
timerId = window.setTimeout(callback, remaining);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_file_contents(filename, callback) {
|
||||||
|
if (window.XMLHttpRequest) {
|
||||||
|
req = new XMLHttpRequest();
|
||||||
|
} else {
|
||||||
|
req = new ActiveXObject("Microsoft.XMLHTTP");
|
||||||
|
}
|
||||||
|
req.open("GET", filename, false);
|
||||||
|
req.onreadystatechange = function() {
|
||||||
|
// status is 0 for local files
|
||||||
|
if (req.readyState==4 && ( req.status==200 || req.status==0)) {
|
||||||
|
callback(req.responseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
req.send(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function play_file(name) {
|
||||||
|
get_file_contents(name+".script", function(typescript_data) {
|
||||||
|
get_file_contents(name+".time", function(timing_data) {
|
||||||
|
run_typescript(typescript_data, timing_data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_speed(evt) {
|
||||||
|
var value = evt.target.options[evt.target.selectedIndex].value;
|
||||||
|
speed = parseFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_fontsize(evt) {
|
||||||
|
var value = evt.target.options[evt.target.selectedIndex].value;
|
||||||
|
document.getElementById("term").style.fontSize=value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function play(evt) {
|
||||||
|
if (evt.target.textContent == "play") {
|
||||||
|
readBlob('typescript', reader_onloadend);
|
||||||
|
} else if (evt.target.textContent == "resume") {
|
||||||
|
evt.target.textContent = "pause";
|
||||||
|
timer.resume();
|
||||||
|
} else if (evt.target.textContent == "pause") {
|
||||||
|
evt.target.textContent = "resume";
|
||||||
|
timer.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop(evt) {
|
||||||
|
document.getElementById("play").textContent = "play";
|
||||||
|
timer.pause();
|
||||||
|
vt.clear();
|
||||||
|
vt.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_typescript(typescript_data, timing_data) {
|
||||||
|
if (timer) timer.pause();
|
||||||
|
document.getElementById("play").textContent = "pause";
|
||||||
|
vt.clear();
|
||||||
|
vt.refresh();
|
||||||
|
|
||||||
|
var where = 0;
|
||||||
|
var linenum = 0;
|
||||||
|
var timings = timing_data.split("\n");
|
||||||
|
var firstlinelen = typescript_data.indexOf("\n") + 1;
|
||||||
|
var text = typescript_data.substr(0, firstlinelen);
|
||||||
|
var newtext = "";
|
||||||
|
where += firstlinelen;
|
||||||
|
|
||||||
|
timer = new Timer(
|
||||||
|
function() {
|
||||||
|
vt.write(text);
|
||||||
|
text = newtext;
|
||||||
|
var me = arguments.callee;
|
||||||
|
var line = timings[linenum].split(" ");
|
||||||
|
var time = parseFloat(line[0]);
|
||||||
|
var bytes = parseInt(line[1]);
|
||||||
|
if (isFinite(time) && isFinite(bytes)) {
|
||||||
|
newtext = typescript_data.substr(where, bytes);
|
||||||
|
where += bytes;
|
||||||
|
linenum += 1;
|
||||||
|
timer = new Timer(me, time*1000*1/speed);
|
||||||
|
} else {
|
||||||
|
vt.write(typescript_data.substr(where, typescript_data.length-where));
|
||||||
|
document.getElementById("play").textContent = "play";
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reader_onloadend(evt) {
|
||||||
|
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
|
||||||
|
typescript_data = evt.target.result;
|
||||||
|
readBlob('timingfile',
|
||||||
|
function(evt) {
|
||||||
|
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
|
||||||
|
timing_data = evt.target.result;
|
||||||
|
run_typescript(typescript_data, timing_data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readBlob(id, onload_handler) {
|
||||||
|
var files = document.getElementById(id).files;
|
||||||
|
if (!files.length) {
|
||||||
|
alert('Please select a file!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var file = files[0];
|
||||||
|
var blob = file.slice(0, file.size);
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onloadend = onload_handler;
|
||||||
|
reader.onerror = function(evt) {alert(evt);};
|
||||||
|
reader.readAsBinaryString(blob);
|
||||||
|
}
|
61441
starwars.script
Normal file
61441
starwars.script
Normal file
File diff suppressed because it is too large
Load diff
3417
starwars.time
Normal file
3417
starwars.time
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue