Programmieren - alles kontrollieren 4.940 Themen, 20.676 Beiträge

Simples, aber tricky problem für C und Kommandozeilen...

Mdl / 6 Antworten / Baumansicht Nickles

~~~~~~~
Prolog:
~~~~~~~

Was passiert, wenn man, z.B. in einer DOS-Box ist, sich z.B. im Verzeichnis c:\windows befindet und von dort aufruft:
> dir c:\
? Antwort: Der Inhalt des Root-Verzeichnisses von Laufwerk C: wird angezeigt.

Was passiert beim Aufruf von
> dir "c:\"
? Antwort: Dasselbe

~~~~~~~
Kapitel 1
~~~~~~~

Folgendes simples C-Programm 'ShowArgs' zeigt die über einen Kommandozeilenaufruf übergebenen Argumente an:

//---------------------------------------------------------------------------
#include
//---------------------------------------------------------------------------
void main(int argc, char *argv[])
{
for(int i=1; i&lt argc; i++)
printf("argv[%i]: %s\n", i, argv[i]);
}
//---------------------------------------------------------------------------

Rufe ich es jetzt analog zu oben auf:
Einmal mit
ShowArgs c:\
zeigt es an
argv[1]: c:\

Rufe ich es jetzt aber mit
ShowArgs "c:\"
auf, zeigt es folgendes an:
argv[1]: c:"

[Die Ursache, die mich in erster Linie weniger interessiert ist vermutlich, dass im zweiten Fall der Backslash '\' als Escape-Character gewertet wird und besagt, dass das folgende Zeichen ('"') nicht speziell interpretiert werden soll.]

???????-----------
? Meine Frage ist: Wie kann ich in C diese unerwünschte Uminterpretation vermeiden?
DIR.EXE ist doch vermutlich auch in C geschrieben?
???????-----------

(Würde DIR.EXE das Argument "c:\" als c:" interpretieren, so würde es beim Aufruf innerhalb von c:\Windows heraus den Inhalt von c:\Windows ausgeben. Einfach mal ausprobieren: dir c:" )

(Im Hinterkopf habe ich noch, dass es die Möglichkeit gibt, noch VOR main auf eine Funktion zuzugreifen (_main()), aber hatte bei einem Versuch keinen Erfolg. Vielleicht war das ja noch bei einem anderen System.)

Über das Problem gestolpert bin ich, als ein kleines Tool von mir, geschrieben zur Unterstützung von Batchdateien plötzlich unsinnig reagierte. Beim Debuggen war mir dann klar, warum...

Vielen Dank,

Mdl

bei Antwort benachrichtigen
the_mic Mdl „Simples, aber tricky problem für C und Kommandozeilen...“
Optionen

Da musst du in C eine Funktion implementieren, die folgende Arbeit verrichtet:
http://de.php.net/manual/de/function.addcslashes.php

vermutlich gibt's schon jede Menge freie Bibliotheken, die sowas können. Google ist dein Freund :-)

cat /dev/brain > /dev/null
bei Antwort benachrichtigen
Mdl the_mic „Da musst du in C eine Funktion implementieren, die folgende Arbeit verrichtet:...“
Optionen

Hallo the_mic,

die Implementierung einer solchen Fkt. addcslashes wäre definitiv nicht das Problem, nur was soll ersetzt werden? Jedes abschließende Anführungszeichen '"' durch einen Backslash '\'?

In diesem konkreten Fall wollte ich - vereinfacht gesagt - eine ECHO.EXE änliche Fkt. bauen, die aber keine zwangsweisen CR/LF am Ende der Zeile ausgibt und ähnlich C's printf auch Formatierungen zulässt. Sie interpretiert die Eingabe auch nicht in dem Sinn, ob das jetzt ein Verzeichnisname oder ein beliebiger Text ist.

Ich würde auch meine Hand nicht dafür ins Feuer halten wollen, dass diese Kommandozeileninterpretation in allen Windows-Versionen, z.B. ab Win95 identisch ist.

????????????
? Eigentlich ist mein Wunsch nicht etwas zurückzuinterpretieren, sondern die Erstinterpretation (die vor dem Aufruf von main() ausgeführt wird), zu umgehen.
D.h. gibt es eine Zugriffsmöglichkeit auf die Übergabeargumente vor main()?
????????????

Vielen Dank,

Mdl



bei Antwort benachrichtigen
Synthetic_codes the_mic „Da musst du in C eine Funktion implementieren, die folgende Arbeit verrichtet:...“
Optionen

Hi MDL, Dir war noch nie in C geschrieben, es existiert unter windows(wie auch unter DOS) keine dir.exe.

Viel mehr ist dir eine art alias auf cmd.exe, bzw command.com unter DOS / Win9x. Wenn du ein Commando unter einem der Windows Commandozeileninterpreter dir eingibst schaut selbiger erstmal in seinem eigenen befehlsreportoire nach, ob es sich um einen inbuilt befehl handelt. dir ist so einer. erst danach wird geschaut ob es eine dir.exe, dir.bat, dir.com oder dir.cmd gibt.

tatsächlich habe ich dein Programm mal ein wenig erweitert, um der ursache auf den grund zu gehen:

#include <stdio.h>

int main(int argc, char **argv)
{
int c;
for(c = 0; c {
printf("%d ",argv[1][c]);
}
return 0;
}

damit wird vom ersten Argument jeder einzelne char als ASCII Nummer auf der konsole ausgegeben:

C:\test>Project1.exe "C:\"
C:"
C:\test>Project1.exe \"C:\"
"C:"
C:\test>Project1.exe \"C:\"
34 67 58 34
C:\test>Project1.exe "C:\"
67 58 34
C:\test>


Dabei drängt sich mir jetzt folgender Verdacht auf:
unter windows escaped cmd.exe den aufruf, bevor das argument an das programm weitergegeben wird.
Daran kann man so auf die schnelle wohl nichts ändern. Aber ich überlege mir was, denn du hast es geschafft, dass mich das jetz beschäftigt

'); DROP TABLE users;--
bei Antwort benachrichtigen
Mdl Synthetic_codes „Hi MDL, Dir war noch nie in C geschrieben, es existiert unter windows wie auch...“
Optionen

Hallo Synthetic_codes,

ja, Du hast wohl recht. Ich hatte in der Schnelle 'which dir.exe' angegeben und das Programm hatte ausgegeben, wo es DIR.EXE nicht gefunden hatte. Habe mir den Text nicht so genau durchgelesen und mich nur kurz gewundert wo es überall auftaucht...

> Aber ich überlege mir was, denn du hast es geschafft, dass mich das jetz beschäftigt.
Ok, bin dann mal gespannt...

Viele Grüße,

Mdl

bei Antwort benachrichtigen
Synthetic_codes Mdl „Hallo Synthetic_codes, ja, Du hast wohl recht. Ich hatte in der Schnelle which...“
Optionen

hehe mir ist grade die lösung gekommen... Die " " arbeiten offensichtlich als begrenzer mit, sprich der Commandozeileninterpreter zieht alles zwischen " " zu einem Argument zusammen. Sprich aus test.exe "Hallo Welt" wird im C-Code argc=1 argv[1] = "Hallo Welt", während test Hallo Welt zu argc=2 und argv[1] = "Hallo", argv[2]="Welt" wird.. Daraus folgt wiederum, dass du die Anführungszeichen wohl escapen musst, wenn du sie als " im Argument tatsächlich haben willst.

Warum dir das richtig macht? Gute Frage, aber ich gehe mal davon aus, dass dir die eingaben selbst bearbeiten darf.

'); DROP TABLE users;--
bei Antwort benachrichtigen
Mdl Synthetic_codes „hehe mir ist grade die lösung gekommen... Die arbeiten offensichtlich als...“
Optionen

Halllo Syntehetic_codes,

> Die " " arbeiten offensichtlich als begrenzer mit, sprich der Commandozeileninterpreter zieht alles zwischen " " zu einem Argument zusammen.

Richtig. Braucht man also z.B. um Verzeichnisse wie 'Dokumente und Einstellungen' ansprechend zu können.

> Warum dir das richtig macht? Gute Frage, aber ich gehe mal davon aus, dass dir die eingaben selbst bearbeiten darf.

Da DIR ja jetzt ein Befehl innerhalb des Betriebssystem ist und nicht außerhalb, ist es natürlich durchaus möglich, dass es mehr kann, als man den externen Prg. außerhalb erlaubt.

Trotzdem: Soweit ich weiß ruft das CMD-Kommando ja nicht gleich main() auf, sondern es wird zuvor ja noch ein Startup-Code ausgeführt, der wie ich meine auch die Argumente entsprechend verwaltet und letztlich eben dann main() aufruft...
In den müsste sich doch eingreifen lassen.

Ich hab jetzt mein ECHO-Tool um eine entsprechende Option erweitert, dass man ein Argument (d.h. einen argv-Index) angeben kann, in dem Ersetzungen stattfinden können, in diesem Fall also '"' durch '\'. Klappt auch und der Aufrufer des Batchfiles kriegt von dieser Verkünstelung ja auch nichts mit. Trotzdem ist das wieder mal eine Lösung, mit der man nicht wirklich glücklich ist...

Viele Grüße.

Mdl


bei Antwort benachrichtigen