2014-07-26 2 views
9

Ich spiele um mit einem neuen Init-System mit #![no_std] und extern crate rlibc und syscalls mit asm zu machen und versucht derzeit nicht entweder Speicher zuzuweisen. Daher ist der Umfang möglicher Werkzeuge, die ich habe, begrenzt.Wie kann ich ein nullterminiertes Array von C-Strings (char **) im Rost erzeugen und übergeben?

Ich muss die Execve syscall aufrufen, und es erfordert eine char** argv und eine char **envp. Ich kann c-Strings als Arrays von Bytes mit Nullen Hack zusammen, aber wie kann ich null kündigen eine statisch deklarierten Liste solcher (der letzte Zeiger ist NULL)?

Antwort

5

Nachdem auf diese schlafen, wachte ich mit der Antwort, und es scheint mir jetzt offensichtlich. Verwenden Sie Scheiben von ganzen Zahlen und stellen Sie den letzten ein bis 0.

// Execute something as an example: 
let filename: &[u8] = b"/usr/bin/sensors\x00";  // <-- Make c strings like this 
let argv1: &[u8] = b"/usr/bin/sensors\x00"; 
let argv2: &[u8] = b"-h\x00"; 
let argv: &[int] = [        // <-- store them in this 
    ::core::intrinsics::transmute(argv1.as_ptr()), // <-- transmuting 
    ::core::intrinsics::transmute(argv2.as_ptr()), 
    0            // <-- and NULL terminate 
]; 
let envp: &[int] = [0]; 

::linux64::execve(filename,argv,envp); 
+2

Sie verwenden sollten, '* const u8' statt' int'. Die 'as_ptr()' Methode gibt bereits ein '* const u8' zurück, so dass Sie einfach' transmute' entfernen können. Um einen Nullzeiger zu erhalten, benutzen Sie 'ptr :: null()' (oder '0 als * const T') anstelle von' 0'. –

+0

Sie können auch '\ 0' anstelle von' \ x00' in Bytestrings verwenden, um ein Nullbyte darzustellen. –

+1

Sie können roh Zeiger gegossen und aus ganzen Zahlen frei ('argv1.as_ptr() als int'), aber wie @ FrancisGagné schlägt, wäre es besser, einen zu speichern' & [* const U8] '. Wissen Sie auch über 'use', während es erlaubt, Namen in den Geltungsbereich zu bringen, z. 'benutze core :: mem; ... mem :: transmutiere (...) '? – huon

Verwandte Themen