Fragen zur Programmieraufgabe Februar 2003

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Fragen zur Programmieraufgabe Februar 2003

  1. Wie habt ihr das Löschen der ausgeführten Datei implementiert? Habe überlegt, eine Liste mit zu löschenden Dateien an zu legen…

  2. Was soll in den SIG_USR1 Signalhandler rein? Ich finde nichts, was man da machen könnte…

  3. Wenn ich den Code compilieren möchte, ohne die zusätzlichen Header ein zu binden, kann ich nicht forken… Ist das ein Fehler der Klausur???

  4. Darf ich in der Klausur z.B. exit(EXIT_FAILURE) oder term(“Aus iss”) benutzen, weil die ja zusätzliche Header brauchen, aber eigentlich für eine gute Lösung wichtig wären…

  5. Wie kann ich Dateinamen auf das Muster “cfxyz” : x,y,z element [0,9] prüfen, ohne mega Aufwand???

Genug der Fragen, hier mein Code:

#include <stdio.h>
#include <dirent.h>
#include <signal.h>
#include <errno.h>

// Müssen zusätzlich für fork included werden...
#include <sys/types.h>
#include <unistd.h>

#define MAXBUFLEN 1023

void handler_SIGUSR1(int signal);
void execute_job(char *filename);

int main(int argc, char **argv){

//Variablen und ...
struct sigaction myaction;
sigemptyset(&myaction.sa_mask);
myaction.sa_flags = 0;
myaction.sa_handler = handler_SIGUSR1;


//Signalhandler einrichten

if((sigaction(SIGUSR1, &myaction, NULL)) == -1)
	exit(-1);


//Hauptschleife
while(1 == 1){
	DIR *dir;
	struct dirent *myentry;
	dir = opendir(argv[1]);

	sigset_t myset;
	sigemptyset(&myset);
	sigaddset(&myset, SIGUSR1);

	//Signalmaske setzen
	if((sigprocmask(SIG_BLOCK, &myset, NULL)) == -1)
		exit(-1);
	while((myentry = readdir(dir)) != NULL){
	//Entspricht Datei dem Schema?
	if(myentry->d_name[0] == 'c' && myentry->d_name[1] == 'f'
			//& weitere Kriterien
		)
		//Gut, jetzt ausführen
		execute_job(myentry->d_name);


	};
	sigprocmask(SIG_UNBLOCK, &myset, NULL);
	//Schlafen legen
	if(sigsuspend(&myset) == -1)
		exit(-1);
}
}

void handler_SIGUSR1(int signal){
	//Was könnte man hier machen???


}

void execute_job(char *filename){

	FILE *myfile;
	int status;
	pid_t mypid;

//Datei öffnen, Kommando einlesen
	if((myfile = fopen(filename, "r")) == NULL){
		printf("Tried to open file %s ...", filename);
		return;
	}
//Prozess für Kommandoausführung
	mypid = fork();
	switch(mypid){
//Fehler bei Prozesserzeugung
	case -1:
		printf("fork-problem");
		exit(-1);
//Sohnprozess
	case 0:
		if((execlp(filename, NULL) == -1))
			perror("Couldn't execute command");
		exit(-1);

//Vaterprozess
	default:
		return;
	}
}

deine schleife sollte so aussehen:

while(1) {

while(x=readdir!=NULL){
/* Was da halt so anfällt */
}
peter=1;
while(PETER){
}
}

Und der Sighandler setzt einfach Peter=0.


der vaterprozess warten mit wait () auf den kindstod - dann ein unlink () der datei.

ja, da hab ich auch nichts. evtl. koennte man das blockieren mit sigprocmask () da reintun… oder?

ich behaupte, dass man sich nicht nach den headern richten kann. mit 4 headern kann man kein richtiges programm programmieren…

unwichtig, siehe anderer thread, lesefehler deinerseits. in der angabe steht „cfxxx“, „xxx steht fuer eine beliebige zeichenfolge“.

	sigset_t myset;
	sigemptyset(&myset);
	sigaddset(&myset, SIGUSR1);

	//Schlafen legen
	if(sigsuspend(&myset) == -1)
		exit(-1);

das stimmt glaube ich nicht, da brauchst du ein extra sigset_t fuer das suspend. so wie du es hast, blockiert es naemlich SIGUSR1 und wacht damit nicht bei einem SIGUSR1 auf, dafuer bei allen anderen signalen. ich hab einfach ein leeres set angegeben, damit er bei allen signalen aufwacht - auch aus dem grund, damit ich ihn mit ctrl+c wieder killen kann.

gruss,
-steppenwolf


Wieso das denn? Da steht doch man soll während das Prog arbeitet SIGUSER blockieren, das kann er doch mit sigprocmask machen. Wenns durchs Verzeichnis gerumpelt ist, deblockiert er ja das Signal und kann somit das SIGUSER empfangen.

Noch eine Frage: Muss man da nicht aus dem übergebenen Pfad und den Namen der Dateien einen kompletten Pfad+DAteiname bauen (fürs fopen und execlp) ?


ja glaub ich schon… ich habs gemacht, aber nur fürs fopen, beim execlp greift er auf PATH zu… so wie ich das verstanden hab.

das signal hab ich erst mit sigprocmask(SIG_BLOCK,…) blockiert und dann mit sigprocmask(SIG_UNBLOCK,…) deblockiert… sigsuspend spar ich mir (wie robert :smiley: ) dadurch dass ich ne schleife bau die durch ein signal verlassen wird … is zwar nich so schick aber geht

… ach ja ich hab execvp genommen mit execvp(befehl,NULL) müsste doch gehn, weil ja keine parameter erlaubt sind…


