Search code examples
cliststructsemantics

semantic error in code


I've written a shell that has some basic features. It shall have an process list in which every executed process is listed. I write these informations in a struct called Pstatus. Pstatus will be written into a global list. If I try to read from this list in getStatus() the Informations don't work. I get some symbols but not the informations. If I do exact the same process in the function where I write the informations into this global list, I get the right informations. I don't know whats wrong with my list.

http://pastebin.com/XGVZcSB4

Informations are written into aufruf() line 203 into the table (proctable).

In getStatus() line 311 I want to have the Information

I've got the struct

typedef struct {
int pid;        /* Prozess ID */
char* name;     /* Prozess Name (Programm) */
char* status;   /* Status des Programms */
int check;      /* bereits abgerufen? 1 - abgerufen, 0 - nicht abgerufen */
} Pstatus;

Listen:

typedef struct liste {
  void *kopf;
  struct liste *rest;
} *Liste;

listeKopf:

void* listeKopf(Liste l) { 
  if(l==NULL)
    abbruch("listeKopf(listeLeer) undefiniert");
  return l->kopf; 
}

listeAnfuegen:

Liste listeAnfuegen(Liste l, void* element){
  Liste neu=reserviere(sizeof (struct liste));
  neu->kopf = element;
  neu->rest = l;
  return neu;
}

Anybody able to help me?

edit! code:

            #include <unistd.h>
            #include <stdlib.h>
            #include <stdio.h>
            #include <string.h>
            #include <unistd.h>
            #include <sys/types.h>
            #include <sys/wait.h>
            #include <fcntl.h>
            #include <errno.h>


            #include "utils.h"
            #include "listen.h"
            #include "wortspeicher.h"
            #include "kommandos.h"
            #include "frontend.h"
            #include "parser.h"
            #include "variablen.h"

            int interpretiere(Kommando k, int forkexec);
            int interpretiere_einfach(Kommando k, int forkexec);
            int getStatus();

            Liste procTable;

            void do_execvp(int argc, char **args){
              execvp(*args, args);
              perror("exec-Fehler"); 
              fprintf(stderr, "bei Aufruf von \"%s\"\n", *args);
              exit(1);
            }

            int interpretiere_pipeline(Kommando k){
              /* NOT IMPLEMENTED */

                int fd1[] = { -1, -1 };
                int fd2[] = { -1, -1 };
                int i = 0;
                int status = 0;
                int pid = -2;
                Liste l = k->u.sequenz.liste;
                Kommando ko;
                Pstatus pDesk;
                int laenge = k->u.sequenz.laenge;

                printf("Länge: %i!\n", laenge);

                for (i = 0; i < laenge; i++) {
                    ko = (Kommando) listeKopf(l);
                    fd2[0] = fd1[0];
                    fd2[1] = fd1[1];

                    if (i > 0) {
                        close(fd2[1]);
                    }

                    if (pipe(fd1) < 0) {
                        perror("Pipe-Fehler");
                        exit(1);
                    }
                    pid = fork();

                    switch (pid) {
                    case -1:
                        perror("Fehler bei fork");
                        return (-1);
                    case 0:
                        /*1. Prozess? Dann den Lesestrom von FD2 nicht umlegen.:*/
                        if (fd2[0] != -1) {
                            dup2(fd2[0], STDIN_FILENO);
                        }

                        /*Letzter Prozess? Dann den Schreibstrom von FD1 nicht umlegen:*/
                        if (i < laenge - 1) {
                            dup2(fd1[1], STDOUT_FILENO);
                        }
                        interpretiere_einfach(ko, 0);
                        exit(1);
                        break;
                    default:
                        /*pDesk = erzeugeProzess (pid, k->u.einfach.worte[0], "RUNNING"); 
                        procTable = listeAnfuegen(procTable, &pDesk); */
                        pDesk = erzeugeProzess( pid, "test", "RUNNING");
                        procTable = listeAnfuegen(procTable, &pDesk);

                        sleep(1);
                        break;
                    }
                    l = listeRest(l);
                }
                return status;
            }

            int umlenkungen(Kommando k){
                Umlenkung *u;       /* Objekt vom Typ Umlenkung (kommandos.h) */
                Modus modus;        /* Objekt vom Typ Modus (kommandos.h) */
                Liste neueListe;    /* Objekt vom Typ Liste (listen.h) */
                FILE *f;            /* File zum erstellen einer eventuellen Datei */    
                /*int fd;           Filedescriptor zum Überprüfen der Datei*/
                char *pfad;         /* Pfad und Dateiname der Datei */

                /**
                typedef     struct {
                    int         filedeskriptor;  beliebige Deskriptoren können umgelenkt werden 
                    Modus       modus;           Umlenkungsart 
                    char *      pfad;            Datei von der / in die umgelenkt wird 
                } Umlenkung; 
                * */ 
                /*
                 *  Wenn Umlenkungen vorhanden sind, hole die Umleitungen aus der Liste
                 *  und wandle sie um in ein struct Umleitungen
                 **/
                if(k->u.einfach.umlenkungen != NULL){
                    fprintf(stdout, "Es sind Umleitungen vorhanden\n");
                    neueListe = k->u.einfach.umlenkungen;

                    u = (Umlenkung *) neueListe->kopf;
                    modus = u->modus;   /* Modi: read, write, append*/
                    pfad = u->pfad;     /* Pfad zur Datei*/


                    /* Modi definiert in kommandos.h */
                    switch(modus) {
                    case READ: /* stellt die Standarteingabe auf die angegeben Datei 'pfad'*/
                        fprintf(stdout, "Modus Read\n");
                        if(freopen(pfad, "r", stdin) == NULL){
                            fprintf(stderr, "Fehler beim Lesen der Datei. \nErrno: %d \n", errno);
                            return 1;
                        }
                        break;

                    case WRITE: /* Standartausgabe wird auf die Datei Pfad gestellt. Existiert die Datei noch nicht, wird sie erstellt. */
                        fprintf(stdout, "Modus Write\n");
                        /*fd = open(pfad, O_RDWR | O_CREAT | O_TRUNC, S_IWGRP | S_IRGRP | S_IXGRP);
                            if(fd == -1) {
                                fprintf(stdout, "Fehler beim Erstellen der Datei.\n Errno: %d", errno);
                            exit(1);
                        }*/
                        if ((f = fopen(pfad, "w+")) == NULL) {
                            fprintf(stderr, "Fehler beim Erstellen der Datei. \nErrno: %d \n", errno);
                            return 1;
                        } 
                        if(freopen(pfad, "w", stdout) == NULL){
                            fprintf(stderr, "Fehler beim Erstellen der Datei. \nErrno: %d \n", errno);
                            return 1;
                        }
                        break;

                    case APPEND: 
                        fprintf(stdout, "Modus Append\n");
                        /*fd = open(pfad, O_RDWR | O_CREAT | O_APPEND, S_IWGRP | S_IRGRP | S_IXGRP | S_IWUSR | S_IRUSR | S_IXUSR | S_IWOTH | S_IROTH | S_IXOTH);
                            if(fd == -1) {
                                fprintf(stdout, "Fehler beim Erstellen der Datei");
                            exit(1);
                        }*/
                        if ((f = fopen(pfad, "a+")) == NULL) {
                            fprintf(stderr, "Fehler beim Erstellen der Datei. \nErrno: %d \n", errno);
                            return 1;
                        } 
                        if(freopen(pfad, "a", stdout) == NULL){
                            fprintf(stderr, "Fehler beim Erstellen der Datei. \nErrno: %d \n", errno);
                            return 1;
                        }
                        break;

                    default:
                        fprintf(stderr, "Modus default.\n No Options defined for default.\n");
                        fprintf(stdout, "Modus default nicht verfuegbar.\n");
                        break;
                    }

                }
              return 0;
            }

            int aufruf(Kommando k, int forkexec){

                Pstatus p;
                Pstatus *test;
                int kind_status, i;

              /* Programmaufruf im aktuellen Prozess (forkexec==0)
                 oder Subprozess (forkexec==1)
              */

              if(forkexec){
                int pid=fork();

                switch (pid){
                case -1:
                  perror("Fehler bei fork"); 
                  return(-1);
                case 0:
                  if(umlenkungen(k))
                exit(1);
                  do_execvp(k->u.einfach.wortanzahl, k->u.einfach.worte);
                  abbruch("interner Fehler 001"); /* sollte nie ausgeführt werden */
                default:
                  if(k->endeabwarten) {
                      /* So einfach geht das hier nicht! */

                      /* schreibt die PID, den Namen und den Status in die Tabelle */  
                      p = erzeugeProzess (pid, k->u.einfach.worte[0], "RUNNING"); /*k->u.einfach.worte[0] */
                      /* Debug: print
                      printf("\npid: %d\tstatus: %s\n", p.pid, p.status); 
                      */
                      i = listeLaenge(procTable);
                      procTable = listeAnfuegen(procTable, &p);
                      if(listeLaenge(procTable) <= i) {
                        fprintf(stderr, "Fehler beim Schreiben in die Liste!");
                      }

                      /* Debug printf: Bis hierhin wird alles ordentlich in die Liste geschrieben!
                      test = listeKopf(procTable);
                      printf("\npid: %d\tstatus: %s\n", test->pid, test->status); 
                      */

                      waitpid(pid, &kind_status, 0);
                        if(WIFEXITED(kind_status)){
                            printf("Kind mit der PID %d wurde beendet\n",pid);
                        }
                        else if(WIFSIGNALED(kind_status)){
                            printf("Kind mit der PID %d wurde durch Signal abgebrochen. Signalnummer: %d\n",pid, WTERMSIG(kind_status));
                        }
                  }
                  else {
                    fprintf(stderr, "Programm nicht beendet\n");
                    fprintf(stdout, "PID: %i\n", pid);
                  }  
                  return 0;
                }
              }

              /* nur exec, kein fork */
              if(umlenkungen(k))
                exit(1);
              do_execvp(k->u.einfach.wortanzahl, k->u.einfach.worte);
              abbruch("interner Fehler 001"); /* sollte nie ausgeführt werden */
              exit(1);
            }


            int interpretiere_einfach(Kommando k, int forkexec){    

              char **worte = k->u.einfach.worte;
              int anzahl=k->u.einfach.wortanzahl;

              if (strcmp(worte[0], "exit")==0) {
                switch(anzahl){
                case 1:
                  exit(0);
                case 2:
                  exit(atoi(worte[1]));
                  printf("Dies ist ein test");
                default:
                  fputs( "Aufruf: exit [ ZAHL ]\n", stderr);
                  return -1;
                }
              }

              if (strcmp(worte[0], "cd")==0) {
                switch(anzahl){
                case 1:
                  return chdir(getenv("HOME"));
                case 2:
                  return chdir(worte[1]);
                default:
                  fputs("Aufruf: cd [ PFAD ]\n", stderr);
                  return -1;
                }
              }

              /* gibt den Status der Subprozesse zurück */
              if (strcmp(worte[0], "status")==0){

                  /* NYI */
                getStatus();

              }

              return aufruf(k, forkexec);
            }

            int getStatus() {

                Pstatus *p;
                Liste temp;

                fprintf(stdout, "---------------------\n----Statustabelle----\n---------------------\n");

                temp = procTable;

                printf("laenge der liste: %d\n",listeLaenge(temp));


                /*fprintf(stdout, "Pid: %d", p->pid);*/



                if(listeLaenge(temp) < 1) {
                    fprintf(stdout, "Liste ist leer.\n");
                    return 0;
                }


                while(temp != NULL){

                    /*fprintf(stdout, "%s", listeKopf(temp));  */
                    p = listeKopf(temp);

                    /*if(p->check < 1) {*/
                    fprintf(stdout,"PID: %d, Programm: %s, Status: %s\n",p->pid, p->name, p->status);
                    /*} */

                    /* wenn status != running -> p.checked() */

                    temp = listeRest(temp);
                  }
                return 0;
            }

            int interpretiere(Kommando k, int forkexec){
              int status;

              switch(k->typ){
              case K_LEER: 
                return 0;
              case K_EINFACH:
                return interpretiere_einfach(k, forkexec);
              case K_SEQUENZ:
                {
                  Liste l = k->u.sequenz.liste;
                  while(!listeIstleer(l)){
                    status=interpretiere ((Kommando)listeKopf(l), forkexec);
                    l=listeRest(l);
                  }
                }
                return status;
              /* 
               * Status wird auf 0 gesetzt. While Schleife arbeitet Befehle 
               * ab solange der return Wert (status) 0 ist. 
               * Erreicht der status den Wert ungleich 0, wird die Funktion mit 
               * return 1 abgebrochen.
               **/
              case K_UND:
               {
                  Liste l = k->u.sequenz.liste;
                  status = 0; 
                  while(!listeIstleer(l) && status == 0){
                    status=interpretiere ((Kommando)listeKopf(l), forkexec);
                    l=listeRest(l);
                    if(status != 0) {
                        return 1;
                    }
                  }
                   /*printf("UND noch nicht implementiert");*/   
               }
               return 0;
              /* 
               * Status wird auf 1 gesetzt. While Schleife arbeitet Befehle 
               * ab solange der return Wert (status) nicht 0 ist. 
               * Erreicht der status den Wert 0, wird die Funktion mit return 1 
               * abgebrochen.
               **/
              case K_ODER:
               {
                  Liste l = k->u.sequenz.liste;
                  status = 1; 
                  while(!listeIstleer(l) && status != 0){
                    status=interpretiere ((Kommando)listeKopf(l), forkexec);
                    l=listeRest(l);
                    if(status == 0) {
                        return 1;
                    }
                  }
                   /*printf("ODER noch nicht implementiert");*/
               }
               return 0;
              /* 
               * UND Befehl. Noch nicht implementiert! 
               * return Wert überarbeiten! 
               **/
              case K_PIPE:
               {
                   /*printf("Pipeline noch nicht implementiert");*/
                   return interpretiere_pipeline(k);
               }
               return 0;
              default:
                fputs("unbekannter Kommandotyp, Bearbeitung nicht implementiert\n", stderr);
                break;
              }
              return 0;
            }

Solution

  • It seems that you are adding a local variable to your global procTable list. This happens in your interpretiere_pipeline function at line 83. pDesk is a local variable, and the C compiler puts those in the stack. When the current function returns, that memory frame will get deallocated and occupied by whatever happens to be called next.

    A solution to your problem is to have pDesk allocated on the heap. This way, in your list will store and address that you know is always valid.

    Hope this helps,

    -Caius