#! /usr/bin/env bash

function usage
{
cat <<EOF

`basename $0` [options] <columns>

Extracts the given columns from an ASCII Bro log on standard input.
Currently, only tab-separated logs are supported. By default,
the format header is not included into the output.

Example: cat conn.log | `basename $0` -d ts id.orig_h id.orig_p

    -h   Include the first format header into the output.
    -H   Include all format headers into the output.
    -d   Convert time values into humand-readable format (needs gawk)

EOF
    exit 1
}

headers=0
fmttime=0
awk=awk

which gawk >/dev/null && awk=gawk

while getopts "hHd" opt; do
    case "$opt" in
        h) headers=1;;
        H) headers=2;;
        d) fmttime=1;;
        *) usage;;
    esac
done

if [ "$fmttime" == 1 -a "$awk" != "gawk" ]; then
    echo "option -d only supported with gawk" >&2
    exit 1
fi

shift $(($OPTIND - 1))
fields=`echo $@ | sed 's/[ ,] */:/g'`

$awk -v fields=$fields -v headers=$headers -v fmttime=$fmttime '

function print_header() {
    return headers == 2 || (headers == 1 && first_header);
}

function error(msg) {
    print msg >"/dev/stderr";
    exit(1);
}

BEGIN {
    FS="\t";
    OFS="\t";
    first_header = 1;
    split(fields, f, /:/);
    for ( i = 1; i <= length(f); ++i )
        idx[f[i]] = i;
}

/^#separator \\x09/ {
    next;
}

/^#separator/ {
    error("bro-cut supports only tab-separated logs currently.");
}

/^#fields/ {
    for ( i = 2; i <= NF; ++i ) {
        if ( $i in idx )
            columns[idx[$i]] = i-1;
        }

    for ( i = 1; i <= length(f); ++i ) {
        if ( columns[idx[f[i]]] == "" )
            error("unknown field "  f[i]);
    }
}

/^#types/ {
    for ( i = 2; i <= NF; ++i )
        times[i-1] = ($i == "time");
}

/^#(fields|types)/ && print_header() {
    printf("%s", $1);
    for ( i = 1; i <= length(columns); ++i ) {
        val = $(int(columns[i]) + 1);

        if ( $1 == "#types" && fmttime && times[i] == "1" )
            val = "string";

        printf("\t%s", val);
        }

    print "";
    next;
}

/^#/ {
    if ( print_header() )
        print;

    next;
}

{
    first_header = 0;

    for ( i = 1; i <= length(columns); ++i ) {
        j = int(columns[i])
        val = $j

        if ( fmttime && times[j] == "1" )
            val = strftime(PROCINFO["strftime"], val);

        if ( i > 1 )
            printf("\t%s", val);
        else
            printf("%s", val);
        }

    print "";
}
'