[quote=snehls]… ach ja ich hab execvp genommen mit execvp(befehl,NULL) müsste doch gehn, weil ja keine parameter erlaubt sind…
[/quote]

So geht das nicht, du muesstest dir ein char * array bauen mit array[0] = command und array[1] = null und dann execvp(array[0] bzw. command, array) so ausführen


es geht um das sigsuspend, die sigprocmasks passen schon. sein sigsuspend wacht bei einem siguser eben nicht auf.


So geht das nicht, du muesstest dir ein char * array bauen mit array[0] = command und array[1] = null und dann execvp(array[0] bzw. command, array) so ausführen
[/quote]

ich behaupte mal dass man sich das array auch sparen kann wenn man exeplp benutzt und dann halt sacht execlp(befehl,befehl,NULL); Bei dem Befehl kann man netterweise die Elemente des argv einzeln angeben. spart in sonem fall wo man eh nur ein Argument hat - das programm - arbeit. :gun:

EDIT: ich glaube auch dass man bei execvp und execlp nur einfach das kommando ohne den kompleten pfad angeben kann weil das ueber PATH gesucht wird wenn es nicht im cwd liegt (siehe dazu die man page)


wie macht man das dann mit dem wait wie oben beschrieben für den Vaterprozess?

waitpid(pid, ?, WNOHANG) ?


Ich hab ein Problem mit execlp.
Mein bisheriger Aufruf:

fgets(befehl, PUFFER, stream);
...
execlp(befehl, NULL);

Die Fehlermeldung beim ausfuhren ist dann:

Fehler bei execlp: No such file or directory

In meiner Datei (cf123) steht nur mozilla, das wird auch richtig ausgelesen.


im Vater: wait(NULL); unlink(file);

nix nur return - das Signal muss aber abgefangen werden, damit der Prozess daran
aufwacht. Ignorieren taet nicht helfen und bei default wuerde er sterben.

komisch, ich hab’ das damals unter Solaris programmiert
und natuerlich nicht tausend Optionen beim compilieren angegeben -
vermutlich wurden die beiden fehlenden includes da irgendwo
indirekt mit reingeholt.

wenn man meint zusaetzliche Header zu brauchen kann man die
einfach dazuschreiben. Es gibt nie nur eine voellig korrekte Loesung
fuer die Aufgaben.

hat Steppenwolf schon beantwortet

In den folgenden Code schreib’ ich meine Kommentare in >>>>> <<<<<

// ist nicht C!


\n aus Puffer rausgemacht???


Steppenwolf hat recht:
wenn er im sigsuspend schlaeft wacht er durch blockierte Signale
nciht auf. Siehe auch meine Anmerkdung im anderen Posting im Code
an der Stelle

Nur fuers fopen - und dann fuer’s unlink!
Das execlp wird ja auf das gemacht was in der Datei drin steht - nicht
auf die Datei selbst.


@juk: da hat sich aber einer muehe gemacht beim kommentieren der verbesserungen!

trotzdem noch eine kleine frage zur schleife:
im moment ist innerhalb des durchlaufs sowohl opendir () als auch closedir ().

ich hab das opendir () aber vor der schleife (IMHO auch das einzig sinnvolle), aber da ich in einer endlosschleife bin, die sowieso nur mit einem SIGINT abgebrochen werden kann, mache ich kein closedir () mehr - ist das auch ok?


Moin!

Ich hab bisher gedacht, dass man das nur abprüfen muss, wenns explizit in der Aufgabenstellung steht, weils bei manchen Klausuren extra angegeben ist, bei der Feb03 allerdings nicht. Also immer abprüfen, ob die korrekte Anzahl der Argumente übergeben wurde, auch wenns nicht explizit dasteht?

Da WELL '4


dann aber rewinddir in der Schleife - sonst bekommt man neue Auftraege
nicht mit. Dann ist’s aber ok - und eigentlich sogar besser.
Da wir rewinddir in den uebungen nicht gemacht haben, hab’ ich auf
das Verteilen der entsprechenden man-page verzichtet. opendir
und closedir tun letzlich ja das gleiche.


das hat nix damit zu tun ob’s da steht oder nicht, sondern eher damit, was mit
dem argv[1] hinterher macht.
Das kommt einfach nicht so gut, wenn man ein opendir auf argv[1] macht
und das war dann NULL.


ja, das hat mich auch etwas zeit gekostet, bis ich das verstanden habe,
warum er manche neuen auftraege verarbeitet und manche nicht…

aber ist eigentlich logisch, dass es etwas wie rewinddir () und zugehoerig
eine laufvariable fuer den katalog geben muss, schliesslich kann readdir ()
auch nicht zaubern und jedes mal „zufaellig“ den richtigen naechsten
eintrag ausgeben.


137 //Datei öffnen, Kommando einlesen
138 if((myfile = fopen(filename, “r”)) == NULL){
139 printf(“Tried to open file %s …”, filename); <<<besser perror!!!>>>
140 return;
141 }
142 <<<<<<<<<<<<<<<
143 Kommando in Puffer einlesen fehlt
144 fgets und dann hinten das ‘\n’ aus dem Puffer rausmachen
145 das execlp dann natuerlich nicht auf filename sondern auf den Puffer
146 >>>>>>>>>>>>>>>>>>>>>

erstmal bin ich wirklich froh über diesen aufschlussreichen thread, daher mein dank an alle beteiligten! :wink:
das einzige was mir jetzt noch unklar ist, warum man den file nicht einfach mithilfe myfile = fopen(filename, “r”)) == NULL öffnen kann, sondern einen Puffer braucht.
Wenn mir das noch einer erklören könnte! :rolleyes: