#!/bin/sh
# Filename:      grml-hwinfo
# Purpose:       get hardware information
# Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
# Bug-Reports:   see http://grml.org/bugs/
# License:       This file is licensed under the GPL v2.
################################################################################
# Notice: Some ideas have been taken from
# http://club.black.co.at/david/hwdb/infodump
# by David Schmitt <david@schmitt.edv-bus.at>
################################################################################

# variables
UNAME="$(uname -r)"
PN="$(basename $0)"
[ -n "$WORKING_DIR" -a -d "$WORKING_DIR" ] || WORKING_DIR=$(pwd)
VERSION='0.4.1'

if [ "$1" = "-h" ] || [ "$1" = "--help" ] ; then
  echo "$PN - collect hardware information

This tool collects information of the hardware this tool is being executed
on.  It can be executed as normal user to collect some basic information or
with root permissions to collect as much information as possible. A file
named info.tar.bz2 storing all collected information will be created in the
current working directory."

  exit 0
fi

TMPDIR=$(mktemp -d) || { echo "Error creating a temporary directory, can not continue. Exiting.">&2 ; exit 1; }
INFODIR="info"

bailout() {
  [ -d "$TMPDIR" ] && rm -rf "$TMPDIR"
  [ -n "$1" ] && exit 1 || exit 0
}

[ -n "$INFOFILE" ] || INFOFILE='info.tar.bz2'
INFOFILE="${WORKING_DIR}/${INFOFILE}"

if [ "$(id -u)" != "0" ] ; then
   NOTROOT=1
   echo "Notice: you are running $PN without root permissions. Not all information will be collected."
   echo
fi

# check whether a binary is available and executable
exectest() {
if [ -z "$1" ] ; then
   echo 'Usage: exectest <binary>'>&2
   return 1
else
   test -e "$(which $1)" && return 0 || return 1
fi
}

# echo a list of all disks and their size
# taken from http://cvs.debian.org/fai/lib/disk-info
diskandsize() {
    local isdisk major minor blocks device suffix
    while read major minor blocks device suffix; do
        isdisk=1
        # skip ide cdrom
        [ -f /proc/ide/$device/media ] && grep -q cdrom /proc/ide/$device/media && isdisk=0
        [ "$isdisk" -eq 1 ] && echo "$device $blocks"
    done
}

list_disks() {
# print only every second entry; used by disk_info
i=0
for ent in $@; do
    if [ "$i" -eq 0 ]; then
        echo $ent
        i=1
    else
        i=0
    fi
done
}

disk_info() {
    # the variable holds a space separated list of devices and their block size
    device_size=`grep -E ' cciss/c.d.$| ida/c.d.$| rd/c.d.$| hd.$| sd.$|/disc$' /proc/partitions | diskandsize`
    # a list of all local disks, without size
    disklist=`list_disks $device_size`
}

echo "Running grml-hwinfo ${VERSION} - collecting hardware information."

mkdir "${TMPDIR}/${INFODIR}"
cd "${TMPDIR}/${INFODIR}" || bailout 1
(
  cd "${TMPDIR}/${INFODIR}"

  echo "Generating hardware information report using file $INFOFILE."
  echo "This might take a few seconds/minutes. Please be patient..."

# some sysinfo
  date > date
  if [ -r /etc/grml_version ] ; then
     cat /etc/grml_version > grml_version
  fi
  if [ -r /etc/debian_version ] ; then
     cat /etc/debian_version > debian_version
  fi
  uname -a > uname

# disks / devices
  [ -f /proc/scsi/scsi ] && cat /proc/scsi/scsi > scsi
  (lspci; lspci -n) | sort > lspci
  [ -r /proc/bus/pnp ] && lspnp > lspnp
  [ -r /proc/bus/usb ] && lsusb > lsusb
  cat /proc/partitions > partitions
  find /proc/ide/ -name geometry -exec grep . {} \; > proc_ide 2>/dev/null
  df -h > df 2>/dev/null
  for i in free lsmod mount lsdev ; do
      exectest $i  && $i > $i
  done

# proc stuff
  for i in cpuinfo interrupts cmdline devices dma fb iomem ioports \
    mdstat meminfo modules mtrr pci version ; do
    [ -r /proc/$i ] && cat /proc/$i > proc_$i
  done
  exectest sysdump  && sysdump > sysdump 2>sysdump.error
# for sysnet in `find /proc/sys/net/*/ -type f | grep -v flush`; do cat $sysnet >> sysnet ; done

# log
  dmesg > dmesg.cur

# hwinfo
  exectest discover && discover -v --type-summary --enable-bus all > discover 2> discover.2
  exectest hwinfo   && hwinfo log=hwinfo
  exectest x86info  && x86info > x86info 2>x86info.2

# net stuff
  exectest ifconfig  && ifconfig -v -a  > ifconfig
  exectest ip        && ip route show   > ip_route
  exectest ip        && ip link show    > ip_link
  exectest route     && route -n        > route

# software
  if exectest dpkg ; then
     dpkg --get-selections   > dpkg_get_selections
     COLUMNS=300 dpkg --list > dpkg_list
     COLUMNS=1000 dpkg -l linux-image-$UNAME | grep linux-image-$UNAME | tr -s ' ' > running_kernel
  fi

# powermanagement
  exectest laptop-detect  && laptop-detect >/dev/null 2>/dev/null && echo "0" > laptop_detected
  exectest acpi_available && acpi_available && cat /proc/acpi/info > acpi_info
  exectest acpi && acpi > acpi 2> acpi.error && acpi -v > acpi.version
  [ -r /proc/apm/ ] && apm > apm

# kernel stuff
  if [ -r /proc/config.gz ] ; then
     zcat /proc/config.gz > kernelconfig
  else
     [ -r /boot/config-$UNAME ] && cat /boot/config-$UNAME > kernelconfig
  fi

# X stuff
  if [ -n "${DISPLAY}" ] ; then
     exectest xviddetect  && xviddetect         > xviddetect
     exectest xvidtune    && xvidtune -show     > xdivtune
     exectest xrandr      && xrandr             > xrandr
     exectest xdpyinfo    && xdpyinfo           > xdpyinfo
     X -version > x_version 2>&1
  fi

  for i in Xorg.0.log Xorg.7.log Xorg.8.log XFree86.0.log XFree86.7.log XFree86.8.log dmesg ; do
      cp /var/log/$i log_$i 2>/dev/null
  done

  cp /etc/X11/xorg.conf    xorg.conf    2>/dev/null
  cp /etc/modules          modules      2>/dev/null
  cp /etc/X11/XF86Config-4 XF86Config-4 2>/dev/null

# not available:
# sysinfo -class device -level all

# as root:
if [ -n "$NOTROOT" ] ; then
   echo "not running as root" > root
else
   echo "running as root" > root
   disk_info
   exectest sfdisk     && sfdisk -d > sfdisk 2>sfdisk.error
   exectest ddcprobe   && ddcprobe  > ddcprobe
   exectest dmidecode  && dmidecode > dmidecode

   exectest dconf && dconf -o dconf

   if [ -x /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl ] ; then
      /usr/share/doc/lm-sensors/examples/eeprom/decode-dimms.pl > decode-dimms 2>decode-dimms.error
   fi

   for disk in $disklist; do
      exectest smartctl  && smartctl -i /dev/$disk >> smartctl
      exectest hdparm    && hdparm -iv /dev/$disk  >> hdparm
      exectest fdisk     && fdisk -lu /dev/$disk   >> fdisk 2>>fdisk.error
      exectest parted    && parted -s /dev/$disk print >> parted
      LC_ALL=C file -s /dev/$disk?* | grep -v ": empty" >> file_disk
   done
fi
)

# finally create the tarball
if [ -f "${INFOFILE}" ] ; then
   DATE="$(date +%Y%m%d_%H%M%S)"
   NEW_INFOFILE="${WORKING_DIR}/info_${DATE}.tar.bz2"
   echo
   echo "Warning: $INFOFILE exists already, using $NEW_INFOFILE instead.">&2
   INFOFILE="$NEW_INFOFILE" # adjust variable for final info message
fi

cd "${TMPDIR}"
tar jcf "${INFOFILE}" "${INFODIR}"
cd "${WORKING_DIR}"

echo
[ -r "$INFOFILE" ] && echo "$INFOFILE ("$(ls -ahl "$INFOFILE" | awk '{print $5}')") has been generated."
echo

bailout

## END OF FILE##################################################################
