#include <iostream>
#include <unistd.h>
#include <sys/wat.h>
#include <cstdlib>
using namespace std;

int main(){
	cout<<"\n==================================================\n";
	cout<<"   [***] PROCESS STATE SIMULATOR [***]\n";
	cout<<"==================================================\n\n";
	pid_t parent_pid=getpid();
	cout<<"[MAIN] The central parent started with PID: "<<parrent_pid<<"\n\n";
	//1. ZOMBIE (State Z)
	//Δημιουργουμε ενα παιδι που τερματιζει αμεσως αλλα ο γωνεας δεν καλει την wait()
	pid_t pid_zombie=fork();
	if(pid_zombie==0){
		cout<<"  [+] ZOMBIE (Z): The child (PID: "<<getpid()<<") dies immediately!\n";
		_exit(0);
	}
	//2. SLEEPING (State S)
	//Ενα παιδι που απλα κοιμαται περιμενοντας να περασει ο χρονος
	pid_t pid_sleep=fork();
	if(pid_sleep==0){
		cout<<"  [+] SLEEPING (S): The child (PID: "<<getpid()<<") falls asleep for 100 seconds.\n";
		sleep(100);
		_exit(0);
	}
	//3. RUNNING (State R)
	//Ενα παιδι που απασχολει διαρκως τον επεξεργαστη με μια απειρη λοοπα
	pid_t pid_run=fork();
	if(pid_run==0){
		cout<<"  [+] RUNNING (R): The child (PDI: "<<getpid()<<") runs constantly in a loop!\n";
		while(true){}
	}
	//4. ORPHAN
	//Οταν ο γονεας πεθαινει πριν απο το παιδι
	pid_t pid_middle_parent=fork();
	if(pid_middle_parent==0){
		pid_t pid_orphan=fork();
		if(pid_orphan==0){
			cout<<"  [+] ORPHAN (S/R): The child (PID: "<<getpid()<<") was born. It's parent will leave it!\n";
			sleep(100);
			_exit(0);
		}
		_exit(0);
	}
	sleep(1);
	cout<<"\n====================================================\n";
	cout<<"[!] The processes are running! [!]\n";
	cout<<"Run NOW the following command: \n\n";
	cout<<"     ps -edaf | grep simulator\n\n";
	cout<<"If you want to see the STAT codes (R, S, Z) more clearly:\n";
	cout<<"     ps -u $USER -o pid,ppid,stat,comm | grep simulator\n\n";
	cout<<"(The programm will finish automatically in 60 seconds...)\n";
	cout<<"====================================================\n";
	sleep(60);
	kill(pid_run,SIGKILL);
	cout<<"\n[MAIN] End of simulation. All processes cleared from the system.\n";
	return 0;
}
