From ba8d9cff5bcbf35c3ab20609d3c21c0ec5d23c35 Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Sat, 12 Sep 2009 20:39:28 +0200 Subject: update Signed-off-by: Florian Pritz --- ack/PKGBUILD | 16 + ack/ack | 2572 +++++++++++++++++++++++++++ dejagnu/PKGBUILD | 28 + foo2zjs/PKGBUILD | 31 + foo2zjs/foo2zjs.install | 48 + foo2zjs/makefile.patch | 45 + initscripts-git/PKGBUILD | 2 +- inxi/PKGBUILD | 18 + inxi/inxi | 4428 ++++++++++++++++++++++++++++++++++++++++++++++ warsow/PKGBUILD | 59 +- 10 files changed, 7224 insertions(+), 23 deletions(-) create mode 100644 ack/PKGBUILD create mode 100644 ack/ack create mode 100644 dejagnu/PKGBUILD create mode 100644 foo2zjs/PKGBUILD create mode 100644 foo2zjs/foo2zjs.install create mode 100644 foo2zjs/makefile.patch create mode 100644 inxi/PKGBUILD create mode 100644 inxi/inxi diff --git a/ack/PKGBUILD b/ack/PKGBUILD new file mode 100644 index 0000000..5fe7b01 --- /dev/null +++ b/ack/PKGBUILD @@ -0,0 +1,16 @@ +# Maintainer: Michael S. Walker +pkgname=ack +pkgver=1.90 +pkgrel=1 +pkgdesc="A tool like grep, aimed at programmers with large trees of heterogeneous source code." +url="http://ack.googlecode.com" +arch=('i686' 'x86_64') +license=('GPL') +depends=('perl') +source=(http://ack.googlecode.com/svn/tags/$pkgver/$pkgname) +md5sums=('d15d059166beff6103d2401aa2d783c7') + +build() { + cd $startdir/src + install -D -m755 ack ${pkgdir}/usr/bin/ack +} \ No newline at end of file diff --git a/ack/ack b/ack/ack new file mode 100644 index 0000000..614ae75 --- /dev/null +++ b/ack/ack @@ -0,0 +1,2572 @@ +#!/usr/bin/env perl +# +# This file, ack, is generated code. +# Please DO NOT EDIT or send patches for it. +# +# Please take a look at the source from +# http://code.google.com/p/ack/source +# and submit patches against the individual files +# that build ack. +# + +use warnings; +use strict; + +our $VERSION = '1.90'; +# Check http://betterthangrep.com/ for updates + +# These are all our globals. + + +MAIN: { + if ( $App::Ack::VERSION ne $main::VERSION ) { + App::Ack::die( "Program/library version mismatch\n\t$0 is $main::VERSION\n\t$INC{'App/Ack.pm'} is $App::Ack::VERSION" ); + } + + # Do preliminary arg checking; + my $env_is_usable = 1; + for ( @ARGV ) { + last if ( $_ eq '--' ); + + # Priorities! Get the --thpppt checking out of the way. + /^--th[pt]+t+$/ && App::Ack::_thpppt($_); + + # See if we want to ignore the environment. (Don't tell Al Gore.) + if ( $_ eq '--noenv' ) { + my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV ); + delete @ENV{@keys}; + $env_is_usable = 0; + } + } + unshift( @ARGV, App::Ack::read_ackrc() ) if $env_is_usable; + App::Ack::load_colors(); + + if ( exists $ENV{ACK_SWITCHES} ) { + App::Ack::warn( 'ACK_SWITCHES is no longer supported. Use ACK_OPTIONS.' ); + } + + if ( !@ARGV ) { + App::Ack::show_help(); + exit 1; + } + + main(); +} + +sub main { + my $opt = App::Ack::get_command_line_options(); + + $| = 1 if $opt->{flush}; # Unbuffer the output if flush mode + + if ( App::Ack::input_from_pipe() ) { + # We're going into filter mode + for ( qw( f g l ) ) { + $opt->{$_} and App::Ack::die( "Can't use -$_ when acting as a filter." ); + } + $opt->{show_filename} = 0; + $opt->{regex} = App::Ack::build_regex( defined $opt->{regex} ? $opt->{regex} : shift @ARGV, $opt ); + if ( my $nargs = @ARGV ) { + my $s = $nargs == 1 ? '' : 's'; + App::Ack::warn( "Ignoring $nargs argument$s on the command-line while acting as a filter." ); + } + my $res = App::Ack::Resource::Basic->new( '-' ); + App::Ack::search_resource( $res, $opt ); + $res->close(); + exit 0; + } + + my $file_matching = $opt->{f} || $opt->{lines}; + if ( !$file_matching ) { + @ARGV or App::Ack::die( 'No regular expression found.' ); + $opt->{regex} = App::Ack::build_regex( defined $opt->{regex} ? $opt->{regex} : shift @ARGV, $opt ); + } + + # check that all regexes do compile fine + App::Ack::check_regex( $_ ) for ( $opt->{regex}, $opt->{G} ); + + my $what = App::Ack::get_starting_points( \@ARGV, $opt ); + my $iter = App::Ack::get_iterator( $what, $opt ); + App::Ack::filetype_setup(); + + my $nmatches = 0; + + App::Ack::set_up_pager( $opt->{pager} ) if defined $opt->{pager}; + if ( $opt->{f} ) { + App::Ack::print_files( $iter, $opt ); + } + elsif ( $opt->{l} || $opt->{count} ) { + $nmatches = App::Ack::print_files_with_matches( $iter, $opt ); + } + else { + $nmatches = App::Ack::print_matches( $iter, $opt ); + } + close $App::Ack::fh; + exit ($nmatches ? 0 : 1); +} + +=head1 NAME + +ack - grep-like text finder + +=head1 SYNOPSIS + + ack [options] PATTERN [FILE...] + ack -f [options] [DIRECTORY...] + +=head1 DESCRIPTION + +Ack is designed as a replacement for 99% of the uses of F. + +Ack searches the named input FILEs (or standard input if no files are +named, or the file name - is given) for lines containing a match to the +given PATTERN. By default, ack prints the matching lines. + +Ack can also list files that would be searched, without actually searching +them, to let you take advantage of ack's file-type filtering capabilities. + +=head1 FILE SELECTION + +I is intelligent about the files it searches. It knows about +certain file types, based on both the extension on the file and, +in some cases, the contents of the file. These selections can be +made with the B<--type> option. + +With no file selections, I only searches files of types that +it recognizes. If you have a file called F, and I +doesn't know what a .wango file is, I won't search it. + +The B<-a> option tells I to select all files, regardless of +type. + +Some files will never be selected by I, even with B<-a>, +including: + +=over 4 + +=item * Backup files: Files ending with F<~>, or F<#*#> + +=item * Coredumps: Files matching F + +=back + +However, I always searches the files given on the command line, +no matter what type. Furthermore, by specifying the B<-u> option all +files will be searched. + +=head1 DIRECTORY SELECTION + +I descends through the directory tree of the starting directories +specified. However, it will ignore the shadow directories used by +many version control systems, and the build directories used by the +Perl MakeMaker system. You may add or remove a directory from this +list with the B<--[no]ignore-dir> option. The option may be repeated +to add/remove multiple directories from the ignore list. + +For a complete list of directories that do not get searched, run +F. + +=head1 WHEN TO USE GREP + +I trumps I as an everyday tool 99% of the time, but don't +throw I away, because there are times you'll still need it. + +E.g., searching through huge files looking for regexes that can be +expressed with I syntax should be quicker with I. + +If your script or parent program uses I C<--quiet> or +C<--silent> or needs exit 2 on IO error, use I. + +=head1 OPTIONS + +=over 4 + +=item B<-a>, B<--all> + +Operate on all files, regardless of type (but still skip directories +like F, F, etc.) + +=item B<-A I>, B<--after-context=I> + +Print I lines of trailing context after matching lines. + +=item B<-B I>, B<--before-context=I> + +Print I lines of leading context before matching lines. + +=item B<-C [I]>, B<--context[=I]> + +Print I lines (default 2) of context around matching lines. + +=item B<-c>, B<--count> + +Suppress normal output; instead print a count of matching lines for +each input file. If B<-l> is in effect, it will only show the +number of lines for each file that has lines matching. Without +B<-l>, some line counts may be zeroes. + +=item B<--color>, B<--nocolor> + +B<--color> highlights the matching text. B<--nocolor> supresses +the color. This is on by default unless the output is redirected. + +On Windows, this option is off by default unless the +L module is installed or the C +environment variable is used. + +=item B<--color-filename=I> + +Sets the color to be used for filenames. + +=item B<--color-match=I> + +Sets the color to be used for matches. + +=item B<--column> + +Show the column number of the first match. This is helpful for editors +that can place your cursor at a given position. + +=item B<--env>, B<--noenv> + +B<--noenv> disables all environment processing. No F<.ackrc> is read +and all environment variables are ignored. By default, F considers +F<.ackrc> and settings in the environment. + +=item B<--flush> + +B<--flush> flushes output immediately. This is off by default +unless ack is running interactively (when output goes to a pipe +or file). + +=item B<-f> + +Only print the files that would be searched, without actually doing +any searching. PATTERN must not be specified, or it will be taken as +a path to search. + +=item B<--follow>, B<--nofollow> + +Follow or don't follow symlinks, other than whatever starting files +or directories were specified on the command line. + +This is off by default. + +=item B<-G I> + +Only paths matching I are included in the search. The entire +path and filename are matched against I, and I is a +Perl regular expression, not a shell glob. + +The options B<-i>, B<-w>, B<-v>, and B<-Q> do not apply to this I. + +=item B<-g I> + +Print files where the relative path + filename matches I. This option is +a convenience shortcut for B<-f> B<-G I>. + +The options B<-i>, B<-w>, B<-v>, and B<-Q> do not apply to this I. + +=item B<--group>, B<--nogroup> + +B<--group> groups matches by file name with. This is the default when +used interactively. + +B<--nogroup> prints one result per line, like grep. This is the default +when output is redirected. + +=item B<-H>, B<--with-filename> + +Print the filename for each match. + +=item B<-h>, B<--no-filename> + +Suppress the prefixing of filenames on output when multiple files are +searched. + +=item B<--help> + +Print a short help statement. + +=item B<-i>, B<--ignore-case> + +Ignore case in the search strings. + +This applies only to the PATTERN, not to the regexes given for the B<-g> +and B<-G> options. + +=item B<--[no]ignore-dir=DIRNAME> + +Ignore directory (as CVS, .svn, etc are ignored). May be used multiple times +to ignore multiple directories. For example, mason users may wish to include +B<--ignore-dir=data>. The B<--noignore-dir> option allows users to search +directories which would normally be ignored (perhaps to research the contents +of F<.svn/props> directories). + +=item B<--line=I> + +Only print line I of each file. Multiple lines can be given with multiple +B<--line> options or as a comma separated list (B<--line=3,5,7>). B<--line=4-7> +also works. The lines are always output in ascending order, no matter the +order given on the command line. + +=item B<-l>, B<--files-with-matches> + +Only print the filenames of matching files, instead of the matching text. + +=item B<-L>, B<--files-without-matches> + +Only print the filenames of files that do I match. This is equivalent +to specifying B<-l> and B<-v>. + +=item B<--match I> + +Specify the I explicitly. This is helpful if you don't want to put the +regex as your first argument, e.g. when executing multiple searches over the +same set of files. + + # search for foo and bar in given files + ack file1 t/file* --match foo + ack file1 t/file* --match bar + +=item B<-m=I>, B<--max-count=I> + +Stop reading a file after I matches. + +=item B<--man> + +Print this manual page. + +=item B<-n> + +No descending into subdirectories. + +=item B<-o> + +Show only the part of each line matching PATTERN (turns off text +highlighting) + +=item B<--output=I> + +Output the evaluation of I for each line (turns off text +highlighting) + +=item B<--pager=I> + +Direct ack's output through I. This can also be specified +via the C and C environment variables. + +Using --pager does not suppress grouping and coloring like piping +output on the command-line does. + +=item B<--passthru> + +Prints all lines, whether or not they match the expression. Highlighting +will still work, though, so it can be used to highlight matches while +still seeing the entire file, as in: + + # Watch a log file, and highlight a certain IP address + $ tail -f ~/access.log | ack --passthru 123.45.67.89 + +=item B<--print0> + +Only works in conjunction with -f, -g, -l or -c (filename output). The filenames +are output separated with a null byte instead of the usual newline. This is +helpful when dealing with filenames that contain whitespace, e.g. + + # remove all files of type html + ack -f --html --print0 | xargs -0 rm -f + +=item B<-Q>, B<--literal> + +Quote all metacharacters in PATTERN, it is treated as a literal. + +This applies only to the PATTERN, not to the regexes given for the B<-g> +and B<-G> options. + +=item B<--smart-case>, B<--no-smart-case> + +Ignore case in the search strings if PATTERN contains no uppercase +characters. This is similar to C in vim. This option is +off by default. + +B<-i> always overrides this option. + +This applies only to the PATTERN, not to the regexes given for the +B<-g> and B<-G> options. + +=item B<--sort-files> + +Sorts the found files lexically. Use this if you want your file +listings to be deterministic between runs of I. + +=item B<--thpppt> + +Display the all-important Bill The Cat logo. Note that the exact +spelling of B<--thpppppt> is not important. It's checked against +a regular expression. + +=item B<--type=TYPE>, B<--type=noTYPE> + +Specify the types of files to include or exclude from a search. +TYPE is a filetype, like I or I. B<--type=perl> can +also be specified as B<--perl>, and B<--type=noperl> can be done +as B<--noperl>. + +If a file is of both type "foo" and "bar", specifying --foo and +--nobar will exclude the file, because an exclusion takes precedence +over an inclusion. + +Type specifications can be repeated and are ORed together. + +See I for a list of valid types. + +=item B<--type-add I=I<.EXTENSION>[,I<.EXT2>[,...]]> + +Files with the given EXTENSION(s) are recognized as being of (the +existing) type TYPE. See also L. + + +=item B<--type-set I=I<.EXTENSION>[,I<.EXT2>[,...]]> + +Files with the given EXTENSION(s) are recognized as being of type +TYPE. This replaces an existing definition for type TYPE. See also +L. + +=item B<-u>, B<--unrestricted> + +All files and directories (including blib/, core.*, ...) are searched, +nothing is skipped. When both B<-u> and B<--ignore-dir> are used, the +B<--ignore-dir> option has no effect. + +=item B<-v>, B<--invert-match> + +Invert match: select non-matching lines + +This applies only to the PATTERN, not to the regexes given for the B<-g> +and B<-G> options. + +=item B<--version> + +Display version and copyright information. + +=item B<-w>, B<--word-regexp> + +Force PATTERN to match only whole words. The PATTERN is wrapped with +C<\b> metacharacters. + +This applies only to the PATTERN, not to the regexes given for the B<-g> +and B<-G> options. + +=item B<-1> + +Stops after reporting first match of any kind. This is different +from B<--max-count=1> or B<-m1>, where only one match per file is +shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does +not. + +=back + +=head1 THE .ackrc FILE + +The F<.ackrc> file contains command-line options that are prepended +to the command line before processing. Multiple options may live +on multiple lines. Lines beginning with a # are ignored. A F<.ackrc> +might look like this: + + # Always sort the files + --sort-files + + # Always color, even if piping to a another program + --color + + # Use "less -r" as my pager + --pager=less -r + +Note that arguments with spaces in them do not need to be quoted, +as they are not interpreted by the shell. Basically, each I +in the F<.ackrc> file is interpreted as one element of C<@ARGV>. + +F looks in your home directory for the F<.ackrc>. You can +specify another location with the F variable, below. + +If B<--noenv> is specified on the command line, the F<.ackrc> file +is ignored. + +=head1 Defining your own types + +ack allows you to define your own types in addition to the predefined +types. This is done with command line options that are best put into +an F<.ackrc> file - then you do not have to define your types over and +over again. In the following examples the options will always be shown +on one command line so that they can be easily copy & pasted. + +I searches for foo in all perl files. I +tells you, that perl files are files ending +in .pl, .pm, .pod or .t. So what if you would like to include .xs +files as well when searching for --perl files? I +does this for you. B<--type-add> appends +additional extensions to an existing type. + +If you want to define a new type, or completely redefine an existing +type, then use B<--type-set>. I defines the type I to include files with +the extensions .e or .eiffel. So to search for all eiffel files +containing the word Bertrand use I. +As usual, you can also write B<--type=eiffel> +instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes +all eiffel files from a search. Redefining also works: I +and I<.xs> files no longer belong to the type I. + +When defining your own types in the F<.ackrc> file you have to use +the following: + + --type-set=eiffel=.e,.eiffel + +or writing on separate lines + + --type-set + eiffel=.e,.eiffel + +The following does B work in the F<.ackrc> file: + + --type-set eiffel=.e,.eiffel + + +In order to see all currently defined types, use I<--help types>, e.g. +I + +Restrictions: + +=over 4 + +=item + +The types 'skipped', 'make', 'binary' and 'text' are considered "builtin" and +cannot be altered. + +=item + +The shebang line recognition of the types 'perl', 'ruby', 'php', 'python', +'shell' and 'xml' cannot be redefined by I<--type-set>, it is always +active. However, the shebang line is only examined for files where the +extension is not recognised. Therefore it is possible to say +I and +only find your shiny new I<.perl> files (and all files with unrecognized extension +and perl on the shebang line). + +=back + +=head1 ENVIRONMENT VARIABLES + +For commonly-used ack options, environment variables can make life much easier. +These variables are ignored if B<--noenv> is specified on the command line. + +=over 4 + +=item ACKRC + +Specifies the location of the F<.ackrc> file. If this file doesn't +exist, F looks in the default location. + +=item ACK_OPTIONS + +This variable specifies default options to be placed in front of +any explicit options on the command line. + +=item ACK_COLOR_FILENAME + +Specifies the color of the filename when it's printed in B<--group> +mode. By default, it's "bold green". + +The recognized attributes are clear, reset, dark, bold, underline, +underscore, blink, reverse, concealed black, red, green, yellow, +blue, magenta, on_black, on_red, on_green, on_yellow, on_blue, +on_magenta, on_cyan, and on_white. Case is not significant. +Underline and underscore are equivalent, as are clear and reset. +The color alone sets the foreground color, and on_color sets the +background color. + +This option can also be set with B<--color-filename>. + +=item ACK_COLOR_MATCH + +Specifies the color of the matching text when printed in B<--color> +mode. By default, it's "black on_yellow". + +This option can also be set with B<--color-match>. + +See B for the color specifications. + +=item ACK_PAGER + +Specifies a pager program, such as C, C or C, to which +ack will send its output. + +Using C does not suppress grouping and coloring like +piping output on the command-line does, except that on Windows +ack will assume that C does not support color. + +C overrides C if both are specified. + +=item ACK_PAGER_COLOR + +Specifies a pager program that understands ANSI color sequences. +Using C does not suppress grouping and coloring +like piping output on the command-line does. + +If you are not on Windows, you never need to use C. + +=back + +=head1 ACK & OTHER TOOLS + +=head2 Vim integration + +F integrates easily with the Vim text editor. Set this in your +F<.vimrc> to use F instead of F: + + set grepprg=ack\ -a + +That examples uses C<-a> to search through all files, but you may +use other default flags. Now you can search with F and easily +step through the results in Vim: + + :grep Dumper perllib + +=head2 Emacs integration + +Phil Jackson put together an F extension that "provides a +simple compilation mode ... has the ability to guess what files you +want to search for based on the major-mode." + +L + +=head2 TextMate integration + +Pedro Melo is a TextMate user who writes "I spend my day mostly +inside TextMate, and the built-in find-in-project sucks with large +projects. So I hacked a TextMate command that was using find + +grep to use ack. The result is the Search in Project with ack, and +you can find it here: +L" + +=head2 Shell and Return Code + +For greater compatibility with I, I in normal use returns +shell return or exit code of 0 only if something is found and 1 if +no match is found. + +(Shell exit code 1 is C<$?=256> in perl with C or backticks.) + +The I code 2 for errors is not used. + +0 is returned if C<-f> or C<-g> are specified, irrespective of +number of files found. + +=cut + +=head1 DEBUGGING ACK PROBLEMS + +If ack gives you output you're not expecting, start with a few simple steps. + +=head2 Use B<--noenv> + +Your environment variables and F<.ackrc> may be doing things you're +not expecting, or forgotten you specified. Use B<--noenv> to ignore +your environment and F<.ackrc>. + +=head2 Use B<-f> to see what files you're scanning + +The reason I created B<-f> in the first place was as a debugging +tool. If ack is not finding matches you think it should find, run +F to see what files are being checked. + +=head1 TIPS + +=head2 Use the F<.ackrc> file. + +The F<.ackrc> is the place to put all your options you use most of +the time but don't want to remember. Put all your --type-add and +--type-set definitions in it. If you like --smart-case, set it +there, too. I also set --sort-files there. + +=head2 Use F<-f> for working with big codesets + +Ack does more than search files. C will create a +list of all the Perl files in a tree, ideal for sending into F. +For example: + + # Change all "this" to "that" in all Perl files in a tree. + ack -f --perl | xargs perl -p -i -e's/this/that/g' + +or if you prefer: + + perl -p -i -e's/this/thatg/' $(ack -f --perl) + +=head2 Use F<-Q> when in doubt about metacharacters + +If you're searching for something with a regular expression +metacharacter, most often a period in a filename or IP address, add +the -Q to avoid false positives without all the backslashing. See +the following example for more... + +=head2 Use ack to watch log files + +Here's one I used the other day to find trouble spots for a website +visitor. The user had a problem loading F, so I +took the access log and scanned it with ack twice. + + ack -Q aa.bb.cc.dd /path/to/access.log | ack -Q -B5 troublesome.gif + +The first ack finds only the lines in the Apache log for the given +IP. The second finds the match on my troublesome GIF, and shows +the previous five lines from the log in each case. + +=head2 Share your knowledge + +Join the ack-users mailing list. Send me your tips and I may add +them here. + +=head1 FAQ + +=head2 Wouldn't it be great if F did search & replace? + +No, ack will always be read-only. Perl has a perfectly good way +to do search & replace in files, using the C<-i>, C<-p> and C<-n> +switches. + +You can certainly use ack to select your files to update. For +example, to change all "foo" to "bar" in all PHP files, you can do +this form the Unix shell: + + $ perl -i -p -e's/foo/bar/g' $(ack -f --php) + +=head1 AUTHOR + +Andy Lester, C<< >> + +=head1 BUGS + +Please report any bugs or feature requests to the issues list at +Google Code: L + +=head1 ENHANCEMENTS + +All enhancement requests MUST first be posted to the ack-users +mailing list at L. I +will not consider a request without it first getting seen by other +ack users. + +There is a list of enhancements I want to make to F in the ack +issues list at Google Code: L + +Patches are always welcome, but patches with tests get the most +attention. + +=head1 SUPPORT + +Support for and information about F can be found at: + +=over 4 + +=item * The ack homepage + +L + +=item * The ack issues list at Google Code + +L + +=item * AnnoCPAN: Annotated CPAN documentation + +L + +=item * CPAN Ratings + +L + +=item * Search CPAN + +L + +=item * Subversion repository + +L + +=back + +=head1 ACKNOWLEDGEMENTS + +How appropriate to have Inowledgements! + +Thanks to everyone who has contributed to ack in any way, including +Ryan Niebur, +Kent Fredric, +Mike Morearty, +Ingmar Vanhassel, +Eric Van Dewoestine, +Sitaram Chamarty, +Adam James, +Richard Carlsson, +Pedro Melo, +AJ Schuster, +Phil Jackson, +Michael Schwern, +Jan Dubois, +Christopher J. Madsen, +Matthew Wickline, +David Dyck, +Jason Porritt, +Jjgod Jiang, +Thomas Klausner, +Uri Guttman, +Peter Lewis, +Kevin Riggle, +Ori Avtalion, +Torsten Blix, +Nigel Metheringham, +GEbor SzabE, +Tod Hagan, +Michael Hendricks, +Evar ArnfjErE Bjarmason, +Piers Cawley, +Stephen Steneker, +Elias Lutfallah, +Mark Leighton Fisher, +Matt Diephouse, +Christian Jaeger, +Bill Sully, +Bill Ricker, +David Golden, +Nilson Santos F. Jr, +Elliot Shank, +Merijn Broeren, +Uwe Voelker, +Rick Scott, +Ask BjErn Hansen, +Jerry Gay, +Will Coleda, +Mike O'Regan, +Slaven ReziE<0x107>, +Mark Stosberg, +David Alan Pisoni, +Adriano Ferreira, +James Keenan, +Leland Johnson, +Ricardo Signes +and Pete Krawczyk. + +=head1 COPYRIGHT & LICENSE + +Copyright 2005-2009 Andy Lester. + +This program is free software; you can redistribute it and/or modify +it under the terms of either: + +=over 4 + +=item * the GNU General Public License as published by the Free +Software Foundation; either version 1, or (at your option) any later +version, or + +=item * the Artistic License version 2.0. + +=back + +=cut +package File::Next; + +use strict; +use warnings; + + +our $VERSION = '1.06'; + + + +use File::Spec (); + + +our $name; # name of the current file +our $dir; # dir of the current file + +our %files_defaults; +our %skip_dirs; + +BEGIN { + %files_defaults = ( + file_filter => undef, + descend_filter => undef, + error_handler => sub { CORE::die @_ }, + sort_files => undef, + follow_symlinks => 1, + ); + %skip_dirs = map {($_,1)} (File::Spec->curdir, File::Spec->updir); +} + + +sub files { + ($_[0] eq __PACKAGE__) && die 'File::Next::files must not be invoked as File::Next->files'; + + my ($parms,@queue) = _setup( \%files_defaults, @_ ); + my $filter = $parms->{file_filter}; + + return sub { + while (@queue) { + my ($dir,$file,$fullpath) = splice( @queue, 0, 3 ); + if ( -f $fullpath ) { + if ( $filter ) { + local $_ = $file; + local $File::Next::dir = $dir; + local $File::Next::name = $fullpath; + next if not $filter->(); + } + return wantarray ? ($dir,$file,$fullpath) : $fullpath; + } + elsif ( -d _ ) { + unshift( @queue, _candidate_files( $parms, $fullpath ) ); + } + } # while + + return; + }; # iterator +} + + + + + + + +sub sort_standard($$) { return $_[0]->[1] cmp $_[1]->[1] } +sub sort_reverse($$) { return $_[1]->[1] cmp $_[0]->[1] } + +sub reslash { + my $path = shift; + + my @parts = split( /\//, $path ); + + return $path if @parts < 2; + + return File::Spec->catfile( @parts ); +} + + + +sub _setup { + my $defaults = shift; + my $passed_parms = ref $_[0] eq 'HASH' ? {%{+shift}} : {}; # copy parm hash + + my %passed_parms = %{$passed_parms}; + + my $parms = {}; + for my $key ( keys %{$defaults} ) { + $parms->{$key} = + exists $passed_parms{$key} + ? delete $passed_parms{$key} + : $defaults->{$key}; + } + + # Any leftover keys are bogus + for my $badkey ( keys %passed_parms ) { + my $sub = (caller(1))[3]; + $parms->{error_handler}->( "Invalid option passed to $sub(): $badkey" ); + } + + # If it's not a code ref, assume standard sort + if ( $parms->{sort_files} && ( ref($parms->{sort_files}) ne 'CODE' ) ) { + $parms->{sort_files} = \&sort_standard; + } + my @queue; + + for ( @_ ) { + my $start = reslash( $_ ); + if (-d $start) { + push @queue, ($start,undef,$start); + } + else { + push @queue, (undef,$start,$start); + } + } + + return ($parms,@queue); +} + + +sub _candidate_files { + my $parms = shift; + my $dir = shift; + + my $dh; + if ( !opendir $dh, $dir ) { + $parms->{error_handler}->( "$dir: $!" ); + return; + } + + my @newfiles; + my $descend_filter = $parms->{descend_filter}; + my $follow_symlinks = $parms->{follow_symlinks}; + my $sort_sub = $parms->{sort_files}; + + for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) { + my $has_stat; + + # Only do directory checking if we have a descend_filter + my $fullpath = File::Spec->catdir( $dir, $file ); + if ( !$follow_symlinks ) { + next if -l $fullpath; + $has_stat = 1; + } + + if ( $descend_filter ) { + if ( $has_stat ? (-d _) : (-d $fullpath) ) { + local $File::Next::dir = $fullpath; + local $_ = $file; + next if not $descend_filter->(); + } + } + if ( $sort_sub ) { + push( @newfiles, [ $dir, $file, $fullpath ] ); + } + else { + push( @newfiles, $dir, $file, $fullpath ); + } + } + closedir $dh; + + if ( $sort_sub ) { + return map { @{$_} } sort $sort_sub @newfiles; + } + + return @newfiles; +} + + +1; # End of File::Next +package App::Ack; + +use warnings; +use strict; + + + + +our $VERSION; +our $COPYRIGHT; +BEGIN { + $VERSION = '1.90'; + $COPYRIGHT = 'Copyright 2005-2009 Andy Lester, all rights reserved.'; +} + +our $fh; + +BEGIN { + $fh = *STDOUT; +} + + +our %types; +our %type_wanted; +our %mappings; +our %ignore_dirs; + +our $input_from_pipe; +our $output_to_pipe; + +our $dir_sep_chars; +our $is_cygwin; +our $is_windows; + +use File::Spec (); +use File::Glob ':glob'; +use Getopt::Long (); + +BEGIN { + %ignore_dirs = ( + '.bzr' => 'Bazaar', + '.cdv' => 'Codeville', + '~.dep' => 'Interface Builder', + '~.dot' => 'Interface Builder', + '~.nib' => 'Interface Builder', + '~.plst' => 'Interface Builder', + '.git' => 'Git', + '.hg' => 'Mercurial', + '.pc' => 'quilt', + '.svn' => 'Subversion', + blib => 'Perl module building', + CVS => 'CVS', + RCS => 'RCS', + SCCS => 'SCCS', + _darcs => 'darcs', + _sgbak => 'Vault/Fortress', + 'autom4te.cache' => 'autoconf', + 'cover_db' => 'Devel::Cover', + _build => 'Module::Build', + ); + + %mappings = ( + actionscript => [qw( as mxml )], + ada => [qw( ada adb ads )], + asm => [qw( asm s )], + batch => [qw( bat cmd )], + binary => q{Binary files, as defined by Perl's -B op (default: off)}, + cc => [qw( c h xs )], + cfmx => [qw( cfc cfm cfml )], + cpp => [qw( cpp cc cxx m hpp hh h hxx )], + csharp => [qw( cs )], + css => [qw( css )], + elisp => [qw( el )], + erlang => [qw( erl hrl )], + fortran => [qw( f f77 f90 f95 f03 for ftn fpp )], + haskell => [qw( hs lhs )], + hh => [qw( h )], + html => [qw( htm html shtml xhtml )], + java => [qw( java properties )], + js => [qw( js )], + jsp => [qw( jsp jspx jhtm jhtml )], + lisp => [qw( lisp lsp )], + lua => [qw( lua )], + make => q{Makefiles}, + mason => [qw( mas mhtml mpl mtxt )], + objc => [qw( m h )], + objcpp => [qw( mm h )], + ocaml => [qw( ml mli )], + parrot => [qw( pir pasm pmc ops pod pg tg )], + perl => [qw( pl pm pod t )], + php => [qw( php phpt php3 php4 php5 )], + plone => [qw( pt cpt metadata cpy py )], + python => [qw( py )], + rake => q{Rakefiles}, + ruby => [qw( rb rhtml rjs rxml erb rake )], + scheme => [qw( scm ss )], + shell => [qw( sh bash csh tcsh ksh zsh )], + skipped => q{Files, but not directories, normally skipped by ack (default: off)}, + smalltalk => [qw( st )], + sql => [qw( sql ctl )], + tcl => [qw( tcl itcl itk )], + tex => [qw( tex cls sty )], + text => q{Text files, as defined by Perl's -T op (default: off)}, + tt => [qw( tt tt2 ttml )], + vb => [qw( bas cls frm ctl vb resx )], + vim => [qw( vim )], + yaml => [qw( yaml yml )], + xml => [qw( xml dtd xslt ent )], + ); + + while ( my ($type,$exts) = each %mappings ) { + if ( ref $exts ) { + for my $ext ( @{$exts} ) { + push( @{$types{$ext}}, $type ); + } + } + } + + # These have to be checked before any filehandle diddling. + $output_to_pipe = not -t *STDOUT; + $input_from_pipe = -p STDIN; + + $is_cygwin = ($^O eq 'cygwin'); + $is_windows = ($^O =~ /MSWin32/); + $dir_sep_chars = $is_windows ? quotemeta( '\\/' ) : quotemeta( File::Spec->catfile( '', '' ) ); +} + + +sub read_ackrc { + my @files = ( $ENV{ACKRC} ); + my @dirs = + $is_windows + ? ( $ENV{HOME}, $ENV{USERPROFILE} ) + : ( '~', $ENV{HOME} ); + for my $dir ( grep { defined } @dirs ) { + for my $file ( '.ackrc', '_ackrc' ) { + push( @files, bsd_glob( "$dir/$file", GLOB_TILDE ) ); + } + } + for my $filename ( @files ) { + if ( defined $filename && -e $filename ) { + open( my $fh, '<', $filename ) or App::Ack::die( "$filename: $!\n" ); + my @lines = grep { /./ && !/^\s*#/ } <$fh>; + chomp @lines; + close $fh or App::Ack::die( "$filename: $!\n" ); + + return @lines; + } + } + + return; +} + + +sub get_command_line_options { + my %opt = ( + pager => $ENV{ACK_PAGER_COLOR} || $ENV{ACK_PAGER}, + ); + + my $getopt_specs = { + 1 => sub { $opt{1} = $opt{m} = 1 }, + 'A|after-context=i' => \$opt{after_context}, + 'B|before-context=i' => \$opt{before_context}, + 'C|context:i' => sub { shift; my $val = shift; $opt{before_context} = $opt{after_context} = ($val || 2) }, + 'a|all-types' => \$opt{all}, + 'break!' => \$opt{break}, + c => \$opt{count}, + 'color|colour!' => \$opt{color}, + 'color-match=s' => \$ENV{ACK_COLOR_MATCH}, + 'color-filename=s' => \$ENV{ACK_COLOR_FILENAME}, + 'column!' => \$opt{column}, + count => \$opt{count}, + 'env!' => sub { }, # ignore this option, it is handled beforehand + f => \$opt{f}, + flush => \$opt{flush}, + 'follow!' => \$opt{follow}, + 'g=s' => sub { shift; $opt{G} = shift; $opt{f} = 1 }, + 'G=s' => \$opt{G}, + 'group!' => sub { shift; $opt{heading} = $opt{break} = shift }, + 'heading!' => \$opt{heading}, + 'h|no-filename' => \$opt{h}, + 'H|with-filename' => \$opt{H}, + 'i|ignore-case' => \$opt{i}, + 'lines=s' => sub { shift; my $val = shift; push @{$opt{lines}}, $val }, + 'l|files-with-matches' => \$opt{l}, + 'L|files-without-matches' => sub { $opt{l} = $opt{v} = 1 }, + 'm|max-count=i' => \$opt{m}, + 'match=s' => \$opt{regex}, + 'n|no-recurse' => \$opt{n}, + o => sub { $opt{output} = '$&' }, + 'output=s' => \$opt{output}, + 'pager=s' => \$opt{pager}, + 'nopager' => sub { $opt{pager} = undef }, + 'passthru' => \$opt{passthru}, + 'print0' => \$opt{print0}, + 'Q|literal' => \$opt{Q}, + 'r|R|recurse' => sub {}, + 'smart-case!' => \$opt{smart_case}, + 'sort-files' => \$opt{sort_files}, + 'u|unrestricted' => \$opt{u}, + 'v|invert-match' => \$opt{v}, + 'w|word-regexp' => \$opt{w}, + + 'ignore-dirs=s' => sub { shift; my $dir = remove_dir_sep( shift ); $ignore_dirs{$dir} = '--ignore-dirs' }, + 'noignore-dirs=s' => sub { shift; my $dir = remove_dir_sep( shift ); delete $ignore_dirs{$dir} }, + + 'version' => sub { print_version_statement(); exit 1; }, + 'help|?:s' => sub { shift; show_help(@_); exit; }, + 'help-types'=> sub { show_help_types(); exit; }, + 'man' => sub { require Pod::Usage; Pod::Usage::pod2usage({-verbose => 2}); exit; }, + + 'type=s' => sub { + # Whatever --type=xxx they specify, set it manually in the hash + my $dummy = shift; + my $type = shift; + my $wanted = ($type =~ s/^no//) ? 0 : 1; # must not be undef later + + if ( exists $type_wanted{ $type } ) { + $type_wanted{ $type } = $wanted; + } + else { + App::Ack::die( qq{Unknown --type "$type"} ); + } + }, # type sub + }; + + # Stick any default switches at the beginning, so they can be overridden + # by the command line switches. + unshift @ARGV, split( ' ', $ENV{ACK_OPTIONS} ) if defined $ENV{ACK_OPTIONS}; + + # first pass through options, looking for type definitions + def_types_from_ARGV(); + + for my $i ( filetypes_supported() ) { + $getopt_specs->{ "$i!" } = \$type_wanted{ $i }; + } + + + my $parser = Getopt::Long::Parser->new(); + $parser->configure( 'bundling', 'no_ignore_case', ); + $parser->getoptions( %{$getopt_specs} ) or + App::Ack::die( 'See ack --help or ack --man for options.' ); + + my $to_screen = not output_to_pipe(); + my %defaults = ( + all => 0, + color => $to_screen, + follow => 0, + break => $to_screen, + heading => $to_screen, + before_context => 0, + after_context => 0, + ); + if ( $is_windows && $defaults{color} && not $ENV{ACK_PAGER_COLOR} ) { + if ( $ENV{ACK_PAGER} || not eval { require Win32::Console::ANSI } ) { + $defaults{color} = 0; + } + } + if ( $to_screen && $ENV{ACK_PAGER_COLOR} ) { + $defaults{color} = 1; + } + + while ( my ($key,$value) = each %defaults ) { + if ( not defined $opt{$key} ) { + $opt{$key} = $value; + } + } + + if ( defined $opt{m} && $opt{m} <= 0 ) { + App::Ack::die( '-m must be greater than zero' ); + } + + for ( qw( before_context after_context ) ) { + if ( defined $opt{$_} && $opt{$_} < 0 ) { + App::Ack::die( "--$_ may not be negative" ); + } + } + + if ( defined( my $val = $opt{output} ) ) { + $opt{output} = eval qq[ sub { "$val" } ]; + } + if ( defined( my $l = $opt{lines} ) ) { + # --line=1 --line=5 is equivalent to --line=1,5 + my @lines = split( /,/, join( ',', @{$l} ) ); + + # --line=1-3 is equivalent to --line=1,2,3 + @lines = map { + my @ret; + if ( /-/ ) { + my ($from, $to) = split /-/, $_; + if ( $from > $to ) { + App::Ack::warn( "ignoring --line=$from-$to" ); + @ret = (); + } + else { + @ret = ( $from .. $to ); + } + } + else { + @ret = ( $_ ); + }; + @ret + } @lines; + + if ( @lines ) { + my %uniq; + @uniq{ @lines } = (); + $opt{lines} = [ sort { $a <=> $b } keys %uniq ]; # numerical sort and each line occurs only once! + } + else { + # happens if there are only ignored --line directives + App::Ack::die( 'All --line options are invalid.' ); + } + } + + return \%opt; +} + + +sub def_types_from_ARGV { + my @typedef; + + my $parser = Getopt::Long::Parser->new(); + # pass_through => leave unrecognized command line arguments alone + # no_auto_abbrev => otherwise -c is expanded and not left alone + $parser->configure( 'no_ignore_case', 'pass_through', 'no_auto_abbrev' ); + $parser->getoptions( + 'type-set=s' => sub { shift; push @typedef, ['c', shift] }, + 'type-add=s' => sub { shift; push @typedef, ['a', shift] }, + ) or App::Ack::die( 'See ack --help or ack --man for options.' ); + + for my $td (@typedef) { + my ($type, $ext) = split /=/, $td->[1]; + + if ( $td->[0] eq 'c' ) { + # type-set + if ( exists $mappings{$type} ) { + # can't redefine types 'make', 'skipped', 'text' and 'binary' + App::Ack::die( qq{--type-set: Builtin type "$type" cannot be changed.} ) + if ref $mappings{$type} ne 'ARRAY'; + + delete_type($type); + } + } + else { + # type-add + + # can't append to types 'make', 'skipped', 'text' and 'binary' + App::Ack::die( qq{--type-add: Builtin type "$type" cannot be changed.} ) + if exists $mappings{$type} && ref $mappings{$type} ne 'ARRAY'; + + App::Ack::warn( qq{--type-add: Type "$type" does not exist, creating with "$ext" ...} ) + unless exists $mappings{$type}; + } + + my @exts = split /,/, $ext; + s/^\.// for @exts; + + if ( !exists $mappings{$type} || ref($mappings{$type}) eq 'ARRAY' ) { + push @{$mappings{$type}}, @exts; + for my $e ( @exts ) { + push @{$types{$e}}, $type; + } + } + else { + App::Ack::die( qq{Cannot append to type "$type".} ); + } + } + + return; +} + + +sub delete_type { + my $type = shift; + + App::Ack::die( qq{Internal error: Cannot delete builtin type "$type".} ) + unless ref $mappings{$type} eq 'ARRAY'; + + delete $mappings{$type}; + delete $type_wanted{$type}; + for my $ext ( keys %types ) { + $types{$ext} = [ grep { $_ ne $type } @{$types{$ext}} ]; + } +} + + +sub ignoredir_filter { + return !exists $ignore_dirs{$_}; +} + + +sub remove_dir_sep { + my $path = shift; + $path =~ s/[$dir_sep_chars]$//; + + return $path; +} + + +use constant TEXT => 'text'; + +sub filetypes { + my $filename = shift; + + return 'skipped' unless is_searchable( $filename ); + + my $basename = $filename; + $basename =~ s{.*[$dir_sep_chars]}{}; + + my $lc_basename = lc $basename; + return ('make',TEXT) if $lc_basename eq 'makefile'; + return ('rake','ruby',TEXT) if $lc_basename eq 'rakefile'; + + # If there's an extension, look it up + if ( $filename =~ m{\.([^\.$dir_sep_chars]+)$}o ) { + my $ref = $types{lc $1}; + return (@{$ref},TEXT) if $ref; + } + + # At this point, we can't tell from just the name. Now we have to + # open it and look inside. + + return unless -e $filename; + # From Elliot Shank: + # I can't see any reason that -r would fail on these-- the ACLs look + # fine, and no program has any of them open, so the busted Windows + # file locking model isn't getting in there. If I comment the if + # statement out, everything works fine + # So, for cygwin, don't bother trying to check for readability. + if ( !$is_cygwin ) { + if ( !-r $filename ) { + App::Ack::warn( "$filename: Permission denied" ); + return; + } + } + + return 'binary' if -B $filename; + + # If there's no extension, or we don't recognize it, check the shebang line + my $fh; + if ( !open( $fh, '<', $filename ) ) { + App::Ack::warn( "$filename: $!" ); + return; + } + my $header = <$fh>; + close $fh; + + if ( $header =~ /^#!/ ) { + return ($1,TEXT) if $header =~ /\b(ruby|p(?:erl|hp|ython))\b/; + return ('shell',TEXT) if $header =~ /\b(?:ba|t?c|k|z)?sh\b/; + } + else { + return ('xml',TEXT) if $header =~ /\Q{Q}; + if ( $opt->{w} ) { + $str = "\\b$str" if $str =~ /^\w/; + $str = "$str\\b" if $str =~ /\w$/; + } + + my $regex_is_lc = $str eq lc $str; + if ( $opt->{i} || ($opt->{smart_case} && $regex_is_lc) ) { + $str = "(?i)$str"; + } + + return $str; +} + + +sub check_regex { + my $regex = shift; + + return unless defined $regex; + + eval { qr/$regex/ }; + if ($@) { + (my $error = $@) =~ s/ at \S+ line \d+.*//; + chomp($error); + App::Ack::die( "Invalid regex '$regex':\n $error" ); + } + + return; +} + + + + +sub warn { + return CORE::warn( _my_program(), ': ', @_, "\n" ); +} + + +sub die { + return CORE::die( _my_program(), ': ', @_, "\n" ); +} + +sub _my_program { + require File::Basename; + return File::Basename::basename( $0 ); +} + + + +sub filetypes_supported { + return keys %mappings; +} + +sub _get_thpppt { + my $y = q{_ /|,\\'!.x',=(www)=, U }; + $y =~ tr/,x!w/\nOo_/; + return $y; +} + +sub _thpppt { + my $y = _get_thpppt(); + App::Ack::print( "$y ack $_[0]!\n" ); + exit 0; +} + +sub _key { + my $str = lc shift; + $str =~ s/[^a-z]//g; + + return $str; +} + + +sub show_help { + my $help_arg = shift || 0; + + return show_help_types() if $help_arg =~ /^types?/; + + my $ignore_dirs = _listify( sort { _key($a) cmp _key($b) } keys %ignore_dirs ); + + App::Ack::print( <<"END_OF_HELP" ); +Usage: ack [OPTION]... PATTERN [FILE] + +Search for PATTERN in each source file in the tree from cwd on down. +If [FILES] is specified, then only those files/directories are checked. +ack may also search STDIN, but only if no FILE are specified, or if +one of FILES is "-". + +Default switches may be specified in ACK_OPTIONS environment variable or +an .ackrc file. If you want no dependency on the environment, turn it +off with --noenv. + +Example: ack -i select + +Searching: + -i, --ignore-case Ignore case distinctions in PATTERN + --[no]smart-case Ignore case distinctions in PATTERN, + only if PATTERN contains no upper case + Ignored if -i is specified + -v, --invert-match Invert match: select non-matching lines + -w, --word-regexp Force PATTERN to match only whole words + -Q, --literal Quote all metacharacters; PATTERN is literal + +Search output: + --line=NUM Only print line(s) NUM of each file + -l, --files-with-matches + Only print filenames containing matches + -L, --files-without-matches + Only print filenames with no matches + -o Show only the part of a line matching PATTERN + (turns off text highlighting) + --passthru Print all lines, whether matching or not + --output=expr Output the evaluation of expr for each line + (turns off text highlighting) + --match PATTERN Specify PATTERN explicitly. + -m, --max-count=NUM Stop searching in each file after NUM matches + -1 Stop searching after one match of any kind + -H, --with-filename Print the filename for each match + -h, --no-filename Suppress the prefixing filename on output + -c, --count Show number of lines matching per file + --column Show the column number of the first match + + -A NUM, --after-context=NUM + Print NUM lines of trailing context after matching + lines. + -B NUM, --before-context=NUM + Print NUM lines of leading context before matching + lines. + -C [NUM], --context[=NUM] + Print NUM lines (default 2) of output context. + + --print0 Print null byte as separator between filenames, + only works with -f, -g, -l, -L or -c. + +File presentation: + --pager=COMMAND Pipes all ack output through COMMAND. For example, + --pager="less -R". Ignored if output is redirected. + --nopager Do not send output through a pager. Cancels any + setting in ~/.ackrc, ACK_PAGER or ACK_PAGER_COLOR. + --[no]heading Print a filename heading above each file's results. + (default: on when used interactively) + --[no]break Print a break between results from different files. + (default: on when used interactively) + --group Same as --heading --break + --nogroup Same as --noheading --nobreak + --[no]color Highlight the matching text (default: on unless + output is redirected, or on Windows) + --[no]colour Same as --[no]color + --color-filename=COLOR + --color-match=COLOR Set the color for matches and filenames. + --flush Flush output immediately, even when ack is used + non-interactively (when output goes to a pipe or + file). + +File finding: + -f Only print the files found, without searching. + The PATTERN must not be specified. + -g REGEX Same as -f, but only print files matching REGEX. + --sort-files Sort the found files lexically. + +File inclusion/exclusion: + -a, --all-types All file types searched; + Ignores CVS, .svn and other ignored directories + -u, --unrestricted All files and directories searched + --[no]ignore-dir=name Add/Remove directory from the list of ignored dirs + -r, -R, --recurse Recurse into subdirectories (ack's default behavior) + -n, --no-recurse No descending into subdirectories + -G REGEX Only search files that match REGEX + + --perl Include only Perl files. + --type=perl Include only Perl files. + --noperl Exclude Perl files. + --type=noperl Exclude Perl files. + See "ack --help type" for supported filetypes. + + --type-set TYPE=.EXTENSION[,.EXT2[,...]] + Files with the given EXTENSION(s) are recognized as + being of type TYPE. This replaces an existing + definition for type TYPE. + --type-add TYPE=.EXTENSION[,.EXT2[,...]] + Files with the given EXTENSION(s) are recognized as + being of (the existing) type TYPE + + --[no]follow Follow symlinks. Default is off. + + Directories ignored by default: + $ignore_dirs + + Files not checked for type: + /~\$/ - Unix backup files + /#.+#\$/ - Emacs swap files + /[._].*\\.swp\$/ - Vi(m) swap files + /core\\.\\d+\$/ - core dumps + +Miscellaneous: + --noenv Ignore environment variables and ~/.ackrc + --help This help + --man Man page + --version Display version & copyright + --thpppt Bill the Cat + +Exit status is 0 if match, 1 if no match. + +This is version $VERSION of ack. +END_OF_HELP + + return; + } + + + +sub show_help_types { + App::Ack::print( <<'END_OF_HELP' ); +Usage: ack [OPTION]... PATTERN [FILES] + +The following is the list of filetypes supported by ack. You can +specify a file type with the --type=TYPE format, or the --TYPE +format. For example, both --type=perl and --perl work. + +Note that some extensions may appear in multiple types. For example, +.pod files are both Perl and Parrot. + +END_OF_HELP + + my @types = filetypes_supported(); + my $maxlen = 0; + for ( @types ) { + $maxlen = length if $maxlen < length; + } + for my $type ( sort @types ) { + next if $type =~ /^-/; # Stuff to not show + my $ext_list = $mappings{$type}; + + if ( ref $ext_list ) { + $ext_list = join( ' ', map { ".$_" } @{$ext_list} ); + } + App::Ack::print( sprintf( " --[no]%-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) ); + } + + return; +} + +sub _listify { + my @whats = @_; + + return '' if !@whats; + + my $end = pop @whats; + my $str = @whats ? join( ', ', @whats ) . " and $end" : $end; + + no warnings 'once'; + require Text::Wrap; + $Text::Wrap::columns = 75; + return Text::Wrap::wrap( '', ' ', $str ); +} + + +sub get_version_statement { + require Config; + + my $copyright = get_copyright(); + my $this_perl = $Config::Config{perlpath}; + if ($^O ne 'VMS') { + my $ext = $Config::Config{_exe}; + $this_perl .= $ext unless $this_perl =~ m/$ext$/i; + } + my $ver = sprintf( '%vd', $^V ); + + return <<"END_OF_VERSION"; +ack $VERSION +Running under Perl $ver at $this_perl + +$copyright + +This program is free software; you can redistribute it and/or modify +it under the terms of either: the GNU General Public License as +published by the Free Software Foundation; or the Artistic License. +END_OF_VERSION +} + + +sub print_version_statement { + App::Ack::print( get_version_statement() ); + + return; +} + + +sub get_copyright { + return $COPYRIGHT; +} + + +sub load_colors { + eval 'use Term::ANSIColor ()'; + + $ENV{ACK_COLOR_MATCH} ||= 'black on_yellow'; + $ENV{ACK_COLOR_FILENAME} ||= 'bold green'; + + return; +} + + +sub is_interesting { + return if /^\./; + + my $include; + + for my $type ( filetypes( $File::Next::name ) ) { + if ( defined $type_wanted{$type} ) { + if ( $type_wanted{$type} ) { + $include = 1; + } + else { + return; + } + } + } + + return $include; +} + + + +# print subs added in order to make it easy for a third party +# module (such as App::Wack) to redefine the display methods +# and show the results in a different way. +sub print { print {$fh} @_ } +sub print_first_filename { App::Ack::print( $_[0], "\n" ) } +sub print_blank_line { App::Ack::print( "\n" ) } +sub print_separator { App::Ack::print( "--\n" ) } +sub print_filename { App::Ack::print( $_[0], $_[1] ) } +sub print_line_no { App::Ack::print( $_[0], $_[1] ) } +sub print_column_no { App::Ack::print( $_[0], $_[1] ) } +sub print_count { + my $filename = shift; + my $nmatches = shift; + my $ors = shift; + my $count = shift; + + App::Ack::print( $filename ); + App::Ack::print( ':', $nmatches ) if $count; + App::Ack::print( $ors ); +} + +sub print_count0 { + my $filename = shift; + my $ors = shift; + + App::Ack::print( $filename, ':0', $ors ); +} + + + +{ + my $filename; + my $regex; + my $display_filename; + + my $keep_context; + + my $last_output_line; # number of the last line that has been output + my $any_output; # has there been any output for the current file yet + my $context_overall_output_count; # has there been any output at all + +sub search_resource { + my $res = shift; + my $opt = shift; + + $filename = $res->name(); + + my $v = $opt->{v}; + my $passthru = $opt->{passthru}; + my $max = $opt->{m}; + my $nmatches = 0; + + $display_filename = undef; + + # for --line processing + my $has_lines = 0; + my @lines; + if ( defined $opt->{lines} ) { + $has_lines = 1; + @lines = ( @{$opt->{lines}}, -1 ); + undef $regex; # Don't match when printing matching line + } + else { + $regex = qr/$opt->{regex}/; + } + + # for context processing + $last_output_line = -1; + $any_output = 0; + my $before_context = $opt->{before_context}; + my $after_context = $opt->{after_context}; + + $keep_context = ($before_context || $after_context) && !$passthru; + + my @before; + my $before_starts_at_line; + my $after = 0; # number of lines still to print after a match + + while ( $res->next_text ) { + # XXX Optimize away the case when there are no more @lines to find. + # XXX $has_lines, $passthru and $v never change. Optimize. + if ( $has_lines + ? $. != $lines[0] # $lines[0] should be a scalar + : $v ? m/$regex/ : !m/$regex/ ) { + if ( $passthru ) { + App::Ack::print( $_ ); + next; + } + + if ( $keep_context ) { + if ( $after ) { + print_match_or_context( $opt, 0, $., $-[0], $+[0], $_ ); + $after--; + } + elsif ( $before_context ) { + if ( @before ) { + if ( @before >= $before_context ) { + shift @before; + ++$before_starts_at_line; + } + } + else { + $before_starts_at_line = $.; + } + push @before, $_; + } + last if $max && ( $nmatches >= $max ) && !$after; + } + next; + } # not a match + + ++$nmatches; + + # print an empty line as a divider before first line in each file (not before the first file) + if ( !$any_output && $opt->{show_filename} && $opt->{break} && defined( $context_overall_output_count ) ) { + App::Ack::print_blank_line(); + } + + shift @lines if $has_lines; + + if ( $res->is_binary ) { + App::Ack::print( "Binary file $filename matches\n" ); + last; + } + if ( $keep_context ) { + if ( @before ) { + print_match_or_context( $opt, 0, $before_starts_at_line, $-[0], $+[0], @before ); + @before = (); + $before_starts_at_line = 0; + } + if ( $max && $nmatches > $max ) { + --$after; + } + else { + $after = $after_context; + } + } + print_match_or_context( $opt, 1, $., $-[0], $+[0], $_ ); + + last if $max && ( $nmatches >= $max ) && !$after; + } # while + + return $nmatches; +} # search_resource() + + + +sub print_match_or_context { + my $opt = shift; # opts array + my $is_match = shift; # is there a match on the line? + my $line_no = shift; + my $match_start = shift; + my $match_end = shift; + + my $color = $opt->{color}; + my $heading = $opt->{heading}; + my $show_filename = $opt->{show_filename}; + my $show_column = $opt->{column}; + + if ( $show_filename ) { + if ( not defined $display_filename ) { + $display_filename = + $color + ? Term::ANSIColor::colored( $filename, $ENV{ACK_COLOR_FILENAME} ) + : $filename; + if ( $heading && !$any_output ) { + App::Ack::print_first_filename($display_filename); + } + } + } + + my $sep = $is_match ? ':' : '-'; + my $output_func = $opt->{output}; + for ( @_ ) { + if ( $keep_context && !$output_func ) { + if ( ( $last_output_line != $line_no - 1 ) && + ( $any_output || ( !$heading && defined( $context_overall_output_count ) ) ) ) { + App::Ack::print_separator(); + } + # to ensure separators between different files when --noheading + + $last_output_line = $line_no; + } + + if ( $show_filename ) { + App::Ack::print_filename($display_filename, $sep) if not $heading; + App::Ack::print_line_no($line_no, $sep); + } + + if ( $output_func ) { + while ( /$regex/go ) { + App::Ack::print( $output_func->() . "\n" ); + } + } + else { + if ( $color && $is_match && $regex && + s/$regex/Term::ANSIColor::colored( substr($_, $-[0], $+[0] - $-[0]), $ENV{ACK_COLOR_MATCH} )/eg ) { + # At the end of the line reset the color and remove newline + s/[\r\n]*\z/\e[0m\e[K/; + } + else { + # remove any kind of newline at the end of the line + s/[\r\n]*\z//; + } + if ( $show_column ) { + App::Ack::print_column_no( $match_start+1, $sep ); + } + App::Ack::print($_ . "\n"); + } + $any_output = 1; + ++$context_overall_output_count; + ++$line_no; + } + + return; +} # print_match_or_context() + +} # scope around search_resource() and print_match_or_context() + + + +sub search_and_list { + my $res = shift; + my $opt = shift; + + my $nmatches = 0; + my $count = $opt->{count}; + my $ors = $opt->{print0} ? "\0" : "\n"; # output record separator + + my $regex = qr/$opt->{regex}/; + + if ( $opt->{v} ) { + while ( $res->next_text ) { + if ( /$regex/ ) { + return 0 unless $count; + } + else { + ++$nmatches; + } + } + } + else { + while ( $res->next_text ) { + if ( /$regex/ ) { + ++$nmatches; + last unless $count; + } + } + } + + if ( $nmatches ) { + App::Ack::print_count( $res->name, $nmatches, $ors, $count ); + } + elsif ( $count && !$opt->{l} ) { + App::Ack::print_count0( $res->name, $ors ); + } + + return $nmatches ? 1 : 0; +} # search_and_list() + + + +sub filetypes_supported_set { + return grep { defined $type_wanted{$_} && ($type_wanted{$_} == 1) } filetypes_supported(); +} + + + +sub print_files { + my $iter = shift; + my $opt = shift; + + my $ors = $opt->{print0} ? "\0" : "\n"; + + while ( defined ( my $file = $iter->() ) ) { + App::Ack::print $file, $ors; + last if $opt->{1}; + } + + return; +} + + +sub print_files_with_matches { + my $iter = shift; + my $opt = shift; + + my $nmatches = 0; + while ( defined ( my $filename = $iter->() ) ) { + my $repo = App::Ack::Repository::Basic->new( $filename ); + my $res; + while ( $res = $repo->next_resource() ) { + $nmatches += search_and_list( $res, $opt ); + $res->close(); + last if $nmatches && $opt->{1}; + } + $repo->close(); + } + + return $nmatches; +} + + +sub print_matches { + my $iter = shift; + my $opt = shift; + + $opt->{show_filename} = 0 if $opt->{h}; + $opt->{show_filename} = 1 if $opt->{H}; + + my $nmatches = 0; + while ( defined ( my $filename = $iter->() ) ) { + my $repo; + my $tarballs_work = 0; + if ( $tarballs_work && $filename =~ /\.tar\.gz$/ ) { + App::Ack::die( 'Not working here yet' ); + require App::Ack::Repository::Tar; # XXX Error checking + $repo = App::Ack::Repository::Tar->new( $filename ); + } + else { + $repo = App::Ack::Repository::Basic->new( $filename ); + } + $repo or next; + + while ( my $res = $repo->next_resource() ) { + my $needs_line_scan; + if ( $opt->{regex} && !$opt->{passthru} ) { + $needs_line_scan = $res->needs_line_scan( $opt ); + if ( $needs_line_scan ) { + $res->reset(); + } + } + else { + $needs_line_scan = 1; + } + if ( $needs_line_scan ) { + $nmatches += search_resource( $res, $opt ); + } + $res->close(); + } + last if $nmatches && $opt->{1}; + $repo->close(); + } + return $nmatches; +} + + +sub filetype_setup { + my $filetypes_supported_set = filetypes_supported_set(); + # If anyone says --no-whatever, we assume all other types must be on. + if ( !$filetypes_supported_set ) { + for my $i ( keys %type_wanted ) { + $type_wanted{$i} = 1 unless ( defined( $type_wanted{$i} ) || $i eq 'binary' || $i eq 'text' || $i eq 'skipped' ); + } + } + return; +} + + +EXPAND_FILENAMES_SCOPE: { + my $filter; + + sub expand_filenames { + my $argv = shift; + + my $attr; + my @files; + + foreach my $pattern ( @{$argv} ) { + my @results = bsd_glob( $pattern ); + + if (@results == 0) { + @results = $pattern; # Glob didn't match, pass it thru unchanged + } + elsif ( (@results > 1) or ($results[0] ne $pattern) ) { + if (not defined $filter) { + eval 'require Win32::File;'; + if ($@) { + $filter = 0; + } + else { + $filter = Win32::File::HIDDEN()|Win32::File::SYSTEM(); + } + } # end unless we've tried to load Win32::File + if ( $filter ) { + # Filter out hidden and system files: + @results = grep { not(Win32::File::GetAttributes($_, $attr) and $attr & $filter) } @results; + App::Ack::warn( "$pattern: Matched only hidden files" ) unless @results; + } # end if we can filter by file attributes + } # end elsif this pattern got expanded + + push @files, @results; + } # end foreach pattern + + return \@files; + } # end expand_filenames +} # EXPAND_FILENAMES_SCOPE + + + +sub get_starting_points { + my $argv = shift; + my $opt = shift; + + my @what; + + if ( @{$argv} ) { + @what = @{ $is_windows ? expand_filenames($argv) : $argv }; + $_ = File::Next::reslash( $_ ) for @what; + + # Show filenames unless we've specified one single file + $opt->{show_filename} = (@what > 1) || (!-f $what[0]); + } + else { + @what = '.'; # Assume current directory + $opt->{show_filename} = 1; + } + + for my $start_point (@what) { + App::Ack::warn( "$start_point: No such file or directory" ) unless -e $start_point; + } + return \@what; +} + + + +sub get_iterator { + my $what = shift; + my $opt = shift; + + # Starting points are always searched, no matter what + my %starting_point = map { ($_ => 1) } @{$what}; + + my $g_regex = defined $opt->{G} ? qr/$opt->{G}/ : undef; + my $file_filter; + + if ( $g_regex ) { + $file_filter + = $opt->{u} ? sub { $File::Next::name =~ /$g_regex/ } # XXX Maybe this should be a 1, no? + : $opt->{all} ? sub { $starting_point{ $File::Next::name } || ( $File::Next::name =~ /$g_regex/ && is_searchable( $File::Next::name ) ) } + : sub { $starting_point{ $File::Next::name } || ( $File::Next::name =~ /$g_regex/ && is_interesting( @_ ) ) } + ; + } + else { + $file_filter + = $opt->{u} ? sub {1} + : $opt->{all} ? sub { $starting_point{ $File::Next::name } || is_searchable( $File::Next::name ) } + : sub { $starting_point{ $File::Next::name } || is_interesting( @_ ) } + ; + } + + my $descend_filter + = $opt->{n} ? sub {0} + : $opt->{u} ? sub {1} + : \&ignoredir_filter; + + my $iter = + File::Next::files( { + file_filter => $file_filter, + descend_filter => $descend_filter, + error_handler => sub { my $msg = shift; App::Ack::warn( $msg ) }, + sort_files => $opt->{sort_files}, + follow_symlinks => $opt->{follow}, + }, @{$what} ); + return $iter; +} + + +sub set_up_pager { + my $command = shift; + + return unless App::Ack::output_to_pipe(); + + my $pager; + if ( not open( $pager, '|-', $command ) ) { + App::Ack::die( qq{Unable to pipe to pager "$command": $!} ); + } + $fh = $pager; + + return; +} + + +sub input_from_pipe { + return $input_from_pipe; +} + + + +sub output_to_pipe { + return $output_to_pipe; +} + + + +1; # End of App::Ack +package App::Ack::Repository; + + +use warnings; +use strict; + +sub FAIL { + require Carp; + Carp::confess( 'Must be overloaded' ); +} + + +sub new { + FAIL(); +} + + +sub next_resource { + FAIL(); +} + + +sub close { + FAIL(); +} + +1; +package App::Ack::Resource; + + +use warnings; +use strict; + +sub FAIL { + require Carp; + Carp::confess( 'Must be overloaded' ); +} + + +sub new { + FAIL(); +} + + +sub name { + FAIL(); +} + + +sub is_binary { + FAIL(); +} + + + +sub needs_line_scan { + FAIL(); +} + + +sub reset { + FAIL(); +} + + +sub next_text { + FAIL(); +} + + +sub close { + FAIL(); +} + +1; +package App::Ack::Plugin::Basic; + + + +package App::Ack::Resource::Basic; + + +use warnings; +use strict; + + +our @ISA = qw( App::Ack::Resource ); + + +sub new { + my $class = shift; + my $filename = shift; + + my $self = bless { + filename => $filename, + fh => undef, + could_be_binary => undef, + opened => undef, + id => undef, + }, $class; + + if ( $self->{filename} eq '-' ) { + $self->{fh} = *STDIN; + $self->{could_be_binary} = 0; + } + else { + if ( !open( $self->{fh}, '<', $self->{filename} ) ) { + App::Ack::warn( "$self->{filename}: $!" ); + return; + } + $self->{could_be_binary} = 1; + } + + return $self; +} + + +sub name { + my $self = shift; + + return $self->{filename}; +} + + +sub is_binary { + my $self = shift; + + if ( $self->{could_be_binary} ) { + return -B $self->{filename}; + } + + return 0; +} + + + +sub needs_line_scan { + my $self = shift; + my $opt = shift; + + return 1 if $opt->{v}; + + my $size = -s $self->{fh}; + if ( $size == 0 ) { + return 0; + } + elsif ( $size > 100_000 ) { + return 1; + } + + my $buffer; + my $rc = sysread( $self->{fh}, $buffer, $size ); + if ( not defined $rc ) { + App::Ack::warn( "$self->{filename}: $!" ); + return 1; + } + return 0 unless $rc && ( $rc == $size ); + + my $regex = $opt->{regex}; + return $buffer =~ /$regex/m; +} + + +sub reset { + my $self = shift; + + seek( $self->{fh}, 0, 0 ) + or App::Ack::warn( "$self->{filename}: $!" ); + + return; +} + + +sub next_text { + if ( defined ($_ = readline $_[0]->{fh}) ) { + $. = ++$_[0]->{line}; + return 1; + } + + return; +} + + +sub close { + my $self = shift; + + if ( not close $self->{fh} ) { + App::Ack::warn( $self->name() . ": $!" ); + } + + return; +} + +package App::Ack::Repository::Basic; + + +our @ISA = qw( App::Ack::Repository ); + + +use warnings; +use strict; + +sub new { + my $class = shift; + my $filename = shift; + + my $self = bless { + filename => $filename, + nexted => 0, + }, $class; + + return $self; +} + + +sub next_resource { + my $self = shift; + + return if $self->{nexted}; + $self->{nexted} = 1; + + return App::Ack::Resource::Basic->new( $self->{filename} ); +} + + +sub close { +} + + + +1; diff --git a/dejagnu/PKGBUILD b/dejagnu/PKGBUILD new file mode 100644 index 0000000..1c793a5 --- /dev/null +++ b/dejagnu/PKGBUILD @@ -0,0 +1,28 @@ +# Contributor: Flavio S. Truzzi (pirunga@gmail.com) +pkgname=dejagnu +pkgver=1.4.4 +pkgrel=2 +pkgdesc="GNU framework for testing other programs." +url="https://www.gnu.org/software/dejagnu/" +license=('GPL') +arch=('i686' 'x86_64') +depends=() +makedepends=() +conflicts=() +replaces=() +backup=() +install= +noextract=() +source=(http://ftp.gnu.org/gnu/dejagnu/$pkgname-$pkgver.tar.gz) +md5sums=(053f18fd5d00873de365413cab17a666) + +build() { + cd $startdir/src/$pkgname-$pkgver + + ./configure --prefix=/usr + + make || return 1 + make DESTDIR=$startdir/pkg install + + find $startdir/pkg -name "*.la" -exec rm -f '{}' \; +} diff --git a/foo2zjs/PKGBUILD b/foo2zjs/PKGBUILD new file mode 100644 index 0000000..43c0f94 --- /dev/null +++ b/foo2zjs/PKGBUILD @@ -0,0 +1,31 @@ +#Contributor: Stefan Lohmaier +#Contributor: hubert_star +pkgname=foo2zjs +pkgver=20090424 +pkgrel=1 +pkgdesc="ZJStream Printer Drivers." +url="http://foo2zjs.rkkda.com/" +license="GPL" +depends=(psutils cups foomatic-db-engine) +makedepends=(wget unzip patch vim) +arch=(i686 x86_64) +install=foo2zjs.install +source=(makefile.patch) +md5sums=('46042339057e6390c98236a9da8b01ee') + +build() { + cd "$srcdir" + rm -f $pkgname.tar.gz + wget "http://foo2zjs.rkkda.com/$pkgname.tar.gz" + tar xfz $pkgname.tar.gz + cd $pkgname + patch -Np1 < ../makefile.patch || return 1 + make || return 1 + ./getweb all || return 1 + mkdir -p $pkgdir/usr/bin $pkgdir/etc/udev/rules.d $pkgdir/bin + mkdir -p $pkgdir/usr/share/{foomatic/db/source/opt,/cups/model} + make DESTDIR=$pkgdir install || return 1 + make DESTDIR=$pkgdir install-hotplug || return 1 + + chmod 755 $pkgdir/usr/share/{foo2oak/icm,foo2hp/icm,foo2zjs/crd,foo2zjs/firmware,foo2zjs/icm,foo2hiperc/icm,foo2lava/icm,foo2xqx/firmware,foo2qpdl/crd,foo2qpdl/icm,foo2slx/icm} +} diff --git a/foo2zjs/foo2zjs.install b/foo2zjs/foo2zjs.install new file mode 100644 index 0000000..284f90b --- /dev/null +++ b/foo2zjs/foo2zjs.install @@ -0,0 +1,48 @@ +# This is a default template for a post-install scriptlet. You can +# remove any functions you don't need (and this header). + +# arg 1: the new package version +pre_install() { + /bin/true +} + +# arg 1: the new package version +post_install() { + echo "-------------------------" + echo "You need to restart cups." + echo "-------------------------" + echo + echo "You need to add your user to the group \"lp\"." +} + +# arg 1: the new package version +# arg 2: the old package version +pre_upgrade() { + /bin/true +} + +# arg 1: the new package version +# arg 2: the old package version +post_upgrade() { + echo "-------------------------" + echo "You need to restart cups." + echo "-------------------------" + +} + +# arg 1: the old package version +pre_remove() { + /bin/true +} + +# arg 1: the old package version +post_remove() { + echo "-------------------------" + echo "You need to restart cups." + echo "-------------------------" + +} + +op=$1 +shift +$op $* diff --git a/foo2zjs/makefile.patch b/foo2zjs/makefile.patch new file mode 100644 index 0000000..b2d99e6 --- /dev/null +++ b/foo2zjs/makefile.patch @@ -0,0 +1,45 @@ +Binary files foo2zjsold/.Makefile.swp and foo2zjs/.Makefile.swp differ +diff -ruN foo2zjsold/Makefile foo2zjs/Makefile +--- foo2zjsold/Makefile 2009-02-23 20:18:37.793066344 +0100 ++++ foo2zjs/Makefile 2009-02-23 20:21:59.653063789 +0100 +@@ -810,28 +810,18 @@ + # + + install-hotplug-prog: +- if [ -d $(UDEVDIR) ]; then \ +- $(INSTALL) -c -m 644 $(RULES) $(UDEVDIR)/11-$(RULES); \ +- fi +- [ -d $(USBDIR) ] || $(INSTALL) -d -m 755 $(USBDIR)/ +- $(INSTALL) -c -m 755 hplj1000 $(USBDIR)/ +- ln -sf $(USBDIR)/hplj1000 $(USBDIR)/hplj1005 +- ln -sf $(USBDIR)/hplj1000 $(USBDIR)/hplj1018 +- ln -sf $(USBDIR)/hplj1000 $(USBDIR)/hplj1020 +- ln -sf $(USBDIR)/hplj1000 $(USBDIR)/hpljP1005 +- ln -sf $(USBDIR)/hplj1000 $(USBDIR)/hpljP1006 +- ln -sf $(USBDIR)/hplj1000 $(USBDIR)/hpljP1007 +- ln -sf $(USBDIR)/hplj1000 $(USBDIR)/hpljP1008 +- ln -sf $(USBDIR)/hplj1000 $(USBDIR)/hpljP1505 +- $(USBDIR)/hplj1000 install-usermap +- $(USBDIR)/hplj1005 install-usermap +- $(USBDIR)/hplj1018 install-usermap +- $(USBDIR)/hplj1020 install-usermap +- $(USBDIR)/hpljP1005 install-usermap +- $(USBDIR)/hpljP1006 install-usermap +- $(USBDIR)/hpljP1007 install-usermap +- $(USBDIR)/hpljP1008 install-usermap +- $(USBDIR)/hpljP1505 install-usermap ++ [ -d $(DESTDIR)/$(UDEVDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)/$(UDEVDIR)/11-$(RULES) ++ $(INSTALL) -c -m 644 $(RULES) $(DESTDIR)/$(UDEVDIR)/11-$(RULES) ++ [ -d $(DESTDIR)/$(USBDIR) ] || $(INSTALL) -d -m 755 $(DESTDIR)/$(USBDIR)/ ++ $(INSTALL) -c -m 755 hplj1000 $(DESTDIR)/$(USBDIR)/ ++ ln -sf $(USBDIR)/hplj1000 $(DESTDIR)/$(USBDIR)/hplj1005 ++ ln -sf $(USBDIR)/hplj1000 $(DESTDIR)/$(USBDIR)/hplj1018 ++ ln -sf $(USBDIR)/hplj1000 $(DESTDIR)/$(USBDIR)/hplj1020 ++ ln -sf $(USBDIR)/hplj1000 $(DESTDIR)/$(USBDIR)/hpljP1005 ++ ln -sf $(USBDIR)/hplj1000 $(DESTDIR)/$(USBDIR)/hpljP1006 ++ ln -sf $(USBDIR)/hplj1000 $(DESTDIR)/$(USBDIR)/hpljP1007 ++ ln -sf $(USBDIR)/hplj1000 $(DESTDIR)/$(USBDIR)/hpljP1008 ++ ln -sf $(USBDIR)/hplj1000 $(DESTDIR)/$(USBDIR)/hpljP1505 + + cups: FRC + if [ -x /etc/init.d/cups ]; then \ diff --git a/initscripts-git/PKGBUILD b/initscripts-git/PKGBUILD index da6c056..b5c9b49 100644 --- a/initscripts-git/PKGBUILD +++ b/initscripts-git/PKGBUILD @@ -2,7 +2,7 @@ # Maintainer: Aaron Griffin pkgname=initscripts-git -pkgver=20090720 +pkgver=20090905 pkgrel=1 pkgdesc="System initialization/bootup scripts - GIT version" arch=('i686' 'x86_64') diff --git a/inxi/PKGBUILD b/inxi/PKGBUILD new file mode 100644 index 0000000..781f3c4 --- /dev/null +++ b/inxi/PKGBUILD @@ -0,0 +1,18 @@ +# Contributor: Florian Pritz +pkgname=inxi +pkgver=1.1.13 +pkgrel=1 +pkgdesc="script to get system information" +arch=('any') +url="http://inxi.org" +license=('GPL') +source=("http://inxi.googlecode.com/svn/trunk/inxi") + +build() { + cd "$srcdir" + install -D -m755 inxi $pkgdir/usr/bin/inxi +} + +# vim:set ts=2 sw=2 et: +md5sums=('c5c2830ede9eed63d2434527e56ee541') +sha256sums=('3d8f0736829754f7aa2d7f85ba3e8bb5b7bd0b3c7ac110abe6c66b440109b5d2') diff --git a/inxi/inxi b/inxi/inxi new file mode 100644 index 0000000..f857208 --- /dev/null +++ b/inxi/inxi @@ -0,0 +1,4428 @@ +#!/bin/bash +######################################################################## +#### Script Name: inxi +#### version: 1.1.13 +#### Date: August 6 2009 +######################################################################## +#### SPECIAL THANKS +######################################################################## +#### Special thanks to all those in #lsc and #smxi for their tireless +#### dedication helping test inxi modules. +######################################################################## +#### ABOUT INXI +######################################################################## +#### inxi is a fork of infobash 3.02, the original bash sys info script by locsmif +#### As time permits functionality improvements and recoding will occur. +#### +#### inxi, the universal, portable, system info script for irc. +#### Tested with Irssi, Xchat, Konversation, BitchX, KSirc, ircII, +#### Gaim/Pidgin, Weechat, KVIrc and Kopete. +#### Original infobash author and copyright holder: +#### Copyright (C) 2005-2007 Michiel de Boer a.k.a. locsmif +#### inxi version: Copyright (C) 2008-9 Scott Rogers & Harald Hope +#### Further fixes (listed as known): Horst Tritremmel +#### Steven Barrett (aka: damentz) - usb audio patch; swap percent used patch +#### +#### Current script home page: http://techpatterns.com/forums/about1131.html +#### Script svn: http://code.google.com/p/inxi +#### +#### This program is free software; you can redistribute it and/or modify +#### it under the terms of the GNU General Public License as published by +#### the Free Software Foundation; either version 3 of the License, or +#### (at your option) any later version. +#### +#### This program is distributed in the hope that it will be useful, +#### but WITHOUT ANY WARRANTY; without even the implied warranty of +#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#### GNU General Public License for more details. +#### +#### You should have received a copy of the GNU General Public License +#### along with this program. If not, see . +#### +#### If you don't understand what Free Software is, please read (or reread) +#### this page: http://www.gnu.org/philosophy/free-sw.html +######################################################################## +#### DEPENDENCIES +#### bash >=3.0(bash), df;readlink;stty;tr;uname;wc(coreutils), +#### gawk(gawk), grep(grep), hostname(hostname), lspci(pciutils), +#### ps;uptime(procps), glxinfo;xdpyinfo;xrandr(xbase-clients) +#### Also the proc filesystem should be present and mounted +#### +#### Apparently unpatched bash 3.0 has arrays broken; bug reports: +#### http://ftp.gnu.org/gnu/bash/bash-3.0-patches/bash30-008 +#### http://lists.gnu.org/archive/html/bug-bash/2004-08/msg00144.html +#### +#### Arrays work in bash 2.05b, but "egrep -m" does not +#### +#### RECOMMENDS (Needed to run certain features) +#### For local interfaces/IP test: ifconfig (in net-tools for Debian systems) +#### runlevel(sysvinit): to view current runlevel while not in X window system +#### Bash 3.1 for proper array use +######################################################################## +#### CONVENTIONS: +#### Indentation: TABS +#### Do not use `....` (back quotes), those are totally non-reabable, use $(....). +#### Do not use one liner flow controls. +#### The ONLY time you should use ';' (semi-colon) is in this single case: if [[ condition ]];then. +#### Never use compound 'if': ie, if [[ condition ]] && statement. +#### Note: [[ -n $something ]] - double brackets does not require quotes for variables: ie, "$something". +#### Always use quotes, double or single, for all string values. +#### +#### All new code/methods must be in a function. +#### For all boolean tests, use 'true' / 'false'. +#### !! Do NOT use 0 or 1 unless it's a function return. +#### Avoid complicated tests in the if condition itself. +#### To 'return' a value in a function, use 'echo '. +#### +#### For gawk: use always if ( num_of_cores > 1 ) { hanging { starter for all blocks +#### This lets us use one method for all gawk structures, including BEGIN/END, if, for, etc +#### +#### VARIABLE/FUNCTION NAMING: +#### All functions should follow standard naming--verb adjective noun. +#### ie, get_cpu_data +#### All variables MUST be initialized / declared explicitly. +#### All variables should clearly explain what they are, except counters like i, j. +#### Each word of variable must be separated by '_' (underscore) (camel form). +#### Global variables are 'UPPER CASE', at top of script. +#### ie, SOME_VARIABLE='' +#### Local variables are 'lower case' and declared at the top of the function. +#### ie, some_variable='' +#### Locals that will be inherited by child functions have first char capitalized (so you know they are inherited). +#### ie, Some_Variable +#### +#### Booleans should start with b_ (local) or B_ (global) and state clearly what is being tested. +#### Arrays should start with a_ (local) or A_ (global). +#### +#### SPECIAL NOTES: +#### The color variable ${C2} must always be followed by a space unless you know what +#### character is going to be next for certain. Otherwise irc color codes can be accidentally +#### activated or altered. +#### +#### For native script konversation support (check distro for correct konvi scripts path): +#### ln -s /usr/share/apps/konversation/scripts/inxi +#### DCOP doesn't like \n, so avoid using it for most output unless required, as in error messages. +#### +#### As with all 'rules' there are acceptions, these are noted where used. +#### +################################################################################### +#### KDE Konversation information. Moving from dcop(qt3/KDE3) to dbus(qt4/KDE4) +################################################################################### +#### dcop and dbus -- these talk back to Konversation from this script +#### +#### Scripting info -- http://konversation.berlios.de/docs/scripting.html +#### -- http://www.kde.org.uk/apps/konversation/ +#### +#### dbus info -- http://dbus.freedesktop.org/doc/dbus-tutorial.html +#### view dbus info -- https://fedorahosted.org/d-feet/ +#### -- or run qdbus +#### Konvi dbus/usage-- qdbus org.kde.konversation /irc say +#### +#### Python usage -- http://wiki.python.org/moin/DbusExamples (just in case) +#### +#### Because webpages come and go, the above information needs to be moved to inxi's wiki +#### +######################################################################## +#### Valuable Resources +#### gawk arrays: http://www.math.utah.edu/docs/info/gawk_12.html +######################################################################## +#### TESTING FLAGS +#### inxi supports advanced testing triggers to do various things, using -! +#### -! 1 - triggers default B_TESTING_1='true' to trigger some test or other +#### -! 2 - triggers default B_TESTING_2='true' to trigger some test or other +#### -! 3 - triggers B_TESTING_1='true' and B_TESTING_2='true' +#### -! 10 - triggers an update from the primary dev download server instead of svn +#### -! 11 - triggers an update from svn branch one - if present, of course +#### -! 12 - triggers an update from svn branch two - if present, of course +#### -! 13 - triggers an update from svn branch three - if present, of course +#### -! 14 - triggers an update from svn branch four - if present, of course +#### -! - Triggers an update from whatever server you list. +#### LOG FLAGS (logs to $HOME/.inxi/inxi.log with rotate 3 total) +#### -@ 8 - Basic data logging of generated data / array values +#### -@ 9 - Full logging of all data used, including cat of files and system data +#### -@ 10 - Basic data logging plus color code logging +######################################################################## +#### VARIABLES +######################################################################## + +## NOTE: we can use hwinfo if it's available in all systems, or most, to get +## a lot more data and verbosity levels going +# set to default LANG to avoid locales errors with , or . +LANG=C +### Variable initializations: null values +CMDL_MAX='' +COLOR_SCHEME='' +COLOR_SCHEME_SET='' +IRC_CLIENT='' +IRC_CLIENT_VERSION='' + +### primary data array holders ## usage: 'A_' +A_AUDIO_DATA='' +A_CMDL='' +A_CPU_CORE_DATA='' +A_CPU_DATA='' +A_CPU_TYPE_PCNT_CCNT='' +A_DEBUG_BUFFER='' +A_GFX_CARD_DATA='' +A_GLX_DATA='' +A_HDD_DATA='' +A_INTERFACES_DATA='' +A_NETWORK_DATA='' +A_PARTITION_DATA='' +A_SENSORS_DATA='' +A_X_DATA='' + +### Boolean true/false globals ## usage: 'B_' +# flag to allow distro maintainers to turn off update features. If false, turns off +# -U and -! testing/advanced update options, as well as removing the -U help menu item +B_ALLOW_UPDATE='true' +# triggers full display of cpu flags +B_CPU_FLAGS_FULL='false' +# Debug flood override: make 'true' to allow long debug output +B_DEBUG_FLOOD='false' +# show extra output data +B_EXTRA_DATA='false' +# override certain errors due to currupted data +B_HANDLE_CORRUPT_DATA='false' +B_LOG_COLORS='false' +B_LOG_FULL_DATA='false' +B_ROOT='false' +# Running in a shell? Defaults to false, and is determined later. +B_RUNNING_IN_SHELL='false' +# this sets the debug buffer +B_SCRIPT_UP='false' +# sensors only if installed +B_SENSORS='false' +# Show sound card data +B_SHOW_AUDIO='false' +B_SHOW_CPU='false' +B_SHOW_DISK='false' +# Show full hard disk output +B_SHOW_FULL_HDD='false' +B_SHOW_GRAPHICS='false' +# Set this to 'false' to avoid printing the hostname +B_SHOW_HOST='true' +B_SHOW_INFO='false' +B_SHOW_IP='false' +B_SHOW_LABELS='false' +B_SHOW_NETWORK='false' +# either -v > 3 or -P will show partitions +B_SHOW_PARTITIONS='false' +B_SHOW_PARTITIONS_FULL='false' +B_SHOW_SENSORS='false' +# triggers only short inxi output +B_SHOW_SHORT_OUTPUT='false' +B_SHOW_SYSTEM='false' +B_SHOW_UUIDS='false' +# triggers various debugging and new option testing +B_TESTING_1='false' +B_TESTING_2='false' +# set to true here for debug logging from script start +B_USE_LOGGING='false' +# Test for X running +B_X_RUNNING='false' +# test for dbus irc client +B_DBUS_CLIENT='false' + +### Directory/file exist flags; test as [[ $(boolean) ]] not [[ $boolean ]] +B_PROC='false' +B_CPUINFO='false' +B_MEMINFO='false' +B_ASOUND_CARDS='false' +B_ASOUND_VERSION='false' +B_BASH_ARRAY='false' +B_IFCONFIG='false' +B_LSB_DIR='false' +B_SCSI_DIR='false' +B_MODULES_DIR='false' # +B_MOUNTS_DIR='false' +B_PARTITIONS_DIR='false' # + +### File's used when present +FILE_CPUINFO='/proc/cpuinfo' +FILE_MEMINFO='/proc/meminfo' +FILE_ASOUND_DEVICE='/proc/asound/cards' +FILE_ASOUND_VERSION='/proc/asound/version' +FILE_LSB_RELEASE='/etc/lsb-release' +FILE_SCSI='/proc/scsi/scsi' +FILE_MODULES='/proc/modules' +FILE_MOUNTS='/proc/mounts' +FILE_PARTITIONS='/proc/partitions' + +### Variable initializations: constants +DCOPOBJ="default" +DEBUG=0 # Set debug levels from 1-10 (8-10 trigger logging levels) +# Debug Buffer Index, index into a debug buffer storing debug messages until inxi is 'all up' +DEBUG_BUFFER_INDEX=0 +## note: the debugger rerouting to /dev/null has been moved to the end of the get_parameters function +## so -@[number] debug levels can be set if there is a failure, otherwise you can't even see the errors + +# Defaults to 2, make this 1 for normal, 0 for no colorcodes at all. Set to any other valid scheme you like. +# Same as runtime parameter. +DEFAULT_SCHEME=2 + +# Default indentation level +INDENT=10 + +# logging eval variables, start and end function: Insert to LOGFS LOGFE when debug level >= 8 +LOGFS_STRING='log_function_data fs $FUNCNAME "$( echo $@ )"' +LOGFE_STRING='log_function_data fe $FUNCNAME' +LOGFS='' +LOGFE='' +# uncomment for debugging from script start +# LOGFS=$LOGFS_STRING +# LOGFE=$LOGFE_STRING + +# default to false, no konversation found, 1 is native konvi (qt3/KDE3) script mode, 2 is /cmd inxi start, +## 3 is Konversation > 1.2 (qt4/KDE4) +KONVI=0 +# NO_CPU_COUNT=0 # Wether or not the string "dual" or similar is found in cpuinfo output. If so, avoid dups. +# This is a variable that controls how many parameters inxi will parse in a /proc//cmdline file before stopping. +PARAMETER_LIMIT=30 +SCHEME=0 # set default scheme +# this is set in user prefs file, to override dynamic temp1/temp2 determination of sensors output in case +# cpu runs colder than mobo +SENSORS_CPU_NO='' +# SHOW_IRC=1 to avoid showing the irc client version number, or SHOW_IRC=0 to disable client information completely. +SHOW_IRC=2 +# Verbosity level defaults to 0, this can also be set with -v0, -v2, -v3, etc as a parameter. +VERBOSITY_LEVEL=0 +# Supported number of verbosity levels, including 0 +VERBOSITY_LEVELS=5 + +# Clear nullglob, because it creates unpredictable situations with IFS=$'\n' ARR=($VAR) IFS="$ORIGINAL_IFS" +# type constructs. Stuff like [rev a1] is now seen as a glob expansion pattern, and fails, and +# therefore results in nothing. +shopt -u nullglob +## info on bash built in: $IFS - http://tldp.org/LDP/abs/html/internalvariables.html +# Backup the current Internal Field Separator +ORIGINAL_IFS="$IFS" + +# These two determine separators in single line output, to force irc clients not to break off sections +SEP1='-' +SEP2='~' + +### Script names/paths - must be non root writable +SCRIPT_DATA_DIR="$HOME/.inxi" +LOG_FILE="$SCRIPT_DATA_DIR/inxi.log" +LOG_FILE_1="$SCRIPT_DATA_DIR/inxi.1.log" +LOG_FILE_2="$SCRIPT_DATA_DIR/inxi.2.log" +SCRIPT_NAME="inxi" +SCRIPT_PATH="" #filled-in in Main +SCRIPT_VERSION_NUMBER="" #filled-in in Main +SCRIPT_DOWNLOAD='http://inxi.googlecode.com/svn/trunk/' +SCRIPT_DOWNLOAD_BRANCH_1='http://inxi.googlecode.com/svn/branches/one/' +SCRIPT_DOWNLOAD_BRANCH_2='http://inxi.googlecode.com/svn/branches/two/' +SCRIPT_DOWNLOAD_BRANCH_3='http://inxi.googlecode.com/svn/branches/three/' +SCRIPT_DOWNLOAD_BRANCH_4='http://inxi.googlecode.com/svn/branches/four/' +SCRIPT_DOWNLOAD_DEV='http://smxi.org/test/' +KONVI_CFG="konversation/scripts/$SCRIPT_NAME.conf" # relative path to $(kde-config --path data) + +### Script Localization +# Make sure every program speaks English. +LC_ALL="C" +export LC_ALL + +### Output Colors +# A more elegant way to have a scheme that doesn't print color codes (neither ANSI nor mIRC) at all. See below. +unset EMPTY +# DGREY BLACK RED DRED GREEN DGREEN YELLOW DYELLOW +ANSI_COLORS="       " +IRC_COLORS=" \x0314 \x0301 \x0304 \x0305 \x0309 \x0303 \x0308 \x0307" +# BLUE DBLUE MAGENTA DMAGENTA CYAN DCYAN WHITE GREY NORMAL +ANSI_COLORS="$ANSI_COLORS         " +IRC_COLORS=" $IRC_COLORS \x0312 \x0302 \x0313 \x0306 \x0311 \x0310 \x0300 \x0315 \x03" + +#ANSI_COLORS=($ANSI_COLORS); IRC_COLORS=($IRC_COLORS) +A_COLORS_AVAILABLE=( DGREY BLACK RED DRED GREEN DGREEN YELLOW DYELLOW BLUE DBLUE MAGENTA DMAGENTA CYAN DCYAN WHITE GREY NORMAL ) +# See above for notes on EMPTY +A_COLOR_SCHEMES=( EMPTY,EMPTY,EMPTY NORMAL,NORMAL,NORMAL BLUE,NORMAL,NORMAL GREEN,YELLOW,NORMAL DYELLOW,NORMAL,NORMAL CYAN,BLUE,NORMAL RED,NORMAL,NORMAL GREEN,NORMAL,NORMAL YELLOW,NORMAL,NORMAL GREEN,DGREEN,NORMAL BLUE,RED,NORMAL BLUE,NORMAL,RED YELLOW,WHITE,GREEN BLUE,NORMAL,GREEN DCYAN,NORMAL,DMAGENTA ) +## Actual color variables +C1='' +C2='' +CN='' + +### Distro Data +# In cases of derived distros where the version file of the base distro can also be found under /etc, +# the derived distro's version file should go first. (Such as with Sabayon / Gentoo) +DISTROS_DERIVED="antix-version kanotix-version knoppix-version mandrake-release pardus-release sabayon-release sidux-version turbolinux-release zenwalk-version" +# debian_version excluded from DISTROS_PRIMARY so Debian can fall through to /etc/issue detection. Same goes for Ubuntu. +DISTROS_EXCLUDE_LIST="debian_version ubuntu_version" +DISTROS_PRIMARY="gentoo-release redhat-release slackware-version SuSE-release" +DISTROS_LSB_GOOD="mandrake-release mandriva-release mandrakelinux-release" +## Distros with known problems +# DSL (Bash 2.05b: grep -m doesn't work; arrays won't work) --> unusable output +# Puppy Linux 4.1.2 (Bash 3.0: arrays won't work) --> works partially + +### Bans Data +# Precede a banword with $'\2' to prevent it from being subject to automated escaping by the make_ban_lists routine +# $'\1' gets weird results : +# user@host $ ARR=($'\x01'"one two" three four); echo ${ARR[0]} | hd -v +# 00000000 01 01 6f 6e 65 20 74 77 6f 0a |..one two.| +A_NORMAL_BANS=( corporation communications gmbh technologies technology group $'\2'"\" ltd. $'\2'"\" inc. $'\2'\ co. "(tm)" "(r)" "®" $'\2'"\(rev ..\)" ) +A_CPU_BANS=( @ cpu deca 'dual core' dual-core 'tri core' tri-core 'quad core' quad-core ennea genuine hepta hexa multi octa penta 'processor' processor single triple $'\2'"[0-9.]+ *[MmGg][Hh][Zz]" ) +# after processing, the ban arrays will be put into these: +BAN_LIST_NORMAL='' +BAN_LIST_CPU='' + +# WARNING: In the main part below (search for 'KONVI') +# there's a check for Konversation-specific config files. +# Any one of these can override the above if inxi is run +# from Konversation! + +######################################################################## +#### MAIN: Where it all begins +######################################################################## +main() +{ + eval $LOGFS + + # This function just initializes variables + initialize_script_data + + # Check for dependencies BEFORE running ANYTHING else except above functions + # Not all distro's have these depends installed by default + check_script_depends + check_script_suggested_apps + + # first init function must be set first for colors etc. Remember, no debugger + # stuff works on this function unless you set the debugging flag manually. + # Debugging flag -@ [number] will not work until get_parameters runs. + + ### Only continue if depends ok + SCRIPT_PATH=$( dirname $0 ) + SCRIPT_VERSION_NUMBER=$( grep -im 1 'version:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $3}' ) + + ### Source global config overrides + if [[ -s /etc/$SCRIPT_NAME.conf ]];then + source /etc/$SCRIPT_NAME.conf + fi + # Source user config overrides, ~/.inxi/inxi.conf + if [[ -s $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf ]];then + source $HOME/.$SCRIPT_NAME/$SCRIPT_NAME.conf + fi + + ## this needs to run before the KONVI stuff is set below + ## Konversation 1.2 apparently does not like the $PPID test in get_start_client + ## So far there is no known way to detect if qt4_konvi is the parent process + ## this method will infer qt4_konvi as parent + + get_start_client + + # note: this only works if it's run from inside konversation as a script builtin or something + # only do this if inxi has been started as a konversation script, otherwise bypass this +# KONVI=3 ## for testing puroses + ## + if [[ $KONVI -eq 1 || $KONVI -eq 3 ]];then + + if [[ $KONVI -eq 1 ]]; then ## dcop Konversation (ie 1.x < 1.2(qt3)) + DCPORT="$1" + DCSERVER="$2" + DCTARGET="$3" + shift 3 + elif [[ $KONVI -eq 3 ]]; then ## dbus Konversation (> 1.2 (qt4)) + DCSERVER="$1" ##dbus testing + DCTARGET="$2" ##dbus testing + shift 2 + fi + + # The section below is on request of Argonel from the Konversation developer team: + # it sources config files like $HOME/.kde/share/apps/konversation/scripts/inxi.conf + IFS=":" + for kde_config in $( kde-config --path data ) + do + if [[ -r ${kde_config}${KONVI_CFG} ]];then + source "${kde_config}${KONVI_CFG}" + break + fi + done + IFS="$ORIGINAL_IFS" + fi + + ## leave this for debugging dcop stuff if we get that working + # print_screen_output "DCPORT: $DCPORT" + # print_screen_output "DCSERVER: $DCSERVER" + # print_screen_output "DCTARGET: $DCTARGET" + + # "$@" passes every parameter separately quoted, "$*" passes all parameters as one quoted parameter. + # must be here to allow debugger and other flags to be set. + get_parameters "$@" + + # If no colorscheme was set in the parameter handling routine, then set the default scheme + if [[ $COLOR_SCHEME_SET != 'true' ]];then + set_color_scheme "$DEFAULT_SCHEME" + fi + + # all the pre-start stuff is in place now + B_SCRIPT_UP='true' + script_debugger "Debugger: $SCRIPT_NAME is up and running..." + + # then create the output + print_it_out + + ## last steps + if [[ $B_RUNNING_IN_SHELL == 'true' && $SCHEME -gt 0 ]];then + echo -n "" + fi + eval $LOGFE + # weechat's executor plugin forced me to do this, and rightfully so, because else the exit code + # from the last command is taken.. + exit 0 +} + +#### ------------------------------------------------------------------- +#### basic tests: set script data, booleans, PATH +#### ------------------------------------------------------------------- + +# Set PATH data so we can access all programs as user. Set BAN lists. +# initialize some boleans, these directories are used throughout the script +# some apps are used for extended functions any directory used, should be +# checked here first. +# No args taken. +initialize_script_data() +{ + eval $LOGFS + local path='' sys_path='' added_path='' b_path_found='' + # Extra path variable to make execute failures less likely, merged below + local extra_paths="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" + + # Fallback paths put into $extra_paths; This might, among others, help on gentoo. + # Now, create a difference of $PATH and $extra_paths and add that to $PATH: + IFS=":" + for path in $extra_paths + do + b_path_found='false' + for sys_path in $PATH + do + if [[ $path == $sys_path ]];then + b_path_found='true' + fi + done + if [[ $b_path_found == 'false' ]];then + added_path="$added_path:$path" + fi + done + + IFS="$ORIGINAL_IFS" + PATH="${PATH}${added_path}" + ##echo "PATH='$PATH'" + ##/bin/sh -c 'echo "PATH in subshell=\"$PATH\""' + + # Do this after sourcing of config overrides so user can customize banwords + BAN_LIST_NORMAL=$( make_ban_lists "${A_NORMAL_BANS[@]}" ) # Contrary to my previous belief, "${ARR[@]}" passes a quoted list, not one string + BAN_LIST_CPU=$( make_ban_lists "${A_CPU_BANS[@]}" ) + ##echo "BAN_LIST_NORMAL='$BAN_LIST_NORMAL'" + + # now set the script BOOLEANS for files required to run features + if [[ -d "/proc/" ]];then + B_PROC='true' + else + error_handler 6 + fi + + if [[ -e $FILE_CPUINFO ]]; then + B_CPUINFO='true' + fi + + if [[ -e $FILE_MEMINFO ]];then + B_MEMINFO='true' + fi + + if [[ -e $FILE_ASOUND_DEVICE ]];then + B_ASOUND_CARDS='true' + fi + + if [[ -e $FILE_ASOUND_VERSION ]];then + B_ASOUND_VERSION='true' + fi + + if [[ -f $FILE_LSB_RELEASE ]];then + B_LSB_DIR='true' + fi + + if [[ -e $FILE_SCSI ]];then + B_SCSI_DIR='true' + fi + + # lack of ifconfig will throw an error only upon it's usage + if [[ -n $( type -p ifconfig ) ]]; then + B_IFCONFIG='true' + else + A_INTERFACES_DATA=( "Interfaces tool requires missing app: ifconfig" ) + fi + + if [[ -n $( type -p sensors ) ]];then + B_SENSORS='true' + fi + + if [[ -n $DISPLAY ]];then + B_X_RUNNING='true' + fi + + if [[ -e $FILE_MODULES ]];then + B_MODULES_DIR='true' + fi + + if [[ -e $FILE_MOUNTS ]];then + B_MOUNTS_DIR='true' + fi + + if [[ -e $FILE_PARTITIONS ]];then + B_PARTITIONS_DIR='true' + fi + # gfx output will require this flag + if [[ $( whoami ) == 'root' ]];then + B_ROOT='true' + fi + eval $LOGFE +} + +# No args taken. +check_script_suggested_apps() +{ + eval $LOGFS + local bash_array_test=( "one" "two" ) + + # check for array ability of bash, this is only good for the warning at this time + # the boolean could be used later + # bash version 2.05b is used in DSL + # bash version 3.0 is used in Puppy Linux; it has a known array bug + # versions older than 3.1 don't handle arrays + # distro's using below 2.05b are unknown, released in 2002 + if [[ ${bash_array_test[1]} -eq "two" ]];then + B_BASH_ARRAY='true' + else + script_debugger "Suggestion: update to Bash v3.1 for optimal inxi output" + fi + eval $LOGFE +} + +# Determine if any of the absolutely necessary tools are absent +# No args taken. +check_script_depends() +{ + eval $LOGFS + local app_name='' app_data='' + # bc removed from deps for now + local depends="df free gawk grep hostname lspci ps readlink tr uname uptime wc" + local x_apps="xrandr xdpyinfo glxinfo" + + if [[ $B_X_RUNNING == 'true' ]];then + for app_name in $x_apps + do + app_data=$( type -p $app_name ) + if [[ -z $app_data ]];then + script_debugger "Resuming in non X mode: $app_name not found in path" + B_X_RUNNING='false' + break + fi + done + fi + + app_name='' + + for app_name in $depends + do + app_data=$( type -p $app_name ) + if [[ -z $app_data ]];then + error_handler 5 "$app_name" + fi + done + eval $LOGFE +} + +## note: this is now running inside each gawk sequence directly to avoid exiting gawk +## looping in bash through arrays, then re-entering gawk to clean up, then writing back to array +## in bash. For now I'll leave this here because there's still some interesting stuff to get re methods +# Enforce boilerplate and buzzword filters +# args: $1 - BAN_LIST_NORMAL/BAN_LIST_CPU; $2 - string to sanitize +sanitize_characters() +{ + eval $LOGFS + # Cannot use strong quotes to unquote a string with pipes in it! + # bash will interpret the |'s as usual and try to run a subshell! + # Using weak quotes instead, or use '"..."' + echo "$2" | gawk " + BEGIN { + IGNORECASE=1 + } + { + gsub(/${!1}/,\"\") + gsub(/ [ ]+/,\" \") ## ([ ]+) with (space) + gsub(/^ +| +$/,\"\") ## (pipe char) with (nothing) + print ## prints (returns) cleaned input + }" + eval $LOGFE +} + +# Filter boilerplate & buzzwords. +# args: $1 - quoted: "$@" array of ban terms +make_ban_lists() +{ + eval $LOGFS + local ban_list='' + # Iterate over $@ + ## note: this is a weird, non-intuitive method, needs some documentation or rewriting + ## if you declare ban_string it stops working, have to read up on this + for ban_string + do + # echo "term=\"$ban_string\"" # >&2 + if [[ ${ban_string:0:1} = $'\2' ]];then + ban_list="${ban_list}${ban_list+|}${ban_string:1:${#ban_string}-1}" + else + # Automatically escapes [ ] ( ) . and + + ban_list="${ban_list}${ban_list+|}$( echo "$ban_string" | gawk '{ + gsub(/([\[\]+().])/,"\\\\&") + print + }' )" + fi + done + + echo "$ban_list" + eval $LOGFS +} +# make_ban_lists "${A_CPU_BANS[@]}";exit + +# Set the colorscheme +# args: $1 = |<"none"> +set_color_scheme() +{ + eval $LOGFS + local i='' script_colors='' color_codes='' + + if [[ $1 -ge ${#A_COLOR_SCHEMES[@]} ]];then + set -- 1 + fi + # Set a global variable to allow checking for chosen scheme later + SCHEME="$1" + if [[ $B_RUNNING_IN_SHELL == 'true' ]];then + color_codes=( $ANSI_COLORS ) + else + color_codes=( $IRC_COLORS ) + fi + for (( i=0; i < ${#A_COLORS_AVAILABLE[@]}; i++ )) + do + eval "${A_COLORS_AVAILABLE[i]}=\"${color_codes[i]}\"" + done + IFS="," + script_colors=( ${A_COLOR_SCHEMES[$1]} ) + IFS="$ORIGINAL_IFS" + # then assign the colors globally + C1="${!script_colors[0]}" + C2="${!script_colors[1]}" + CN="${!script_colors[2]}" + # ((COLOR_SCHEME++)) ## note: why is this? ## + eval $LOGFE +} + +######################################################################## +#### UTILITY FUNCTIONS +######################################################################## + +#### ------------------------------------------------------------------- +#### error handler, debugger, script updater +#### ------------------------------------------------------------------- + +# Error handling +# args: $1 - error number; $2 - optional, extra information +error_handler() +{ + eval $LOGFS + local error_message='' + + # assemble the error message + case $1 in + 2) error_message="large flood danger, debug buffer full!" + ;; + 3) error_message="unsupported color scheme number: $2" + ;; + 4) error_message="unsupported verbosity level: $2" + ;; + 5) error_message="dependency not met: $2 not found in path" + ;; + 6) error_message="/proc not found! Quitting..." + ;; + 7) error_message="One of the options you entered in your script parameters: $2\nIs not supported. For supported options, check the help menu: $SCRIPT_NAME -h" + ;; + 8) error_message="the self-updater failed, wget exited with error: $2.\nYou probably need to be root.\nHint, to make for easy updates without being root, do: chown $SCRIPT_PATH/$SCRIPT_NAME" + ;; + 9) error_message="unsupported debugging level: $2" + ;; + 10) + error_message="the alt download url you provided: $2\nappears to be wrong, download aborted. Please note, the url\nneeds to end in /, without $SCRIPT_NAME, like: http://yoursite.com/downloads/" + ;; + 11) + error_message="unsupported testing option argument: -! $2" + ;; + 12) + error_message="the svn branch download url: $2\nappears to be empty currently. Make sure there is an actual svn branch version\nactive before you try this again. Check http://code.google.com/p/inxi\nto verify the branch status." + ;; + *) error_message="error unknown: $@" + set -- 99 + ;; + esac + # then print it and exit + print_screen_output "Error $1: $error_message" + eval $LOGFE + exit $1 +} + +# prior to script up set, pack the data into an array +# then we'll print it out later. +# args: $1 - $@ debugging string text +script_debugger() +{ + eval $LOGFS + if [[ $B_SCRIPT_UP == 'true' ]];then + # only return if debugger is off and no pre start up errors have occured + if [[ $DEBUG -eq 0 && $DEBUG_BUFFER_INDEX -eq 0 ]];then + return 0 + # print out the stored debugging information if errors occured + elif [[ $DEBUG_BUFFER_INDEX -gt 0 ]];then + for (( DEBUG_BUFFER_INDEX=0; DEBUG_BUFFER_INDEX < ${#A_DEBUG_BUFFER[@]}; DEBUG_BUFFER_INDEX++ )) + do + print_screen_output "${A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]}" + done + DEBUG_BUFFER_INDEX=0 + fi + # or print out normal debugger messages if debugger is on + if [[ $DEBUG -gt 0 ]];then + print_screen_output "$1" + fi + else + if [[ $B_DEBUG_FLOOD == 'true' && $DEBUG_BUFFER_INDEX -gt 10 ]];then + error_handler 2 + # this case stores the data for later printout, will print out only + # at B_SCRIPT_UP == 'true' if array index > 0 + else + A_DEBUG_BUFFER[$DEBUG_BUFFER_INDEX]="$1" + # increment count for next pre script up debugging error + (( DEBUG_BUFFER_INDEX++ )) + fi + fi + eval $LOGFE +} + +# NOTE: no logging available until get_parameters is run, since that's what sets logging +# in order to trigger earlier logging manually set B_USE_LOGGING to true in top variables. +# $1 alone: logs data; $2 with or without $3 logs func start/end. +# $1 type (fs/fe/cat/raw) or logged data; [$2 is $FUNCNAME; [$3 - function args]] +log_function_data() +{ + if [ "$B_USE_LOGGING" == 'true' ];then + local logged_data='' spacer=' ' line='----------------------------------------' + case $1 in + fs) + logged_data="Function: $2 - Primary: Start" + if [ -n "$3" ];then + logged_data="$logged_data\n${spacer}Args: $3" + fi + spacer='' + ;; + fe) + logged_data="Function: $2 - Primary: End" + spacer='' + ;; + cat) + if [[ $B_LOG_FULL_DATA == 'true' ]];then + logged_data="\n$line\nFull file data: cat $2\n\n$( cat $2 )\n$line\n" + spacer='' + fi + ;; + raw) + if [[ $B_LOG_FULL_DATA == 'true' ]];then + logged_data="\n$line\nRaw system data:\n\n$2\n$line\n" + spacer='' + fi + ;; + *) + logged_data="$1" + ;; + esac + # Create any required line breaks and strip out escape color code, either ansi (case 1)or irc (case 2). + # This pattern doesn't work for irc colors, if we need that someone can figure it out + if [[ -n $logged_data ]];then + if [[ $B_LOG_COLORS != 'true' ]];then + echo -e "${spacer}$logged_data" | sed -r 's/\x1b\[[0-9]{1,2}(;[0-9]{1,2}){0,2}m//g' >> $LOG_FILE + else + echo -e "${spacer}$logged_data" >> $LOG_FILE + fi + fi + fi +} + +# called in the initial -@ 10 script args setting so we can get logging as soon as possible +# will have max 3 files, inxi.log, inxi.1.log, inxi.2.log +create_rotate_logfiles() +{ + if [[ ! -d $SCRIPT_DATA_DIR ]];then + mkdir $SCRIPT_DATA_DIR + fi + # do the rotation if logfile exists + if [[ -f $LOG_FILE ]];then + # copy if present second to third + if [[ -f $LOG_FILE_1 ]];then + mv -f $LOG_FILE_1 $LOG_FILE_2 + fi + # then copy initial to second + mv -f $LOG_FILE $LOG_FILE_1 + fi + # now create the logfile + touch $LOG_FILE + # and echo the start data + echo "=========================================================" >> $LOG_FILE + echo "START $SCRIPT_NAME LOGGING:" >> $LOG_FILE + echo "Script started: $( date +%Y-%m-%d-%H:%M:%S )" >> $LOG_FILE + echo "=========================================================" >> $LOG_FILE +} + +# args: $1 - download url, not including file name; $2 - string to print out +# note that $1 must end in / to properly construct the url path +script_self_updater() +{ + eval $LOGFS + local wget_error=0 + print_screen_output "Starting $SCRIPT_NAME self updater." + print_screen_output "Currently running $SCRIPT_NAME version number: $SCRIPT_VERSION_NUMBER" + print_screen_output "Updating $SCRIPT_NAME in $SCRIPT_PATH using $2 as download source..." + # first test if path is good, need to make sure it's good because we're -O overwriting file + wget -q --spider $1$SCRIPT_NAME || wget_error=$? + # then do the actual download + if [[ $wget_error -eq 0 ]];then + wget -q -O $SCRIPT_PATH/$SCRIPT_NAME $1$SCRIPT_NAME || wget_error=$? + if [[ $wget_error -eq 0 ]];then + SCRIPT_VERSION_NUMBER=$( grep -im 1 'version:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $3}' ) + print_screen_output "Successfully updated to $2 version: $SCRIPT_VERSION_NUMBER" + print_screen_output "To run the new version, just start $SCRIPT_NAME again." + exit 0 + fi + fi + # now run the error handlers on any wget failure + if [[ $wget_error -gt 0 ]];then + if [[ $2 == 'svn server' ]];then + error_handler 8 "$wget_error" + elif [[ $2 == 'alt server' ]];then + error_handler 10 "$1" + else + error_handler 12 "$1" + fi + fi + eval $LOGFS +} + +#### ------------------------------------------------------------------- +#### print / output cleaners +#### ------------------------------------------------------------------- + +# inxi speaks through here. When run by Konversation script alias mode, uses DCOP +# for dcop to work, must use 'say' operator, AND colors must be evaluated by echo -e +# note: dcop does not seem able to handle \n so that's being stripped out and replaced with space. +print_screen_output() +{ + eval $LOGFS + # the double quotes are needed to avoid losing whitespace in data when certain output types are used + local print_data="$( echo -e "$1" )" + + # just using basic debugger stuff so you can tell which thing is printing out the data. This + # should help debug kde 4 konvi issues when that is released into sid, we'll see. Turning off + # the redundant debugger output which as far as I can tell does exactly nothing to help debugging. + if [[ $DEBUG -gt 5 ]];then + if [[ $KONVI -eq 1 ]];then + # konvi doesn't seem to like \n characters, it just prints them literally + # print_data="$( tr '\n' ' ' <<< "$print_data" )" + # dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "konvi='$KONVI' saying : '$print_data'" + print_data="KP-$KONVI: $print_data" + elif [[ $KONVI -eq 2 ]];then + # echo "konvi='$KONVI' saying : '$print_data'" + print_data="KP-$KONVI: $print_data" + else + # echo "printing out: '$print_data'" + print_data="P: $print_data" + fi + fi + + if [[ $KONVI -eq 1 ]]; then ## dcop Konversation (<= 1.1 (qt3)) + # konvi doesn't seem to like \n characters, it just prints them literally + $print_data="$( tr '\n' ' ' <<< "$print_data" )" + dcop "$DCPORT" "$DCOPOBJ" say "$DCSERVER" "$DCTARGET" "$print_data" + + elif [[ $KONVI -eq 3 ]]; then ## dbus Konversation (> 1.2 (qt4)) + qdbus org.kde.konversation /irc say "$DCSERVER" "$DCTARGET" "$print_data" + +# elif [[ $IRC_CLIENT == 'X-Chat' ]]; then +# qdbus org.xchat.service print "$print_data\n" + + else + # the -n is needed to avoid double spacing of output in terminal + echo -ne "$print_data\n" + fi + eval $LOGFE +} + +## this handles all verbose line construction with indentation/line starter +## args: $1 - null (, actually: " ") or line starter; $2 - line content +create_print_line() +{ + eval $LOGFS + printf "${C1}%-${INDENT}s${C2} %s" "$1" "$2" + eval $LOGFE +} + +# this removes newline and pipes. +# args: $1 - string to clean +remove_erroneous_chars() +{ + eval $LOGFS + ## RS is input record separator + ## gsub is substitute; + gawk ' + BEGIN { + RS="" + } + { + gsub(/\n$/,"") ## (newline; end of string) with (nothing) + gsub(/\n/," "); ## (newline) with (space) + gsub(/^ *| *$/, "") ## (pipe char) with (nothing) + gsub(/ +/, " ") ## ( +) with (space) + gsub(/ [ ]+/, " ") ## ([ ]+) with (space) + gsub(/^ +| +$/, "") ## (pipe char) with (nothing) + printf $0 + }' "$1" ## prints (returns) cleaned input + eval $LOGFE +} + +#### ------------------------------------------------------------------- +#### parameter handling, print usage functions. +#### ------------------------------------------------------------------- + +# Get the parameters. Note: standard options should be lower case, advanced or testing, upper +# args: $1 - full script startup args: $@ +get_parameters() +{ + eval $LOGFS + local opt='' wget_test='' update_flags='U!:' + local use_short='true' # this is needed to trigger short output, every v/d/F/line trigger sets this false + + # + if [[ $B_ALLOW_UPDATE == 'false' ]];then + update_flags='' + fi + + # the short form only runs if no args output args are used + # no need to run through these if there are no args + if [[ -n $1 ]];then + while getopts Ac:CdDfFGhHiIlNpPsSuv:Vx%@:${update_flags} opt + do + case $opt in + A) B_SHOW_AUDIO='true' + use_short='false' + ;; + c) if [[ -n $( egrep '^[0-9][0-9]?$' <<< $OPTARG ) ]];then + COLOR_SCHEME_SET='true' + ## note: not sure about this, you'd think user values should be overridden, but + ## we'll leave this for now + if [[ -z $COLOR_SCHEME ]];then + set_color_scheme "$OPTARG" + fi + else + error_handler 3 "$OPTARG" + fi + ;; + C) B_SHOW_CPU='true' + use_short='false' + ;; + d) VERBOSITY_LEVEL=1 + use_short='false' + ;; + D) B_SHOW_DISK='true' + use_short='false' + ;; + f) B_SHOW_CPU='true' + B_CPU_FLAGS_FULL='true' + use_short='false' + ;; + F) VERBOSITY_LEVEL=$VERBOSITY_LEVELS + B_EXTRA_DATA='true' + B_SHOW_DISK='true' + B_SHOW_PARTITIONS='true' + B_SHOW_AUDIO='true' + use_short='false' + ;; + G) B_SHOW_GRAPHICS='true' + use_short='false' + ;; + i) B_SHOW_IP='true' + B_SHOW_NETWORK='true' + use_short='false' + ;; + I) B_SHOW_INFO='true' + use_short='false' + ;; + l) B_SHOW_LABELS='true' + B_SHOW_PARTITIONS='true' + use_short='false' + ;; + N) B_SHOW_NETWORK='true' + use_short='false' + ;; + p) B_SHOW_PARTITIONS_FULL='true' + B_SHOW_PARTITIONS='true' + use_short='false' + ;; + P) B_SHOW_PARTITIONS='true' + use_short='false' + ;; + s) B_SHOW_SENSORS='true' + use_short='false' + ;; + S) B_SHOW_SYSTEM='true' + use_short='false' + ;; + u) B_SHOW_UUIDS='true' + B_SHOW_PARTITIONS='true' + use_short='false' + ;; + v) if [[ -n $( egrep "^[0-9][0-9]?$" <<< $OPTARG ) && $OPTARG -le $VERBOSITY_LEVELS ]];then + VERBOSITY_LEVEL="$OPTARG" + if [[ $OPTARG -gt 0 ]];then + use_short='false' + fi + else + error_handler 4 "$OPTARG" + fi + ;; + U) script_self_updater "$SCRIPT_DOWNLOAD" 'svn server' + ;; + V) print_version_info + exit 0 + ;; + x) B_EXTRA_DATA='true' + ;; + h) show_options + exit 0 + ;; + H) show_options 'full' + exit 0 + ;; + ## debuggers and testing tools + %) B_HANDLE_CORRUPT_DATA='true' + ;; + @) if [[ -n $( egrep "^([1-9]|10)$" <<< $OPTARG ) ]];then + DEBUG=$OPTARG + exec 2>&1 + # switch on logging only for -@ 8-10 + if [[ $OPTARG -ge 8 ]];then + if [[ $OPTARG -eq 10 ]];then + B_LOG_COLORS='true' + elif [[ $OPTARG -eq 9 ]];then + B_LOG_FULL_DATA='true' + fi + B_USE_LOGGING='true' + # pack the logging data for evals function start/end + LOGFS=$LOGFS_STRING + LOGFE=$LOGFE_STRING + create_rotate_logfiles # create/rotate logfiles before we do anything else + fi + else + error_handler 9 "$OPTARG" + fi + ;; + !) # test for various supported methods + case $OPTARG in + 1) B_TESTING_1='true' + ;; + 2) B_TESTING_2='true' + ;; + 3) B_TESTING_1='true' + B_TESTING_2='true' + ;; + 10) + script_self_updater "$SCRIPT_DOWNLOAD_DEV" 'dev server' + ;; + 11) + script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_1" 'svn: branch one server' + ;; + 12) + script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_2" 'svn: branch two server' + ;; + 13) + script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_3" 'svn: branch three server' + ;; + 14) + script_self_updater "$SCRIPT_DOWNLOAD_BRANCH_4" 'svn: branch four server' + ;; + http*) + script_self_updater "$OPTARG" 'alt server' + ;; + *) error_handler 11 "$OPTARG" + ;; + esac + ;; + *) error_handler 7 "$1" + ;; + esac + done + fi + ## this must occur here so you can use the debugging flag to show errors + ## Reroute all error messages to the bitbucket (if not debugging) + if [[ $DEBUG -eq 0 ]];then + exec 2>/dev/null + fi + #((DEBUG)) && exec 2>&1 # This is for debugging konversation + + # after all the args have been processed, if no long output args used, run short output + if [[ $use_short == 'true' ]];then + B_SHOW_SHORT_OUTPUT='true' + fi + eval $LOGFE +} + +## print out help menu, not including Testing or Debugger stuff because it's not needed +show_options() +{ + local color_scheme_count=${#A_COLOR_SCHEMES[@]} + + print_screen_output "$SCRIPT_NAME supports the following options. You can combine them, or list them" + print_screen_output "one by one: Examples: $SCRIPT_NAME -v4 -c6 OR $SCRIPT_NAME -dDc 6" + print_screen_output "" + print_screen_output "If you start $SCRIPT_NAME with no arguments, it will show the short form." + print_screen_output "The following options if used without -d or -v will show just that complete line:" + print_screen_output "A,C,D,G,I,N,P,S - you can use these together to show just the lines you want to see." + print_screen_output "If you use them with a -v level (or -d), it will show the full output for that line " + print_screen_output "along with the output for the chosen verbosity level." + print_screen_output "- - - - - - - - - - - - - - - - - - - - - - - - - - - - -" + print_screen_output "Output Control Options:" + print_screen_output "-A Show Audio/sound card information." + print_screen_output "-c Available color schemes. Scheme number is required." + print_screen_output " Supported schemes: 0-$color_scheme_count Example: $SCRIPT_NAME -c 11" + print_screen_output "-C Show full CPU output, including per CPU clockspeed." + print_screen_output "-d Default output verbosity level, same as: $SCRIPT_NAME -v 1" + print_screen_output "-D Show full hard Disk info, not only model, ie: /dev/sda ST380817AS 80.0GB." + print_screen_output "-f Show all cpu flags used, not just the short list. Not shown with -F to avoid spamming." + print_screen_output "-F Show Full output for $SCRIPT_NAME. Does not show extra verbose options like -f -u -l or -p" + print_screen_output "-G Show Graphic card information (card, x type, resolution, glx renderer, version)." + print_screen_output "-i Show Wan IP address, and shows local interfaces (requires ifconfig network tool)." + print_screen_output " Not shown with -F for user security reasons, you shouldn't paste your local/wan IP." + print_screen_output "-I Show Information: processes, uptime, memory, irc client, inxi version." + print_screen_output "-l Show partition labels. Default: short partition -P. For full -p output, use: -pl (or -plu)." + print_screen_output "-N Show Network card information." + print_screen_output "-p Show full partition information (-P plus all other detected partitions)." + print_screen_output "-P Show Partition information (shows what -v 4 would show, but without extra data)." + print_screen_output " Shows, if detected: / /boot /home /tmp /usr /var. Use -p to see all mounted partitions." + print_screen_output "-s Show sensors output (if sensors installed/configured): mobo/cpu temp; detected fan speeds." + print_screen_output "-S Show System information: host name, kernel, distro" + print_screen_output "-u Show partition UUIDs. Default: short partition -P. For full -p output, use: -pu (or -plu)." + print_screen_output "-v Script verbosity levels. Verbosity level number is required." + print_screen_output " Supported levels: 0-${VERBOSITY_LEVELS} Example: $SCRIPT_NAME -v 4" + print_screen_output " 0 - short output, same as: $SCRIPT_NAME" + print_screen_output " 1 - basic verbose, same as: $SCRIPT_NAME -d" + print_screen_output " 2 - Also show networking card data" + print_screen_output " 3 - Also show hard disk names as detected." + print_screen_output " 4 - Also show partition size/filled data for (if present):/, /home, /var/, /boot" + print_screen_output " 5 - For multicore systems, also shows: per core clock speeds; audio card; full disk data." + print_screen_output "-x Show extra data: bogomips on Cpu; driver version (if available) for Network/Audio;" + print_screen_output " direct rendering status for Graphics (in X). Only works with verbose or line output." + print_screen_output " Shows hdd temp with disk data if you have hddtemp installed, if you are root OR if you have" + print_screen_output " added to /etc/sudoers (sudo v. 1.7 or newer) (path to hddtemp): ALL = NOPASSWD: /usr/sbin/hddtemp" + print_screen_output "" + print_screen_output "Additional Options:" + print_screen_output "-h - this help menu." + if [[ $B_ALLOW_UPDATE == 'true' ]];then + print_screen_output "-U Auto-update script. Note: if you installed as root, you" + print_screen_output " must be root to update, otherwise user is fine." + fi + print_screen_output "-V $SCRIPT_NAME version information. Prints information then exits." + print_screen_output "-% Overrides defective or corrupted data." + print_screen_output "-@ Triggers debugger output. Requires debugging level 1-10 (8-10 - logging)." + print_screen_output " 8 - basic logging; 9 - full file/sys info logging; 10 - color logging." + if [[ $1 == 'full' ]];then + print_screen_output "" + print_screen_output "Developer and Testing Options (Advanced):" + print_screen_output "-! 1 - Sets testing flag B_TESTING_1='true' to trigger testing condition 1." + print_screen_output "-! 2 - Sets testing flag B_TESTING_2='true' to trigger testing condition 2." + print_screen_output "-! 3 - Sets flags B_TESTING_1='true' and B_TESTING_2='true'." + print_screen_output "-! 10 - Triggers an update from the primary dev download server instead of svn." + print_screen_output "-! 11 - Triggers an update from svn branch one - if present, of course." + print_screen_output "-! 12 - Triggers an update from svn branch two - if present, of course." + print_screen_output "-! 13 - Triggers an update from svn branch three - if present, of course." + print_screen_output "-! 14 - Triggers an update from svn branch four - if present, of course." + print_screen_output "-! - Triggers an update from whatever server you list." + print_screen_output "" + fi + print_screen_output "" +} + +## print out version information for -V/--version +print_version_info() +{ + local last_modified=$( grep -im 1 'date:' $SCRIPT_PATH/$SCRIPT_NAME | gawk '{print $3,$4,$5}' ) + + print_screen_output "$SCRIPT_NAME - the universal, portable, system info script for irc." + print_screen_output "Version: $SCRIPT_VERSION_NUMBER" + print_screen_output "Script Last Modified: $last_modified" + print_screen_output "Script Location: $SCRIPT_PATH" + print_screen_output "" + print_screen_output "Tested with Irssi, Xchat, Konversation, BitchX, KSirc, ircII," + print_screen_output "Gaim/Pidgin, Weechat, KVIrc and Kopete." + print_screen_output "" + print_screen_output "This script is a fork of Infobash 3.02, which is:" + print_screen_output "Copyright (C) 2005-2007 Michiel de Boer a.k.a. locsmif" + print_screen_output "Subsequent changes and modifications (after Infobash 3.02) are:" + print_screen_output "Copyright (C) 2008-9 Scott Rogers, Harald Hope, aka trash80 & h2" + print_screen_output "" + print_screen_output "This program is free software; you can redistribute it and/or modify" + print_screen_output "it under the terms of the GNU General Public License as published by" + print_screen_output "the Free Software Foundation; either version 3 of the License, or" + print_screen_output "(at your option) any later version." +} + +######################################################################## +#### MAIN FUNCTIONS +######################################################################## + +#### ------------------------------------------------------------------- +#### initial startup stuff +#### ------------------------------------------------------------------- + +# Determine where inxi was run from, set IRC_CLIENT and IRC_CLIENT_VERSION +get_start_client() +{ + eval $LOGFS + local irc_client_path='' irc_client_path_lower='' non_native_konvi='' i='' + local b_non_native_app='false' pppid='' app_working_name='' + local b_qt4_konvi='false' + + if tty >/dev/null;then + IRC_CLIENT='Shell' + unset IRC_CLIENT_VERSION + B_RUNNING_IN_SHELL='true' + elif [[ -n $PPID && -f /proc/$PPID/exe ]];then + irc_client_path=$( readlink /proc/$PPID/exe ) + irc_client_path_lower=$( tr '[:upper:]' '[:lower:]' <<< $irc_client_path ) + app_working_name=$( basename $irc_client_path_lower ) + # handles the xchat/sh/bash/dash cases, and the konversation/perl cases, where clients + # report themselves as perl or unknown shell. IE: when konversation starts inxi + # from inside itself, as a script, the parent is konversation/xchat, not perl/bash etc + # note: perl can report as: perl5.10.0, so it needs wildcard handling + case $app_working_name in + bash|dash|sh|perl*) # We want to know who wrapped it into the shell or perl. + pppid="$( ps -p $PPID -o ppid --no-headers | sed 's/ //g' )" + if [[ -n $pppid && -f /proc/$pppid/exe ]];then + irc_client_path="$( readlink /proc/$pppid/exe )" + irc_client_path_lower="$( tr '[:upper:]' '[:lower:]' <<< $irc_client_path )" + app_working_name=$( basename $irc_client_path_lower ) + b_non_native_app='true' + fi + ;; + esac + # replacing loose detection with tight detection, bugs will be handled with app names + # as they appear. + case $app_working_name in + # check for shell first + bash|dash|sh) + unset IRC_CLIENT_VERSION + IRC_CLIENT="Shell wrapper" + ;; + # now start on irc clients, alphabetically + bitchx) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk ' + /Version/ { + a=tolower($2) + gsub(/[()]|bitchx-/,"",a) + print a + exit + } + $2 == "version" { + a=tolower($3) + sub(/bitchx-/,"",a) + print a + exit + }' )" + IRC_CLIENT="BitchX" + ;; + finch) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $2 + }' )" + IRC_CLIENT="Finch" + ;; + gaim) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $2 + }' )" + IRC_CLIENT="Gaim" + ;; + ircii) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $3 + }' )" + IRC_CLIENT="ircII" + ;; + irssi-text|irssi) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $2 + }' )" + IRC_CLIENT="Irssi" + ;; + konversation) ## konvi < 1.2 (qt4) + # this is necessary to avoid the dcop errors from starting inxi as a /cmd started script + if [[ $b_non_native_app == 'true' ]];then ## true negative is confusing + KONVI=2 + else # if native app + KONVI=1 + fi + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk ' + /Konversation:/ { + for ( i=2; i<=NF; i++ ) { + if (i == NF) { + print $i + } + else { + printf $i" " + } + } + exit + }' )" + + T=($IRC_CLIENT_VERSION) + if [[ ${T[0]} == *+* ]];then + # < Sho_> locsmif: The version numbers of SVN versions look like this: + # "+ #= 20090226)) + # Quassel IRC: v0.4.0 [+60] (git-22effe5) + # note: early < 0.4.1 quassels do not have -v + IRC_CLIENT_VERSION=" $( $irc_client_path -v 2>/dev/null | gawk -F ': ' ' + BEGIN { + IGNORECASE=1 + clientVersion="" + } + /Quassel IRC/ { + clientVersion = $2 + } + END { + # this handles pre 0.4.1 cases with no -v + if ( clientVersion == "" ) { + clientVersion = "(pre v0.4.1)" + } + print clientVersion + }' )" + # now handle primary, client, and core. quasselcore doesn't actually + # handle scripts with exec, but it's here just to be complete + case $app_working_name in + quassel) + IRC_CLIENT="Quassel [M]" + ;; + quasselclient) + IRC_CLIENT="Quassel" + ;; + quasselcore) + IRC_CLIENT="Quassel (core)" + ;; + esac + ;; + weechat-curses) + IRC_CLIENT_VERSION=" $( $irc_client_path -v ) " + IRC_CLIENT="Weechat" + ;; + xchat-gnome) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $2 + }' )" + IRC_CLIENT="X-Chat-Gnome" + ;; + xchat) + IRC_CLIENT_VERSION=" $( $irc_client_path -v | gawk 'NR == 1 { + print $2 + }' )" + IRC_CLIENT="X-Chat" + ;; + # then do some perl type searches, do this last since it's a wildcard search + perl*|ksirc|dsirc) + unset IRC_CLIENT_VERSION + # KSirc is one of the possibilities now. KSirc is a wrapper around dsirc, a perl client + get_cmdline $PPID + for (( i=0; i <= $CMDL_MAX; i++ )) + do + case ${A_CMDL[i]} in + *dsirc*) + IRC_CLIENT="KSirc" + # Dynamic runpath detection is too complex with KSirc, because KSirc is started from + # kdeinit. /proc//exe is a link to /usr/bin/kdeinit + # with one parameter which contains parameters separated by spaces(??), first param being KSirc. + # Then, KSirc runs dsirc as the perl irc script and wraps around it. When /exec is executed, + # dsirc is the program that runs inxi, therefore that is the parent process that we see. + # You can imagine how hosed I am if I try to make inxi find out dynamically with which path + # KSirc was run by browsing up the process tree in /proc. That alone is straightjacket material. + # (KSirc sucks anyway ;) + IRC_CLIENT_VERSION=" $( ksirc -v | gawk ' + /KSirc:/ { + print $2 + exit + }' )" + break + ;; + esac + done + if [[ -z $IRC_CLIENT_VERSION ]];then + IRC_CLIENT="Unknown Perl client" + fi + ;; + # then unset, set unknown data + *) + IRC_CLIENT="Unknown : ${irc_client_path##*/}" + unset IRC_CLIENT_VERSION + ;; + esac + if [[ $SHOW_IRC -lt 2 ]];then + unset IRC_CLIENT_VERSION + fi + else + ## lets look to see if qt4_konvi is the parent. There is no direct way to tell, so lets infer it. + ## because $PPID does not work with qt4_konvi, the above case does not work + b_qt4_konvi=$( is_this_qt4_konvi ) + if [[ $b_qt4_konvi == 'true' ]];then + KONVI=3 + IRC_CLIENT='Konversation' + IRC_CLIENT_VERSION=" $( konversation -v | gawk ' + /Konversation:/ { + for ( i=2; i<=NF; i++ ) { + if (i == NF) { + print $i + } + else { + printf $i" " + } + } + exit + }' )" + else + IRC_CLIENT="PPID=\"$PPID\" - empty?" + unset IRC_CLIENT_VERSION + fi + fi + log_function_data "IRC_CLIENT: $IRC_CLIENT :: IRC_CLIENT_VERSION: $IRC_CLIENT_VERSION :: PPID: $PPID" + eval $LOGFE +} + +## try to infer the use of Konversation >= 1.2, which shows $PPID improperly +## no known method of finding Kovni >= 1.2 as parent process, so we look to see if it is running, +## and all other irc clients are not running. +is_this_qt4_konvi() +{ + local konvi_qt4_client='' konvi_dbus_exist='' konvi_pid='' konvi_home_dir='' + local konvi='' konvi_qt4_ver='' b_is_qt4='' + + konvi_dbus_exist=$( qdbus | grep "org.kde.konversation" ) + + if [[ -n $konvi_dbus_exist && -e /usr/share/kde4/apps/konversation ]]; then + + konvi_pid=$( ps -A | grep -i 'konversation' ) + konvi_pid=$( echo $konvi_pid | gawk '{ print $1 }' ) + + konvi_home_dir=$( readlink /proc/$konvi_pid/exe ) + konvi=$( echo $konvi_home_dir | sed "s/\// /g" ) + konvi=($konvi) + + if [[ ${konvi[2]} == 'konversation' ]];then + konvi_qt4_ver=$( konversation -v | grep -i 'konversation' ) + konvi_qt4_client=$( echo "$konvi_qt4_ver" | gawk '{ print $2 }' ) + + if [[ $konvi_qt4_client > 1.1 ]]; then + b_is_qt4='true' + fi + fi + else + konvi_qt4="qt3" + b_is_qt4='false' + fi + + echo $b_is_qt4 + ## for testing this module + #qdbus org.kde.konversation /irc say $1 $2 "getpid_dir: $konvi_qt4 qt4_konvi: $konvi_qt4_ver verNum: $konvi_qt4_ver_num pid: $konvi_pid ppid: $PPID konvi_home_dir: ${konvi[2]}" +} + +# This needs some cleanup and comments, not quite understanding what is happening, although generally output is known +# Parse the null separated commandline under /proc//cmdline +# args: $1 - $PPID +get_cmdline() +{ + eval $LOGFS + local i=0 ppid=$1 + + if [[ ! -e /proc/$ppid/cmdline ]];then + echo 0 + return + fi + ##print_screen_output "Marker" + ##print_screen_output "\$ppid='$ppid' -=- $(< /proc/$ppid/cmdline)" + unset A_CMDL + ## note: need to figure this one out, and ideally clean it up and make it readable + while read -d $'\0' L && [[ $i -lt 32 ]] + do + A_CMDL[i++]="$L" ## note: make sure this is valid - What does L mean? ## + done < /proc/$ppid/cmdline + ##print_screen_output "\$i='$i'" + if [[ $i -eq 0 ]];then + A_CMDL[0]=$(< /proc/$ppid/cmdline) + if [[ -n ${A_CMDL[0]} ]];then + i=1 + fi + fi + CMDL_MAX=$i + log_function_data "CMDL_MAX: $CMDL_MAX" + eval $LOGFE +} + +#### ------------------------------------------------------------------- +#### get data types +#### ------------------------------------------------------------------- +## create array of sound cards installed on system, and if found, use asound data as well +get_audio_data() +{ + eval $LOGFS + local i='' alsa_data='' alsa_driver='' device_count='' + local usb_proc_file='' array_count='' usb_id='' usb_data='' + + IFS=$'\n' + # this first step handles the drivers for cases where the second step fails to find one + device_count=$( echo "$Lspci_Data" | egrep -ic '(multimedia audio controller|audio device)' ) + if [[ $device_count -eq 1 ]] && [[ $B_ASOUND_CARDS == 'true' ]];then + alsa_driver=$( gawk -F ']: ' ' + BEGIN { + IGNORECASE=1 + } + # filtering out modems and usb devices like webcams, this might get a + # usb audio card as well, this will take some trial and error + $0 !~ /modem/ || $0 !~ /usb/ { + driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 ) + gsub(/^ +| +$/,"",driver) + if ( driver != "" ){ + print driver + } + }' $FILE_ASOUND_DEVICE ) + log_function_data 'cat' "$FILE_ASOUND_DEVICE" + fi + + # this is to safeguard against line breaks from results > 1, which if inserted into following + # array will create a false array entry. This is a hack, not a permanent solution. + alsa_driver=$( echo $alsa_driver ) + # now we'll build the main audio data, card name, driver, and port. If no driver is found, + # and if the first method above is not null, and one card is found, it will use that instead. + A_AUDIO_DATA=( $( echo "$Lspci_Data" | gawk -F ': ' -v alsaDriver="$alsa_driver" ' + BEGIN { + IGNORECASE=1 + } + /multimedia audio controller|audio device/ { + audioCard=gensub(/^[0-9a-f:.]+ [^:]+: (.+)$/,"\\1","g",$0) + # The doublequotes are necessary because of the pipes in the variable. + gsub(/'"$BAN_LIST_NORMAL"'/, "", audioCard) + gsub(/,/, " ", audioCard) + gsub(/^ +| +$/, "", audioCard) + gsub(/ [ \t]+/, " ", audioCard) + + cards[audioCard]++ + + # loop until you get to the end of the data block + while (getline && !/^$/) { + if (/driver in use/) { + drivers[audioCard] = drivers[audioCard] gensub(/(.*): (.*)/,"\\2","g",$0) "" + } + else if (/kernel modules:/) { + modules[audioCard] = modules[audioCard] gensub(/(.*): (.*)/,"\\2","g",$0) "" + } + else if (/I\/O/) { + portsTemp = gensub(/\t*I\/O ports at (.*) \[.*\]/,"\\1","g",$0) + ports[audioCard] = ports[audioCard] portsTemp " " + } + } + } + + END { + j=0 + for (i in cards) { + useDrivers="" + useModules="" + usePorts="" + if (cards[i]>1) { + a[j]=cards[i]"x "i + if (drivers[i] != "") { + useDrivers=drivers[i] + } + if (ports[i] != "") { + usePorts = ports[i] + } + if (modules[i] != "" ) { + useModules = modules[i] + } + } + else { + a[j]=i + # little trick here to try to catch the driver if there is + # only one card and it was null, from the first test of asound/cards + if (drivers[i] != "") { + useDrivers=drivers[i] + } + else if ( alsaDriver != "" ) { + useDrivers=alsaDriver + } + if (ports[i] != "") { + usePorts=ports[i] + } + if (modules[i] != "" ) { + useModules = modules[i] + } + } + # create array primary item for master array + print a[j] "," useDrivers "," usePorts "," useModules + j++ + } + }') ) + + # in case of failure of first check do this instead + if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]] && [[ $B_ASOUND_CARDS == 'true' ]];then + A_AUDIO_DATA=( $( gawk -F ']: ' ' + BEGIN { + IGNORECASE=1 + } + $1 !~ /modem/ && $2 !~ /modem/ { + card=gensub( /^(.+)( - )(.+)$/, "\\3", 1, $2 ) + driver=gensub( /^(.+)( - )(.+)$/, "\\1", 1, $2 ) + if ( card != "" ){ + print card","driver + } + }' $FILE_ASOUND_DEVICE ) ) + fi + + # alsa usb detection by damentz + # for every sound card symlink in /proc/asound - display information about it + for usb_proc_file in /proc/asound/* + do + # if lsusb exists, the file is a symlink, and contains an important usb exclusive file: continue + if [[ -n $( which lsusb ) && -L $usb_proc_file && -e $usb_proc_file/usbid ]]; then + # send error messages of lsusb to /dev/null as it will display a bunch if not a super user + # also, find the contents of usbid in lsusb and print everything after the 7th word on the + # corresponding line. Finally, strip out commas as they will change the driver :) + usb_id=$( cat $usb_proc_file/usbid ) + usb_data=$( lsusb -v 2>/dev/null | grep "$usb_id" ) + log_function_data 'raw' "usb_data:\n$usb_data" + usb_data=$( gawk '{ + gsub( /,/, " ", $0 ) + for( i=7; i <= NF; i++ ) { + printf( $i " " ) + } + }' <<< "$usb_data" ) + # this method is interesting, it shouldn't work but it does + #A_AUDIO_DATA=( "${A_AUDIO_DATA[@]}" "$usb_data,snd-usb-audio,," ) + # but until we learn why the above worked, I'm using this one, which is safer + if [[ -n $usb_data ]];then + array_count=${#A_AUDIO_DATA[@]} + A_AUDIO_DATA[$array_count]="$usb_data,snd-usb-audio,," + fi + fi + done + IFS="$ORIGINAL_IFS" + + # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes.. + if [[ ${#A_AUDIO_DATA[@]} -eq 0 ]];then + A_AUDIO_DATA[0]='Failed to Detect Sound Card!' + fi + log_function_data "A_AUDIO_DATA: ${A_AUDIO_DATA[@]}" + eval $LOGFE +} + +get_audio_alsa_data() +{ + eval $LOGFS + local alsa_data='' + + # now we'll get the alsa data if the file exists + if [[ $B_ASOUND_VERSION == 'true' ]];then + alsa_data=$( gawk ' + BEGIN { + IGNORECASE=1 + } + # some alsa strings have the build date in (...) + # remove trailing . and remove possible second line if compiled by user + $0 !~ /compile/ { + gsub( "Driver | [(].*[)]|\.$","",$0 ) + gsub(/,/, " ", $0) + gsub(/^ +| +$/, "", $0) + gsub(/ [ \t]+/, " ", $0) + if ( $0 != "" ){ + print $0 + } + }' $FILE_ASOUND_VERSION ) + log_function_data 'cat' "$FILE_ASOUND_VERSION" + fi + echo "$alsa_data" + log_function_data "alsa_data: $alsa_data" + eval $LOGFE +} + +## create A_CPU_CORE_DATA, currently with two values: integer core count; core string text +## return value cpu core count string, this helps resolve the multi redundant lines of old style output +get_cpu_core_count() +{ + eval $LOGFS + if [[ $B_CPUINFO == 'true' ]]; then + # load the A_CPU_TYPE_PCNT_CCNT core data array + get_cpu_ht_multicore_smp_data + ## Because of the upcoming release of cpus with core counts over 6, a count of cores is given after Deca (10) + # count the number of processors given + local cpu_physical_count=${A_CPU_TYPE_PCNT_CCNT[1]} + local cpu_core_count=${A_CPU_TYPE_PCNT_CCNT[2]} + local cpu_type=${A_CPU_TYPE_PCNT_CCNT[0]} + + # match the numberic value to an alpha value + case $cpu_core_count in + 1) cpu_alpha_count='Single';; + 2) cpu_alpha_count='Dual';; + 3) cpu_alpha_count='Triple';; + 4) cpu_alpha_count='Quad';; + 5) cpu_alpha_count='Penta';; + 6) cpu_alpha_count='Hexa';; + 7) cpu_alpha_count='Hepta';; + 8) cpu_alpha_count='Octa';; + 9) cpu_alpha_count='Ennea';; + 10) cpu_alpha_count='Deca';; + *) cpu_alpha_count='Multi';; + esac + # create array, core count integer; core count string + # A_CPU_CORE_DATA=( "$cpu_core_count" "$cpu_alpha_count Core$cpu_type" ) + A_CPU_CORE_DATA=( "$cpu_physical_count" "$cpu_alpha_count" "$cpu_type" "$cpu_core_count" ) + fi + log_function_data "A_CPU_CORE_DATA: ${A_CPU_CORE_DATA[@]}" + eval $LOGFE +} + +## main cpu data collector +get_cpu_data() +{ + eval $LOGFS + local i='' j='' cpu_array_nu='' a_cpu_working='' multi_cpu='' bits='' + + if [[ $B_CPUINFO == 'true' ]];then + IFS=$'\n' + A_CPU_DATA=( $( gawk -F': ' ' + BEGIN { + IGNORECASE=1 + } + # TAKE STRONGER NOTE: \t+ does NOT always work, MUST be [ \t]+ + # TAKE NOTE: \t+ will work for $FILE_CPUINFO, but SOME ARBITRARY FILE used for TESTING might contain SPACES! + # Therefore PATCH to use [ \t]+ when TESTING! + /^processor[ \t]+:/ { + nr = $NF + } + + /^model name|^cpu\t+:/ { + gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF ) + gsub(/'"$BAN_LIST_CPU"'/, "", $NF ) + gsub(/,/, " ", $NF) + gsub(/^ +| +$/, "", $NF) + gsub(/ [ \t]+/, " ", $NF) + cpu[nr, "model"] = $NF + } + + /^cpu MHz|^clock\t+:/ { + if (!min) { + min = $NF + } + else { + if ($NF < min) { + min = $NF + } + } + + if ($NF > max) { + max = $NF + } + gsub(/MHZ/,"",$NF) ## clears out for cell cpu + gsub(/.00[0]+$/,".00",$NF) ## clears out excessive zeros + cpu[nr, "speed"] = $NF + } + + /^cache size/ { + cpu[nr, "cache"] = $NF + } + + /^flags/ { + cpu[nr, "flags"] = $NF + } + + /^bogomips/ { + cpu[nr, "bogomips"] = $NF + } + + /vendor_id/ { + gsub(/genuine|authentic/,"",$NF) + cpu[nr, "vendor"] = tolower( $NF ) + } + + END { + #if (!nr) { print ",,,"; exit } # <- should this be necessary or should bash handle that + for ( i = 0; i <= nr; i++ ) { + print cpu[i, "model"] "," cpu[i, "speed"] "," cpu[i, "cache"] "," cpu[i, "flags"] "," cpu[i, "bogomips"] "," cpu[nr, "vendor"] + } + if (!min) { + print "not found" + exit + } + if (min != max) { + printf("Min:%s%s Max:%s%s\n", min, "Mhz", max, "Mhz") + } + else { + printf("%s %s\n", max, "Mhz") + } + }' $FILE_CPUINFO ) ) + log_function_data 'cat' "$FILE_CPUINFO" + fi + + IFS="$ORIGINAL_IFS" + log_function_data "A_CPU_DATA: ${A_CPU_DATA[@]}" + eval $LOGFE +# echo getMainCpu: ${[@]} +} + +## this is for counting processors and finding HT types +get_cpu_ht_multicore_smp_data() +{ + eval $LOGFS + # in /proc/cpuinfo + # algorithm + # if > 1 processor && processor id (physical id) == core id then Hyperthreaded (HT) + # if > 1 processor && different processor ids then Multiple Processors (SMP) + # if > 1 processor && processor id != core id then Multi-Core Processors (MCP) + # if = 1 processor then single core/processor Uni-Processor (UP) + + if [[ $B_CPUINFO == 'true' ]]; then + A_CPU_TYPE_PCNT_CCNT=( $( + gawk ' + BEGIN { + FS=": " + IGNORECASE = 1 + core_count = 0 + i = 0 + index_temp = "" + num_of_cores = 0 + physical_cpu_count = 0 + processor_logical_count = 0 + processors = 1 + type = "UP" + } + # counts logical processors, both HT and physical + /^processor/ { + processor_logical_count = $NF + 1 + } + # counts physical cores (not used currently) + /^cpu cores/ { + num_of_cores = $NF + } + # array of physical cpus ids + /^physical/ { + a_physical_id[i] = $NF + } + # array of core ids + /^core id/ { + a_core_id[i] = $NF + i++ + } + END { + # look for the largest id number, and assign it + for ( j = 0; j < processor_logical_count; j++ ) { + if ( a_core_id[j] > core_count ) { + core_count = a_core_id[j] + } + } + core_count = core_count + 1 + # trick, set the index equal to value, if the same, it will overwrite + # this lets us create the actual array of true cpu physical ids + for ( j in a_physical_id ) { + index_temp = a_physical_id[j] + a_cpu_physical_working[index_temp] = a_physical_id[j] + } + # note that length() is a gawk >= 3.1.5 only method, better to do it manually + for ( j in a_cpu_physical_working ) { + ++physical_cpu_count + } + + # looking at logical processor counts over 1, which means either HT, SMP or MCP + # http://en.wikipedia.org/wiki/Symmetric_multiprocessing + if ( processor_logical_count > 1 && core_count > 1 ) { + if ( processor_logical_count > core_count && physical_cpu_count > 1 ) { + type = "SMP-HT" # could be Xeon/P4 HT dual cpu + } + else if ( processor_logical_count > core_count ) { + type = "HT" # this is more than likely a P4 w/HT or an Atom 270 + } + else { + type = "SMP" + } + } + # make sure to handle up cpus too + else { + core_count = 1 + physical_cpu_count = 1 + } + print type " " physical_cpu_count " " core_count + } + ' $FILE_CPUINFO ) ) + fi + log_function_data "A_CPU_TYPE_PCNT_CCNT: ${A_CPU_TYPE_PCNT_CCNT[@]}" + eval $LOGFE +} + +# for more on distro id, please reference this python thread: http://bugs.python.org/issue1322 +## return distro name/id if found +get_distro_data() +{ + eval $LOGFS + local i='' j='' distro='' distro_file='' a_distro_glob='' + + # get the wild carded array of release/version /etc files if present + shopt -s nullglob + cd /etc + a_distro_glob=(*[-_]{release,version}) + cd "$OLDPWD" + shopt -u nullglob + + if [[ ${#a_distro_glob[@]} -eq 1 ]];then + distro_file="${a_distro_glob}" + # use the file if it's in the known good lists + elif [[ ${#a_distro_glob[@]} -gt 1 ]];then + for i in $DISTROS_DERIVED $DISTROS_PRIMARY + do + # Only echo works with ${var[@]}, not print_screen_output() or script_debugger() + # This is a known bug, search for the word "strange" inside comments + # echo "i='$i' a_distro_glob[@]='${a_distro_glob[@]}'" + if [[ " ${a_distro_glob[@]} " == *" $i "* ]];then + # Now lets see if the distro file is in the known-good working-lsb-list + # if so, use lsb-release, if not, then just use the found file + # this is for only those distro's with self named release/version files + # because Mint does not use such, it must be done as below + ## this if statement requires the spaces and * as it is, else it won't work + ## + if [[ " $DISTROS_LSB_GOOD " == *" ${i} "* ]] && [[ $B_LSB_DIR == 'true' ]];then + distro_file='lsb-release' + else + distro_file="${i}" + fi + break + fi + done + fi + log_function_data "distro_file: $distro_file" + # first test for the legacy antiX distro id file + if [[ -e /etc/antiX ]];then + distro="$( egrep -oi 'antix.*\.iso' <<< $( remove_erroneous_chars '/etc/antiX' ) | sed 's/\.iso//' )" + # this handles case where only one release/version file was found, and it's lsb-release. This would + # never apply for ubuntu or debian, which will filter down to the following conditions. In general + # if there's a specific distro release file available, that's to be preferred, but this is a good backup. + elif [[ -n $distro_file && -f $FILE_LSB_RELEASE && " $DISTROS_LSB_GOOD" == *" $distro_file "* ]];then + distro=$( get_distro_lsb_data ) + elif [[ $distro_file == 'lsb-release' ]];then + distro=$( get_distro_lsb_data ) + # then if the distro id file was found and it's not in the exluded primary distro file list, read it + elif [[ -n $distro_file && -s /etc/$distro_file && " $DISTROS_EXCLUDE_LIST " != *" $distro_file "* ]];then + distro=$( remove_erroneous_chars "/etc/$distro_file" ) + # otherwise try the default debian/ubuntu /etc/issue file + elif [[ -f /etc/issue ]];then + # lsb gives more manageable and accurate output than issue, but mint should use issue for now + # some bashism, boolean must be in parenthesis to work correctly, ie [[ $(boolean) ]] not [[ $boolean ]] + if [[ $B_LSB_DIR == 'true' ]] && [[ -z $( grep -i 'mint' /etc/issue ) ]];then + distro=$( get_distro_lsb_data ) + else + distro=$( gawk ' + BEGIN { + RS="" + } + { + gsub(/\\[a-z]/, "") + gsub(/,/, " ") + gsub(/^ +| +$/, "") + gsub(/ [ \t]+/, " ") + print + }' /etc/issue ) + fi + fi + + if [[ ${#distro} -gt 80 ]] && [[ $B_HANDLE_CORRUPT_DATA != 'true' ]];then + distro="${RED}/etc/${distro_file} corrupted, use -% to override${NORMAL}" + fi + ## note: would like to actually understand the method even if it's not used + # : ${distro:=Unknown distro o_O} + ## test for /etc/lsb-release as a backup in case of failure, in cases where > one version/release file + ## were found but the above resulted in null distro value + if [[ -z $distro ]] && [[ $B_LSB_DIR == 'true' ]];then + distro=$( get_distro_lsb_data ) + fi + ## finally, if all else has failed, give up + if [[ -z $distro ]];then + distro='Unknown distro o_O' + fi + + # this handles an arch bug where /etc/arch-release is empty and /etc/issue is corrupted + if [[ -n $( grep -i 'arch linux' <<< $distro ) ]];then + distro='Arch Linux' + fi + + echo "$distro" + log_function_data "distro: $distro" + eval $LOGFE +} + +# args: $1 - optional, app, uses the app test, not being used now +get_distro_lsb_data() +{ + eval $LOGFS + local distro='' + + if [[ $B_LSB_DIR == 'true' ]] && [[ $1 != 'app' ]];then + distro=$( gawk -F '=' ' + BEGIN { + IGNORECASE=1 + } + # note: adding the spacing directly to variable to make sure distro output is null if not found + /^DISTRIB_ID/ { + gsub(/^ +| +$/, "", $NF) + # this is needed because grep for "arch" is too loose to be safe + if ( $NF == "arch" ) { + distroId = "Arch Linux" + } + else if ( $NF != "n/a" ) { + distroId = $NF " " + } + } + /^DISTRIB_RELEASE/ { + gsub(/^ +| +$/, "", $NF) + if ( $NF != "n/a" ) { + distroRelease = $NF " " + } + } + /^DISTRIB_CODENAME/ { + gsub(/^ +| +$/, "", $NF) + if ( $NF != "n/a" ) { + distroCodename = $NF " " + } + } + END { + print distroId distroRelease distroCodename + }' $FILE_LSB_RELEASE ) + log_function_data 'cat' "$FILE_LSB_RELEASE" + fi + # this is HORRIBLY slow, but I don't know why, it runs fast in shell +# if [[ -n $( which lsb_release ) && $1 == 'app' ]];then +# distro=$( echo "$( lsb_release -irc )" | gawk ' +# { IGNORECASE=1 } +# /^Distributor ID/ { +# gsub(/^ +| +$/, "", $NF) +# distroId = $NF +# } +# /^Release/ { +# gsub(/^ +| +$/, "", $NF) +# distroRelease = $NF +# } +# /^Codename/ { +# gsub(/^ +| +$/, "", $NF) +# distroCodename = $NF +# } +# END { +# print distroId " " distroRelease " (" distroCodename ")" +# }' ) +# fi + + echo $distro + log_function_data "distro: $distro" + eval $LOGFE +} + +get_gpu_temp_data() +{ + local gpu_temp='' gpu_fan='' + + # we'll try for nvidia/ati, then add if more are shown + if [[ -n $( type -p nvidia-settings ) ]];then + gpu_temp=$( nvidia-settings -q GPUCoreTemp | gawk -F ': ' ' + BEGIN { + IGNORECASE=1 + gpuTemp="" + gpuTempWorking="" + } + /Attribute (.*)[0-9]+\.$/ { + gsub(/\./, "", $2) + if ( $2 ~ /^[0-9]+$/ ) { + gpuTemp=gpuTemp $2 "C " + } + } + END { + print gpuTemp + }' + ) + elif [[ -n $( type -p aticonfig ) ]];then +# gpu_temp=$( aticonfig --adapter=0 --od-gettemperature | gawk -F ': ' ' + gpu_temp=$( aticonfig --adapter=all --od-gettemperature | gawk -F ': ' ' + BEGIN { + IGNORECASE=1 + gpuTemp="" + gpuTempWorking="" + } + /Sensor (.*)[0-9\.]+ / { + gpuTempWorking=gensub(/(.*) ([0-9\.]+) (.*)/, "\\2", "1", $2) + if ( gpuTempWorking ~ /^[0-9\.]+$/ ) { + gpuTemp=gpuTemp gpuTempWorking "C " + } + } + END { + print gpuTemp + }' + ) + fi + + if [[ -n $gpu_temp ]];then + echo $gpu_temp + fi +} + +## create array of gfx cards installed on system +get_graphics_card_data() +{ + eval $LOGFS + local i='' + + IFS=$'\n' + A_GFX_CARD_DATA=( $( echo "$Lspci_Data" | gawk -F': ' ' + BEGIN { + IGNORECASE=1 + } + /vga compatible controller/ { + gsub(/'"$BAN_LIST_NORMAL"'/, "", $NF) + gsub(/,/, " ", $NF) + gsub(/^ +| +$/, "", $NF) + gsub(/ [ \t]+/, " ", $NF) + print $NF + }' ) ) + IFS="$ORIGINAL_IFS" +# for (( i=0; i < ${#A_GFX_CARD_DATA[@]}; i++ )) +# do +# A_GFX_CARD_DATA[i]=$( sanitize_characters BAN_LIST_NORMAL "${A_GFX_CARD_DATA[i]}" ) +# done + # handle cases where card detection fails, like in PS3, where lspci gives no output, or headless boxes.. + if [[ ${#A_GFX_CARD_DATA[@]} -eq 0 ]];then + A_GFX_CARD_DATA[0]='Failed to Detect Video Card!' + fi + + # GFXMEM is UNUSED at the moment, because it shows AGP aperture size, which is not necessarily equal to GFX memory.. + # GFXMEM="size=[$(echo "$Lspci_Data" | gawk '/VGA/{while (!/^$/) {getline;if (/size=[0-9][0-9]*M/) {size2=gensub(/.*\[size=([0-9]+)M\].*/,"\\1","g",$0);if (size 1 cases of detections I guess + function join( arr, sep ) { + s="" + i=flag=0 + for ( i in arr ) { + if ( flag++ ) { + s = s sep + } + s = s i + } + return s + } + + BEGIN { + IGNORECASE=1 + } + /opengl renderer/ { + if ( $2 ~ /mesa/ ) { + # Allow all mesas +# if ( $2 ~ / r[3-9][0-9][0-9] / ) { + gsub(/'"$BAN_LIST_NORMAL"'/, "", $2) + a[$2] + # this counter failed in one case, a bug, and is not needed now +# f++ +# } + next + } + $2 && a[$2] + } + # dropping all conditions from this test to just show full mesa information + # there is a user case where not f and mesa apply, atom mobo + # /opengl version/ && ( f || $2 !~ /mesa/ ) { + /opengl version/ { + $2 && b[$2] + } + /direct rendering/ { + $2 && c[$2] + } + END { + printf( "%s\n%s\n%s\n", join( a, ", " ), join( b, ", " ), join( c, ", " ) ) + }' ) ) + IFS="$ORIGINAL_IFS" + + # GLXR=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl renderer/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}') + # GLXV=$(glxinfo | gawk -F ': ' 'BEGIN {IGNORECASE=1} /opengl version/ && $2 !~ /mesa/ {seen[$2]++} END {for (i in seen) {printf("%s ",i)}}') + fi + log_function_data "A_GLX_DATA: ${A_GLX_DATA[@]}" + eval $LOGFE +} + +## return screen resolution / tty resolution +get_graphics_res_data() +{ + eval $LOGFS + local screen_resolution='' + + if [[ $B_X_RUNNING == 'true' && $B_ROOT != 'true' ]];then + # Added the two ?'s , because the resolution is now reported without spaces around the 'x', as in + # 1400x1050 instead of 1400 x 1050. Change as of X.org version 1.3.0 + screen_resolution=$( xrandr | gawk ' + /\*/ { + res[++m] = gensub(/^.* ([0-9]+) ?x ?([0-9]+)[_ ].* ([0-9\.]+)\*.*$/,"\\1x\\2@\\3hz","g",$0) + } + END { + for (n in res) { + if (res[n] ~ /^[[:digit:]]+x[[:digit:]]+/) { + line = line ? line ", " res[n] : res[n] + } + } + if (line) { + print(line) + } + }' ) + if [[ -z $screen_resolution ]];then + screen_resolution=$( xdpyinfo | gawk ' + /dimensions/ { + print $2 + }' ) + fi + else + screen_resolution=$( stty -F $( readlink /proc/$PPID/fd/0 ) size | gawk '{ + print $2"x"$1 + }' ) + fi + echo "$screen_resolution" + log_function_data "screen_resolution: $screen_resolution" + eval $LOGFE +} + +## for possible future data, not currently used +get_graphics_agp_data() +{ + eval $LOGFS + local agp_module='' + + if [[ $B_MODULES_DIR == 'true' ]];then + ## not used currently + agp_module=$( gawk ' + /agp/ && !/agpgart/ && $3 > 0 { + print(gensub(/(.*)_agp.*/,"\\1","g",$1)) + }' $FILE_MODULES ) + log_function_data 'cat' "$FILE_MODULES" + fi + log_function_data "agp_module: $agp_module" + eval $LOGFE +} + +## create array of x vendor/version data +get_graphics_x_data() +{ + eval $LOGFS + local x_vendor='' x_version='' + + if [[ $B_X_RUNNING == 'true' && $B_ROOT != 'true' ]];then + # X vendor and version detection. + x_vendor=$( xdpyinfo | gawk -F': +' ' + BEGIN { + IGNORECASE=1 + } + /vendor string/ { + gsub(/the|inc|foundation|project|corporation/, "", $2) + gsub(/,/, " ", $2) + gsub(/^ +| +$/, "", $2) + gsub(/ [ \t]+/, " ", $2) + print $2 + }' ) + + # new method added since radeon and X.org and the disappearance of version : ...etc + # Later on, the normal textual version string returned, e.g. like: X.Org version: 6.8.2 + # A failover mechanism is in place. (if $x_version is empty, the release number is parsed instead) + x_version=$( xdpyinfo | gawk ' + /version:/ { + print $NF + }' ) + if [[ -z $x_version ]];then + x_version=$(xdpyinfo | gawk -F': +' ' + BEGIN { + IGNORECASE=1 + } + /vendor release number/ { + gsub(/0+$/, "", $2) + gsub(/0+/, ".", $2) + print $2 + }' ) + fi + A_X_DATA[0]="$x_vendor" + A_X_DATA[1]="$x_version" + + #X -version 2>&1 | gawk '/^X Window System Version/ { print $5 }' + #This method could be used in the future to detect X when X is not running, + #however currently inxi ignores X checks when X is not found. + fi + log_function_data "A_X_DATA: ${A_X_DATA[@]}" + eval $LOGFE +} + +# this gets just the raw data, total space/percent used and disk/name/per disk capacity +get_hdd_data_basic() +{ + eval $LOGFS + local hdd_used='' + local hdd_data="$( df --exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660 )" + log_function_data 'raw' "hdd_data:\n$hdd_data" + + hdd_used=$( echo "$hdd_data" | gawk ' + # also handles odd dm-1 type, from lvm + /^\/dev\/(mapper\/|[hs]d[a-z][0-9]+|dm[-]?[0-9]+)/ { + # this handles the case where the first item is too long + # and makes df wrap output to next line, so here we advance + # it to the next line for that single case + if ( NF < 5 && $0 !~ /.*\%/ ) { + getline + } + # if the first item caused a wrap, use one less than standard + # testing for the field with % in it, ie: 34%, then go down from there + # this also protects against cases where the mount point has a space in the + # file name, thus breaking going down from $NF directly. + if ( $4 ~ /.*\%/ ) { + used += $2 + } + # otherwise use standard + else if ( $5 ~ /.*\%/ ) { + used += $3 + } + # and if this is not detected, give up, we need user data to debug + else { + next + } + } + END { + print used + }' ) + + if [[ -z $hdd_used ]];then + hdd_used='na' + fi + log_function_data "hdd_used: $hdd_used" + # create the initial array strings: + # disk-dev, capacity, name, usb or not + # final item is the total of the disk + IFS=$'\n' + + if [[ $B_PARTITIONS_DIR == 'true' ]];then + A_HDD_DATA=( $( + gawk -v hddused="$hdd_used" ' + /[hs]d[a-z]$/ { + driveSize = $(NF - 1)*1024/1000**3 + gsub(/,/, " ", driveSize) + gsub(/^ +| +$/, "", driveSize) + printf( $NF",%.1fGB,,\n", driveSize ) + } + # See http://lanana.org/docs/device-list/devices-2.6+.txt for major numbers used below + # $1 ~ /^(3|22|33|8)$/ && $2 % 16 == 0 { + # size += $3 + # } + # special case from this data: 8 0 156290904 sda + $1 ~ /^(3|22|33|8)$/ && $NF ~ /[hs]d[a-z]$/ && ( $2 % 16 == 0 || $2 % 16 == 8 ) { + size += $3 + } + + END { + size = size*1024/1000**3 # calculate size in GB size + workingUsed = hddused*1024/1000**3 # calculate workingUsed in GB used + # this handles a special case with livecds where no hdd_used is detected + if ( size > 0 && hddused == "na" ) { + size = sprintf( "%.1f", size ) + print size "GB,-" + } + else if ( size > 0 && workingUsed > 0 ) { + diskUsed = workingUsed*100/size # calculate used percentage + diskUsed = sprintf( "%.1f", diskUsed ) + size = sprintf( "%.1f", size ) + print size "GB," diskUsed "% used" + } + else { + print "NA,-" # print an empty array, this will be further handled in the print out function + } + }' $FILE_PARTITIONS ) ) + log_function_data 'cat' "$FILE_PARTITIONS" + fi + IFS="$ORIGINAL_IFS" + log_function_data "A_HDD_DATA: ${A_HDD_DATA[@]}" + eval $LOGFE +} + +## fills out the A_HDD_DATA array with disk names +get_hard_drive_data_advanced() +{ + eval $LOGFS + local a_temp_working='' a_temp_scsi='' temp_holder='' temp_name='' i='' j='' + local sd_ls_by_id='' ls_disk_by_id='' + + ## check for all ide type drives, non libata, only do it if hdx is in array + if [[ -n $( egrep 'hd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then + # remember, we're using the last array item to store the total size of disks + for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ )) + do + IFS="," + a_temp_working=( ${A_HDD_DATA[i]} ) + IFS="$ORIGINAL_IFS" + if [[ -n $( egrep '^hd[a-z]' <<< ${a_temp_working[0]} ) ]];then + if [[ -e /proc/ide/${a_temp_working[0]}/model ]];then + a_temp_working[2]="$( remove_erroneous_chars /proc/ide/${a_temp_working[0]}/model )" + else + a_temp_working[2]="Name n/a" + fi + # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu. + for (( j=0; j < ${#a_temp_working[@]}; j++ )) + do + if [[ $j -gt 0 ]];then + A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}" + else + A_HDD_DATA[i]="${a_temp_working[$j]}" + fi + done + fi + done + fi + + ## then handle libata names + # first get the ata device names, put them into an array + IFS=$'\n' + if [[ $B_SCSI_DIR == 'true' ]]; then + a_temp_scsi=( $( gawk ' + BEGIN { + IGNORECASE=1 + } + /host/ { + getline a[$0] + getline b[$0] + } + END { + for (i in a) { + if (b[i] ~ / *type: *direct-access.*/) { + #c=gensub(/^ *vendor: (.+) +model: (.+) +rev: (.+)$/,"\\1 \\2 \\3","g",a[i]) + #c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/,"\\1 \\2","g",a[i] ) + # the vendor: string is useless, and is a bug, ATA is not a vendor for example + c=gensub( /^ *vendor: (.+) +model: (.+) +rev:.*$/, "\\2", "g", a[i] ) + gsub(/,/, " ", c) + gsub(/^ +| +$/, "", c) + gsub(/ [ \t]+/, " ", c) + #print a[i] + # we actually want this data, so leaving this off for now +# if (c ~ /\|\|memory stick|memory card/) { +# continue +# } + print c + } + } + }' $FILE_SCSI ) ) + log_function_data 'cat' "$FILE_SCSI" + fi + IFS="$ORIGINAL_IFS" + + ## then we'll loop through that array looking for matches. + if [[ -n $( egrep 'sd[a-z]' <<< ${A_HDD_DATA[@]} ) ]];then + # first pack the main ls variable so we don't have to keep using ls /dev... + ls_disk_by_id="$( ls -l /dev/disk/by-id )" + for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ )) + do + if [[ -n $( egrep '^sd[a-z]' <<< ${A_HDD_DATA[$i]} ) ]];then + IFS="," + a_temp_working=( ${A_HDD_DATA[$i]} ) + IFS="$ORIGINAL_IFS" + if [[ ${#a_temp_scsi[@]} -gt 0 ]];then + for (( j=0; j < ${#a_temp_scsi[@]}; j++ )) + do + ## ok, ok, it's incomprehensible, search /dev/disk/by-id for a line that contains the + # discovered disk name AND ends with the correct identifier, sdx + # get rid of whitespace for some drive names and ids, and extra data after - in name + temp_name=$( tr ' ' '_' <<< ${a_temp_scsi[$j]} | cut -d '-' -f 1 ) + sd_ls_by_id=$( egrep -m1 ".*$temp_name.*${a_temp_working[0]}$" <<< "$ls_disk_by_id" ) + + if [[ -n $sd_ls_by_id ]];then + a_temp_working[2]=${a_temp_scsi[$j]} + if [[ -n $( grep 'usb-' <<< $sd_ls_by_id ) ]];then + a_temp_working[3]='USB' + fi + break + else + # test to see if we can get a better name output when null + if [[ -n $temp_name ]];then + a_temp_working[2]=$temp_name + else + a_temp_working[2]="Name n/a" + fi + fi + done + else + a_temp_working[2]="Name n/a" + fi + + # these loops are to easily extend the cpu array created in the gawk script above with more fields per cpu. + for (( j=0; j < ${#a_temp_working[@]}; j++ )) + do + if [[ $j -gt 0 ]];then + A_HDD_DATA[i]="${A_HDD_DATA[i]},${a_temp_working[$j]}" + else + A_HDD_DATA[i]="${a_temp_working[$j]}" + fi + done + fi + done + unset ls_disk_by_id # and then let's dump the data we don't need + fi + log_function_data "A_HDD_DATA: ${A_HDD_DATA[@]}" + eval $LOGFE +} + +# a few notes, normally hddtemp requires root, but you can set user rights in /etc/sudoers. +# args: $1 - /dev/ to be tested for +get_hdd_temp_data() +{ + local hdd_temp='' sudo_command='' + + if [[ -n $( which hddtemp ) && -n $1 ]];then + # only use sudo if not root, -n option requires sudo -V 1.7 or greater. sudo will just error out + # which is the safest course here for now, otherwise that interactive sudo password thing is too annoying + # important: -n makes it non interactive, no prompt for password + if [[ $B_ROOT != 'true' && -n $( which sudo ) ]];then + sudo_command='sudo -n ' + fi + # this will fail if regular user and no sudo present, but that's fine, it will just return null + hdd_temp=$( eval $sudo_command hddtemp -nq -u C $1 ) + if [[ -n $hdd_temp && -n $( grep -E '^([0-9]+)$' <<< $hdd_temp ) ]];then + echo $hdd_temp + fi + fi +} + +get_lspci_data() +{ + eval $LOGFS + local lspci_data="$( lspci -v | gawk '{ + gsub(/\(prog-if[^)]*\)/,"") + print + }' )" + + echo "$lspci_data" + log_function_data 'raw' "lspci_data:\n$lspci_data" + eval $LOGFE +} + +## return memory used/installed +get_memory_data() +{ + eval $LOGFS + local memory='' + if [[ $B_MEMINFO == 'true' ]];then + memory=$( gawk ' + /^MemTotal:/ { + tot = $2 + } + /^(MemFree|Buffers|Cached):/ { + notused+=$2 + } + END { + used = tot-notused + printf("%.1f/%.1fMB\n", used/1024, tot/1024) + }' $FILE_MEMINFO ) + log_function_data 'cat' "$FILE_MEMINFO" + fi + echo "$memory" + log_function_data "memory: $memory" + eval $LOGFE +} + +# process and return module version data +get_module_version_number() +{ + eval $LOGFS + local module_version='' + + if [[ -n $( which modinfo ) ]];then + module_version=$( modinfo $1 | gawk ' + BEGIN { + IGNORECASE=1 + } + /^version/ { + gsub(/,/, " ", $2) + gsub(/^ +| +$/, "", $2) + gsub(/ [ \t]+/, " ", $2) + print $2 + } + ' ) + fi + + echo "$module_version" + log_function_data "module_version: $module_version" + eval $LOGFE +} + +## create array of network cards +get_networking_data() +{ + eval $LOGFS + IFS=$'\n' + A_NETWORK_DATA=( $( echo "$Lspci_Data" | gawk ' + BEGIN { + IGNORECASE=1 + } + /^[0-9a-f:.]+ (ethernet|network) (controller|bridge)/ || /^[0-9a-f:.]+ [^:]+: .*(ethernet|network).*$/ { + nic=gensub(/^[0-9a-f:.]+ [^:]+: (.+)$/,"\\1","g",$0) + gsub(/realtek semiconductor/, "Realtek", nic) + gsub(/davicom semiconductor/, "Davicom", nic) + # The doublequotes are necessary because of the pipes in the variable. + gsub(/'"$BAN_LIST_NORMAL"'/, "", nic) + gsub(/,/, " ", nic) + gsub(/^ +| +$/, "", nic) + gsub(/ [ \t]+/, " ", nic) + + eth[nic]++ + while (getline && !/^$/) { + if (/I\/O/) { + ports[nic] = ports[nic] $4 " " + } + if (/driver in use/) { + drivers[nic] = drivers[nic] gensub(/(.*): (.*)/,"\\2","g",$0) "" + } + else if (/kernel modules/) { + modules[nic] = modules[nic] gensub(/(.*): (.*)/,"\\2","g",$0) "" + } + } + } + + END { + j=0 + for (i in eth) { + useDrivers="" + usePorts="" + useModules="" + if (eth[i]>1) { + a[j]=eth[i]"x "i + ## note: this loses the plural ports case, is it needed anyway? + if (ports[i] != "") { + usePorts=ports[i] + } + if (drivers[i] != "") { + useDrivers=drivers[i] + } + if (modules[i] != "" ) { + useModules = modules[i] + } + } + else { + a[j]=i + if (ports[i] != "") { + usePorts=ports[i] + } + if (drivers[i] != "") { + useDrivers=drivers[i] + } + if (modules[i] != "" ) { + useModules = modules[i] + } + } + # create array primary item for master array + print a[j] "," useDrivers "," usePorts "," useModules + j++ + } + }') ) + IFS="$ORIGINAL_IFS" + log_function_data "A_NETWORK_DATA: ${A_NETWORK_DATA[@]}" + eval $LOGFE +} + +get_networking_wan_ip_data() +{ + eval $LOGFS + local ip='' + + # get ip using wget redirect to stdout. This is a clean, text only IP output url. + ip=$( wget -q -O - http://smxi.org/opt/ip.php | gawk -F 'is: ' '{ + #gsub("\n","",$2") + print $2 + }' ) + + if [[ -z $ip ]];then + ip='None Detected!' + fi + echo "$ip" + log_function_data "ip: $ip" + eval $LOGFE +} + +get_networking_local_ip_data() +{ + eval $LOGFS + if [[ $B_IFCONFIG == 'true' ]];then + IFS=$'\n' + A_INTERFACES_DATA=( $( ifconfig | gawk ' + BEGIN { + IGNORECASE=1 + } + $0 !~ /^lo/ { + # not clear on why inet is coming through, but this gets rid of it + # as first line item. + interface = $1 + gsub(/,/, " ", interface) + gsub(/^ +| +$/, "", interface) + gsub(/ [ \t]+/, " ", interface) + + aInterfaces[interface]++ + while (getline && !/^$/) { + if (/inet addr:/) { + ipAddresses[interface] = gensub( /addr:([0-9\.]+)/, "\\1", "g", $2 ) + } + } + } + + END { + j=0 + for (i in aInterfaces) { + useInterfaceIp = "" + a[j] = i + if (ipAddresses[i] != "") { + useInterfaceIp = ipAddresses[i] + } + # create array primary item for master array + # tested needed to avoid bad data from above, if null it is garbage + # this is the easiest way to handle junk I found, improve if you want + if ( useInterfaceIp != "" ) { + print a[j] "," useInterfaceIp + } + j++ + } + }') ) + IFS="$ORIGINAL_IFS" + fi + log_function_data "A_INTERFACES_DATA: ${A_INTERFACES_DATA[@]}" + eval $LOGFE +} + +get_partition_data() +{ + eval $LOGFS + #local excluded_file_types='--exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660' + # df doesn't seem to work in script with variables like at the command line + local main_partition_data="$( df -h -T --exclude-type=aufs --exclude-type=tmpfs --exclude-type=iso9660 )" + local swap_data="$( swapon -s )" + log_function_data 'raw' "main_partition_data:\n$main_partition_data\n\nswap_data:\n$swap_data" + + IFS=$'\n' + # sample line: /dev/sda2 ext3 15G 8.9G 4.9G 65% /home + # $NF = partition name; $(NF - 4) = partition size; $(NF - 3) = used, in gB; $(NF - 1) = percent used + ## note: by subtracting from the last field number NF, we avoid a subtle issue with LVM df output, where if + ## the first field is too long, it will occupy its own line, this way we are getting only the needed data + A_PARTITION_DATA=( $( echo "$main_partition_data" | gawk ' + BEGIN { + IGNORECASE=1 + } + # this has to be nulled for every iteration so it does not retain value from last iteration + devBase="" + # this is required because below we are subtracting from NF, so it has to be > 4 + # the real issue is long file system names that force the wrap of df output: //fileserver/main + # but we still need to handle more dynamically long space containing file names, but later. + ( NF < 5 ) && ( $0 !~ /[0-9]+\%/ ) { + # set the dev location here for cases of wrapped output + if ( NF == 1 ){ + devBase=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 ) + } + getline + } + # this handles yet another fredforfaen special case where a mounted drive + # has the search string in its name + $NF ~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$/ { + print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",main," devBase + } + # skip all these, including the first, header line. Use the --exclude-type + # to handle new filesystems types we do not want listed here + $NF !~ /^\/$|^\/boot$|^\/var$|^\/home$|^\/tmp$|^\/usr$|^filesystem/ { + # this is to avoid file systems with spaces in their names, that will make + # the test show the wrong data in each of the fields, if no x%, then do not use + # using 3 cases, first default, standard, 2nd, 3rd, handles one and two spaces in name + if ( $(NF - 1) ~ /[0-9]+\%/ ) { + print $NF "," $(NF - 4) "," $(NF - 3) "," $(NF - 1) ",secondary," devBase + } + # these two cases construct the space containing name + else if ( $(NF - 2) ~ /[0-9]+\%/ ) { + print $(NF - 1) " " $NF "," $(NF - 5) "," $(NF - 4) "," $(NF - 2) ",secondary," devBase + } + else if ( $(NF - 3) ~ /[0-9]+\%/ ) { + print $(NF - 2) " " $(NF - 1) " " $NF "," $(NF - 6) "," $(NF - 5) "," $(NF - 3) ",secondary," devBase + } + } + ' ) + # now add the swap partition data, don't want to show swap files, just partitions, + # though this can include /dev/ramzswap0. Note: you can also use /proc/swaps for this + # data, it's the same exact output as swapon -s + $( echo "$swap_data" | gawk ' + BEGIN { + swapCounter = 1 + } + /^\/dev/ { + size = sprintf( "%.2f", $3*1024/1000**3 ) + devBase = gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 ) + used = sprintf( "%.2f", $4*1024/1000**3 ) + percentUsed = sprintf( "%.0f", ( $4/$3 )*100 ) + print "swap-" swapCounter "," size "GB," used "GB," percentUsed "\%,main," devBase + swapCounter = ++swapCounter + }' ) ) + IFS="$ORIGINAL_IFS" + + if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then + get_partition_data_advanced + fi + log_function_data "A_PARTITION_DATA: ${A_PARTITION_DATA[@]}" + eval $LOGFE +} + +# first get the locations of the mount points for label/uuid detection +get_partition_data_advanced() +{ + eval $LOGFS + local a_partition_working='' dev_partition_data='' + local dev_disk_label='' dev_disk_uuid='' dev_item='' dev_label='' dev_uuid='' + local mount_point='' + + if [[ -d /dev/disk/by-label ]];then + dev_disk_label="$( ls -l /dev/disk/by-label )" + fi + if [[ -d /dev/disk/by-uuid ]];then + dev_disk_uuid="$( ls -l /dev/disk/by-uuid )" + fi + log_function_data 'raw' "dev_disk_label:\n$dev_disk_label\n\ndev_disk_uuid:\n$dev_disk_uuid" + + if [[ $B_MOUNTS_DIR == 'true' ]];then + for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ )) + do + IFS="," + a_partition_working=( ${A_PARTITION_DATA[i]} ) + IFS="$ORIGINAL_IFS" + # note: for swap this will already be set + if [[ -z ${a_partition_working[5]} ]];then + mount_point=$( sed 's|/|\\/|g' <<< ${a_partition_working[0]} ) + #echo mount_point $mount_point + dev_partition_data=$( gawk ' + BEGIN { + IGNORECASE = 1 + partition = "" + partTemp = "" + } + # trying to handle space in name +# gsub( /\\040/, " ", $0 ) + /[ \t]'$mount_point'[ \t]/ && $1 != "rootfs" { + # initialize the variables + label = "" + uuid = "" + + # slice out the /dev + partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, $1 ) + # label and uuid can occur for root, set partition to null now + if ( partition ~ /by-label/ ) { + label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, $1 ) + partition = "" + } + if ( partition ~ /by-uuid/ ) { + uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, $1 ) + partition = "" + } + + # handle /dev/root for / id + if ( partition == "root" ) { + # if this works, great, otherwise, just set this to null values + partTemp="'$( readlink /dev/root 2>/dev/null )'" + if ( partTemp != "" ) { + if ( partTemp ~ /[hs]d[a-z][0-9]/ ) { + partition=gensub( /^(\/dev\/)(.+)$/, "\\2", 1, partTemp ) + } + else if ( partTemp ~ /by-uuid/ ) { + uuid=gensub( /^(\/dev\/disk\/by-uuid\/)(.+)$/, "\\2", 1, partTemp ) + partition="" # set null to let real location get discovered + } + else if ( partTemp ~ /by-label/ ) { + label=gensub( /^(\/dev\/disk\/by-label\/)(.+)$/, "\\2", 1, partTemp ) + partition="" # set null to let real location get discovered + } + } + else { + partition = "" + label = "" + uuid = "" + } + } + print partition "," label "," uuid + }' $FILE_MOUNTS ) + +# echo dev_partition_data: $dev_partition_data + # assemble everything we could get for dev/h/dx, label, and uuid + IFS="," + A_PARTITION_DATA[i]=${a_partition_working[0]}","${a_partition_working[1]}","${a_partition_working[2]}","${a_partition_working[3]}","${a_partition_working[4]}","$dev_partition_data + IFS="$ORIGINAL_IFS" + fi + ## now we're ready to proceed filling in the data + IFS="," + a_partition_working=( ${A_PARTITION_DATA[i]} ) + IFS="$ORIGINAL_IFS" + + dev_item=${a_partition_working[5]} + dev_label=${a_partition_working[6]} + dev_uuid=${a_partition_working[7]} + + # then if dev data/uuid is incomplete, try to get missing piece + # it's more likely we'll get a uuid than a label. But this should get the + # dev item set no matter what, so then we can get the rest of any missing data + # first we'll get the dev_item if it's missing + if [[ -n $dev_disk_uuid ]] && [[ -z $dev_item && -n $dev_uuid ]];then + dev_item=$( echo "$dev_disk_uuid" | gawk ' + /'$dev_uuid'/ { + item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF ) + print item + }' ) + elif [[ -n $dev_disk_label ]] && [[ -z $dev_item && -n $dev_label ]];then + dev_item=$( echo "$dev_disk_label" | gawk ' + # first we need to change space x20 in by-label back to a real space + #gsub( /x20/, " ", $0 ) + # then we can see if the string is there + /'$dev_label'/ { + item=gensub( /..\/..\/(.+)/, "\\1", 1, $NF ) + print item + }' ) + fi + if [[ -n $dev_disk_uuid ]] && [[ -n $dev_item && -z $dev_uuid ]];then + dev_uuid=$( echo "$dev_disk_uuid" | gawk ' + /'$dev_item'$/ { + print $(NF - 2) + }' ) + fi + if [[ -n $dev_disk_label ]] && [[ -n $dev_item && -z $dev_label ]];then + dev_label=$( echo "$dev_disk_label" | gawk ' + /'$dev_item'/ { + print $(NF - 2) + }' ) + + fi + # assemble everything we could get for dev/h/dx, label, and uuid + IFS="," + A_PARTITION_DATA[i]=${a_partition_working[0]}","${a_partition_working[1]}","${a_partition_working[2]}","${a_partition_working[3]}","${a_partition_working[4]}","$dev_item","$dev_label","$dev_uuid + IFS="$ORIGINAL_IFS" + done + log_function_data 'cat' "$FILE_MOUNTS" + fi + log_function_data "A_PARTITION_DATA: ${A_PARTITION_DATA[@]}" + eval $LOGFE +} + +get_sensors_data() +{ + eval $LOGFS + + IFS=$'\n' + if [[ $B_SENSORS == 'true' ]];then + # note: non-configured sensors gives error message, which we need to redirect to stdout + # also, -F ':' no space, since some cases have the data starting right after,like - :1287 + A_SENSORS_DATA=( $( + sensors | gawk -F ':' -v userCpuNo="$SENSORS_CPU_NO" ' + BEGIN { + IGNORECASE=1 + core0Temp="" # only if all else fails... + cpuTemp="" + cpuTempReal="" + fanWorking="" + indexCountaFanMain=0 + indexCountaFanDefault=0 + i="" + j="" + moboTemp="" + moboTempReal="" + psuTemp="" + separator="" + sysFanString="" + temp1="" + temp2="" + tempFanType="" # set to 1 or 2 + tempUnit="" + tempWorking="" + tempWorkingUnit="" + } + # dumping the extra + signs after testing for them, nobody has negative temps. + # also, note gawk treats ° as a space, so we have to get the C/F data + # there are some guesses here, but with more sensors samples it will get closer. + # note: using arrays starting at 1 for all fan arrays to make it easier overall + # more validation because gensub if fails to get match returns full string, so + # we have to be sure we are working with the actual real string before assiging + # data to real variables and arrays. Extracting C/F degree unit as well to use + # when constructing temp items for array. + # note that because of charset issues, no tempUnit="°" tempWorkingUnit degree sign + # used, but it is required in testing regex to avoid error. + /^(M\/B|MB|SYS)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + moboTemp=gensub( /[ \t]+\+([0-9\.]*)(.*)/, "\\1", 1, $2 ) + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + /^CPU(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + cpuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + /^(P\/S|Power)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + psuTemp=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + $1 ~ /^temp1$/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + if ( temp1 == "" || tempWorking > 0 ) { + temp1=tempWorking + } + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + $1 ~ /^temp2$/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + if ( temp2 == "" || tempWorking > 0 ) { + temp2=tempWorking + } + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + + # final fallback if all else fails, funtoo user showed sensors putting + # temp on wrapped second line, not handled + /^(core0|core 0)(.*)\+([0-9]+)(.*)[ \t°](C|F)/ && $2 ~ /^[ \t]*\+([0-9]+)/ { + tempWorking=gensub( /[ \t]+\+([0-9\.]+)(.*)/, "\\1", 1, $2 ) + if ( core0Temp == "" || tempWorking > 0 ) { + core0Temp=tempWorking + } + tempWorkingUnit=gensub( /[ \t]+\+([0-9\.]+)[ \t°]+([CF])(.*)/, "\\2", 1, $2 ) + if ( tempWorkingUnit ~ /^C|F$/ && tempUnit == "" ){ + tempUnit=tempWorkingUnit + } + } + + # note: can be cpu fan:, cpu fan speed:, etc. Some cases have no space before + # $2 starts (like so :1234 RPM), so skip that space test in regex + /^CPU(.*)[ \t]*([0-9]+)[ \t]RPM/ { + aFanMain[1]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + /^(M\/B|MB|SYS)(.*)[ \t]*([0-9]+)[ \t]RPM/ { + aFanMain[2]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + /(Power|P\/S|POWER)(.*)[ \t]*([0-9]+)[ \t]RPM/ { + aFanMain[3]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + + /^(AUX|FAN(1)? |CASE(1)? |CHASSIS(1)? )(.*)[ \t]*([0-9]+)[ \t]RPM/ { + aFanMain[4]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + /^(FAN([2-9]) |CASE([2-9]) |CHASSIS([2-9]) )(.*)[ \t]*([0-9]+)[ \t]RPM/ { + sysFanNu=gensub( /^(FAN|CASE|CHASSIS)([2-9])[ \t]+(.*)/, "\\2", 1, $1 ) + if ( sysFanNu ~ /^([2-9])$/ ) { + # note: cpu/mobo/ps/fan1 above are 1/2/3/4 + sysFanNu = sysFanNu + 3 + aFanMain[sysFanNu]=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + } + } + /^fan([0-9]+)(.*)[ \t]*([0-9]+)[ \t]RPM/ { + fanWorking=gensub( /[ \t]*([0-9]+)[ \t]+(.*)/, "\\1", 1, $2 ) + sysFanNu=gensub( /fan([0-9]+)/, "\\1", 1, $1 ) + if ( sysFanNu ~ /^([0-9]+)$/ ) { + # add to array if array index does not exist OR if number is > existing number + if ( ! sysFanNu in aFanDefault || fanWorking >= aFanDefault[sysFanNu] ) { + aFanDefault[sysFanNu]=fanWorking + } + } + } + + END { + # first we need to handle the case where we have to determine which temp/fan to use for cpu and mobo: + # note, for rare cases of weird cool cpus, user can override in their prefs and force the assignment + if ( temp1 != "" && temp2 != "" ){ + if ( userCpuNo != "" && userCpuNo ~ /(1|2)/ ) { + tempFanType=userCpuNo + } + else { + # first some fringe cases with cooler cpu than mobo: assume which is cpu temp based on fan speed + # but only if other fan speed is 0 + if ( temp1 >= temp2 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[1] == 0 && aFanDefault[2] > 0 ) { + tempFanType=2 + } + else if ( temp2 >= temp1 && 1 in aFanDefault && 2 in aFanDefault && aFanDefault[2] == 0 && aFanDefault[1] > 0 ) { + tempFanType=1 + } + # then handle the standard case if these fringe cases are false + else if ( temp1 >= temp2 ) { + tempFanType=1 + } + else { + tempFanType=2 + } + } + } + # need a case for no temps at all reported, like with old intels + else if ( temp1 == "" && temp2 == "" && cpuTemp == "" && moboTemp == "" ){ + tempFanType=1 + } + + # then get the real cpu temp, best guess is hottest is real + if ( cpuTemp != "" ){ + cpuTempReal=cpuTemp + } + else if ( tempFanType != "" ){ + if ( tempFanType == 1 ){ + cpuTempReal=temp1 + } + else { + cpuTempReal=temp2 + } + } + else { + cpuTempReal=temp1 + } + # if all else fails, use core0 temp if it is present and cpu is null + if ( cpuTempReal == "" && core0Temp != "" ) { + cpuTempReal=core0Temp + } + + # then the real mobo temp + if ( moboTemp != "" ){ + moboTempReal=moboTemp + } + else if ( tempFanType != "" ){ + if ( tempFanType == 1 ) { + moboTempReal=temp2 + } + else { + moboTempReal=temp1 + } + } + else { + moboTempReal=temp2 + } + # then set the cpu fan speed + if ( aFanMain[1] == "" ) { + # note, you cannot test for aFanDefault[1] or [2] != "" + # because that creates an array item in gawk just by the test itself + if ( tempFanType == 1 && 1 in aFanDefault ) { + aFanMain[1]=aFanDefault[1] + aFanDefault[1]="" + } + else if ( tempFanType == 2 && 2 in aFanDefault ) { + aFanMain[1]=aFanDefault[2] + aFanDefault[2]="" + } + } + + # then we need to get the actual numeric max array count for both fan arrays + for (i = 0; i <= 14; i++) { + if ( i in aFanMain && i > indexCountaFanMain ) { + indexCountaFanMain=i + } + } + for (i = 0; i <= 14; i++) { + if ( i in aFanDefault && i > indexCountaFanDefault ) { + indexCountaFanDefault=i + } + } + + # clear out any duplicates. Primary fan real trumps fan working always if same speed + for (i = 1; i <= indexCountaFanMain; i++) { + if ( i in aFanMain && aFanMain[i] != "" && aFanMain[i] != 0 ) { + for (j = 1; j <= indexCountaFanDefault; j++) { + if ( j in aFanDefault && aFanMain[i] == aFanDefault[j] ) { + aFanDefault[j] = "" + } + } + + } + } + + # now see if you can find the fast little mobo fan, > 5000 rpm and put it as mobo + # note that gawk is returning true for some test cases when aFanDefault[j] < 5000 + # which has to be a gawk bug, unless there is something really weird with arrays + # note: 500 > aFanDefault[j] < 1000 is the exact trigger, and if you manually + # assign that value below, the > 5000 test works again, and a print of the value + # shows the proper value, so the corruption might be internal in awk. + # Note: gensub is the culprit I think, assigning type string for range 501-1000 but + # type integer for all others, this triggers true for > + for (j = 1; j <= indexCountaFanDefault; j++) { + if ( j in aFanDefault && int( aFanDefault[j] ) > 5000 && aFanMain[2] == "" ) { + aFanMain[2] = aFanDefault[j] + aFanDefault[j] = "" + # then add one if required for output + if ( indexCountaFanMain < 2 ) { + indexCountaFanMain = 2 + } + } + } + + # then construct the sys_fan string for echo, note that iteration 1 + # makes: fanDefaultString separator null, ie, no space or , + for (j = 1; j <= indexCountaFanDefault; j++) { + fanDefaultString = fanDefaultString separator aFanDefault[j] + separator="," + } + separator="" # reset to null for next loop + # then construct the sys_fan string for echo + for (j = 1; j <= indexCountaFanMain; j++) { + fanMainString = fanMainString separator aFanMain[j] + separator="," + } + + # and then build the temps: + if ( moboTempReal != "" ) { + moboTempReal = moboTempReal tempUnit + } + if ( cpuTempReal != "" ) { + cpuTempReal = cpuTempReal tempUnit + } + + # if they are ALL null, print error message. psFan is not used in output currently + if ( cpuTempReal == "" && moboTempReal == "" && aFanMain[1] == "" && aFanMain[2] == "" && aFanMain[3] == "" && fanDefaultString == "" ) { + print "No active sensors found. Have you configured your sensors yet?" + } + else { + # then build array arrays: + print cpuTempReal "," moboTempReal "," psuTemp + # this is for output, a null print line does NOT create a new array index in bash + if ( fanMainString == "" ) { + fanMainString="," + } + print fanMainString + print fanDefaultString + } + } + ' + ) ) + # the error case needs to go here because we are setting special array delimiter ',' + else + A_SENSORS_DATA=( "You do not have the sensors app installed." ) + fi + + IFS="$ORIGINAL_IFS" + log_function_data "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}" +# echo "A_SENSORS_DATA: ${A_SENSORS_DATA[@]}" + eval $LOGFE +} + +## return uptime string +get_uptime() +{ + eval $LOGFS + ## note: removing gsub(/ /,"",a); to get get space back in there, goes right before print a + local uptime_value="$( uptime | gawk '{ + a = gensub(/^.*up *([^,]*).*$/,"\\1","g",$0) + print a + }' )" + echo "$uptime_value" + log_function_data "uptime_value: $uptime_value" + eval $LOGFE +} + +#### ------------------------------------------------------------------- +#### special data handling for specific options and conditions +#### ------------------------------------------------------------------- + +## multiply the core count by the data to be calculated, bmips, cache +# args: $1 - string to handle; $2 - cpu count +calculate_multicore_data() +{ + eval $LOGFS + local string_number=$1 string_data='' + + if [[ -n $( egrep -i '( mb| kb)' <<< $1 ) ]];then + string_data=" $( gawk '{print $2}' <<< $1 )" # add a space for output + string_number=$( gawk '{print $1}' <<< $1 ) + fi + # handle weird error cases where it's not a number + if [[ -n $( egrep '^[0-9\.,]+$' <<< $string_number ) ]];then + string_number=$( echo $string_number $2 | gawk '{ + total = $1*$2 + print total + }' ) + elif [[ $string_number == '' ]];then + string_number='Not Available' + else + # I believe that the above returns 'unknown' by default so no need for extra text + string_number="$string_number " + fi + echo "$string_number$string_data" + log_function_data "string_numberstring_data: $string_number$string_data" + eval $LOGFE +} + +# prints out shortened list of flags, the main ones of interest +# args: $1 - string of cpu flags to process +process_cpu_flags() +{ + eval $LOGFS + local cpu_flags="$1" + + # nx = AMD stack protection extensions + # lm = Intel 64bit extensions + # sse, sse2, pni = sse1,2,3,4,5 gfx extensions + # svm = AMD pacifica virtualization extensions + # vmx = Intel IVT (vanderpool) virtualization extensions + cpu_flags=$( echo "$cpu_flags" | gawk ' + BEGIN { + RS=" " + a_ssel["sse"] = 1 + a_ssel["sse2"] = 2 + a_ssel["pni"] = 3 + a_ssel["sse4a"] = 4 # 4a must precede 4 + a_ssel["sse4"] = 5 + a_ssel["sse5"] = 6 + a_sses[1] = "sse" + a_sses[2] = "sse2" + a_sses[3] = "sse3" + a_sses[4] = "sse4a" + a_sses[5] = "sse4" + a_sses[6] = "sse5" + sseCounter = 0 + flag_string = "" + } + /^(nx|lm|svm|vmx)$/ { + if ( flag_string != "" ) { + flag_string = flag_string " " $0 + } + else { + flag_string = $0 + } + } + /^(sse|sse2|sse4a|sse4|sse5|pni)$/ { + if ( a_ssel[$0] > sseCounter ) { + sseCounter = a_ssel[$0] + } + } + END { + if ( sseCounter > 0 ) { + if ( flag_string != "" ) { + flag_string = a_sses[sseCounter] " " flag_string + } + else { + flag_string = a_sses[sseCounter] + } + } + print flag_string + }' ) + + #grep -oE '\<(nx|lm|sse[0-9]?|pni|svm|vmx)\>' | tr '\n' ' ')) + if [[ -z $cpu_flags ]];then + cpu_flags="-" + fi + echo "$cpu_flags" + log_function_data "cpu_flags: $cpu_flags" + eval $LOGFE +} + +#### ------------------------------------------------------------------- +#### print and processing of output data +#### ------------------------------------------------------------------- + +#### MASTER PRINT FUNCTION - triggers all line item print functions +## main function to print out, master for all sub print functions. +print_it_out() +{ + eval $LOGFS + # note that print_it_out passes local variable values on to its children, + # and in some cases, their children, with Lspci_Data + local Lspci_Data='' # only for verbose + + if [[ $B_SHOW_SHORT_OUTPUT == 'true' ]];then + print_short_data + else + Lspci_Data="$( get_lspci_data )" + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_SYSTEM == 'true' ]];then + print_system_data + fi + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_CPU == 'true' ]];then + print_cpu_data + fi + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_GRAPHICS == 'true' ]];then + print_gfx_data + fi + if [[ $VERBOSITY_LEVEL -ge 5 || $B_SHOW_AUDIO == 'true' ]];then + print_audio_data + fi + if [[ $VERBOSITY_LEVEL -ge 2 || $B_SHOW_NETWORK == 'true' ]];then + print_networking_data + fi + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_DISK == 'true' ]];then + print_hard_disk_data + fi + if [[ $VERBOSITY_LEVEL -ge 4 || $B_SHOW_PARTITIONS == 'true' ]];then + print_partition_data + fi + if [[ $VERBOSITY_LEVEL -ge 5 || $B_SHOW_SENSORS == 'true' ]];then + print_sensors_data + fi + if [[ $VERBOSITY_LEVEL -ge 1 || $B_SHOW_INFO == 'true' ]];then + print_info_data + fi + fi + eval $LOGFE +} + +#### SHORT OUTPUT PRINT FUNCTION, ie, verbosity 0 +# all the get data stuff is loaded here to keep execution time down for single line print commands +# these will also be loaded in each relevant print function for long output +print_short_data() +{ + eval $LOGFS + local current_kernel=$( uname -rm ) # | gawk '{print $1,$3,$(NF-1)}' ) + local processes="$(( $( ps aux | wc -l ) - 1 ))" + local short_data='' i='' b_background_black='false' + local memory=$( get_memory_data ) + local up_time="$( get_uptime )" + + # set A_CPU_CORE_DATA + get_cpu_core_count + local cpc_plural='' cpu_count_print='' model_plural='' + local cpu_physical_count=${A_CPU_CORE_DATA[0]} + local cpu_core_count=${A_CPU_CORE_DATA[3]} + local cpu_core_alpha=${A_CPU_CORE_DATA[1]} + local cpu_type=${A_CPU_CORE_DATA[2]} + + if [[ $cpu_physical_count -gt 1 ]];then + cpc_plural='(s)' + model_plural='s' + cpu_count_print="$cpu_physical_count " + fi + + local cpu_data_string="${cpu_count_print}${cpu_core_alpha} core" +# local cpu_core_count=${A_CPU_CORE_DATA[0]} + + # load A_HDD_DATA + get_hdd_data_basic + ## note: if hdd_model is declared prior to use, whatever string you want inserted will + ## be inserted first. In this case, it's desirable to print out (x) before each disk found. + local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 )) + IFS="," + local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} ) + IFS="$ORIGINAL_IFS" + local hdd_capacity=${a_hdd_basic_working[0]} + local hdd_used=${a_hdd_basic_working[1]} + + # load A_CPU_DATA + get_cpu_data + + IFS="," + local a_cpu_working=(${A_CPU_DATA[0]}) + IFS="$ORIGINAL_IFS" + local cpu_model="${a_cpu_working[0]}" + ## assemble data for output + local cpu_clock="${a_cpu_working[1]}" # old CPU3 + # this gets that weird min/max final array item + local min_max_clock_nu=$(( ${#A_CPU_DATA[@]} - 1 )) + local min_max_clock=${A_CPU_DATA[$min_max_clock_nu]} + + #set_color_scheme 12 + if [[ $B_RUNNING_IN_SHELL == 'false' ]];then + for i in $C1 $C2 $CN + do + case "$i" in + "$GREEN"|"$WHITE"|"$YELLOW"|"$CYAN") + b_background_black='true' + ;; + esac + done + if [[ $b_background_black == 'true' ]];then + for i in C1 C2 CN + do + ## these need to be in quotes, don't know why + if [[ ${!i} == $NORMAL ]];then + declare $i="${!i}15,1" + else + declare $i="${!i},1" + fi + done + #C1="${C1},1"; C2="${C2},1"; CN="${CN},1" + fi + fi + short_data="${C1}CPU$cpc_plural${CN}[${C2}${SEP1}${cpu_data_string} ${cpu_model}$model_plural (${cpu_type}) clocked at ${min_max_clock}${SEP1}${CN}] ${C1}Kernel${CN}[${C2}${SEP1}${current_kernel}${SEP1}${CN}] ${C1}Up${CN}[${C2}${SEP1}${up_time}${SEP1}${CN}] ${C1}Mem${CN}[${C2}${SEP1}${memory}${SEP1}${CN}] ${C1}HDD${CN}[${C2}${SEP1}${hdd_capacity}($hdd_used)${SEP1}${CN}] ${C1}Procs${CN}[${C2}${SEP1}${processes}${SEP1}${CN}]" + + if [[ $SHOW_IRC -gt 0 ]];then + short_data="${short_data} ${C1}Client${CN}[${C2}${SEP1}${IRC_CLIENT}${IRC_CLIENT_VERSION}${SEP1}${CN}]" + fi + short_data="${short_data} ${C1}$SCRIPT_NAME${C2}${CN}[${C2}${SEP1}$SCRIPT_VERSION_NUMBER${SEP1}${CN}]" + if [[ $SCHEME -gt 0 ]];then + short_data="${short_data} $NORMAL" + fi + print_screen_output "$short_data" + eval $LOGFE +} + +#### LINE ITEM PRINT FUNCTIONS + +# print sound card data +print_audio_data() +{ + eval $LOGFS + local i='' card_one='Card-1' audio_data='' a_audio_data='' port_data='' + local a_audio_working='' alsa_driver='' alsa_data='' port_plural='' module_version='' + # set A_AUDIO_DATA and get alsa data + get_audio_data + alsa_data=$( get_audio_alsa_data ) + IFS="," + a_audio_working=(${A_AUDIO_DATA[0]}) + IFS="$ORIGINAL_IFS" + + if [[ -n ${A_AUDIO_DATA[@]} ]];then + # slightly complicated because 2nd array item could be the alsa data + if [[ ${#A_AUDIO_DATA[@]} -le 1 ]];then + card_one='Card' + fi + +# if [[ -n ${a_audio_working[2]} ]];then +# port_data=" ${C1}at port${C2} ${a_audio_working[2]}" +# fi + # this should only trigger if the $FILE_ASOUND_DEVICE data is used, not lspci -nn + if [[ -n ${a_audio_working[3]} && $B_EXTRA_DATA == 'true' ]];then + module_version=$( print_module_version "${a_audio_working[3]}" ) + fi + if [[ -n ${a_audio_working[1]} ]];then + alsa_driver=" ${C1}driver${C2} ${a_audio_working[1]}$module_version" + fi + if [[ -n ${a_audio_working[2]} && $B_EXTRA_DATA == 'true' ]];then + if [[ $( wc -w <<< ${a_audio_working[2]} ) -gt 1 ]];then + port_plural='s' + fi + port_data=" ${C1}at port$port_plural${C2} ${a_audio_working[2]}" + fi + audio_data="${C1}$card_one${C2} ${a_audio_working[0]}$alsa_driver$port_data" + audio_data=$( create_print_line "Audio:" "$audio_data" ) + print_screen_output "$audio_data" + i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1 + while [[ -n ${A_AUDIO_DATA[++i]} ]] + do + IFS="," + a_audio_working=( ${A_AUDIO_DATA[i]} ) + IFS="$ORIGINAL_IFS" + port_data='' + alsa_driver='' + port_plural='' + module_version='' + if [[ -n ${a_audio_working[3]} && $B_EXTRA_DATA == 'true' ]];then + module_version=$( print_module_version "${a_audio_working[3]}" ) + fi + # we're testing for the presence of the 2nd array item here, which is the driver name + if [[ -n ${a_audio_working[1]} ]];then + alsa_driver="${C1}driver${C2} ${a_audio_working[1]}" + fi + if [[ -n ${a_audio_working[2]} && $B_EXTRA_DATA == 'true' ]];then + if [[ $( wc -w <<< ${a_audio_working[2]} ) -gt 1 ]];then + port_plural='s' + fi + port_data=" ${C1}at port$port_plural${C2} ${a_audio_working[2]}" + fi + if [[ -n ${a_audio_working[0]} ]];then + audio_data="${C1}Card-$(( $i + 1 ))${C2} ${a_audio_working[0]}$alsa_driver$port_data" + fi + if [[ -n $audio_data ]];then + audio_data=$( create_print_line " " "$audio_data" ) + print_screen_output "$audio_data" + fi + done + # alsa driver data only prints out if sound card data is found + if [[ -n $alsa_data ]];then + audio_data="${C1}Sound:${C2} $alsa_data" + audio_data=$( create_print_line " " "$audio_data" ) + print_screen_output "$audio_data" + fi + fi + eval $LOGFE +} + +print_cpu_data() +{ + eval $LOGFS + local cpu_data='' i='' cpu_clock_speed='' cpu_multi_clock_data='' + local bmip_data='' cpu_cache='' cpu_vendor='' cpu_flags='' + + ##print_screen_output "A_CPU_DATA[0]=\"${A_CPU_DATA[0]}\"" + # Array A_CPU_DATA always has one extra element: max clockfreq found. + # that's why its count is one more than you'd think from cores/cpus alone + # load A_CPU_DATA + get_cpu_data + + IFS="," + local a_cpu_working=(${A_CPU_DATA[0]}) + IFS="$ORIGINAL_IFS" + local cpu_model="${a_cpu_working[0]}" + ## assemble data for output + local cpu_clock="${a_cpu_working[1]}" + + cpu_vendor=${a_cpu_working[5]} + + # set A_CPU_CORE_DATA + get_cpu_core_count + local cpc_plural='' cpu_count_print='' model_plural='' + local cpu_physical_count=${A_CPU_CORE_DATA[0]} + local cpu_core_count=${A_CPU_CORE_DATA[3]} + local cpu_core_alpha=${A_CPU_CORE_DATA[1]} + local cpu_type=${A_CPU_CORE_DATA[2]} + + if [[ $cpu_physical_count -gt 1 ]];then + cpc_plural='(s)' + cpu_count_print="$cpu_physical_count " + model_plural='s' + fi + + local cpu_data_string="${cpu_count_print}${cpu_core_alpha} core" + # Strange (and also some expected) behavior encountered. If print_screen_output() uses $1 + # as the parameter to output to the screen, then passing " ${ARR[@]} " + # will output only and first element of ARR. That "@" splits in elements and "*" _doesn't_, + # is to be expected. However, that text2 is consecutively truncated is somewhat strange, so take note. + # This has been confirmed by #bash on freenode. + # The above mentioned only emerges when using the debugging markers below + ## print_screen_output "a_cpu_working=\"***${a_cpu_working[@]} $hostName+++++++\"----------" + + if [[ -z ${a_cpu_working[2]} ]];then + a_cpu_working[2]="unknown" + fi + + cpu_data=$( create_print_line "CPU$cpc_plural:" "${C1}${cpu_data_string}${C2} ${a_cpu_working[0]}$model_plural (${cpu_type})" ) + if [[ $VERBOSITY_LEVEL -ge 3 || $B_SHOW_CPU == 'true' ]];then + # update for multicore, bogomips x core count. + if [[ $B_EXTRA_DATA == 'true' ]];then +# if [[ $cpu_vendor != 'intel' ]];then + bmip_data=$( calculate_multicore_data "${a_cpu_working[4]}" "$(( $cpu_core_count * $cpu_physical_count ))" ) +# else +# bmip_data="${a_cpu_working[4]}" +# fi + bmip_data=" ${C1}bmips${C2} $bmip_data" + fi + ## note: this handles how intel reports L2, total instead of per core like AMD does + # note that we need to multiply by number of actual cpus here to get true cache size + if [[ $cpu_vendor != 'intel' ]];then + cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$(( $cpu_core_count * $cpu_physical_count ))" ) + else + cpu_cache=$( calculate_multicore_data "${a_cpu_working[2]}" "$cpu_physical_count" ) + fi + # only print shortened list + if [[ $B_CPU_FLAGS_FULL != 'true' ]];then + cpu_flags=$( process_cpu_flags "${a_cpu_working[3]}" ) + cpu_flags=" ${C1}flags${C2} ($cpu_flags)" + fi + cpu_data="$cpu_data${C2} ${C1}cache${C2} $cpu_cache$cpu_flags$bmip_data${CN}" + fi + # we don't this printing out extra line unless > 1 cpu core + if [[ ${#A_CPU_DATA[@]} -gt 2 ]] && [[ $B_SHOW_CPU == 'true' || $VERBOSITY_LEVEL -ge 5 ]];then + cpu_clock_speed='' # null < verbosity level 5 + else + cpu_data="$cpu_data ${C1}clocked at${C2} ${a_cpu_working[1]} MHz${CN}" + fi + + cpu_data="$cpu_data $cpu_clock_speed" + print_screen_output "$cpu_data" + + # we don't this printing out extra line unless > 1 cpu core + if [[ ${#A_CPU_DATA[@]} -gt 2 ]] && [[ $B_SHOW_CPU == 'true' || $VERBOSITY_LEVEL -ge 5 ]];then + for (( i=0; i < ${#A_CPU_DATA[@]}-1; i++ )) + do + IFS="," + a_cpu_working=(${A_CPU_DATA[i]}) + IFS="$ORIGINAL_IFS" + # note: the first iteration will create a first space, for color code separation below + cpu_multi_clock_data="$cpu_multi_clock_data ${C1}($(( i + 1 )))${C2} ${a_cpu_working[1]} MHz${CN}" + if [[ $i -gt 10 ]];then + break + fi + done + if [[ -n $cpu_multi_clock_data ]];then + cpu_multi_clock_data=$( create_print_line " " "${C1}Clock Speeds:${C2}$cpu_multi_clock_data" ) + print_screen_output "$cpu_multi_clock_data" + fi + fi + if [[ $B_CPU_FLAGS_FULL == 'true' ]];then + print_cpu_flags_full "${a_cpu_working[3]}" + fi + eval $LOGFE +} + +# takes list of all flags, split them and prints x per line +# args: $1 - cpu flag string +print_cpu_flags_full() +{ + eval $LOGFS + local cpu_flags_full="$1" a_cpu_flags='' line_starter='' + local i=0 counter=0 max_length=18 max_length_add=18 flag='' flag_data='' + + # build the flag line array + for flag in $cpu_flags_full + do + a_cpu_flags[$counter]="${a_cpu_flags[$counter]}$flag " + if [[ $i -ge $max_length ]];then + (( counter++ )) + max_length=$(( $max_length + $max_length_add )) + fi + ((i++)) + done + # then print it out + for (( i=0; i < ${#a_cpu_flags[@]};i++ )) + do + if [[ $i -eq 0 ]];then + line_starter="${C1}CPU Flags${C2} " + else + line_starter='' + fi + flag_data=$( create_print_line " " "$line_starter${a_cpu_flags[$i]}" ) + print_screen_output "$flag_data" + done + eval $LOGFE +} + +print_gfx_data() +{ + eval $LOGFS + local gfx_data='' i='' card_one='Card' root_alert='' + local screen_resolution="$( get_graphics_res_data )" + local b_is_mesa='false' display_full_string='' + # set A_GFX_CARD_DATA + get_graphics_card_data + # set A_X_DATA + get_graphics_x_data + local x_vendor=${A_X_DATA[0]} + local x_version=${A_X_DATA[1]} + # set A_GLX_DATA + get_graphics_glx_data + local glx_renderer="${A_GLX_DATA[0]}" + local glx_version="${A_GLX_DATA[1]}" + # this can contain a long No case debugging message, so it's being sliced off + # note: using grep -ioE '(No|Yes)' <<< ${A_GLX_DATA[2]} did not work in Arch, no idea why + local glx_direct_render=$( gawk '{ + print $1 + }' <<< "${A_GLX_DATA[2]}" ) + # some basic error handling: + if [[ -z $screen_resolution ]];then + screen_resolution='N/A' + fi + + if [[ $B_X_RUNNING == 'true' && $B_ROOT != 'true' ]];then + if [[ -z $x_vendor || -z $x_version ]];then + x_vendor='X-Vendor: N/A' + fi + display_full_string="${C1}$x_vendor${C2} $x_version ${C1}Res:${C2} ${screen_resolution} " + else + if [[ $B_X_RUNNING == 'true' && $B_ROOT == 'true' ]];then + root_alert="${C1}Gfx Data:${C2} N/A for root user" + fi + display_full_string="${C1}tty res:${C2} ${screen_resolution} $root_alert" + fi + + if [[ ${#A_GFX_CARD_DATA[@]} -gt 1 ]];then + i=1 + while [[ -n ${A_GFX_CARD_DATA[i]} && $i -le 3 ]] + do + gfx_data=" ${C1}Card-$(($i+1))${C2} ${A_GFX_CARD_DATA[i]}" + ((i++)) + done + card_one='Card-1' + fi + gfx_data=$( create_print_line "Graphics:" "${C1}$card_one${C2} ${A_GFX_CARD_DATA[0]}${gfx_data} $display_full_string" ) + print_screen_output "$gfx_data" + +# if [[ -z $glx_renderer || -z $glx_version ]];then +# b_is_mesa='true' +# fi + + ## note: if glx render or version have no content, then mesa is true + # if [[ $B_X_RUNNING == 'true' ]] && [[ $b_is_mesa != 'true' ]];then + if [[ $B_X_RUNNING == 'true' && $B_ROOT != 'true' ]];then + if [[ -z $glx_renderer ]];then + glx_renderer='N/A' + fi + if [[ -z $glx_version ]];then + glx_version='N/A' + fi + if [[ -z $glx_direct_render ]];then + glx_direct_render='N/A' + fi + gfx_data=$( create_print_line " " "${C1}GLX Renderer${C2} ${glx_renderer} ${C1}GLX Version${C2} ${glx_version}${CN}" ) + if [[ $B_HANDLE_CORRUPT_DATA == 'true' || $B_EXTRA_DATA == 'true' ]];then + gfx_data="$gfx_data ${C1}Direct Rendering${C2} ${glx_direct_render}${CN}" + fi + print_screen_output "$gfx_data" + fi + eval $LOGFE +} + +print_hard_disk_data() +{ + eval $LOGFS + local hdd_data='' hdd_data_2='' a_hdd_working='' hdd_temp_data='' hdd_string='' + local dev_data='' size_data='' hdd_model='' usb_data='' hdd_name='' divisor=5 + + # load A_HDD_DATA + get_hdd_data_basic + ## note: if hdd_model is declared prior to use, whatever string you want inserted will + ## be inserted first. In this case, it's desirable to print out (x) before each disk found. + local a_hdd_data_count=$(( ${#A_HDD_DATA[@]} - 1 )) + IFS="," + local a_hdd_basic_working=( ${A_HDD_DATA[$a_hdd_data_count]} ) + IFS="$ORIGINAL_IFS" + local hdd_capacity=${a_hdd_basic_working[0]} + local hdd_used=${a_hdd_basic_working[1]} + + if [[ $VERBOSITY_LEVEL -ge 3 || $B_SHOW_DISK == 'true' ]];then + ## note: the output part of this should be in the print hdd data function, not here + get_hard_drive_data_advanced + for (( i=0; i < ${#A_HDD_DATA[@]} - 1; i++ )) + do + # this adds the (x) numbering in front of each disk found, and creates the full disk string + IFS="," + a_hdd_working=( ${A_HDD_DATA[i]} ) + IFS="$ORIGINAL_IFS" + if [[ $B_SHOW_DISK == 'true' || $VERBOSITY_LEVEL -ge 5 ]];then + if [[ -n ${a_hdd_working[3]} ]];then + usb_data="${a_hdd_working[3]} " + else + usb_data='' + fi + dev_data="/dev/${a_hdd_working[0]} " + size_data=" ${a_hdd_working[1]}" + if [[ $B_EXTRA_DATA == 'true' && -n $dev_data ]];then + hdd_temp_data=$( get_hdd_temp_data "$dev_data" ) + # error handling is done in get data function + if [[ -n $hdd_temp_data ]];then + hdd_temp_data=" ${hdd_temp_data}C" + else + hdd_temp_data='' + fi + fi + divisor=2 # for modulus line print out, either 2 items for full, or default for short + fi + hdd_name="${a_hdd_working[2]}" + hdd_string="$usb_data$dev_data$hdd_name$size_data$hdd_temp_data" + hdd_model="${hdd_model}${C1}$(($i+1)):${C2} $hdd_string " + # printing line one, then new lines according to $divisor setting, and after, if leftovers, print that line. + case $i in + 0) + hdd_data=$( create_print_line "Disks:" "${C1}HDD${C2} ${C1}Total Size:${C2} ${hdd_capacity} (${hdd_used}) ${hdd_model}" ) + print_screen_output "$hdd_data" + hdd_model='' + ;; + *) + # using modulus here, if divisible by $divisor, print line, otherwise skip + if [[ $(( $i % $divisor )) -eq 0 ]];then + hdd_data=$( create_print_line " " "${hdd_model}${CN}" ) + print_screen_output "$hdd_data" + hdd_model='' + fi + ;; + esac + done + # then print any leftover items + if [[ -n $hdd_model ]];then + hdd_data=$( create_print_line " " "${hdd_model}${CN}" ) + print_screen_output "$hdd_data" + fi + else + hdd_data=$( create_print_line "Disks:" "${C1}HDD Total Size:${C2} ${hdd_capacity} (${hdd_used})${CN}" ) + print_screen_output "$hdd_data" + fi + + eval $LOGFE +} + +print_info_data() +{ + eval $LOGFS + local suggested_app="runlevel" + local info_data='' + local runlvl='' + local memory="$( get_memory_data )" + local processes="$(( $( ps aux | wc -l ) - 1 ))" + local up_time="$( get_uptime )" + + # Some code could look superfluous but BitchX doesn't like lines not ending in a newline. F*&k that bitch! + # long_last=$( echo -ne "${C1}Processes${C2} ${processes}${CN} | ${C1}Uptime${C2} ${up_time}${CN} | ${C1}Memory${C2} ${MEM}${CN}" ) + info_data=$( create_print_line "Info:" "${C1}Processes${C2} ${processes} ${C1}Uptime${C2} ${up_time} ${C1}Memory${C2} ${memory}${CN}" ) + + # this only triggers if no X data is present + if [[ $B_X_RUNNING != 'true' ]];then + if [[ -e $suggested_app ]];then + runlvl="$( runlevel | gawk '{ print $2 }' )" + info_data="${info_data} ${C1}Runlevel${C2} ${runlvl}${CN}" + fi + fi + + if [[ $SHOW_IRC -gt 0 ]];then + info_data="${info_data} ${C1}Client${C2} ${IRC_CLIENT}${IRC_CLIENT_VERSION}${CN}" + fi + info_data="${info_data} ${C1}$SCRIPT_NAME${C2} $SCRIPT_VERSION_NUMBER${CN}" + + if [[ $SCHEME -gt 0 ]];then + info_data="${info_data} ${NORMAL}" + fi + print_screen_output "$info_data" + eval $LOGFE +} + +# args: $1 - module name (could be > 1, so loop it ) +print_module_version() +{ + eval $LOGFS + local module_versions='' module='' version='' + + for module in $1 + do + version=$( get_module_version_number $module ) + if [[ -n $version ]];then + module_versions="$module_versions $version" + fi + done + + if [[ -n $module_versions ]];then + echo " ${C1}v:${C2}$module_versions" + fi + eval $LOGFE +} + +print_networking_data() +{ + eval $LOGFS + local i='' card_one='Card-1' network_data='' a_network_working='' port_data='' driver_data='' + local card_string='' port_plural='' module_version='' + # set A_NETWORK_DATA + get_networking_data + + IFS="," + a_network_working=(${A_NETWORK_DATA[0]}) + IFS="$ORIGINAL_IFS" + + # will never be null because null is handled in get_network_data, but in case we change + # that leaving this test in place. + if [[ -n ${A_NETWORK_DATA[@]} ]];then + if [[ ${#A_NETWORK_DATA[@]} -le 1 ]];then + card_one='Card' + fi + if [[ -n ${a_network_working[3]} && $B_EXTRA_DATA == 'true' ]];then + module_version=$( print_module_version "${a_network_working[3]}" ) + fi + if [[ -n ${a_network_working[1]} ]];then + driver_data=" ${C1}driver${C2} ${a_network_working[1]}$module_version" + fi + if [[ -n ${a_network_working[2]} && $B_EXTRA_DATA == 'true' ]];then + if [[ $( wc -w <<< ${a_network_working[2]} ) -gt 1 ]];then + port_plural='s' + fi + port_data=" ${C1}at port$port_plural${C2} ${a_network_working[2]}" + fi + card_string='' + network_data="${C1}$card_one${C2} ${a_network_working[0]}$driver_data$port_data" + network_data=$( create_print_line "Network:" "$network_data" ) + print_screen_output "$network_data" + i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1 + while [[ -n ${A_NETWORK_DATA[++i]} ]] + do + IFS="," + a_network_working=( ${A_NETWORK_DATA[i]} ) + IFS="$ORIGINAL_IFS" + port_data='' + driver_data='' + port_plural='' + module_version='' + if [[ -n ${a_network_working[3]} && $B_EXTRA_DATA == 'true' ]];then + module_version=$( print_module_version "${a_network_working[3]}" ) + fi + if [[ -n ${a_network_working[1]} ]];then + driver_data=" ${C1}driver${C2} ${a_network_working[1]}$module_version" + fi + if [[ -n ${a_network_working[2]} && $B_EXTRA_DATA == 'true' ]];then + if [[ $( wc -w <<< ${a_network_working[2]} ) -gt 1 ]];then + port_plural='s' + fi + port_data=" ${C1}at port$port_plural${C2} ${a_network_working[2]}" + fi + network_data="${C1}Card-$(( $i + 1 ))${C2} ${a_network_working[0]}$driver_data$port_data" + network_data=$( create_print_line " " "$network_data" ) + print_screen_output "$network_data" + done + fi + if [[ $B_SHOW_IP == 'true' ]];then + print_networking_ip_data + fi + eval $LOGFE +} + +print_networking_ip_data() +{ + eval $LOGFS + local ip=$( get_networking_wan_ip_data ) + local ip_data='' a_interfaces_working='' interfaces='' interfaces_2='' i='' + + # set A_INTERFACES_DATA + get_networking_local_ip_data + # first print output for wan ip line. Null is handled in the get function + ip_data=$( create_print_line " " "${C1}Wan IP:${C2} $ip" ) + + # then create the list of local interface/ip + interfaces=" ${C1}Interface:${C2}" + i=0 ## loop starts with 1 by auto-increment so it only shows cards > 1 + while [[ -n ${A_INTERFACES_DATA[i]} ]] + do + IFS="," + a_interfaces_working=(${A_INTERFACES_DATA[i]}) + IFS="$ORIGINAL_IFS" + if [[ $i -lt 3 ]];then + if [[ -n ${a_interfaces_working[0]} ]];then + interfaces="$interfaces ${C1}${a_interfaces_working[0]}${C2} ${a_interfaces_working[1]}" + fi + else + if [[ -n ${a_interfaces_working[0]} ]];then + # space on end here for lining up with line starter + interfaces_2="$interfaces_2${C1}${a_interfaces_working[0]}${C2} ${a_interfaces_working[1]} " + fi + fi + ((i++)) + done + print_screen_output "$ip_data$interfaces" + # then wrap it if needed + if [[ -n $interfaces_2 ]];then + interfaces_2=$( create_print_line " " "$interfaces_2" ) + print_screen_output "$interfaces_2" + fi + eval $LOGFE +} + +print_partition_data() +{ + eval $LOGFS + local a_partition_working='' partition_used='' partition_data='' + local counter=0 line_max=160 i=0 a_partition_data='' line_starter='' + local partitionIdClean='' part_dev='' full_dev='' part_label='' full_label='' + local part_uuid='' full_uuid='' dev_remote='' + + # this handles the different, shorter, irc colors strings embedded in variable data + if [[ $B_RUNNING_IN_SHELL != 'true' ]];then + line_max=130 + fi + # and no color string data at all + if [[ $SCHEME -eq 0 ]];then + line_max=75 + fi + if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then + line_max=20 + fi + + # set A_PARTITION_DATA + get_partition_data + + for (( i=0; i < ${#A_PARTITION_DATA[@]}; i++ )) + do + IFS="," + a_partition_working=(${A_PARTITION_DATA[i]}) + IFS="$ORIGINAL_IFS" + full_label='' + full_uuid='' + if [[ $B_SHOW_PARTITIONS_FULL == 'true' ]] || [[ ${a_partition_working[4]} == 'main' ]];then + if [[ -n ${a_partition_working[2]} ]];then + partition_used=" ${C1}used:${C2} ${a_partition_working[2]} (${a_partition_working[3]})" + else + partition_used='' # reset partition used to null + fi + + # don't show user names in output + if [[ $B_SHOW_LABELS == 'true' || $B_SHOW_UUIDS == 'true' ]];then + if [[ -n ${a_partition_working[5]} ]];then + if [[ -z $( grep -E '(^//|:/)' <<< ${a_partition_working[5]} ) ]];then + part_dev="/dev/${a_partition_working[5]}" + dev_remote='dev' + else + part_dev="${a_partition_working[5]}" + dev_remote='remote' + fi + else + dev_remote='dev' + part_dev='N/A' + fi + full_dev=" ${C1}$dev_remote:${C2} $part_dev" + if [[ $B_SHOW_LABELS == 'true' && $dev_remote != 'remote' ]];then + if [[ -n ${a_partition_working[6]} ]];then + part_label="${a_partition_working[6]}" + else + part_label='N/A' + fi + full_label=" ${C1}label:${C2} $part_label" + fi + if [[ $B_SHOW_UUIDS == 'true' && $dev_remote != 'remote' ]];then + if [[ -n ${a_partition_working[7]} ]];then + part_uuid="${a_partition_working[7]}" + else + part_uuid='N/A' + fi + full_uuid=" ${C1}uuid:${C2} $part_uuid" + fi + fi + partitionIdClean=$( sed -r 's|/home/(.*)/(.*)|/home/##/\2|' <<< ${a_partition_working[0]} ) + # because these lines can vary widely, using dynamic length handling here + a_partition_data[$counter]="${a_partition_data[$counter]}${C1}ID:${C2}$partitionIdClean ${C1}size:${C2} ${a_partition_working[1]}$partition_used$full_dev$full_label$full_uuid " + + if [[ $( wc -c <<< ${a_partition_data[$counter]} ) -gt $line_max ]];then + ((counter++)) + fi + fi + done + # print out all lines, line starter on first line + for (( i=0; i < ${#a_partition_data[@]};i++ )) + do + if [[ $i -eq 0 ]];then + line_starter='Partition:' + else + line_starter=' ' + fi + partition_data=$( create_print_line "$line_starter" "${a_partition_data[$i]}" ) + print_screen_output "$partition_data" + done + eval $LOGFE +} + +print_sensors_data() +{ + eval $LOGFS + local mobo_temp='' cpu_temp='' psu_temp='' cpu_fan='' mobo_fan='' ps_fan='' sys_fans='' sys_fans2='' + local temp_data='' fan_data='' fan_data2='' b_is_error='false' fan_count=0 gpu_temp='' + local a_sensors_working='' + get_sensors_data + + IFS="," + a_sensors_working=( ${A_SENSORS_DATA[0]} ) + IFS="$ORIGINAL_IFS" + # initial error cases, for missing app or unconfigured sensors. Note that array 0 + # always has at least 3 items, cpu/mobo/psu temp in it. If it's a single item, then + # it's an error message, not the real data arrays. + if [[ ${#a_sensors_working[@]} -eq 1 ]];then + cpu_temp="${C1}Error:${C2} ${A_SENSORS_DATA[0]}" + b_is_error='true' + else + for (( i=0; i < ${#A_SENSORS_DATA[@]}; i++ )) + do + IFS="," + a_sensors_working=( ${A_SENSORS_DATA[i]} ) + IFS="$ORIGINAL_IFS" + case $i in + # first the temp data + 0) + if [[ -n ${a_sensors_working[0]} ]];then + cpu_temp=${a_sensors_working[0]} + else + cpu_temp='N/A' + fi + cpu_temp="${C1}System Temperatures: cpu:${C2} $cpu_temp " + + if [[ -n ${a_sensors_working[1]} ]];then + mobo_temp=${a_sensors_working[1]} + else + mobo_temp='N/A' + fi + mobo_temp="${C1}mobo:${C2} $mobo_temp " + + if [[ -n ${a_sensors_working[2]} ]];then + psu_temp="${C1}psu:${C2} ${a_sensors_working[2]} " + fi + gpu_temp=$( get_gpu_temp_data ) + if [[ -n $gpu_temp ]];then + gpu_temp="${C1}gpu:${C2} ${gpu_temp} " + fi + ;; + # then the fan data from main fan array + 1) + for (( j=0; j < ${#a_sensors_working[@]}; j++ )) + do + case $j in + 0) + # we need to make sure it's either cpu fan OR cpu fan and sys fan 1 + if [[ -n ${a_sensors_working[0]} ]];then + cpu_fan="${a_sensors_working[0]}" + elif [[ -z ${a_sensors_working[0]} && -n ${a_sensors_working[1]} ]];then + cpu_fan="${a_sensors_working[1]}" + else + cpu_fan='N/A' + fi + cpu_fan="${C1}Fan Speeds (in rpm): cpu:${C2} $cpu_fan " + (( fan_count++ )) + ;; + 1) + if [[ -n ${a_sensors_working[1]} ]];then + mobo_fan="${C1}mobo:${C2} ${a_sensors_working[1]} " + (( fan_count++ )) + fi + ;; + 2) + if [[ -n ${a_sensors_working[2]} ]];then + ps_fan="${C1}psu:${C2} ${a_sensors_working[2]} " + (( fan_count++ )) + fi + ;; + [3-9]) + if [[ -n ${a_sensors_working[$j]} ]];then + fan_number=$(( $j - 2 )) # sys fans start on array key 5 + # wrap after fan 6 total + if [[ $fan_count -lt 7 ]];then + sys_fans="$sys_fans${C1}sys-$fan_number:${C2} ${a_sensors_working[$j]} " + else + sys_fans2="$sys_fans2${C1}sys-$fan_number:${C2} ${a_sensors_working[$j]} " + fi + (( fan_count++ )) + fi + ;; + esac + done + ;; + 2) + for (( j=0; j < ${#a_sensors_working[@]}; j++ )) + do + case $j in + [0-9]|10|11|12|13|14) + if [[ -n ${a_sensors_working[$j]} ]];then + fan_number=$(( $j + 1 )) # sys fans start on array key 5 + # wrap after fan 6 total + if [[ $fan_count -lt 7 ]];then + sys_fans="$sys_fans${C1}fan-$fan_number:${C2} ${a_sensors_working[$j]} " + else + sys_fans2="$sys_fans2${C1}fan-$fan_number:${C2} ${a_sensors_working[$j]} " + fi + (( fan_count++ )) + fi + ;; + esac + done + ;; + esac + done + fi + # turning off all output for case where no sensors detected or no sensors output + # unless -s used explicitly. So for -F type output won't show unless valid or -! 1 used + if [[ $b_is_error != 'true' || $B_SHOW_SENSORS == 'true' || $B_TESTING_1 == 'true' ]];then + temp_data="$cpu_temp$mobo_temp$psu_temp$gpu_temp" + temp_data=$( create_print_line "Sensors:" "$temp_data" ) + print_screen_output "$temp_data" + # don't print second or subsequent lines if error data + fan_data="$cpu_fan$mobo_fan$ps_fan$sys_fans" + if [[ $b_is_error != 'true' && -n $fan_data ]];then + fan_data=$( create_print_line " " "$fan_data" ) + print_screen_output "$fan_data" + # and then second wrapped fan line if needed + if [[ -n $sys_fans2 ]];then + fan_data2=$( create_print_line " " "$sys_fans2" ) + print_screen_output "$fan_data2" + fi + fi + fi + eval $LOGFE +} + +print_system_data() +{ + eval $LOGFS + local system_data='' bits='' + local host_name=$( hostname ) + local current_kernel=$( uname -rm ) # | gawk '{print $1,$3,$(NF-1)}' ) + local distro="$( get_distro_data )" + # check for 64 bit first + if [[ -n $( uname -m | grep -o 'x86_64' ) ]];then + bits="(64 bit)" + else + bits="(32 bit)" + fi + + if [[ $B_SHOW_HOST == 'true' ]];then + system_data=$( create_print_line "System:" "${C1}Host${C2} $host_name ${C1}Kernel${C2}" ) + else + system_data=$( create_print_line "System:" "${C1}Kernel${C2}" ) + fi + system_data="$system_data $current_kernel $bits ${C1}Distro${C2} $distro" + print_screen_output "$system_data" + eval $LOGFE +} + +######################################################################## +#### SCRIPT EXECUTION +######################################################################## + +main $@ ## From the End comes the Beginning + +## note: this EOF is needed for smxi handling, this is what triggers the full download ok +###**EOF**### diff --git a/warsow/PKGBUILD b/warsow/PKGBUILD index cddbd62..f295811 100644 --- a/warsow/PKGBUILD +++ b/warsow/PKGBUILD @@ -1,49 +1,64 @@ # Contributor: Slash +# Contributor: Babets +# Contributor: Vain pkgname=warsow -pkgver=0.42 -pkgrel=2 +pkgver=0.5 +pkgrel=3 pkgdesc="Free online multiplayer competitive FPS based on the Qfusion engine." url="http://www.warsow.net/" license=('GPL' 'custom:Warsow Content License') arch=('i686' 'x86_64') -depends=('sdl' 'curl' 'libxxf86dga' 'libjpeg' 'libvorbis' 'libxxf86vm' 'libxinerama') -makedepends=('mesa' 'openal' 'unzip' 'hd2u') +depends=('curl' 'libjpeg' 'libvorbis' 'libxinerama' 'libxxf86dga' 'libxxf86vm' 'sdl') +makedepends=('mesa' 'openal' 'unzip') source=('warsow.desktop' 'warsow.launcher' 'wsw-server.launcher' 'wswtv-server.launcher' \ -"http://www.iqclan.com/mirror/0.42/warsow_${pkgver}_unified.zip" \ -"https://launchpad.net/warsow/0.4/0.42/+download/warsow_${pkgver}_sdk.zip") +"http://www.derchris.eu/warsow/warsow_${pkgver}_unified.zip" \ +"http://www.derchris.eu/warsow/warsow_${pkgver}_sdk.zip") md5sums=('f9bf60c80820237f7097c4e50a9582cd' 'ec00081d81ad9802a8ca42fc2eac5498' 'f73e10c26197178df71b941b10bf83d7' 'd7e4a69835bbcf801e58307e9d6b951e' - 'cba5fe9b8af01b378e685959098fa84f' - '94c9bb2a48ac6f2687b38809e003f3b9') + 'd0cb961256bbc1b93bf240b8bcf8eff5' + 'acd0244435cc63967b0eb3468c21c454') +noextract=("warsow_${pkgver}_unified.zip" "warsow_${pkgver}_sdk.zip") build() { - cd $srcdir/warsow_${pkgver}_unified + cd $srcdir/ + + # Extract Game Data + unzip -o warsow_${pkgver}_unified.zip -d $srcdir/warsow + + # Extract Game Source Code + unzip -o warsow_${pkgver}_sdk.zip -d $srcdir/warsow-src # Create Destination Directories install -d $pkgdir/opt/warsow/ - # Delete Pre-Built Binaries/Libraries - rm {warsow,warsow.i386,warsow.x86_64,warsow_x86.exe,warsow_x64.exe,wsw_portable_x86.exe} wsw_server* wswtv_server* libs/* - # Move Data to Destination Directory - cp -r $srcdir/warsow_${pkgver}_unified/basewsw $pkgdir/opt/warsow - + cp -r $srcdir/warsow/basewsw $pkgdir/opt/warsow + + # Patch Makefile to use correct program to query for system information + sed -i 's:openal-config:pkg-config:g' $srcdir/warsow-src/source/Makefile + + # Patch Sound Code to point to base openal library + sed -i 's:libopenal.so.0:libopenal.so:g' $srcdir/warsow-src/source/snd_openal/snd_main.c + + # Patch AngelScript so it compiles correctly on i686 + if [ "$CARCH" == "i686" ]; then + sed -i 's:CXXFLAGS = \(.*\):CXXFLAGS = -march=i686 \1:' \ + $srcdir/warsow-src/libsrcs/angelscript/angelSVN/sdk/angelscript/projects/gnuc/makefile + fi + # Compile Warsow - cd $srcdir/warsow_${pkgver}_src/source/ - make || return 1 + cd $srcdir/warsow-src/source/ + make -j1 || return 1 # Move Compiled Data to Destination Directory - cp -r $srcdir/warsow_${pkgver}_src/source/release/* \ + cp -r $srcdir/warsow-src/source/release/* \ $pkgdir/opt/warsow - # Fix File Format on Created Scripts - /usr/bin/dos2unix --d2u $pkgdir/opt/warsow/{warsow,wsw_server,wswtv_server} - # Install Custom License: Warsow Content License - install -D -m 0644 $srcdir/docs/license.txt \ + install -D -m 0644 $srcdir/warsow/docs/license.txt \ $pkgdir/usr/share/licenses/${pkgname}/license.txt # Install Client Game Launcher @@ -63,6 +78,6 @@ build() { $pkgdir/usr/share/applications/warsow.desktop # Install Icon - install -D -m 0644 $srcdir/warsow_${pkgver}_src/source/win32/warsow.ico \ + install -D -m 0644 $srcdir/warsow-src/source/win32/warsow.ico \ $pkgdir/usr/share/pixmaps/warsow.ico } -- cgit v1.2.3-24-g4f1b