#!/bin/sh # # Script for using ViM as a PAGER. # Based on Bram's less.sh. # git://github.com/rkitover/vimpager.git version_tag=2.06 # Just pass through if not on a tty if [ ! -t 1 ]; then exec cat "$@" fi # FIND REAL PARENT DIRECTORY link=$0 while [ -h "$link" ]; do ls0=`ls -l "$link"` new_link=`expr "$ls0" : '.* -> \(.*\)$'` if expr "$new_link" : '/.*' > /dev/null; then link="$new_link" else link=`dirname "$link"`/"$new_link" fi done project_dir=`dirname "$link"` # END OF FIND REAL PARENT DIRECTORY . "$project_dir/inc/prologue.sh" [ -n "$ZSH_VERSION" ] && emulate -R sh 2>/dev/null # force zsh into full POSIX version="$(cd "$project_dir" && git describe 2>/dev/null) (git)" || version="$version_tag (checkout)" runtime='$project_dir' vimcat='$project_dir/vimcat' system_vimpagerrc='$project_dir/vimpagerrc' case "$(uname -s)" in Linux) linux=1 ;; SunOS) solaris=1 ;; Darwin) osx=1; bsd=1 ;; CYGWIN*) cygwin=1; win32=1 ;; MINGW*) msys=1; win32=1 ;; MSYS*) msys=1; win32=1 ;; OpenBSD) openbsd=1; bsd=1 ;; FreeBSD) freebsd=1; bsd=1 ;; NetBSD) netbsd=1; bsd=1 ;; *) bsd=1 ;; esac main() { # if no args and no stdin, display usage if [ $# -eq 0 -a -t 0 ]; then usage quit 0 fi # Parse the command line options as early as possible. These variables might be set because of command line options and are thus initialized. vim_options= vimrc= extra_c= extra_cmd= line_numbers=0 no_pass_thru= tail=0 # Check for certain parameters to pass on to vim (or conceivably do something else) # Couldn't use getopt or getopts as neither supports options prepended with + while [ $# -gt 0 ] ; do case "$1" in -h|--help|-help|--usage|-usage) usage quit 0 ;; -v|--version|-version) echo "vimpager $version" quit 0 ;; +G|+) vim_options="$vim_options +" shift ;; +F) tail=1 shift ;; -N|--LINE-NUMBERS) line_numbers=1 shift ;; -c) shift extra_c="${extra_c:+$extra_c | }$1" shift ;; --cmd) shift extra_cmd="${extra_cmd:+$extra_cmd | }$1" shift ;; -u) shift vimrc=$1 shift ;; -s) # Ubuntu man passes this option to /usr/bin/pager shift squeeze_blank_lines=1 ;; --passthrough) shift no_pass_thru=0 ;; --force-passthrough) shift no_pass_thru=0 cat_files=1 ;; --no-passthrough) shift no_pass_thru=1 ;; --) shift break ;; -x) trace=1 shift set -x ;; -) break ;; -*) echo "$0: bad option '$1', see --help for usage." >&2 quit 1 ;; *) break ;; esac done if [ $tail -eq 1 ]; then no_pass_thru=1 fi find_tmp_directory trap "quit 1" PIPE HUP INT QUIT ILL TRAP KILL BUS TERM detect_term_size expand_config_vars find_vim_executable find_vimpagerrc_files read_vim_settings parse_pstree # if no args, assume stdin if [ $# -eq 0 ]; then set -- - # turn off man/perldoc support for > 1 arg elif [ $# -gt 1 ]; then is_man= is_perldoc= is_doc= force_strip_ansi= fi file_idx=1 for file in "$@"; do if [ "$file" = - ]; then filename=stdin else if [ -d "$file" ]; then echo "$0: '$file' is a directory" >&2 quit 1 fi if [ ! -r "$file" ]; then echo "$0: cannot read file '$file'" >&2 quit 1 fi filename=$(resolve_path "$file") fi set_key orig_file_names $file_idx "$filename" # $file still holds the orginal file name. $filename will be # the encoded version of $file. $tempfile is the path under # $tmp if the file is to be opend from there instead of the # original location. If $tempfile is empty the file is to be # opened as $file. filename=$(encode_filename "$filename") tempfile= case "$(echo "$file" | tr 'A-Z' 'a-z')" in *.gz) filename=${filename%.??} tempfile=$tmp/$filename gunzip -c -- "$file" > "$tempfile" ;; *.bz2) filename=${filename%.??2} tempfile=$tmp/$filename bunzip2 -c -- "$file" > "$tempfile" ;; *.xz) filename=${filename%.??} tempfile=$tmp/$filename xzcat -c -- "$file" > "$tempfile" ;; *.z) filename=${filename%.?} tempfile=$tmp/$filename uncompress -c -- "$file" > "$tempfile" ;; *) if [ "$file" = - ]; then tempfile=$tmp/$filename cat -- "$file" > "$tempfile" fi ;; esac # check for ANSI codes and strip if not using ansiesc # don't use ansiesc if file is too big, or it hangs if head -100 "${tempfile:-$file}" | grep -Eq "$ANSI_RE"; then if [ -z "$ansiesc_available" ] || [ -n "$force_strip_ansi" ] || [ "$(wc -l "${tempfile:-$file}" | awk '{print $1}')" -ge 1250 ]; then ansi_filter "${tempfile:-$file}" > "$tmp/$filename.work" tempfile=$tmp/$filename mv -f -- "$tempfile.work" "$tempfile" else echo 'call vimpager_utils#DoAnsiEsc()' >> "$tmp/$file_idx.vim" set_key ansi_files "$file_idx" yes fi fi # squeeze blank lines if option was specified, Ubuntu man with /usr/bin/pager does this if [ "${squeeze_blank_lines:-0}" -eq 1 ]; then sed -e '/^[ ]*$/{ N /^[ ]*\n[ ]*$/D }' < "${tempfile:-$file}" > "$tmp/$filename.work" tempfile=$tmp/$filename mv -f -- "$tempfile.work" "$tempfile" fi if [ -z "$is_doc" ]; then # Dumb man detection when the pstree heuristic fails. if head -12 "${tempfile:-$file}" | grep -Eq '^N(.)?A(.)?M(.)?E(.)?[ \t]*$'; then is_man=1 is_doc=1 # Detect python docs. elif head -1 "${tempfile:-$file}" | grep -Eq '^Help on .+:$'; then is_man=1 is_doc=1 fi fi # if it's a man page, remove starting blank lines, or the C syntax highlighting fails # and write out ft command for vim if [ -n "$is_doc" ]; then ansi_filter "${tempfile:-$file}" | overstrike_filter | awk ' BEGIN { skipblank=1 } /^[ ]*$/ { if (!skipblank) print } /[^ ]/ { skipblank=0; print } ' > "$tmp/$filename.work" tempfile=$tmp/$filename mv -f -- "$tempfile.work" "$tempfile" if [ -n "$is_man" ]; then echo 'set ft=man' >> "$tmp/$file_idx.vim" elif [ -n "$is_perldoc" ]; then echo 'set ft=perldoc' >> "$tmp/$file_idx.vim" fi fi # if file is zero length, or one blank line (cygwin), and is only arg, exit if [ ! -s "${tempfile:-$file}" \ -a $# -eq 1 \ -o "$(cat "${tempfile:-$file}")" = "" \ -a "$(wc -l < "${tempfile:-$file}")" -eq 1 ]; then quit 0 fi set_key files $file_idx "$(resolve_path "${tempfile:-$file}")" file_idx=$((file_idx + 1)) done file_count=$# set -- i=1 while [ $i -le $file_count ]; do set -- "$@" "$(get_key files $i)" i=$((i + 1)) done if [ "${no_pass_thru:-0}" -ne 1 ] && fits_on_screen "$@"; then cat_files=1 fi page_files "$@" quit $? } find_tmp_directory() { # Find and create the temporary directory used by vimpager. Set the $tmp variable. mkdir_options="-m 700" if [ -n "$win32" ]; then # Use the real TEMP directory on windows in case we are # using a native vim/gvim # TEMP can be /tmp sometimes too tmp=$(resolve_path "$TEMP") # chmod doesn't work here, even in /tmp sometimes mkdir_options= else # ... and /tmp otherwise tmp=${TMPDIR:-/tmp} fi # Create a safe directory in which we place all other tempfiles. tmp=$tmp/vimpager_$$ if ! mkdir $mkdir_options "$tmp"; then echo "ERROR: Could not create temporary directory $tmp" >&2 quit 1 fi } detect_term_size() { # Detect the terminal size and set the variables $cols and $lines. If necessary $no_pass_thru is set. if command -v tput >/dev/null; then # this is the only way it works on some versions of Cygwin # 2>/dev/null makes tput not work, so don't do that # we are just going to hope that tput errors don't happen tput cols "$tmp/cols" tput lines "$tmp/lines" cols=$(cat "$tmp/cols") lines=$(cat "$tmp/lines") rm -f -- "$tmp/cols" "$tmp/lines" fi # this often works if tput is not available, on msys as well if [ -z "$lines" ] && command -v bash >/dev/null; then cols=$(bash -O checkwinsize -i -c 'echo $COLUMNS' &1 >/dev/null); do case "$var" in VAL:*) case $i in 1) vim_dir=${var#VAL:} ;; 2) user_vimrc=${var#VAL:} user_vimrc_dir=${user_vimrc%/*} break ;; esac i=$((i + 1)) ;; esac done IFS=$OLDIFS # find system vimrc system_vimrc=$("$tvim" --version | sed -n '/system vimrc file: "/{ s|\$VIM|'"$vim_dir"'| s/.*: "\([^"]*\).*/\1/p q }') # find the users vimpagerrc if [ -n "$vimrc" ]; then # The vimrc file was given on the command line. : elif [ -n "$VIMPAGER_RC" ]; then vimrc=$VIMPAGER_RC # check for vimpagerrc in same dir as vimrc in case it is set in VIMINIT elif [ -n "$user_vimrc_dir" -a -r "$user_vimrc_dir/.vimpagerrc" ]; then vimrc=$user_vimrc_dir/.vimpagerrc elif [ -n "$user_vimrc_dir" -a -r "$user_vimrc_dir/_vimpagerrc" ]; then vimrc=$user_vimrc_dir/_vimpagerrc elif [ -n "$user_vimrc_dir" -a -r "$user_vimrc_dir/vimpagerrc" ]; then vimrc=$user_vimrc_dir/vimpagerrc # check standard paths, according to :h initialization elif [ -r ~/.vimpagerrc ]; then vimrc=~/.vimpagerrc elif [ -r ~/.vim/vimpagerrc ]; then vimrc=~/.vim/vimpagerrc elif [ -r ~/_vimpagerrc ]; then vimrc=~/_vimpagerrc elif [ -r ~/vimfiles/vimpagerrc ]; then vimrc=~/vimfiles/vimpagerrc elif [ -r "$vim_dir/_vimpagerrc" ]; then vimrc=$vim_dir/_vimpagerrc # try the user's ~/.vimrc elif [ -n "$user_vimrc" ]; then : # if no user vimrc, then check for a global /etc/vimpagerrc elif [ -n "$system_vimpagerrc" -a -f "$system_vimpagerrc" ]; then : # check a couple of common places for the standalone version elif [ -f /usr/local/etc/vimpagerrc ]; then vimrc=/usr/local/etc/vimpagerrc elif [ -f /etc/vimpagerrc ]; then vimrc=/etc/vimpagerrc fi } read_vim_settings() { # Read settings from the vimpagerrc file and possibly set $use_gvim, $ansiesc_available, $disable_x11 and $no_pass_thru. i=1 OLDIFS=$IFS IFS=' ' for var in $(IFS=$OLDIFS; "$tvim" -NEnR ${vimrc:+-u "$vimrc"} -i NONE --cmd 'let g:vimpager = { "enabled": 1 }' +' if !exists("g:vimpager.gvim") if !exists("g:vimpager_use_gvim") let g:vimpager.gvim = 0 else let g:vimpager.gvim = g:vimpager_use_gvim endif endif if !exists("g:vimpager.X11") if !exists("g:vimpager_disable_x11") let g:vimpager.X11 = 1 else let g:vimpager.X11 = !g:vimpager_disable_x11 endif endif if !exists("g:vimpager.passthrough") if !exists("g:vimpager_passthrough") let g:vimpager.passthrough = 1 else let g:vimpager.passthrough = g:vimpager_passthrough endif endif let g:use_ansiesc = 0 if has("conceal") && (!exists("g:vimpager.ansiesc") || g:vimpager.ansiesc == 1) && (!exists("g:vimpager_disable_ansiesc") || g:vimpager_disable_ansiesc == 0) let g:use_ansiesc = 1 endif call writefile([""] + map([g:vimpager.gvim, g:vimpager.X11, g:vimpager.passthrough, g:use_ansiesc], "\"VAL:\".v:val"), "/dev/stderr") quit ' &1 >/dev/null); do case "$var" in VAL:*) case $i in 1) [ "${var#VAL:}" -eq 1 ] && use_gvim=1 ;; 2) [ "${var#VAL:}" -eq 0 ] && disable_x11=1 ;; 3) if [ -z "$no_pass_thru" ]; then [ "${var#VAL:}" -eq 0 ] && no_pass_thru=1 fi ;; 4) [ "${var#VAL:}" -ne 0 ] && ansiesc_available=1 break ;; esac i=$((i + 1)) ;; esac done IFS=$OLDIFS } find_vim_executable() { # Find the vim executable to use. Set $vim_cmd and $gui. if [ -n "$win32" ]; then # msys/cygwin may be using a native vim, and if we're not in a real # console the native vim will not work, so we have to use gvim. if [ "x$TERM" != "xdumb" -a "x$TERM" != "xcygwin" -a "x$TERM" != "x" ]; then if command -v vim >/dev/null | grep -Eq '^/(cygdrive/)?[a-z]/'; then use_gvim=1 fi fi fi tvim=vim if [ -n "$EDITOR" -a -z "$VIMPAGER_VIM" ]; then case "${EDITOR##*/}" in *vim*) export VIMPAGER_VIM=$EDITOR ;; esac fi if [ -n "$VIMPAGER_VIM" ]; then case "${VIMPAGER_VIM##*/}" in vim*) tvim=$VIMPAGER_VIM ;; nvim*) tvim=$VIMPAGER_VIM ;; gvim*|mvim*) use_gvim=1 gvim=$VIMPAGER_VIM ;; esac fi if [ -n "$use_gvim" ]; then # determine if this is an ssh session and/or $DISPLAY is set if [ -n "$osx" ]; then if [ -z "$SSH_CONNECTION" ] && command -v mvim >/dev/null; then vim_cmd=${gvim:-mvim} gui=1 else vim_cmd=$tvim fi elif [ -n "$cygwin" ]; then if command -v gvim >/dev/null; then if [ -n "$SSH_CONNECTION" ]; then vim_cmd=$tvim # The Cygwin gvim uses X elif win32_native gvim; then if [ -z "$DISPLAY" ]; then vim_cmd=$tvim else vim_cmd=${gvim:-gvim} gui=1 fi else vim_cmd=${gvim:-gvim} gui=1 fi else vim_cmd=$tvim fi elif [ -n "$msys" ]; then if [ -z "$SSH_CONNECTION" ] && command -v gvim >/dev/null; then vim_cmd=${gvim:-gvim} gui=1 else vim_cmd=$tvim fi elif [ -z "$DISPLAY" ]; then vim_cmd=$tvim else if command -v gvim >/dev/null; then vim_cmd=${gvim:-gvim} gui=1 else vim_cmd=$tvim fi fi else vim_cmd=${vim_cmd:-${tvim:-vim}} fi if [ ! -n "$gui" -a -n "$disable_x11" ]; then vim_cmd="$vim_cmd -X" fi } parse_pstree() { # Parse the process tree and set $is_man, $is_doc, $is_perldoc, $force_strip_ansi and $extra_cmd. ptree=$(do_ptree) # Check if called from man, perldoc or pydoc if echo "$ptree" | grep -Eq '([ \t]+|/)(man|[Pp]ydoc[0-9.]*|[Rr](uby|i)[0-9.]*)([ \t]|$)'; then is_man=1 is_doc=1 force_strip_ansi=1 elif echo "$ptree" | grep -Eq '([ \t]+|/)perl(doc)?([0-9.]*)?([ \t]|$)'; then is_perldoc=1 is_doc=1 force_strip_ansi=1 fi extra_cmd="${extra_cmd:+$extra_cmd | }let g:vimpager.ptree=[$(echo "$ptree" | awk '{ print "\"" $2 "\"" }' | tr '\n' ',')] | call remove(g:vimpager.ptree, -1) | let g:vimpager_ptree = g:vimpager.ptree" } expand_config_vars() { eval runtime=\"$runtime\" eval vimcat=\"$vimcat\" eval system_vimpagerrc=\"$system_vimpagerrc\" } # special handling to rewrite cygwin/msys paths to windows POSIX paths if [ -n "$win32" ] && command -v cygpath >/dev/null; then _have_cygpath=1 fi resolve_path() { if [ -n "$_have_cygpath" ]; then cygpath -w "$1" | tr '\\' '/' else echo "$1" fi } quit() { rm -f gvim.exe.stackdump # for a cygwin bug cd "${tmp%/*}" 2>/dev/null # some systems cannot remove CWD rm -rf "$tmp" 2>/dev/null # rm -rf "" shows error on OpenBSD exit "$@" } usage() { cat <<'EOF' Usage: vimpager [OPTION]... [FILE | -]... Display FILE(s) in (n)vim with a pager emulating less. With no FILE, or when FILE is -, read standard input. -h, --help, --usage Show this help screen and exit. -v, --version Show version information and exit. +G, + Go to the end of the file. +F Follow file, like tail -f or less +F -N, --LINE-NUMBERS Show line numbers. -s Squeeze multiple blank lines into one. --passthrough If files fit on screen, print them with highlighting (DEFAULT.) --force-passthrough Always print the files with highlighting, don't invoke pager. --no-passthrough Never print the files, always invoke pager. --cmd COMMAND Run (n)vim COMMAND before initialization. -c COMMAND Run (n)vim COMMAND after initialization. -u FILE Use FILE as the vimrc. -x  Give debugging output on stderr. Examples: vimpager program.py # view program.py in the pager PAGER=vimpager man 3 sprintf # view man page for sprintf(3) Project homepage and documentation: <http://github.com/rkitover/vimpager> or available locally via: man vimpager Press ',h' for a summary of keystrokes in the program. EOF } if command -v gawk >/dev/null; then _awk=gawk elif command -v nawk >/dev/null; then _awk=nawk elif command -v mawk >/dev/null; then _awk=mawk elif [ -x /usr/xpg4/bin/awk ]; then _awk=/usr/xpg4/bin/awk elif command -v awk >/dev/null; then _awk=awk else echo "ERROR: No awk found!" >&2 quit 1 fi awk() { command "$_awk" "$@" } if command -v gsed >/dev/null; then _sed=gsed elif [ -x /usr/xpg4/bin/sed ]; then _sed=/usr/xpg4/bin/sed elif command -v sed >/dev/null; then _sed=sed else echo "ERROR: No sed found!" >&2 quit 1 fi sed() { command "$_sed" "$@" } if command -v ggrep >/dev/null; then _grep=ggrep elif [ -x /usr/xpg4/bin/grep ]; then _grep=/usr/xpg4/bin/grep elif command -v grep >/dev/null; then _grep=grep else echo "ERROR: No grep found!" >&2 quit 1 fi # check that grep -Eq works if [ -z "$(echo foo | "$_grep" -Eq foo >/dev/null 2>&1)" -a $? -eq 0 ]; then _have_grep_E_q=1 fi grep() { case "$1" in -Eq) # we only check for -Eq when it's the only option case "$2" in -*) command "$_grep" "$@" ;; *) if [ "${_have_grep_E_q:-0}" -eq 1 ]; then command "$_grep" "$@" else shift awk_grep_E_q "$@" fi ;; esac ;; *) command "$_grep" "$@" ;; esac } awk_grep_E_q() { _pat=$(printf '%s' "$1" | sed -e 's!/!\\/!g') shift awk ' BEGIN { exit_val = 1 } /'"$_pat"'/ { exit_val = 0; exit(exit_val) } END { exit(exit_val) } ' "$@" } if command -v ghead >/dev/null; then _head=ghead else _head=head fi if [ "$(echo xx | head -n 1 2>/dev/null)" = "xx" ]; then _head_syntax=new else if ! head -1 -- "$0" >/dev/null 2>&1; then _head_no_double_dash=1 fi fi head() { _lines= case "$1" in -[0-9]*) _lines=${1#-} shift esac if [ -z "$_lines" ]; then command "$_head" "$@" elif [ "$_head_syntax" = "new" ]; then command "$_head" -n $_lines -- "$@" elif [ -z "$_head_no_double_dash" ]; then command "$_head" -$_lines -- "$@" else command "$_head" -$_lines "$@" fi } # We are escaping only slashes (because they are special in file paths) and # percent (because it is our escape char). This makes it possible to encode # the path to the original file in the basename of the temporary file. encode_filename() { echo "$@" | sed -e 's|%|%25|g' -e 's|/|%2F|g' } # emulate arrays set_key() { eval "$1_$2=\"$3\"" } get_key() { eval "echo \"\${$1_$2}\"" } # this actually runs vim or gvim, or vimcat, or just cats the file page_files() { # EXTRACT BUNDLED SCRIPTS HERE if [ -n "$cat_files" ]; then i=1 for cur_file in "$@"; do orig_file=$(get_key orig_file_names $i) if [ $# -gt 1 ]; then if [ $i -gt 1 ]; then printf '\n' fi printf '==> %s <==\n\n' "$orig_file" fi if [ -n "$(get_key ansi_files $i)" ]; then cat "$cur_file" _exit_status=$? else "$POSIX_SHELL" ${trace:+-x} "$vimcat" ${vimrc:+-u "$vimrc"} \ --cmd "set rtp^=$runtime | let vimpager={ 'enabled': 1 }" \ ${extra_cmd:+--cmd "$extra_cmd"} \ -c 'silent! source '"$tmp/$i"'.vim' \ ${extra_c:+-c "$extra_c"} \ "$cur_file" /dev/null } win32_native() { if [ "x$(get_key _win32_native "$1")" = x1 ]; then return 0 else if [ -n "$msys" -o -n "$cygwin" ]; then if command -v "$1" > /dev/null | grep -Eq '^/(cygdrive/)?[a-z]/'; then set_key _win32_native "$1" 1 return 0 else set_key _win32_native "$1" 0 return 1 fi else set_key _win32_native "$1" 0 return 1 fi fi return 1 } # this is compatible with osed ANSI_RE='\[[;?]*[0-9.;]*[A-Za-z]' ansi_filter() { sed -e 's/'"$ANSI_RE"'//g' "$@" } # Even /bin/sed on Solaris handles UTF-8 characters correctly, so we can safely # use sed for this. overstrike_filter() { sed 's/.//g' "$@" } fits_on_screen() { [ $# -eq 0 ] && set -- - # First remove overstrikes and ANSI codes with sed ansi_filter "$@" | overstrike_filter | \ awk ' { if (NR == 1) { lines = total_lines - 2 - (num_files - 1) * file_sep_lines if (num_files - 1) lines -= first_file_sep_lines total_cols += 0 # coerce to number } col = 0 for (pos = 1; pos <= length($0); pos++) { c = substr($0, pos, 1) # handle tabs if (c == "\t") col += 8 - (col % 8) else col++ if (col > total_cols) { if (!--lines) exit(1) col = 1 } } if (!--lines) exit(1) } ' num_files=$# total_lines=$lines total_cols=$cols file_sep_lines=3 first_file_sep_lines=2 - } # INCLUDE BUNDLED SCRIPTS HERE # END OF BUNDLED SCRIPTS main "$@" # Copyright (c) 2016, Rafael Kitover and # Contributors (below.) # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # CONTRIBUTORS: # # Rafael Kitover # Antonio Ospite # Jean-Marie Gaillourdet # Perry Hargrave # Koen Smits # Ivan S. Freitas # Wout Mertens (Solaris compatibility, less processes) # Jacobo de Vera (add -X option for faster startup) # Damien Pollet # Peter Fern # Wei Dai # Iftekharul Haque # Anselm Strauss # Anisse Astier # Simon Olofsson # lickel: Adam Lickel # eworm-de: Christian Hesse # krijesta: Chris Chambers # vincer: vince rosso # justinkb: Paul Mulders # nonakap: NONAKA Kimihiro # dfechner: Dustin Fechner # lucc: Lucas Hoffmann # aroig: Abdo Roig-Maranges # mortonfox: Morton Fox # mapeiqi88: # snordhausen: Stefan Nordhausen # renatosilva: Renato Silva # dragon788: # ahamad-s: donnie' # SethMilliken: Seth Milliken # trapd00r: Magnus Woldrich # ghedo: Alessandro Ghedini # guiniol: Guillaume Brogi # leandro-lucarella-sociomantic: Leandro Lucarella # derekschrok: Derek Schrock # wilywampa: Jacob Niehus # cmcaine: Colin Caine # vim: sw=4 et tw=0: