Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //fragen / logout braucht mehrere aufrufe wenn davor ungültige eingabe war (z.B. asdf)
- #include <cstdlib>
- #include <stdio.h>
- #include <iostream>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sstream>
- #include <cstring>
- #include <vector>
- #include <signal.h>
- using namespace std;
- pid_t pid; //globale variable als übergabeparameter für handler, handler braucht PID
- pid_t pid_stopped;
- pid_t parentid;
- void handle_SIGTSTP(int signum){ //normalerweise: stop/abbruch von FG prozess durch ctrl-z, z.B. sleep
- cout << "caught SIGTSTP" << endl;
- cout << pid << endl;
- pid_stopped=pid; //pid_stopped erhält die PID von gedit/firefox
- kill(pid_stopped,SIGSTOP); //hält gedit/firefox an
- return;
- }
- void handle_SIGINT(int signum){ //ausschließlich tastaturinterrupt durch ctrl-c
- cout << "SIGINT aufgerufen " << endl;
- kill(pid_stopped,SIGINT); //gedit/firefox wird SIGINT zugestellt, dadurch wird es beendet
- return;
- }
- void handle_SIGCHLD_zombiekiller(int signum){ //beim Beenden von Kindprozess,z.B. gedit aufgerufen
- int stat;
- while(waitpid(-1, &stat, WNOHANG) > 0); //löscht Zombies aus table / wartet bis sie weg sind
- //WNOHANG verhindert, dass handler blockiert wenn SIGCHILD aus anderen gründen aufgerufen wird
- //http://www.microhowto.info/howto/reap_zombie_processes_using_a_sigchld_handler.html
- return;
- }
- int main(int argc, char** argv) {
- char* inputorg;
- string s;
- vector<pid_t>programme;
- do{
- cout << "debian@:myShell$ ";
- //handlerdeklaration für SWI
- signal(SIGINT,handle_SIGINT);
- signal(SIGTSTP,handle_SIGTSTP);
- signal(SIGCHLD,handle_SIGCHLD_zombiekiller);
- getline(cin,s);
- const char* cc=s.c_str();
- inputorg=const_cast<char*>(cc);
- int run_background=0;
- vector<char*>substrings;
- char* input=strtok(inputorg, " ");
- while (input)
- {
- if (strncmp(input,"&",1)==0)
- {
- run_background = 1;
- break;
- }
- substrings.push_back(input);
- input = strtok(NULL," ");
- }
- substrings.push_back(NULL); //letzte parameter muss immer NULL sein
- if(substrings[0]==NULL){
- substrings[0]="error";
- substrings.push_back(NULL);
- }
- char* param[substrings.size()]; //gleiche größe wie vector
- for(int i=0;i<substrings.size();i++){ //kopiere vector in param
- param[i]=substrings[i];
- }
- // PARSING DONE
- if(strncmp(param[0],"fg",2)==0){
- kill(pid_stopped,SIGCONT); //führt gedit/firefox fort
- waitpid(pid_stopped, 0, WUNTRACED); //wartet auf beendigung von gedit/firefox
- }else if(strncmp(param[0],"bg",2)==0){
- kill(pid_stopped,SIGCONT); //gleiche wie fg, nur wartet nicht, sondern lässt im hintergrund laufen
- }else{
- pid=fork();
- parentid=getppid();
- if(pid==0){ //wenn im child prozess
- int mypid=getpid();
- programme.push_back(mypid); //speichert alle PIDs von aufgerufenen funktionen
- setpgid(mypid,mypid);
- execvp(param[0],param);
- }
- if(run_background!=1){
- int status;
- waitpid(pid,&status,WUNTRACED); //bei & nicht auf childprozess warten
- }
- }
- }while(s!="logout");
- for(int i=0;i<programme.size();i++){ //sollte theoretisch alle prozesse beenden, beendet aber nur letzten..
- pid_t temppid=programme[i];
- kill(temppid,SIGINT); //SIGINT beendet prozess
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement