binstats-1.08.orig/0040755000175000001440000000000007231561214013260 5ustar mvelausersbinstats-1.08.orig/README0100644000175000001440000001350507231561206014142 0ustar mvelausersIntroduction ------------ This is binstats 1.08 - an administration utility for tracking down the various types of binary formats for Linux executables and their dynamic library dependencies and also executable scripts and man pages. Features include: 1) tally of a.out (Linux/i386), ELF and ECOFF (new!) binaries, dynamically and statically linked, unstripped and setuid 2) tally of Java bytecode binaries (if you run file-3.20+) 3) tally of text files distinguishing between Bourne, bash and [T]C shells, awk, perl, python & tcl scripts, other interpreted scripts & unidentified texts 4) tally of duplicated executable names 5) tally of binaries with missing dynamic libraries 6) tally of DLL and ELF dynamic libraries, used and unused 7) tally of man pages and duplicated manual names (new!) 8) a log of all the above tallies plus listing a.out binaries, statically linked binaries, unstripped binaries, setuid binaries, duplicated executables, missing library binaries, all unidentified text files, all used and unused dynamic libraries, duplicated manuals 9) a C program that dereferences symbolic links 10) a command line interface It was inspired by "execount" written by Murple (murple@clark.net) . Originally, when binstats was created in 1996 it was useful during the a.out to ELF transition for pruning a system of a.out executables. Now in 2001, times have changed with fancy package management systems being common on Linux distributions. This makes binstats much less needed. But the hurdle of creating binary packages suffices that people still compile stuff from tar balls of source code - I know I do. Of course, with the ravages of time, after many compilations and installations your system gets into a rather untidy state: forgotten binaries that once used libc5 populated /usr/local/bin; multiple versions of dynamically linked libraries lie forlorn; various man pages are scattered across your file hierarchy. All because you were enjoying the vicarious pleasure of trying the latest and greatest version of rapidly changing open sources. Thus binstats is a last resort to restore order to the chaos that this ad-hoc approach to software installation brings. Go on, try it. You know you want to: it's the latest version... Technical details ----------------- Binstats has been written as a bash script utilising the following common unix tools: echo, tr, cat, xargs, cut, dirname, sed, find, sort, uniq, grep, file, ldd, awk, col, diff, wc, uname, date. [As usual, a Linux distribution is indebted to the GNU project for most of these tools.] This latest version has been tested on Redhat 6.2 which contains GNU bash 1.14.7, GNU sh-utils 2.0, GNU findutils 4.1, GNU textutils 2.0e, GNU grep 2.4, file 3.28, ld.so 1.9.5, Gnu libc 2.1.3, Gnu Awk (gawk) 3.0.4, util-linux 2.10f and GNU diffutils 2.7. Also binstats (1.0.7) had been tested on Redhat 5.1 which contains GNU bash 1.14.7, GNU sh-utils 1.16, GNU findutils 4.1, GNU textutils 1.22, GNU grep 2.0, file 3.24, ld.so 1.9.5, Gnu libc 2.0.7, Gnu Awk (gawk) 3.0.3, util-linux 2.7 and GNU diffutils 2.7. Finally versions up to 1.05 have been tested on Redhat 4.2 which contains GNU bash 1.14.7, GNU sh-utils 1.16, GNU findutils 4.1, GNU textutils 1.22, GNU grep 2.0, file 3.22, ld.so 1.7.14, Gnu Awk (gawk) 3.0.2 and GNU diffutils 2.7. Historical bugs --------------- Of the numerous commands used by binstats, some old versions of two utilities have slight problems. file: For ELF 'not stripped' support, pick up "file 3.15-grr1" plus the patch from Mitch D'Souza . Compile and install accordingly to instructions. There is a bug in the magic of file-3.15: in Magdir/commands, the six lines from 40-45 inclusive should be moved to the end. file-3.20 has ELF 'not stripped' support and Java bytecode support. ldd: ldd has at least one bug (in ld.so 1.7.14) and one inconsistency (or feature) which binstats has to be cope with. The latter problem is still present in the version that comes with Red Hat 5.1 - when only a single name is passed to ldd, it does not print the name of the file. The solutions to these problems are controlled by switches in the script. Running ------- Edit the Makefile to suit your setup. Compile derefsymlink, install the executables and man pages. Read the notes in the script before using binstats. Now you have three options: 1) leave binstats as is and it will use your PATH and ld.so.conf 2) edit the variables to fit your system or 3) use the command line interface ./binstats [-b[inaries]="list of executable directories"] [-d[ebug]] [-f[ile]=bstats.log] [-h[elp]] [-l[ibraries]="list of library directories"] [-m[anuals]="list of manual directories"] [-p[ath]="usual path for binstats"] [-t[emp]=/tmp] [-v[ersion]] For example, if you have a minimal system then try ./binstats -b="/bin /sbin /usr/bin /usr/sbin" if you only have the four specified directories. If you don't run it as root then any executable without world readable status (especially setuid binaries) will register in the tallies or log as "can't read setuid". Acknowledgements ---------------- Thanks goes to the people who have provided feedback. Special thanks goes to Matej Vela who contributed the man pages. Bugs, etc --------- Please send any bug reports, patches, etc to me. The latest version can be found at . The distribution is also archived at . To do ----- Maybe it's better use Perl or Python [when I read up on it] for all this. Peter Chang 18th January 2001 PS binstats is released under the GPL and as such the usual licence conditions and lack of warranty apply. binstats-1.08.orig/Makefile0100644000175000001440000000136207023010045014705 0ustar mvelausers# -*- sh -*- # Makefile for derefsymlink compilation and installation # # Edit the following to suit your system and type "make install" CC= gcc CFLAGS= -Wall -O6 LDFLAGS= -s # This sets the prefix for the executable and manual page directories # during installation PREFIX= /usr/local # If you want to install derefsymlink in some place other than # /usr/local/bin then make sure PATH is set accordingly in binstats DESTBIN= $(PREFIX)/bin DESTMAN= $(PREFIX)/man/man1 derefsymlink: derefsymlink.o $(CC) -o $@ $(CFLAGS) $(LDFLAGS) derefsymlink.o install:: derefsymlink install -m 755 derefsymlink $(DESTBIN) install -m 755 binstats $(DESTBIN) install -m 644 binstats.1 derefsymlink.1 $(DESTMAN) clean: rm -f derefsymlink derefsymlink.o binstats-1.08.orig/derefsymlink.c0100644000175000001440000001552006447524331016127 0ustar mvelausers/* * derefsymlink - a program to dereference symbolic links * * Copyright (c) 1996 by Peter Chang * Peter.Chang@nottingham.ac.uk * * It takes in pathnames and spits them out fully dereference. * If any of the components of the pathnames do not exist or * contain circular symlinks, the program stays silent or * prints a message to stderr. * [Some of the error checking is rather paranoid but it's better * to be safe than sorry.] * * Revision 0.1 created on 1996/8/21 * made skeleton program which processes options and filenames * correctly, derefname() just echos back at the moment * Revision 0.2 written on 1996/8/23 * filled in rest of program, including derefname() and striprel() * added verbose flag * Revision 0.3 debugged on 1997/12/22 * the last test in derefname() did not cope with a single link to * a top directory */ #include #include #include #include #include #define IN_USE_ARGV 0 #define IN_USE_FILE 1 #define IN_USE_STDIN 2 #define OUT_USE_STDOUT 0 #define OUT_USE_FILE 1 #define DEPTH_LIMIT 25 /* max directory depth */ int in_method = IN_USE_ARGV; int out_method = OUT_USE_STDOUT; int verbose = 0; int main(int argc, char *argv[]) { static char iname[FILENAME_MAX], oname[FILENAME_MAX], cname[FILENAME_MAX]; int al, i; FILE *fi, *fo; int pcl(int , char **, char *, char *); int derefname(char *, int ); /* look for options */ al = pcl(argc, argv, iname, oname); /* set up output */ if (out_method == OUT_USE_FILE) { if ((fo = fopen(oname, "w")) == NULL) { if (verbose) fprintf(stderr, "can't open output file %s", oname); exit(EXIT_FAILURE); } } else fo = stdout; /* if there is a list from a file or stdin * then go through this first */ if (in_method != IN_USE_ARGV) { if (in_method == IN_USE_FILE) { if ((fi = fopen(iname, "r")) == NULL) { if (verbose) fprintf(stderr, "can't open input file %s", iname); exit(EXIT_FAILURE); } } else fi = stdin; while ((i = fscanf(fi, "%s", cname)) != EOF) { if (derefname(cname, 0) >= 0) fprintf(fo, "%s\n", cname); } } /* now finish off the remaining arguments */ while (al < argc) { strncpy(cname, argv[al++], FILENAME_MAX-1); if (derefname(cname, 0) >= 0) fprintf(fo, "%s\n", cname); } if (out_method == OUT_USE_FILE) fclose(fo); return EXIT_SUCCESS; } static char curdir[FILENAME_MAX]; /* do the real work here */ int derefname(char *name, int depth) { char tempa[FILENAME_MAX], cname[FILENAME_MAX]; struct stat sbuf; int len, sc; char *ptra; int striprel(char *); /* check if we are bombing out */ if (depth < 0) return depth; if (depth > DEPTH_LIMIT) { /* recursion limit to prevent circular reference */ if (verbose) fprintf(stderr, "circular symbolic link: %s\n", name); return -1; } strncpy(cname, name, FILENAME_MAX-1); if (name[0] != '/') { /* is name absolute */ if (curdir[0] == '\0') { /* initialise current directory */ getcwd(curdir, FILENAME_MAX-1); strncat(curdir, "/", FILENAME_MAX-1); } /* append cwd to local name */ strncpy(cname, curdir, FILENAME_MAX-1); strncat(cname, name, FILENAME_MAX-1); } if (striprel(cname) != 0) return -1; if (lstat(cname, &sbuf) != 0) { if (verbose) fprintf(stderr, "%s does not exist\n", cname); return -1; } sc = 0; while (S_ISLNK(sbuf.st_mode)) { /* check for symlink and deref it */ if (sc > DEPTH_LIMIT) { /* recursion limit to prevent circular reference */ if (verbose) fprintf(stderr, "circular symbolic link: %s\n", cname); return -1; } len = readlink(cname, tempa, FILENAME_MAX-1); tempa[len] = '\0'; if (tempa[0] != '/') { if ((ptra = strrchr(cname, '/')) == NULL) { if (verbose) fprintf(stderr, "Error in stripping link\n"); return -1; } *(ptra+1) = '\0'; strncat(cname, tempa, FILENAME_MAX-1); } else { strncpy(cname, tempa, FILENAME_MAX-1); } if (striprel(cname) != 0) return -1; if (lstat(cname, &sbuf) != 0) { if (verbose) fprintf(stderr, "%s does not exist\n", cname); return -1; } sc++; } /* strip last name */ if ((ptra = strrchr(cname, '/')) == NULL) { if (verbose) fprintf(stderr, "Error in stripping name\n"); return -1; } if (ptra != cname) { strncpy(tempa, ptra, FILENAME_MAX-1); *ptra = '\0'; /* dereference rest of path */ depth = derefname(cname, depth+1); strncpy(name, cname, FILENAME_MAX-1); strncat(name, tempa, FILENAME_MAX-1); } else strncpy(name, cname, FILENAME_MAX-1); return depth; } /* remove all "/../" and "/./" in pathnames */ int striprel(char *name) { static char tempa[FILENAME_MAX], tempb[FILENAME_MAX]; char *ptra, *ptrb; strncpy(tempa, name, FILENAME_MAX-1); while ((ptra = strstr(tempa, "/../")) != NULL) { *ptra = '\0'; if ((ptrb = strrchr(tempa, '/')) == NULL) { if (verbose) fprintf(stderr, "Error in stripping '..'\n"); return -1; } *(ptrb+1) = '\0'; strncpy(tempb, ptra+4, FILENAME_MAX-1); strncat(tempa, tempb, FILENAME_MAX-1); } while ((ptra = strstr(tempa, "/./")) != NULL) { *ptra = '\0'; strncpy(tempb, ptra+2, FILENAME_MAX-1); strncat(tempa, tempb, FILENAME_MAX-1); } strncpy(name, tempa, FILENAME_MAX-1); return 0; } /* * Parse the command line set the filename and the appropriate flags */ int pcl(int argc, char **argv, char *iname, char *oname) { static const char *options[] = { "help print this message", "file use a list of filenames", "output use file instead of stdout", "stdin use stdin as input", "verbose print error messages", NULL }; static const char usage0[] = "usage: derefsymlink [options] [filename] ...", usage1[] = " try derefsymlink -help for a list of options"; int i, optno, olen; const char **sptr; for (i = 1; i < argc; i++) { olen = strlen(argv[i])-1; if (argv[i][0] == '-') { for (sptr = options, optno = 0; *sptr != NULL; sptr++, optno++) if (strncmp(argv[i]+1, *sptr, olen) == 0) break; switch(optno) { case 0: printf("%s\n", usage0); printf("Options:\n"); for (sptr = options; *sptr != NULL; sptr++) printf(" -%s\n", *sptr); printf("\n"); exit(EXIT_SUCCESS); break; case 1: in_method = IN_USE_FILE; strcpy(iname, argv[++i]); break; case 2: out_method = OUT_USE_FILE; strcpy(oname, argv[++i]); break; case 3: in_method = IN_USE_STDIN; break; case 4: verbose = 1; break; default: fprintf(stderr, "%s\n%s\n", usage0, usage1); exit(EXIT_FAILURE); break; } } else return i; } return i; } binstats-1.08.orig/derefsymlink.10100644000175000001440000000153107023010250016017 0ustar mvelausers.TH DEREFSYMLINK 1 "October 31, 1999" "Debian Project" "Debian Manual" .SH NAME derefsymlink \- dereference symbolic links .SH SYNOPSIS .B derefsymlink .RB [ -f [ ile ]\c .I input-file | .RB -s [ tdin ] .RB [ -o [ utput ]\c .IR output-file ] .RB [ -v [ erbose ]] .RI [ symbolic-link ...] .PP .B derefsymlink .BR -h [ elp ] .SH OPTIONS .TP .BI -file " input-file" Dereference whitespace delimited symbolic links read from .IR input-file . .TP .B -help Display a usage summary and exit. .TP .BI -output " output-file" Output resulting filenames to .I output-file instead of standard output. .TP .B -stdin Dereference whitespace delimited symbolic links read from standard input. .TP .B -verbose Display verbose error messages. .SH AUTHOR Peter Chang . .BR This manual page was originally written by Matej Vela . binstats-1.08.orig/binstats.lsm0100644000175000001440000000233007231561177015627 0ustar mvelausersBegin4 Title: binstats Version: 1.08 Entered-date: 2001-01-18 Description: An admin utility to aid the tidying up of binaries, interpreted scripts, dynamic libraries and man pages. It can find the number and identity of a.out, ELF & ECOFF binaries, plus their debugging symbols status, setuid status and dynamic library dependence. It can count the number of Java bytecode programs. It can tally up the main types of scripts and look for unidentified executable text files. Also it is able to look for any duplicated executable and manual page names, unused libraries, binaries with missing libraries and statically linked binaries. Also includes a C program to dereference symbolic links. Keywords: aout elf binary dynamic library symbolic link Author: Peter.Chang@nottingham.ac.uk (Peter Chang) Maintained-by: Peter.Chang@nottingham.ac.uk (Peter Chang) Primary-site: metalab.unc.edu /pub/Linux/utils/scripts 12k binstats-1.08.tar.gz Alternate-site: http://www.nottingham.ac.uk/~etzpc/binstats.html Original-site: Platforms: Linux, bash script needs lots of unix (or GNU) tools, the Linux (or Gnu libc) ldd and gcc (for compiling derefsymlink) Copying-policy: GPL End binstats-1.08.orig/binstats.10100644000175000001440000000300407023010224015150 0ustar mvelausers.TH BINSTATS 1 "October 31, 1999" "Debian Project" "Debian Manual" .SH NAME binstats \- display statistics about programs and libraries .SH SYNOPSIS .B binstats .RB [ -b [ inaries ]\c .RI = bindirs ] .RB [ -d [ ebug ]] .RB [ -f [ ile ]\c .RI = logfile ] .RB [ -l [ ibraries ]\c .RI = libdirs ] .RB [ -m [ anuals ]\c .RI = mandirs ] .RB [ -p [ ath ]\c .RI = path ] .RB [ -t [ emp ]\c .RI = tmpdir ] .PP .B binstats .BR -h [ elp ] .PP .B binstats .BR -v [ ersion ] .SH OPTIONS .TP .BI -binaries " bindirs" .I bindirs is a quoted list of whitespace delimited directories where programs should be searched for. .TP .B -debug Store temporary files in the current directory and do not remove them when finished. .TP .BI -file " logfile" Output report to .I logfile instead of standard output. .TP .B -help Display a usage summary and exit. .TP .BI -libraries " libdirs" .I libdirs is a quoted list of whitespace delimited directories where libraries should be searched for. .TP .BI -manuals " mandirs" .I mandirs is a quoted list of whitespace delimited directories where manpages should be searched for. .TP .BI -path " path" Use the specified .I path instead of the value of the environment variable .BR PATH . .TP .BI -temp " tmpdir" Store temporary files in .IR tmpdir instead of the value of the environment variable .BR TMPDIR , if defined, or .IR /tmp . .TP .B -version Output version information and exit. .SH AUTHOR Peter Chang . .BR This manual page was originally written by Matej Vela . binstats-1.08.orig/binstats0100755000175000001440000005704607231561052015046 0ustar mvelausers#!/bin/bash # -*- sh -*- # binstats - a Linux utility to find the number and identity of i386 a.out # 1.08 ELF and ECOFF binaries, plus their debugging symbols status, # setuid status and dynamic library dependence. The number of shell, # awk, perl, python & tcl scripts are counted. Also it looks for # any duplicated executable name, unused libraries, binaries with # missing libraries and statically linked binaries. Finally it # counts man pages and looks for duplicated names. # version number of binstats BSVER="1.08" # Make sure 1) the PATH, EXEDIR, DLIBDIR & MANDIR variables are correct. # If you want to use the current PATH for the executables search # then set USEPATH to 1. If you want to use /etc/ld.so.conf for # dynamic library search then set USELDSOCONF to 1. # Alternatively you can set these via the command line. # 2) there is enough room in TMPDIR (<300k); # 3) that the C program 'derefsymlink' has been built and # installed in /usr/local/bin (or where PATH points to) # if USECDS is set to 1. # Then run it (if you are not root then any executable without world # readable status [especially setuid binaries] will register in the # tallies or log as "can't read setuid"). After a while, a summary will # appear on screen and a log of more information is recorded in BSLOG # (bstats.log). # Copyright (c) 1996, 1997, 1999 & 2000 by (Peter.Chang@nottingham.ac.uk) # Inspired by "execount" # written by Murple (murple@clark.net) # Version History: # 0.5 - Created on 1996/7/19 # 0.7 - Modified output format on 1996/7/23 # 0.9 - Added unused dynamic library hunt, logging to file # and duplicate executable search on 1996/7/25 # 0.91 - TMPDIR introduced and added search for binaries # with missing libraries on 1996/7/26 # 0.92 - Derefenced symbolic links that ldd (1.7.14) gives # which confused the list of unused libraries on 1996/8/9 # 0.93 - Put in un-stripped binaries counting (relies on ELF patch to # file), make sure we only count executables and include NMAGIC # type on 1996/8/12 # 0.94 - Improved the symbolic link dereferencing to cope with some # types of relative links on 1996/8/20 # 0.95 - Wrote a C program to do dereferencing, added setuid counting # and beautified output on 1996/8/23 # 0.96 - (Thanks to Preston.F.Crow@Dartmouth.EDU for his feedback and # suggestions.) Stopped "find" recursing down directories in # EXEDIR, fixed ldd inconsistency, added support for using PATH # and script counting on 1996/9/3 # 0.97 - Added automatic dynamic library directories detection using the # contents of /etc/ld.so.conf on 1996/9/9 # 0.98 - Tightened search for dynamic libraries, used derefsymlink for # libraries, checked for derefsymlink and # generalized grep for [sS]hell on 1997/3/28 # 0.99 - Added Java bytecode detection (need magic support) on 1997/3/29 # 1.00 - Added command line interface on 1997/4/1 # 1.01 - Fixed for new version of ldd (1.9.1+), courtesy of # Markus Rex , # on 1997/9/23 # 1.02 - (Thanks to Matej Vela for passing on the # following fixes.) Fixed shared library filename patterns (from # Laurent Bonnaud ), added use of # environment variable TMPDIR and added -follow to find binaries # that are symlinked on 1999/11/11 # 1.03 - Removed shell function deref_symlink and fullpath. Added # OMAGIC, ECOFF support and man page checking (the latter # item was suggested in a Debian bug report by Adam P. Harris # ) on 1999/11/12 # 1.04 - The man page code didn't cope with the double colons in many # perl man pages. It is now fixed thanks to Matej Vela # on 1999/11/15 # 1.05 - Included count of awk scripts as noticed by Arnaud # Launay on 1999/11/30 # 1.06 - Included fixes and counts of python and tcl scripts from Osamu Aoki # , generalized some matches and tweaked # on 2000/6/13 # 1.07 - Yet another attempt to fix the vagaries of shell and subshell # expansions on 2000/6/14 # 1.08 - Included some more fixes to the scripts counting as pointed out by # Osamu Aoki , added some more directories # to defaults and made binstat immune to "symlinks in tmp" attacks # from patches by Matej Vela on 2001/1/16 # save old path OLDPATH=$PATH #---------Customise the variables below or use the command line---------- # to use your PATH for a list of binary directories instead of setting # EXEDIR separately, set to 1 [beware of having . in your PATH if you only # want to see "official" binaries.] # otherwise set to 0 and edit EXEDIR USEPATH=1 # the list of directories where your executables reside (change to suit # your system or ignore if USEPATH=1) EXEDIR="/bin /usr/bin /usr/local/bin /sbin /usr/sbin /usr/local/sbin /usr/X11R6/bin /usr/games" # the list of directories where your man pages reside MANDIR="/usr/man /usr/share/man /usr/X11R6/man /usr/local/man" # to use /etc/ld.so.conf to fill in DLIBDIR, set to 1 USELDSOCONF=1 # otherwise set to 0 and edit DLIBDIR # the list of dynamic library directories (change to suit your system # or ignore if USELDSOCONF=1) DLIBDIR="/lib /usr/lib /usr/local/lib /usr/X11R6/lib" # the path needed by binstats # for echo, sed, tr, cat, xargs, cut, dirname, find, sort, awk, uniq, grep, # file, ldd, col, diff, wc, uname, date, col & derefsymlink (assumed to be # in /usr/local/bin) PATH=/bin:/usr/bin:/usr/local/bin #---------nothing further to edit below (unless you're hacking)---------- # name of log file BSLOG=bstats.log # temporary storage directory, use environment variable if defined TMPDIR=${TMPDIR-/tmp} # ldd has at least one bug (in 1.7.14) and one inconsistency (or feature) which # have to be worked around, see comments in code below for more details LDDBA=0 # garbage output LDDBB=0 # executable name missing for single name # when these are fixed or changed then the following variables to 1 # debugging option, set to 1 to retain files DEBUG=0 # another debugging option, set to 0 to reuse old temp files FILEOPS=1 #----------process command line arguments--------------- CLI_USAGE=\ "Usage: ./binstats [-b[inaries]=\"/bin /usr/bin\"] [-d[ebug]] [-f[ile]=bstats.log] [-h[elp]] [-l[ibraries]=\"/lib /usr/lib\"] [-m[anuals]=\"/usr/man /usr/local/man\"] [-p[ath]=\"/bin:/usr/bin:/usr/local/bin\"] [-t[emp]=/tmp] [-v[ersion]]" for CLI_OPT do case "$CLI_OPT" in -*=*) CLI_ARG=`echo "$CLI_OPT" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) CLI_ARG= ;; esac case "$CLI_OPT" in -b*=*) USEPATH=0 EXEDIR="$CLI_ARG" ;; -d*) DEBUG=1 ;; -f*=*) BSLOG="$CLI_ARG" ;; -h*) echo "$CLI_USAGE" exit 0 ;; -l*=*) USELDSOCONF=0 DLIBDIR="$CLI_ARG" ;; -m*=*) MANDIR="$CLI_ARG" ;; -p*=*) PATH="$CLI_ARG" ;; -t*=*) TMPDIR="$CLI_ARG" ;; -v*) echo "binstats-$BSVER" exit 0 ;; *) echo "$CLI_USAGE" exit 1 ;; esac done #----------define variables and functions--------------- if [ $USEPATH -eq 1 ]; then # use old PATH (not sure if the substitution is needed) EXEDIR=`echo $OLDPATH | tr : ' ' | sed s:\~:$HOME:g` fi if [ $USELDSOCONF -eq 1 ]; then # use /etc/ld.so.conf plus the two "trusted" locations LDSOCONF=`cat /etc/ld.so.conf | grep -v '^#' | xargs echo` DLIBDIR="/lib /usr/lib $LDSOCONF" fi # ID number PIDNO=$$ # name of temp log BSLOGTMP=$BSLOG.$PIDNO if [ $DEBUG -gt 0 ]; then TMPDIR=. PIDNO=00 else TMPDIR=$TMPDIR/binstats.$PIDNO mkdir -m 700 $TMPDIR || exit 1 fi # list of executables EXELIST=$TMPDIR/exelist.$PIDNO # list of dynamic libraries DLIBLIST=$TMPDIR/dliblist.$PIDNO # list of man pages MANLIST=$TMPDIR/manlist.$PIDNO # executable types EXEFILE=$TMPDIR/exefile.$PIDNO # list of dependent (used) libraries EXELIB=$TMPDIR/exelib.$PIDNO # list of unused libraries DLIBUN=$TMPDIR/dlibun.$PIDNO # temporary storage DTEMPA=$TMPDIR/dtempa.$PIDNO # all dynamic libs in $DLIBDIR DTEMPB=$TMPDIR/dtempb.$PIDNO # missing dynamic libs in $EXELIB DTEMPC=$TMPDIR/dtempc.$PIDNO # dereferenced list of $DTEMPA ETEMPA=$TMPDIR/etempa.$PIDNO # all files in $EXEDIR ETEMPB=$TMPDIR/etempb.$PIDNO # output of ldd on files in $EXEFILE ETEMPC=$TMPDIR/etempc.$PIDNO # statically linked binaries in $ETEMPB ETEMPD=$TMPDIR/etempd.$PIDNO # duplicate executable names in $ETEMPA ETEMPE=$TMPDIR/etempe.$PIDNO # 'not stripped' binaries in $EXEFILE ETEMPF=$TMPDIR/etempf.$PIDNO # setuid binaries in $EXEFILE MTEMPA=$TMPDIR/mtempa.$PIDNO # all files in $MANDIR MTEMPB=$TMPDIR/mtempb.$PIDNO # duplicate executable names in $MTEMPA #----------begin program--------------- if [ $FILEOPS -gt 0 ]; then echo "Look in $EXEDIR for executables" find $EXEDIR -perm +111 -maxdepth 1 -type f -follow -print | \ derefsymlink -s | sort | uniq | \ awk -F '/' '{ printf "%s:%s\n", $NF, $0 }' > $ETEMPA echo "Find duplicated executable names" # use an awk script instead of whereis later (as suggested by Preston Crow) # R=repetition, N=name, P=path sort -t ':' $ETEMPA | awk -F ':' \ 'BEGIN { R=0;N="";P="" } { if ($1==N) { printf("%s ",P); R=1 } else { if (R==1) { printf("%s\n",P); R=0 } }; N=$1; P=$2 } END { if (R==1) {printf("%s\n",P)} }' \ > $ETEMPD echo "Sort out list by alphabetical order" sort -t ':' $ETEMPA | cut -d ':' -f 2- > $EXELIST echo "Find executable type (this will take a long time)" cat $EXELIST | xargs file > $EXEFILE echo "Look for dynamic library dependence (this will take an even longer time)" # hmm, ldd (1.7.14) seems to output some unprintable character when it # encounters a static a.out image # And ldd (1.9.2) prints some hex numbers after library name in parentheses if [ $LDDBA -eq 0 ]; then grep 'executable' $EXEFILE | cut -d ':' -f 1 | \ xargs ldd | col -b | cut -d '(' -f 1 >& $ETEMPB else grep 'executable' $EXEFILE | cut -d ':' -f 1 | \ xargs ldd | awk cut -d '(' -f 1 >& $ETEMPB fi echo "List the used dynamic libraries" grep 'lib[^:]*\.so' $ETEMPB | sort -b | uniq -c > $EXELIB grep 'statically linked' $ETEMPB > $ETEMPC echo "Hunt down binaries that depend on missing libraries" awk \ '/^\// { CURPROG = $0; NEW = 1 } /not found/ { if (NEW == 1) print CURPROG; NEW = 0 }' \ $ETEMPB > $DTEMPB echo "Look in $DLIBDIR for dynamic libraries" find $DLIBDIR -maxdepth 1 -type f -name 'lib*.so*' | \ derefsymlink -s | sort | uniq > $DLIBLIST echo "Search for unused dynamic libraries" grep -v 'not found' $EXELIB | cut -d '/' -f 2- | cut -d ' ' -f 1 | \ sort | uniq | sed 's,^,/,g' > $DTEMPA derefsymlink -f $DTEMPA | sort | uniq > $DTEMPC diff -du $DLIBLIST $DTEMPC | grep '^-/' | cut -b 2- > $DLIBUN echo "Find un-stripped binaries" grep 'not stripped' $EXEFILE | sort > $ETEMPE echo "Find setuid binaries" grep 'setuid' $EXEFILE | sort > $ETEMPF fi echo "Look in $MANDIR for man pages" find $MANDIR -maxdepth 2 -type f -follow -name '*.*' -print | \ derefsymlink -s | sort | uniq | \ awk -F '/' '{ printf "%s;%s\n", $NF, $0 }' > $MTEMPA echo "Find duplicated man page names" sort -t ';' $MTEMPA | awk -F ';' \ 'BEGIN { R=0;N="";P="" } { if ($1==N) { printf("%s ",P); R=1 } else { if (R==1) { printf("%s\n",P); R=0 } }; N=$1; P=$2 } END { if (R==1) {printf("%s\n",P)} }' \ > $MTEMPB # finish messing around with files and lists of files # now work out some numbers echo "Gather statistics" AOUTC=`grep 'Linux/i386.*executable' $EXEFILE | wc -l` OMAGIC=`grep 'OMAGIC' $EXEFILE | wc -l` NMAGIC=`grep 'NMAGIC' $EXEFILE | wc -l` QMAGIC=`grep 'QMAGIC' $EXEFILE | wc -l` ZMAGIC=`grep 'ZMAGIC' $EXEFILE | wc -l` ELFC=`grep 'ELF.*executable' $EXEFILE | wc -l` ECOFFC=`grep 'ECOFF.*executable' $EXEFILE | wc -l` JAVAC=`grep 'Java bytecode' $EXEFILE | wc -l` LIBC=`cat $EXELIB | wc -l` UNLIBC=`cat $DLIBUN | wc -l` DLLIBC=`grep 'DLL' $EXELIB | wc -l` SELFC=`grep 'ELF' $ETEMPC | wc -l` SECOFFC=`grep 'ECOFF' $ETEMPC | wc -l` #SAOUTC=`grep -v 'ELF' $ETEMPC | wc -l` SAOUTC=`grep 'Linux/i386' $ETEMPC | wc -l` DUPC=`cat $ETEMPD | wc -l` MISSC=`cat $DTEMPB | wc -l` ELFUNSTR=`grep 'ELF.*executable' $ETEMPE | wc -l` ECOFFUNSTR=`grep 'ECOFF.*executable' $ETEMPE | wc -l` AOUTUNSTR=`grep 'Linux/i386.*executable' $ETEMPE | wc -l` ELFSETUID=`grep 'ELF.*executable' $ETEMPF | wc -l` ECOFFSETUID=`grep 'ECOFF.*executable' $ETEMPF | wc -l` AOUTSETUID=`grep 'Linux/i386.*executable' $ETEMPF | wc -l` UNSETUID=`grep "can\'t" $ETEMPF | wc -l` TEXTC=`grep ':.* text' $EXEFILE | wc -l` ALLSCRIPTC=`grep -e ':.* script' -e ':.* commands' $EXEFILE | wc -l` SHC=`grep 'Bourne [sS]hell' $EXEFILE | wc -l` BASHC=`grep 'Bourne-Again' $EXEFILE | wc -l` CSHC=`grep '[^x] C [sS]hell' $EXEFILE | wc -l` TCSHC=`grep 'Tenex C' $EXEFILE | wc -l` AWKC=`grep ':.*awk' $EXEFILE | wc -l` PERLC=`grep ':.*perl' $EXEFILE | wc -l` PYTHONC=`grep ':.*python' $EXEFILE | wc -l` TCLC=`grep -e ':.*tcl' -e ':.*wish ' $EXEFILE | wc -l` OTHERC=$[($ALLSCRIPTC)-($SHC+$BASHC+$CSHC+$TCSHC+$AWKC+$PERLC+$PYTHONC+$TCLC)] UNIDTC=$[($TEXTC-($ALLSCRIPTC))] MANC=`cat $MTEMPA | wc -l` MANDUPC=`cat $MTEMPB | wc -l` MACHNAME=`uname -n` DATESTAMP=`date +'%Y/%m/%d %T %Z'` #----------log all info--------------- echo "binstats-$BSVER output from $MACHNAME on $DATESTAMP" > $BSLOGTMP echo "" >> $BSLOGTMP echo "Binaries: $[($AOUTC+$ELFC+$ECOFFC)]" >> $BSLOGTMP echo " OMAGIC Demand Paged: $OMAGIC" >> $BSLOGTMP echo " NMAGIC Demand Paged: $NMAGIC" >> $BSLOGTMP echo " QMAGIC Demand Paged: $QMAGIC" >> $BSLOGTMP echo " ZMAGIC Demand Paged: $ZMAGIC" >> $BSLOGTMP echo " statically linked: $SAOUTC" >> $BSLOGTMP echo " not stripped: $AOUTUNSTR" >> $BSLOGTMP echo " setuid: $AOUTSETUID" >> $BSLOGTMP echo " ELF: $ELFC" >> $BSLOGTMP echo " statically linked: $SELFC" >> $BSLOGTMP echo " not stripped: $ELFUNSTR" >> $BSLOGTMP echo " setuid: $ELFSETUID" >> $BSLOGTMP echo " ECOFF: $ECOFFC" >> $BSLOGTMP echo " statically linked: $SECOFFC" >> $BSLOGTMP echo " not stripped: $ECOFFUNSTR" >> $BSLOGTMP echo " setuid: $ECOFFSETUID" >> $BSLOGTMP echo " Java: $JAVAC" >> $BSLOGTMP if [ $UNSETUID -gt 0 ]; then echo " Can't read setuid: $UNSETUID" >> $BSLOGTMP fi echo " Duplicate names: $DUPC" >> $BSLOGTMP echo " Missing libraries: $MISSC" >> $BSLOGTMP echo "Text: $TEXTC" >> $BSLOGTMP echo " Bourne shell: $SHC" >> $BSLOGTMP echo " Bourne-Again shell: $BASHC" >> $BSLOGTMP echo " C shell: $CSHC" >> $BSLOGTMP echo " Tenex C shell: $TCSHC" >> $BSLOGTMP echo " Awk: $AWKC" >> $BSLOGTMP echo " Perl: $PERLC" >> $BSLOGTMP echo " Python: $PYTHONC" >> $BSLOGTMP echo " Tcl: $TCLC" >> $BSLOGTMP if [ $OTHERC -gt 9 ]; then echo " Other interpreted: $OTHERC" >> $BSLOGTMP else echo " Other interpreted: $OTHERC" >> $BSLOGTMP fi if [ $UNIDTC -gt 9 ]; then echo " Unidentified: $UNIDTC" >> $BSLOGTMP else echo " Unidentified: $UNIDTC" >> $BSLOGTMP fi echo "Used libraries: $LIBC" >> $BSLOGTMP echo " DLL: $DLLIBC" >> $BSLOGTMP echo "Unused libs: $UNLIBC" >> $BSLOGTMP echo "Man pages: $MANC" >> $BSLOGTMP echo " Duplicate names: $MANDUPC" >> $BSLOGTMP DOTLINE=0 echo "==============================================================" >> $BSLOGTMP if [ $OMAGIC -gt 0 ]; then DOTLINE=1 echo "OMAGIC binaries:" >> $BSLOGTMP grep 'OMAGIC' $EXEFILE | cut -d ':' -f 1 | sort >> $BSLOGTMP fi if [ $NMAGIC -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "NMAGIC binaries:" >> $BSLOGTMP grep 'NMAGIC' $EXEFILE | cut -d ':' -f 1 | sort >> $BSLOGTMP fi if [ $QMAGIC -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "QMAGIC binaries:" >> $BSLOGTMP grep 'QMAGIC' $EXEFILE | cut -d ':' -f 1 | sort >> $BSLOGTMP fi if [ $ZMAGIC -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "ZMAGIC binaries:" >> $BSLOGTMP grep 'ZMAGIC' $EXEFILE | cut -d ':' -f 1 | sort >> $BSLOGTMP fi if [ $SAOUTC -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "statically linked (a.out):" >> $BSLOGTMP grep -B 1 'statically linked$' $ETEMPB | \ grep '^/' | cut -d ':' -f 1 >> $BSLOGTMP fi if [ $AOUTUNSTR -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "not stripped (a.out):" >> $BSLOGTMP grep 'Linux/i386.*executable' $ETEMPE | cut -d ':' -f 1 >> $BSLOGTMP fi if [ $AOUTSETUID -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "setuid (a.out):" >> $BSLOGTMP grep 'Linux/i386.*executable' $ETEMPF | cut -d ':' -f 1 >> $BSLOGTMP fi if [ $DOTLINE -gt 0 ]; then echo "==============================================================" >> $BSLOGTMP fi DOTLINE=0 if [ $SELFC -gt 0 ]; then echo "statically linked (ELF):" >> $BSLOGTMP grep -B 1 'statically linked (ELF)' $ETEMPB | grep '^/' | \ cut -d ':' -f 1 >> $BSLOGTMP DOTLINE=1 fi if [ $ELFUNSTR -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "not stripped (ELF):" >> $BSLOGTMP grep 'ELF.*executable' $ETEMPE | cut -d ':' -f 1 >> $BSLOGTMP fi if [ $ELFSETUID -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "setuid (ELF):" >> $BSLOGTMP grep 'ELF.*executable' $ETEMPF | cut -d ':' -f 1 >> $BSLOGTMP fi if [ $DOTLINE -gt 0 ]; then echo "==============================================================" >> $BSLOGTMP fi DOTLINE=0 if [ $SECOFFC -gt 0 ]; then echo "statically linked (ECOFF):" >> $BSLOGTMP grep -B 1 'statically linked (ECOFF)' $ETEMPB | grep '^/' | \ cut -d ':' -f 1 >> $BSLOGTMP DOTLINE=1 fi if [ $ECOFFUNSTR -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "not stripped (ECOFF):" >> $BSLOGTMP grep 'ECOFF.*executable' $ETEMPE | cut -d ':' -f 1 >> $BSLOGTMP fi if [ $ECOFFSETUID -gt 0 ]; then if [ $DOTLINE -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP fi DOTLINE=1 echo "setuid (ECOFF):" >> $BSLOGTMP grep 'ECOFF.*executable' $ETEMPF | cut -d ':' -f 1 >> $BSLOGTMP fi if [ $DOTLINE -gt 0 ]; then echo "==============================================================" >> $BSLOGTMP fi if [ $UNSETUID -gt 0 ]; then echo "can't read setuid:" >> $BSLOGTMP grep "can\'t" $ETEMPF | cut -d ':' -f 1 >> $BSLOGTMP echo "==============================================================" >> $BSLOGTMP fi if [ $DUPC -gt 0 ]; then echo "duplicated executable names:" >> $BSLOGTMP cat $ETEMPD >> $BSLOGTMP echo "==============================================================" >> $BSLOGTMP fi if [ $MISSC -gt 0 ]; then echo "binaries with missing libraries:" >> $BSLOGTMP # work around ldd inconsistency (1.7.14) if [ $LDDBB -eq 0 ]; then if [ $MISSC -eq 1 ]; then cat $DTEMPB >> $BSLOGTMP fi fi cut -d ':' -f 1 $DTEMPB | xargs ldd | cut -d '(' -f 1 >> $BSLOGTMP echo "==============================================================" >> $BSLOGTMP fi if [ $OTHERC -gt 0 ]; then echo "other interpreted files:" >> $BSLOGTMP grep -e ':.* script' -e ':.* commands' $EXEFILE | \ grep -v 'Bourne [sS]hell' | \ grep -v 'Bourne-Again' | \ grep -v '[^x] C [sS]hell' | \ grep -v 'Tenex C' | \ grep -v ':.*awk' | \ grep -v ':.*perl' | \ grep -v ':.*python' | \ grep -v -e ':.*tcl' -e ':.*wish ' >> $BSLOGTMP echo "==============================================================" >> $BSLOGTMP fi if [ $UNIDTC -gt 0 ]; then echo "unidentified text files:" >> $BSLOGTMP grep ':.* text' $EXEFILE | grep -v ':.* script' | grep -v ':.*perl' | \ cut -d ':' -f 1 | sort >> $BSLOGTMP echo "==============================================================" >> $BSLOGTMP fi echo " usage count | dynamic library" >> $BSLOGTMP echo "--------------------------------------------------------------" >> $BSLOGTMP if [ $DLLIBC -gt 0 ]; then echo "DLL:" >> $BSLOGTMP grep 'DLL' $EXELIB >> $BSLOGTMP echo "--------------------------------------------------------------" >> $BSLOGTMP fi echo "ELF:" >> $BSLOGTMP grep -v 'DLL' $EXELIB >> $BSLOGTMP if [ $UNLIBC -gt 0 ]; then echo "--------------------------------------------------------------" >> $BSLOGTMP echo "unused:" >> $BSLOGTMP cat $DLIBUN >> $BSLOGTMP fi echo "==============================================================" >> $BSLOGTMP if [ $MANDUPC -gt 0 ]; then echo "duplicated man page names:" >> $BSLOGTMP cat $MTEMPB >> $BSLOGTMP echo "==============================================================" >> $BSLOGTMP fi # backup old log file if [ -f $BSLOG ]; then mv -f $BSLOG $BSLOG~; fi # filter through sed to beautify (note the embedded TAB) sed -e 's,^/\(.*[^:]\)$, /\1,g' $BSLOGTMP > $BSLOG rm -f $BSLOGTMP # begin on-screen summary echo "" echo "" echo "binstats-$BSVER output from $MACHNAME on $DATESTAMP" echo "" echo "Binaries: $[($AOUTC+$ELFC+$ECOFFC)]" echo " OMAGIC Demand Paged: $OMAGIC" echo " NMAGIC Demand Paged: $NMAGIC" echo " QMAGIC Demand Paged: $QMAGIC" echo " ZMAGIC Demand Paged: $ZMAGIC" echo " statically linked: $SAOUTC" echo " not stripped: $AOUTUNSTR" echo " setuid: $AOUTSETUID" echo " ELF: $ELFC" echo " statically linked: $SELFC" echo " not stripped: $ELFUNSTR" echo " setuid: $ELFSETUID" echo " ECOFF: $ECOFFC" echo " statically linked: $SECOFFC" echo " not stripped: $ECOFFUNSTR" echo " setuid: $ECOFFSETUID" echo " Java: $JAVAC" if [ $UNSETUID -gt 0 ]; then echo " Can't read setuid: $UNSETUID" fi echo " Duplicate names: $DUPC" echo " Missing libraries: $MISSC" echo "Text: $TEXTC" echo " Bourne shell: $SHC" echo " Bourne-Again shell: $BASHC" echo " C shell: $CSHC" echo " Tenex C shell: $TCSHC" echo " Awk: $AWKC" echo " Perl: $PERLC" echo " Python: $PYTHONC" echo " Tcl: $TCLC" if [ $OTHERC -gt 9 ]; then echo " Other interpreted: $OTHERC" else echo " Other interpreted: $OTHERC" fi if [ $UNIDTC -gt 9 ]; then echo " Unidentified: $UNIDTC" else echo " Unidentified: $UNIDTC" fi echo "Used libraries: $LIBC" echo " DLL: $DLLIBC" echo "Unused libs: $UNLIBC" echo "Man pages: $MANC" echo " Duplicate names: $MANDUPC" # tidy up if [ $DEBUG -eq 0 ]; then rm -rf $TMPDIR fi echo "==============================================================" echo "More detailed information can be obtained in $BSLOG" # end of script