pax_global_header00006660000000000000000000000064147716556660014541gustar00rootroot0000000000000052 comment=8b7572449706b48a80e290e1ef88c4a4dd24bda9 colorized-logs-2.7/000077500000000000000000000000001477165566600143455ustar00rootroot00000000000000colorized-logs-2.7/.gitignore000066400000000000000000000002621477165566600163350ustar00rootroot00000000000000.#* ansi2html ansi2txt DEADJOE Makefile *.o *.orig *~ pipetty lesstty ttyrec2ansi config.h valgrind.* CMakeCache.txt CMakeFiles/ cmake_install.cmake CTestTestfile.cmake Testing/ colorized-logs-2.7/.travis.yml000066400000000000000000000003631477165566600164600ustar00rootroot00000000000000arch: - amd64 - ppc64le language: c matrix: include: - os: linux dist: trusty addons: apt: packages: - cmake - os: osx script: cmake . && make && CTEST_OUTPUT_ON_FAILURE=on make test colorized-logs-2.7/CMakeLists.txt000066400000000000000000000027411477165566600171110ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.1...3.25) project(colorized-logs C) include(CheckIncludeFiles) include(CheckLibraryExists) include(CheckFunctionExists) set (CMAKE_C_STANDARD 99) set (CMAKE_C_FLAGS "-Wall -Werror=format-security ${CMAKE_C_FLAGS}") CHECK_INCLUDE_FILES(pty.h HAVE_PTY_H) CHECK_INCLUDE_FILES(libutil.h HAVE_LIBUTIL_H) CHECK_INCLUDE_FILES(util.h HAVE_UTIL_H) CHECK_LIBRARY_EXISTS(util openpty "" HAVE_LIB_UTIL) if (HAVE_LIB_UTIL) set(CMAKE_REQUIRED_LIBRARIES util) endif (HAVE_LIB_UTIL) CHECK_FUNCTION_EXISTS(openpty HAVE_FUNC_OPENPTY) add_executable(ansi2html ansi2html.c) add_executable(ansi2txt ansi2txt.c) add_executable(ttyrec2ansi ttyrec2ansi.c) add_executable(pipetty pipetty.c signals.c) add_custom_target(lesstty ALL DEPENDS pipetty COMMAND ln -sf pipetty lesstty WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "LINK lesstty -> pipetty") set_target_properties(lesstty PROPERTIES ADDITIONAL_CLEAN_FILES lesstty) IF (HAVE_LIB_UTIL) set(LIB_UTIL util) ENDIF (HAVE_LIB_UTIL) target_link_libraries(pipetty ${LIB_UTIL}) configure_file(config.h.cmake ${CMAKE_BINARY_DIR}/config.h) include_directories(${CMAKE_BINARY_DIR}) install(TARGETS ansi2html ansi2txt ttyrec2ansi pipetty RUNTIME DESTINATION bin) install(FILES ${CMAKE_BINARY_DIR}/lesstty DESTINATION bin) install(FILES ansi2html.1 ansi2txt.1 ttyrec2ansi.1 pipetty.1 lesstty.1 DESTINATION share/man/man1 ) enable_testing() add_subdirectory(tests) colorized-logs-2.7/ChangeLog000066400000000000000000000013511477165566600161170ustar00rootroot000000000000002.7: * pipetty: pass terminal size (or 80×24) to the program being run * ansi2*: parse and ignore some more codes 2.6: * ansi2html: fix crash on invalid options * ansi2html: make OSC 8 hyperlinks clickable 2.5: * pipetty: write an obituary for child killed by a signal * lesstty: pipetty redirected to "less -R" 2.4: * ansi2html: -l (--no-wrap), --style, -c (--contrast) * allow testing installed binaries 2.3: * pipetty: hard-code PAGER=cat 2.2: * ttyrec2ansi: use cached stdio, for >4× speedup 2.1: * bugfix: infinite loop on 0xFF on unsigned-char architectures 2.0: * split out of KBtin * migrate from autotools to CMake * relicense to MIT * use a much darker palette in on-white mode, especially for brown and yellow colorized-logs-2.7/LICENSE000066400000000000000000000020001477165566600153420ustar00rootroot00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. colorized-logs-2.7/README000066400000000000000000000013741477165566600152320ustar00rootroot00000000000000============== colorized-logs ============== Here's a handful of tools for dealing with logs with ANSI color. Some tools like gcc, dmesg, grep --color, colordiff, ccze, etc can enhance their output with color, making reading a lot more pleasant. The difference can be as big as between slogging through twenty pages of a build log to find a failure, and a swift drag of the scroller to do the same within a second. Such colored logs can be usually viewed on a terminal or with "less -R"; this package gives you: * ansi2html: convert logs to HTML * ansi2txt: drop ANSI control codes * ttyrec2ansi: drop timing data from ttyrec files * pipetty: makes a program think its stdout and stderr are connected to a terminal; use as a prefix: "pipetty dmesg|tee" colorized-logs-2.7/ansi2html.1000066400000000000000000000041531477165566600163330ustar00rootroot00000000000000.TH ansi2html 1 2018-05-27 .SH NAME ansi2html \- ansi to HTML converter .SH SYNOPSIS .B ansi2html .RB [ -nwctl ] .BI < log .BI > outfile .SH DESCRIPTION .B ansi2html will convert the ANSI log into an HTML page, converting ANSI color codes into appropriate tags. All common colors and attributes are supported. .SH OPTIONS .TP .BR -n ", " --no-header Don't produce an HTML header. This allows including the log into a web page you make some other way. You are responsible for setting background color appropriately \(em to black or something dark in the default on-black mode, or to white/light when \fB-w\fR is used. Fancy-schmancy background images are fine as long as they are dark (or light) enough. .TP .BR -w ", " --white Make the background white. This is contrary to most terminals but matches most webpages. Text requested to be bolded (normally bright white) will be turned bold black, but explicit bright white \fIwill not\fR be changed, becoming invisible (just like explicit black is invisible in the normal on-black mode), same as on real terminals (see \fB-c\fR). .TP .BR -c ", " --contrast Forbid invisible text. Whenever foreground color is same as background, it'll be turned halfway across the color space (so white and black become gray). This is inaccurate wrt real terminals, and most web users already know how to mouse-highlight "spoiler" text, but can be useful if you process logs that assume different white-vs-black background than you. .TP .BR -t ", " --title " \fItext\fR" Set the page title to the next argument. Mutually exclusive with .BR -n . .TP .BR -l ", " --no-wrap Disable word-wrapping. Like text terminals, ansi2html wraps text by default, which is contrary to the usual browser default for plain text. .TP .BR --style " \fItext\fR" Injects some text into the stylesheet, obviously doesn't make any sense with .BR -n . Example: .I --style 'pre {font-family: Consolas}' .SH CAVEATS Most ANSI codes other than color codes are ignored; possibly causing misformatted output. In general, anything unfit for a hardcopy terminal won't work. .SH "SEE ALSO" .BR ansi2txt (1), .BR ttyrec2ansi (1), .BR pipetty (1). colorized-logs-2.7/ansi2html.c000066400000000000000000000404331477165566600164160ustar00rootroot00000000000000#include #include #include #include #define BOLD 0x010000 #define DIM 0x020000 #define ITALIC 0x040000 #define UNDERLINE 0x080000 #define BLINK 0x100000 #define INVERSE 0x200000 #define STRIKE 0x400000 static bool no_header=false, white=false, contrast=false, no_wrap=false, in_span; static bool in_hyperlink=false; static int fg, bg, fl, frgb, brgb; static const char *title=0; static char *style=0; static const char *cols[]={"BLK","RED","GRN","YEL","BLU","MAG","CYN","WHI", "HIK","HIR","HIG","HIY","HIB","HIM","HIC","HIW"}; typedef unsigned char u8; static int rgb_from_256(int i) { if (i < 16) { // Standard colours. if (white) { if (i == 3) return 0x806000; if (i == 3+8) return 0xcccc00; int c = (i&1 ? 0x010000 : 0x000000) | (i&2 ? 0x000100 : 0x000000) | (i&4 ? 0x000001 : 0x000000); return i<8 ? c*0x80 : c*0xff; } if (i == 3) return 0xaa5500; int c = (i&1 ? 0xaa0000 : 0x000000) | (i&2 ? 0x00aa00 : 0x000000) | (i&4 ? 0x0000aa : 0x000000); return i<8 ? c : c+0x555555; } else if (i < 232) { // 6x6x6 colour cube. i-=16; int r = i / 36, g = i / 6 % 6, b = i % 6; return (r ? r * 0x280000 + 0x370000 : 0) | (g ? g * 0x002800 + 0x003700 : 0) | (b ? b * 0x000028 + 0x000037 : 0); } else// Grayscale ramp. return i*0xa0a0a-((232*10-8)*0x10101); } static inline int rgb_to_int(u8 r, u8 g, u8 b) { return (int)r<<16|(int)g<<8|(int)b; } static int get_frgb(int fg) { return fg==-1?white?0x000000:0xaaaaaa:rgb_from_256(fg); } static int get_brgb(int bg) { return bg==-1?white?0xaaaaaa:0x000000:rgb_from_256(bg); } static void span(void) { int tmp, _fg=fg, _bg=bg, _frgb=frgb, _brgb=brgb; char clbuf[32], *cl=clbuf; if (fg==-1 && bg==-1 && frgb==-1 && brgb==-1 && !fl) return; if (fl&INVERSE) { if (_fg==-1) _fg=white?0:7; if (_bg==-1) _bg=white?7:0; tmp=_fg; _fg=_bg; _bg=tmp; tmp=_frgb; _frgb=_brgb; _brgb=tmp; } if (fl&BLINK) { if (_frgb==-1) _frgb=get_frgb(_fg); _frgb=rgb_to_int((_frgb>>16&0xff)*3/4, (_frgb>> 8&0xff)*3/4, (_frgb &0xff)*3/4)+0x606060; if (_brgb==-1) _brgb=get_brgb(_bg); _brgb=rgb_to_int((_brgb>>16&0xff)*3/4, (_brgb>> 8&0xff)*3/4, (_brgb &0xff)*3/4)+0x606060; } if (fl&DIM) _fg=8; if (contrast && (_frgb==-1?get_frgb(_fg):_frgb)==(_brgb==-1?get_brgb(_bg):_brgb)) { if (_frgb==-1) _frgb=get_frgb(_fg); _frgb^=0x808080; } if (no_header) goto do_span; printf(" helps Braille and speech readers. if (_fg!=-1) { if (fl&BOLD) _fg|=8; cl+=sprintf(cl, " %s", cols[_fg]); } else if (fl&BOLD) cl+=sprintf(cl, " BOLD"); if (_bg!=-1) cl+=sprintf(cl, " B%s", cols[_bg]); if (fl&ITALIC) cl+=sprintf(cl, " ITA"); if (fl&UNDERLINE) cl+=sprintf(cl, (fl&STRIKE)?" UNDSTR":" UND"); else if (fl&STRIKE) cl+=sprintf(cl, " STR"); if (cl>clbuf) { *cl=0; if (cl>=clbuf+5) printf(" class=\"%s\"", clbuf+1); else // implies no spaces printf(" class=%s", clbuf+1); } if (_frgb!=-1 || _brgb!=-1) { printf(" style=\""); if (_frgb!=-1) printf("color:#%06x;", _frgb); if (_brgb!=-1) printf("background-color:#%06x", _brgb); printf("\""); } printf(">"); in_span=1; return; do_span: printf(""); in_span=1; } static void unspan(void) { if (in_span) printf(no_header?"":""); in_span=0; } static void print_string(const char *restrict str) { for (; *str; str++) switch (*str) { case '<': printf("<"); break; case '>': printf(">"); break; case '&': printf("&"); break; default: putchar(*str); } } // return value is pending ch static int osc(void) { int ch=getchar(); if (ch<'0'||ch>'9') /* not an OSC, don't try to parse */ return ch; int cmd=0; while (ch>='0' && ch<='9') { cmd=cmd*10 + ch-'0'; ch=getchar(); } if (ch==';') ch=getchar(); else cmd=-1; // not a well-formed OSC char str[4096], *ps=str; for (;;ch=getchar()) switch (ch) { case 27: ch=getchar(); // if not ST, ESC is illegal here if (ch!='\\') goto abort; // fallthru case 7: ch=getchar(); // BELL is the alternate terminator *ps=0; goto ok; default: if (ps < str+sizeof(str)-1) { *ps++=ch; break; } // fallthru case EOF: abort: *ps=0; print_string(str); return ch; } ok: if (cmd!=8) // hyperlink return ch; unspan(); if (in_hyperlink) printf(""), in_hyperlink=0; // only the first semicolon (after cmd number) is mandatory when closing ps=strchr(str, ';'); if (!ps) return ch; if (*ps) ps++; if (ps[strcspn(ps, "\"<>")]) return ch; if (!*ps) return ch; printf("", ps); in_hyperlink=1; return ch; } #define DIE(msg) return fprintf(stderr, "%s: " msg, argv[0]), 1; int main(int argc, char **argv) { while (1) { static const struct option long_options[] = { {"no-header", 0, 0, 'n'}, {"white", 0, 0, 'w'}, {"contrast", 0, 0, 'c'}, {"title", 1, 0, 't'}, {"no-wrap", 0, 0, 'l'}, {"style", 1, 0, -257}, {0, 0, 0, 0} }; int c = getopt_long(argc, argv, "-nwt:lc", long_options, 0); if (c == -1) break; switch (c) { case 'n': no_header=true; break; case 'w': white=true; break; case 'c': contrast=true; break; case 't': if (title) DIE("title was already given.\n"); title=optarg; break; case 'l': no_wrap=true; break; case -257: if (style) DIE("style was already given.\n"); style=optarg; break; case '?': return 1; case 1: DIE("this program works as a filter, please pipe the input in instead.\n"); } } if (no_header) { if (title || style) DIE("--no-header forbids --title and --style.\n"); printf( "
",
                white?"000":"bbb",
                no_wrap?"":";white-space:pre-wrap;word-wrap:break-word;overflow-wrap:break-word");
    }
    else
    {
        printf(
"\n"
"\n"
"\n");
        if (title)
        {
            printf("");
            print_string(title);
            printf("\n");
        }
        printf(
"\n"
"\n"
"\n"
"
");
    }

    fg=bg=-1;
    fl=0;
    in_span=false;
    frgb=brgb=-1;
    int ch=getchar();
    unsigned int ntok, tok[16];
normal:
    switch (ch)
    {
    case EOF:
        unspan();
        printf("
\n"); if (!no_header) printf("\n\n"); return 0; case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 11: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 28: case 29: case 30: case 31: printf("$%02X;", ch);// → ␀␁␂␃␄␅␆ ␋ ␎␏ ␐␑␒␓␔␕␖␗ ␘␙␚ ␜␝␞␟ ch=getchar(); goto normal; case 7: // bell printf("♪"); // → ♪ ch=getchar(); goto normal; case 8: // backspace printf("⌫"); // → ⌫ ch=getchar(); goto normal; case 12: // form feed formfeed: ch=getchar(); unspan(); printf("\n
\n"); goto normal; case 13: // \r ch=getchar(); // → ↵ unspan(); if (ch!=10) printf("↵\n"); goto normal; case 27: // ESC ch=getchar(); goto esc; case '<': printf("<"); ch=getchar(); goto normal; case '>': printf(">"); ch=getchar(); goto normal; case '&': printf("&"); ch=getchar(); goto normal; case 127: // delete printf("⌦"); // → ⌦ ch=getchar(); goto normal; case 10: // newline if (in_hyperlink) { unspan(); printf("
"); in_hyperlink=0; } // fallthru default: putchar(ch); ch=getchar(); goto normal; } /****************************************************************************/ esc: switch (ch) { case '[': break; case ']': ch=osc(); goto normal; case '%': case '(': case ')': ch=getchar(); // fallthru default: ch=getchar(); goto normal; } /* [ */ ch=getchar(); ntok=0; tok[0]=0; /****************************************************************************/ csi: switch (ch) { case '?': ch=getchar(); goto csiopt; case ';': if (++ntok>=sizeof(tok)/sizeof(tok[0])) goto normal; // too many tokens, something is fishy tok[ntok]=0; ch=getchar(); goto csi; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': tok[ntok]=tok[ntok]*10+ch-'0'; ch=getchar(); goto csi; case 'm': for (unsigned int i=0;i<=ntok;i++) switch (tok[i]) { case 0: fg=bg=-1; fl=0; frgb=brgb=-1; break; case 1: fl|=BOLD; fl&=~DIM; break; case 2: fl|=DIM; fl&=~BOLD; break; case 3: fl|=ITALIC; break; case 4: fl|=UNDERLINE; break; case 5: fl|=BLINK; break; case 7: fl|=INVERSE; break; case 9: fl|=STRIKE; break; case 21: case 22: fl&=~(BOLD|DIM); break; case 23: fl&=~ITALIC; break; case 24: fl&=~UNDERLINE; break; case 25: fl&=~BLINK; break; case 27: fl&=~INVERSE; break; case 29: fl&=~STRIKE; break; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: fg=tok[i]-30; frgb=-1; break; case 38: i++; if (i>ntok) break; if (tok[i]==5 && intok) break; if (tok[i]==5 && i512) // sanity ntok=512; for (unsigned int i=0;i='0'&&ch<='9')) { ch=getchar(); goto csiopt; } ch=getchar(); goto normal; } colorized-logs-2.7/ansi2txt.1000066400000000000000000000011761477165566600162100ustar00rootroot00000000000000.TH ansi2txt 1 2002-09-02 .SH NAME ansi2txt \- ansi to plain text converter .SH SYNOPSIS .B ansi2txt < .I log > .I outfile .SH DESCRIPTION .B ansi2txt can be used to convert text containing ANSI color codes (such as MUD logs, text processed by syntax highlighters, colorgcc, colordiff, ccze, loco, etc) into plain ASCII text. It works as a filter, reading from stdin, removing all ANSI codes and sending the output to stdout. .SH CAVEATS All ANSI codes are simply ignored, including all cursor positioning ones. Sometimes this is what you want, sometimes it isn't. .SH "SEE ALSO" .BR ansi2html (1), .BR ttyrec2ansi (1), .BR pipetty (1). colorized-logs-2.7/ansi2txt.c000066400000000000000000000014641477165566600162720ustar00rootroot00000000000000#include int main() { int ch; do { ch=getchar(); while (ch==13) if ((ch=getchar())!=10) putchar(13); /* suppress \r only when followed by \n */ if (ch==27) if ((ch=getchar())=='[') while ((ch=getchar())==';'||(ch>='0'&&ch<='9')||ch=='?'); else if (ch==']'&&(ch=getchar())>=0&&ch<='9') for (;;) { if ((ch=getchar())==EOF||ch==7) break; else if (ch==27) {ch=getchar(); break;} } else if (ch=='%'||ch=='('||ch==')') ch=getchar(); else {} else if (ch!=EOF) putchar(ch); } while (ch!=EOF); return 0; } colorized-logs-2.7/config.h.cmake000066400000000000000000000001701477165566600170400ustar00rootroot00000000000000#ifndef CONFIG_H #define CONFIG_H #cmakedefine HAVE_PTY_H #cmakedefine HAVE_LIBUTIL_H #cmakedefine HAVE_UTIL_H #endif colorized-logs-2.7/lesstty.1000066400000000000000000000007231477165566600161400ustar00rootroot00000000000000.TH lesstty 1 2017-10-09 .SH NAME lesstty \- execute a program redirecting its output to a color-capable pager .SH SYNOPSIS .B lesstty .I command [ .I args...\& ] .SH DESCRIPTION .B lesstty runs a program that ordinarily behaves differently when its output is redirected, and sends it output to .B less -R for viewing. .P This is merely a shorthand for .I pipetty command | less -R that passes errors from \fIcommand\fR. .SH "SEE ALSO" .BR pipetty (1), .BR less (1). colorized-logs-2.7/pipetty.1000066400000000000000000000014361477165566600161310ustar00rootroot00000000000000.TH pipetty 1 2016-06-25 .SH NAME pipetty \- a tool to pipe from a pseudoterminal .SH SYNOPSIS .B pipetty .I command [ .I args...\& ] .SH DESCRIPTION .B pipetty lets you make a program unaware that its output is being redirected. This is usually useful for tools that detect whether they're run from a terminal and modify their output, typically colorizing it only when run interactively. .P Usually, disabling colors when redirected is a good thing as most tools can't cope with ANSI codes. Use .B pipetty when you do want colors, like when you're going to feed that output to .B ansi2html or .BR "less -R" . .SH CAVEATS Certain programs, such as .BR bash , don't quite like their stdin to be on a different terminal than stdout. .SH "SEE ALSO" .BR ansi2html (1), .BR ansi2txt (1), .BR less (1). colorized-logs-2.7/pipetty.c000066400000000000000000000057051477165566600162160ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include "config.h" #ifdef HAVE_PTY_H # include #endif #ifdef HAVE_LIBUTIL_H # include #endif #ifdef HAVE_UTIL_H # include #endif extern void sigobit(int ret); #define PN "pipetty" void syserr(const char *msg, ...) { int err=errno; va_list ap; fprintf(stderr, PN ": "); va_start(ap, msg); vfprintf(stderr, msg, ap); va_end(ap); if (err) fprintf(stderr, ": %s", strerror(err)); fprintf(stderr, "\n"); exit(1); } static int basename_is(const char *proc, const char *name) { int plen = strlen(proc); int nlen = strlen(name); if (plen==nlen && !memcmp(proc, name, nlen)) return 1; if (plen>nlen && proc[plen-nlen-1]=='/' && !memcmp(proc+plen-nlen, name, nlen)) return 1; return 0; } int main(int argc, const char **argv) { if (argc<2) errno=0, syserr("missing command"); int less = basename_is(argv[0], "lesstty"); struct winsize ws = {}; if (less) { if (ioctl(0, TIOCGWINSZ, &ws) && ioctl(1, TIOCGWINSZ, &ws)) ws.ws_row=24, ws.ws_col=80; } int master, slave; if (openpty(&master, &slave, 0, 0/*termios*/, less? &ws : 0)) syserr("can't allocate a pseudo-terminal"); if (master>31) errno=0, syserr("bad fd from openpty(): %d", master); struct termios ti; if (!tcgetattr(slave, &ti)) { cfmakeraw(&ti); tcsetattr(slave, TCSANOW, &ti); } int pid=fork(); if (pid==-1) syserr("fork failed"); if (!pid) { putenv("PAGER=cat"); close(master); setsid(); dup2(slave, 1); dup2(slave, 2); close(slave); int zero=0; ioctl(1, TIOCSCTTY, &zero); execvp(argv[1], (char*const*)argv+1); syserr("%s", argv[1]); return 127; } close(slave); if (less) { int p[2]; if (pipe(p)) syserr("pipe failed"); less=fork(); if (less==-1) syserr("fork failed"); if (!less) { close(p[1]); dup2(p[0], 0); close(p[0]); execlp("less", "less", "-R", "-", NULL); syserr("can't run less"); return 127; } close(p[0]); dup2(p[1], 1); close(p[1]); } char buf[16384]; int r; while ((r=read(master, buf, sizeof(buf)))>0) { if (write(1, buf, r)!=r) syserr("error writing to stdout"); } close(master); int ret; if (waitpid(pid, &ret, 0)==-1) syserr("waitpid failed"); if (WIFSIGNALED(ret)) sigobit(ret); if (less) { close(1); waitpid(less, 0, 0); } return WIFEXITED(ret)?WEXITSTATUS(ret):WTERMSIG(ret)+128; } colorized-logs-2.7/signals.c000066400000000000000000000030371477165566600161540ustar00rootroot00000000000000#include #include #include static const char* sigobits[NSIG]= { [SIGHUP] = "Hangup", [SIGINT] = "Interrupt", [SIGQUIT] = "Quit", [SIGILL] = "Illegal instruction", [SIGTRAP] = "Breakpoint trap", [SIGABRT] = "Aborted", [SIGBUS] = "Bus error", [SIGFPE] = "Floating point exception", [SIGKILL] = "Killed", [SIGUSR1] = "User signal 1", [SIGSEGV] = "Segmentation fault", [SIGUSR2] = "User signal 2", [SIGPIPE] = "Broken pipe", [SIGALRM] = "Alarm clock", [SIGTERM] = "Terminated", #ifdef SIGSTKFLT [SIGSTKFLT] = "Stack fault on coprocessor", #endif [SIGCHLD] = "Child died", [SIGCONT] = "Continue", [SIGSTOP] = "Stopped", [SIGTSTP] = "Stop request on terminal", [SIGTTIN] = "Stopped on tty input", [SIGTTOU] = "Stopped on tty output", [SIGURG] = "Urgent condition on socket", [SIGXCPU] = "CPU limit exceeded", [SIGXFSZ] = "File size limit exceeded", [SIGVTALRM] = "Virtual alarm clock", [SIGPROF] = "Profiler timer expired", [SIGWINCH] = "Window size changed", [SIGIO] = "I/O ready", #ifdef SIGPWR [SIGPWR] = "Power loss", #endif [SIGSYS] = "Bad system call", }; void sigobit(int ret) { int core = WCOREDUMP(ret); int s = WTERMSIG(ret); if (s>0 && s; s|.*.*||s; s,\n
\n,\f,sg; s,<(?:[^>"]|"[^"]*")*>,,g; s,¡,\a,g; s,<,<,g; s,>,>,g; s,&,&,g; print; colorized-logs-2.7/tests/testsuite000077500000000000000000000052601477165566600174710ustar00rootroot00000000000000#!/usr/bin/env perl use warnings; print "Running tests...\n" unless @ARGV; undef $/; my $DATADIR = $0; $DATADIR=~s|testsuite$||; $DATADIR//='.'; my $BINDIR = $ENV{'BINDIR'}//'.'; -x "$DATADIR/unescape" or $DATADIR="$DATADIR/tests"; -x "$DATADIR/unescape" or die "unescape missing from $DATADIR?\n"; -x "$BINDIR/ansi2html" or $BINDIR="$BINDIR/.."; -x "$BINDIR/ansi2html" or die "ansi2html not yet built in $BINDIR?\n"; my $id = $$; my ($pass,$fail) = (0,0); sub test($$$$;$) { my ($name, $cmd, $stdin, $stdout, $expret) = @_; $expret //= 0; return if @ARGV && !grep { $name eq $_ } @ARGV; printf '* %-20s ', $name unless @ARGV; open I, '>', "stdin.$id" or die "Can't write to \"stdin.$id\": $!\n"; print I $stdin; close I; open O, '>', "expout.$id" or die "Can't write to \"expout.$id\": $!\n"; print O $stdout; close O; my $pid = fork; unless ($pid) { alarm 20; open STDIN, '<', "stdin.$id" or die "Can't dup stdin: $!\n"; open STDOUT, '>', "stdout.$id" or die "Can't dup stdout: $!\n"; open STDERR, '>', "stderr.$id" or die "Can't dup stderr: $!\n"; exec $cmd; die "Couldn't exec: $!\n"; } waitpid $pid, 0; my $ret = $?; my $bad = system "cmp -s stdout.$id expout.$id" || system "cmp -s stderr.$id /dev/null"; if (($ret != $expret) || $bad) { $fail++; print "\e[31mFAIL\e[0m\n" unless @ARGV; system "cat stderr.$id"; system "diff -u expout.$id stdout.$id"; print "return value: $ret\n" if ($ret != $expret); } else { $pass++; print "\e[32mok\e[0m\n" unless @ARGV; } unlink "$_.$id" for qw(stdin expout stdout stderr); } test('ansi2txt', "$DATADIR/unescape|$BINDIR/ansi2txt", <<'IN', <<'OUT'); foo\e[1mbar\e[0m\n \e[?2004l \e]0;title1\e\\ \e]4;16;rgb:0/0/0\e\\ \e]0;title2\a \n IN foobar OUT test('ansi2html', "$DATADIR/unescape|$BINDIR/ansi2html|$DATADIR/htmlpre2txt", <<'IN', <<"OUT"); foo\e[1mbar\e[0m\n \e[?2004l \e]0;title1\e\\ \e]4;16;rgb:0/0/0\e\\ \e]0;title2\a \n \f\n \xff\n IN foobar \f \xff OUT test('pipetty', "$BINDIR/pipetty &1", <<'IN', <<'OUT', 0x8f00); PID=$$ (kill $PID) & sleep 10 IN Terminated OUT test('ttyrec2ansi', "$DATADIR/unescape|$BINDIR/ttyrec2ansi", <<'IN', <<'OUT'); aaaa10\a\0\b\0\0\0foo bar\n aaaa10\b\0\b\0\0\0baz qux\n IN foo bar baz qux OUT print "Passed: $pass, failed: $fail.\n" unless @ARGV; exit($fail>0); colorized-logs-2.7/tests/unescape000077500000000000000000000003731477165566600172430ustar00rootroot00000000000000#!/usr/bin/env perl use warnings; while(<>) { chomp; s/^#.*//; s/\\b/\b/g; s/\\n/\n/g; s/\\e/\e/g; s/\\a/\a/g; s/\\f/\f/g; s/\\0/\0/g; s/\\x([0-9a-fA-F]{2})/sprintf('%c',hex "$1")/ge; s/\\\\/\\/g; print; } colorized-logs-2.7/ttyrec2ansi.1000066400000000000000000000006611477165566600167010ustar00rootroot00000000000000.TH ttyrec2ansi 1 2005-03-21 .SH NAME ttyrec2ansi \- ttyrec to ansi converter .SH SYNOPSIS .B ttyrec2ansi < .I log.ttyrec > .I outfile .SH DESCRIPTION .B ttyrec2ansi will strip the timing information from .ttyrec files, retaining all ANSI codes. You can then convert them to plain text using .B ansi2txt or, if they contain nothing but color codes, to HTML using .B ansi2html \&. .SH "SEE ALSO" .BR ansi2txt (1), .BR ansi2html (1). colorized-logs-2.7/ttyrec2ansi.c000066400000000000000000000027521477165566600167660ustar00rootroot00000000000000#include #include #include #include #include #include #include #ifdef __ANDROID__ #include #endif #ifdef __sun # include # define LITTLE_ENDIAN 1234 # define BIG_ENDIAN 4321 # ifdef _LITTLE_ENDIAN # define BYTE_ORDER LITTLE_ENDIAN # else # define BYTE_ORDER BIG_ENDIAN # endif #endif #ifndef htole32 #if BYTE_ORDER == LITTLE_ENDIAN #define htole32(x) (x) #else #if BYTE_ORDER == BIG_ENDIAN #define htole32(x) \ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) #else #error No endianness given. #endif #endif #endif struct ttyrec_header { uint32_t sec; uint32_t usec; uint32_t len; }; #define BUFFER_SIZE 4096 int main() { struct ttyrec_header th; char buf[BUFFER_SIZE]; int s, n, r; while (1) { if (fread(&th, 1, 12, stdin)!=12) return 0; n=htole32(th.len); while (n>0) { s=(n>BUFFER_SIZE)?BUFFER_SIZE:n; if ((r=fread(buf, 1, s, stdin))<=0) { fprintf(stderr, "%s\n", r?strerror(errno):"File was truncated"); return 1; } if ((ssize_t)fwrite(buf, 1, r, stdout)!=r) { fprintf(stderr, "Write error\n"); return 1; } n-=r; } } return 0; }