#!/bin/sh

# usage: psinfo.sh keyword cmd [args...]
#  keyword = [EXEC, FILES, FILES(RD), FILES(WR), LCALLS, SCALLS, LCALLS(set), SCALLS(set)]
#   set = [files, dirs, links, pipes, fileaccess, sharing, process, memory, signals, networking]

### vytvor unikatni temp soubor (obycejne 'mktemp' mi v Intepidu vytvarelo soubor s nazvem mktemp, proto takhle slozite)
TEMP="$(mktemp tmp.XXXXXX)" || exit 1
### zjisti zakladni operaci pomoci odriznuti vseho v zavorce - z LCALLS(neco) zbude LCALLS atd
OPERATION="$( echo $1 | sed 's/[:blank:]*(.*//' )"
### zjisti subset operaci [LS]CALLS pomoci odriznuti vseho kolem zavorky
SUBSET="$(echo $1 | egrep 'SCALLS|LCALLS|FILES' | sed 's/[SL]CALLS//' | sed 's/FILES//'| sed 's/.*(//' | sed 's/).*//')"
shift
######## EXEC
if [ "$OPERATION" = "EXEC" ]; then
  #to co vypadne behem trasovani nas nezajima, zbytek do souboru
  strace -f -e execve -o "$TEMP" "$@" > /dev/null
  #vypis soubor | odrizni PID | odrizni vsechno az po nazev volani | odrizni vse po nazvu volani | vymaz prazdne radky | protrid
  cat "$TEMP" | sed 's/[0-9]*//' | sed 's/.*execve("//' | sed 's/"*,* .*//' | sed '/^$/d' | sort -u
fi
######## FILES
if [ "$OPERATION" = "FILES" ]; then
  #to co vypadne behem trasovani nas nezajima, zbytek do souboru
  strace -f -e open -o "$TEMP" "$@" > /dev/null
  #vypis soubor | odrizni vsechno az po nazev souboru | odrizni vsechno nezacinajici '/' | vymaz prazdne radky | odrizni vsechno po nazvu souboru a/nebo grepuj | protrid
	if [ "$SUBSET" = "" ]; then
      cat "$TEMP" | sed 's/.*open("//' | sed 's/^[^\/.].*$//' | sed '/^$/d' | sed 's/"*,* .*//' | sort -u
    elif [ "$SUBSET" = "RD" ]; then
      cat "$TEMP" | sed 's/.*open("//' | sed 's/^[^\/.].*$//' | sed '/^$/d' | egrep 'O_RDONLY|O_RDWR' | grep ') = 3' | sed 's/"*,* .*//' | sort -u
    elif [ "$SUBSET" = "WR" ]; then
      cat "$TEMP" | sed 's/.*open("//' | sed 's/^[^\/.].*$//' | sed '/^$/d' | egrep 'O_WRONLY|O_RDWR' | grep ') = 3' | sed 's/"*,* .*//' | sort -u
    fi
fi
######## [SL]CALLS
if [ "$OPERATION" = "LCALLS" -o "$OPERATION" = "SCALLS" ]; then
  if [ "$OPERATION" = "LCALLS" ]; then
    #to co vypadne behem trasovani nas nezajima, zbytek do souboru
    ltrace -o "$TEMP" "$@" > /dev/null
  elif [ "$OPERATION" = "SCALLS" ]; then
    #to co vypadne behem trasovani nas nezajima, zbytek do souboru
    strace -o "$TEMP" -f "$@" > /dev/null
  fi
  case "$SUBSET" in
	"files") #ulozime si do promenne jen ta systemova volani, ktera budeme chtit vyhledavat
      APROPO="open|fopen|read|fread|write|fwrite|lseek|fseek|close|fclose";;
    "dirs")
      APROPO="rename|getcwd|chdir|mkdir|rmdir|opendir|closedir|scandir|seekdir|telldir|getdents|readdir|fopendir|dirfd|fchdir";;
    "links")
      APROPO="link|unlink|readlink|symlink";;
    "pipes")
      APROPO="dup|dup2|pipe|mknod";;
    "fileaccess")
      APROPO="access|stat|fstat|lstat|chmod|fchmod|chown|fchown|utime";;
    "sharing")
      APROPO="select|poll|semop|semget|semctl|shmat|shmget|shmctl|shmdt|msgctl|msgget|msgrcv|msgsnd";;
    "process")
      APROPO="clone|execve|_exit|exit_group|fork|unshare|getpid|getppid|getpgrp|setpgrp|wait4|waitid|waitpid";;
    "memory")
      APROPO="calloc|malloc|free|realloc|brk|mmap|alloca|shmat|shmget|shmctl|shmdt";;
    "signals")
      APROPO="kill|sigprocmask|sigaction|sigdelset|sigemptyset|rt_sigaction|rt_sigprocmask";;
    "networking")
      APROPO="socket|bind|connect|listen|accept|send|recv";;
  esac
  #vypis | odrizni pripadny PID | odrizni vsechno po nazvu volani | progrepuj | protrid | napumpuj do cyklu
  if [ "$SUBSET" ]; then
    cat "$TEMP" | sed 's/^[0-9]* *//' | sed 's/(.*//' | sed 's/<.*//' | egrep -w "$APROPO" | sort -u | while read line
    do
      if [ "$OPERATION" = "SCALLS" ]; then
        #jen volani, ve kterych je PRESNE klicove slovo a pak jestli to na strance najde
        PARAM1=$(apropos $line | egrep "^\b($line)\b" | egrep "(2)")
        if [ "$PARAM1" ]; then
          apropos $line | egrep "^\b($line)\b" | egrep '\(2\)' | sed "s/.*(/$line(/" | sed 's/).*-/) -/'
        fi
      elif [ "$OPERATION" = "LCALLS" ]; then
        #jen volani, ve kterych je PRESNE klicove slovo a pak zjistit, na ktere strance to najde
        PARAM1=$(apropos $line | egrep "^\b$line\b" | grep "\(3p\)")
        PARAM2=$(apropos $line | egrep "^\b$line\b" | grep "\(3\)")
        PARAM3=$(apropos $line | egrep "^\b$line\b" | grep "\(2\)")
        if [ "$PARAM1" ]; then
          apropos $line | egrep "^\b$line\b" | grep "\(3p\)" | sed "s/.*(/$line(/" | sed 's/).*-/) -/'
        elif [ "$PARAM2" ]; then
          apropos $line | egrep "^\b$line\b" | grep "\(3\)" | sed "s/.*(/$line(/" | sed 's/).*-/) -/'
        elif [ "$PARAM3" ]; then
          apropos $line | egrep "^\b$line\b" | grep "\(2\)" | sed "s/.*(/$line(/" | sed 's/).*-/) -/'
        fi
      fi
    done
  elif [ -z "$SUBSET" ]; then #nemame zadnou specifikovanou mnozinu volani
    cat "$TEMP" | sed 's/^[0-9]* *//' | sed 's/(.*//' | sed 's/<.*//' | sed 's/--- .*//' | sed '/^$/d' | sort -u | while read line
    do
      if [ "$OPERATION" = "SCALLS" ]; then
        #jen volani, ve kterych je PRESNE klicove slovo a pak jestli to na strance najde
        PARAM1=$(apropos $line | egrep "^\b($line)\b" | egrep "(2)")
        if [ "$PARAM1" ]; then
          apropos $line | egrep "^\b($line)\b" | egrep '\(2\)' | sed "s/.*(/$line(/" | sed 's/).*-/) -/'
        fi
      elif [ "$OPERATION" = "LCALLS" ]; then
        #jen volani, ve kterych je PRESNE klicove slovo a pak zjistit, na ktere strance to najde
        PARAM1=$(apropos $line | egrep "^\b$line\b" | grep "\(3p\)")
        PARAM2=$(apropos $line | egrep "^\b$line\b" | grep "\(3\)")
        PARAM3=$(apropos $line | egrep "^\b$line\b" | grep "\(2\)")
        if [ "$PARAM1" ]; then
          apropos $line | egrep "^\b$line\b" | grep "\(3p\)" | sed "s/.*(/$line(/" | sed 's/).*-/) -/'
        elif [ "$PARAM2" ]; then
          apropos $line | egrep "^\b$line\b" | grep "\(3\)" | sed "s/.*(/$line(/" | sed 's/).*-/) -/'
        elif [ "$PARAM3" ]; then
          apropos $line | egrep "^\b$line\b" | grep "\(2\)" | sed "s/.*(/$line(/" | sed 's/).*-/) -/'
        fi
      fi
    done
  fi
fi
#### a zase po sobe uklidime
rm -f $TEMP

exit 0


