Aufgabe 4 - maxline & maxarg

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.

aufgabe 4 - maxline & maxarg
hi,

wie ich die maximale anzahl an zeichen in einer shellzeile und die maximale anzahl der parameter, die ich einer funktion uebergeben kann, ermitteln kann, habe ich schon rausgefunden. konkret ist ersteres bei mir 2048 und letzteres ~ 130000. hat das sinn, so viele pointer zu allokieren, obwohl man bei 2048 zeichen schlecht 130000 parameter uebergeben kann? oder sollte man (maxline / 2) pointer allokieren, was ja das theoretische maximum ist…?


naechste frage:
was soll die mysh ausgeben, wenn ein unbekanntes programm aufgerufen wird? bei mir macht sie im moment folgendes:

mysh> dfslk
execvp (): Aufruf fehlgeschlagen: No such file or directory
Exitstatus [dfslk] = 1

passt das?


  1. ich frag mich grad wie du auf die 130000 kommst, aber egal. Speicher allokieren musst du logischerweise erst, wenn du den Speicher auch brauchst, bzw. wenn du neuen Speicher brauchst.
    Fuer des parsen gibts eine Funktion namens strtok, allerdings faellt man da garantiert auf die Schnauze, wenn man nicht genau versteht was die macht und wie sie das macht.
  2. Das ein Benutzer in einer shell einen falschen Befehl eingibt ist was ziemlich alltaegliches, dass das in C mit einem execvp zusammenhaengt kann ihm eigentlich egal sein, von daher wuerde “no such file or directory” reichen. Kannst aber auch so lassen, das macht sowieso ein perror oder?
    Der Exitstatus ist dann aber fast nimmer interessant, das ist ja nicht der Exitstatus des Programmes (das du mit exec ersetzen wolltest) sondern das exit(EXIT_FAILURE); deines child.

printf ("argmax: %li",  sysconf (_SC_ARG_MAX));

gibt aus:

argmax: 131072

oder ist das das falsche makro?

hmm, aber ich weiss doch vorher nicht, wieviele argumente der benutzer eingeben wird. soll ich dann jedesmal dynamisch mit realloc () speicher nachfordern? wahrscheinlich schon, oder?

JAAA! ich hab gestern bestimmt eine stunde dran rumgemacht, bis es funktioniert hat. aber dafuer funktioniert es jetzt auch - hoffe ich.

ok, danke, das werde ich dann so machen. der 2. teil der meldung kommt tatsaechlich von einem perror () und das werde ich auch so lassen. aber auf jeden fall den exitstatus entfernen, stimmt schon.

ERGAENZUNG:
wie komme ich denn aus dem kindprozess raus, wenn der exec-aufruf fehlgeschlagen ist (weil datei nicht vorhanden), wenn nicht mit exit ()? dann schlaegt aber das WIFEXITED im vaterprozess an und gibt mir den exitstatus aus… wie laesst sich das umgehen?


also ich hab die maximale eingabe länge mit _SC_LINE_MAX geprüft.
is das falsch? was bedeutet eigentlich posix1/2 ?

auch interessant ist es das die maximale länge sich ändert…
glaub ich. ich mein gestern 4kb gehabt zu haben jetzt grade hab ich 72048 ausgegeben bekommen.


Zerlegen in Argumente:

Wenn du die Befehlszeile nochmal brauchst dann kopier sie dir vorher, da strtok die Zeichenkette bei Anwendung verändert.

um die argumente der eingaben herauszubekommen legst du ähnlich wie bei wsort so eine Liste an und fügst sie einzeln an die Liste an.

Ganz wichtig bei strtok: Der erste Aufruf mit dem zu zerlegenden String, alle weiteren Aufrufe dann mit NULL als erstem parameter …

z.B. so :

value = strtok (eingabe, " ");
anlisteanhaengen(value);
while (value != NULL) {
   value = strtok (NULL, " ");
   anlisteanhaengen(value);
}

anlisteanhaengen wäre in dem Fall eine Funktion die als argument einen char-pointer will und eben wie oben schon geschrieben das neue argument in die liste einträgt (mit all dem malloc und realloc zeug, das schon für wsort verwendet wurde) …

Und sonst brauchst du eigentlich nur die _SC_LINE_MAX Zahl, da du ja, sofern du es so wie bei wsort machst, die liste dynamisch erweiterst :slight_smile:

Grüße,
Sebbi

P.S.: Speziell bei diesem Programm: nicht vergessen Speicher wieder freizugeben, sonst frisst eure Shell Speicher wie blöde g


BUGS
Never use these functions. If you do, note that:

          These functions modify their first argument.

          The identity of the delimiting character is lost.

          These functions cannot be used on constant strings.

          The  strtok()  function  uses a static buffer while
          parsing, so it's not thread safe. Use strtok_r() if
          this matters to you.

euch egal, oder benutzt ihr ne andere möglichkeit eure char** zu erstellen?


ich machs ohne strtok, geh die kommandozeile durch und filter mir die einzelnen wörter raus, die ich dann in mein char** kopier… ist nicht wirklich kompliziert und erspart das rumgesockse mit strtok … wobei man auch in so einfachem code 1000 Fehler bauen kann wie ich feststellen musste :#:

aber :heart: DDD :heart: ist mein retter ! :smiley:


Also ich komm mit dem strtok wunderbar zurecht… der filtert auch so Blödsinn wie mehrere Leerzeichen und die Zeilenschaltung raus, so dass ich mich nicht auch noch darum kümmern muss.

Ich wollts auch erst selber schreiben - aber wozu? Meine Routine würde genau das selbe machen, wie das strtok - nur wahrscheinlich schlechter :slight_smile:


und sicherer…


DEINE vielleicht … :smiley:


strtok ist hier schon ein geeignetes Mittel,
den Originalstring braucht man eh nichtmehr nach dem exec.


Und es ist allemal besser, man kopiert/sichert sich den String [wenn man den noch fuer irgendwas brauchen sollte], denn man von fgets
bekommen hat, VOR dem Aufruf von strtok, als dass man danach irgendwelche wilden Speicheroperationen macht, wie ich es heute leider in der Rechneruebung sehen musste.


Deswegen sagte ich das ja :slight_smile:

wir mussten damals noch in der Fehlerausgabe die Eingabezeile ausgeben, deshalb ein strcpy in einen gleich großen Array bevor man mit der strtok-funktion hantiert.

btw: gibt es eigentlich noch mehr funktionen bei denen in der Manpage steht, dass man sie nicht verwenden soll? :slight_smile:


gets zum Beispiel…


hmmm, bei mir kommt da Permission denied, wenn ich einen ungültigen Namen angebe…

woran kann das liegen?


permission denied bekommst du wenn du eine Datei angibst, die es zwar gibt (oder geben koennte in einem Unterverz.) aber du keine berechtigung hast die auszufuehren.
z.B.
mysh> mysh.c

oder
mysh> /root/rootspersonaldir/bofh/flipevrytenthbit simaxmod


und wie ist dann das zu erklären?

mysh> ls blubb                  
ls: blubb: No such file or directory
Exitstatus [ls blubb] = 1
mysh> which blubb               
Exitstatus [which blubb] = 1    
mysh> blubb                     
blubb: Permission denied        
Exitstatus [blubb] = 1          
mysh>