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.
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;
}
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