#!/bin/bash

# Patryk Czarnik
# Zadanie nr 1 z Systemow Operacyjnych
# wersja z sygnalem

# Skrypt dziala w petli nieskonczonej co N sekund za pomoca programu
# who sprawdzajac na ktorych sesjach zalogowany jest uzytkownik.
# Dla kazdej sesji tworzona jest lokalna zmienna o nazwie zaleznej
# od nazwy sesji (POCZ<nazwa sesji>), do ktorej zapisywany jest czas
# zalogowania. Sesje, na ktorych zalogowany jest uzytkownik (zmienna
# Teraz) porownywane sa z sesjami, na ktorych byl zalogowany poprzednio
# (Ostatnio). Dla nowych dodawana jest odpowiednia zmienna, dla
# zakonczonych do zmiennej ZakonczoneSesje dopisywany tekst z
# informacja o tej sesji i usuwana zmienna.
# Do wypisania w wyniku aktualnie uruchomionych sesji i przy dopisywaniu
# zakonczonych do ZakonczoneSesje korzysta sie ze zmiennych POCZ...

# Skrypt przechwytuje sygnal SIGUSR1 i w przypadku jego pojawienia sie
# wypisuje informacje na standardowe wyjscie.

# Skrypt uruchomiony z opcja -show wysyla sygnal SIGUSR1 do wszystkich
# procesow danego uzytkownika o nazwie logstat. Jesli dziala gdzies
# logstat, to wypisze wyniki.

# Skrypt wypisuje wyniki na swoje standardowe wyjscie, a wiec uruchomienie
# -show na innej konsoli spowoduje wypisanie wyniku nie tam, gdzie pewnie
# jest to oczekiwane. Jeszcze gorzej, jesli skrypt straci powiazanie
# z jakakolwiek konsola (np. przez wylogowane sie) - wtedy nic juz nie
# wypisze.

function spowoduj_wypisanie()
{
# Wysyla sygnal SIGUSR1 do wszystkich procesow o nazwie logstat
# uruchomionych przez biezacego uzytkownika, takze do siebie samego,
# ale skrypt uruchomiony z -show nie ma ustawionego trap.

  pidLogstat=`ps --user $USER | grep logstat | cut -c1-5`
  echo $pidLogstat
  kill -SIGUSR1 $pidLogstat
}

function wypisz_wyniki()
{
# Wypisuje wyniki na standardowe wyjscie
  echo "Sumaryczny czas pracy: $CzasSumaryczny sekund"
  echo "Rozpoczete sesje:"
  for sesja in $Ostatnio
  do
    echo "$sesja od "`daj_wart_zmiennej 'POCZ'$sesja`
  done
  echo -e "Zakonczone sesje:\n"$ZakonczoneSesje
}

function daj_wart_zmiennej()
{
# Na wyjsciu daje wartosc zmiennej o nazwie okreslonej przez pierwszy parametr
 eval echo '$'$1
}

# Poczatek skryptu #
# Sprawdzenie parametrow
if [ $# -eq 0 ]
  then
# domyslny odstep czasu
    N=3
  else
    if [ $# -eq 1 ]
      then
        if [ $1 = "-show" ]
          then
	    spowoduj_wypisanie
            exit
          else
# odstep czasu wczytany z parametru
	    N=$1
        fi
      else
        exit
    fi
fi

CzasSumaryczny=0
# Ta zmienna bedzie trzymala sumaryczny czas pracy
ZakonczoneSesje=""
# Tu napis mowiacy o zakonczonych sesjach
Ostatnio=""
# A ta nazwy sesji, na ktorych uzytkownik byl zalogowany podczas poprzedniego
# obrotu petli.
OstatniCzas=0
# Czas systemowy w sekundach od... ktory byl przy ostatnim obrocie petli

# Sygnal SIGUSR1 spowoduje wypisanie wynikow,
# pozostale, standardowe sygnaly dzialaja normalnie
trap "wypisz_wyniki" SIGUSR1

# Skrypt dziala w petli nieskonczonej
while true; do

TerazCzas=`date +%s`
Minelo=$(($TerazCzas - $OstatniCzas))
# W zmiennej Teraz bedzie lista nazw sesji, na ktorych uzytkownik jest
# aktualnie zalogowany
  Teraz=`who | grep $USER | cut -c10-18`

# Dla kazdej sesji...
  for sesja in $Teraz
  do
# Jesli ostatnio jej nie bylo, to pod zmienna POCZ<nazwa sesji>
# zapisuje biezacy czas jako czas jej rozpoczecia (z dokl. do dlugosci petli)
    if echo $Ostatnio | grep $sesja > /dev/null
      then
        :
      else
        "POCZ$sesja"=`date +%H:%M:%S`
    fi
  done
  
  for sesja in $Ostatnio
# Dla kazdej sesji, ktora byla ostatnio...
  do
# Do czasu sumarycznego dodaje odstep czasowy od ostatniego obrotu
    CzasSumaryczny=$(($CzasSumaryczny + $Minelo))
# Jesli tej sesji nie ma juz teraz, do zmiennej ZakonczoneSesje dopisuje
# odpowiednia informacje i usuwam zmienna POCZ<nazwa sesji>
    if echo $Teraz | grep $sesja > /dev/null
      then
        :
      else
        ZakonczoneSesje="$ZakonczoneSesje$sesja, od "`daj_wart_zmiennej 'POCZ'$sesja`" do "`date +%H:%M:%S`"\n"
	unset "POCZ$sesja"
    fi
  done
  Ostatnio=$Teraz
  OstatniCzas=$TerazCzas
  sleep $N
done
