2013-04-02 2 views
2

Tout en jouant avec des variables d'environnement binaires sous Linux, j'ai trouvé un comportement étrange où il semble que certains octets étaient mauvais. Je l'ai examiné de plus près et il semble que certains octets seront toujours "convertis" incorrectement quand ils seront donnés à setenv(). Regardez ceci:Binary environnement variables et setenv()

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) 
{ 
    char array[256]; 

    int i; 
    for(i = 1; i < 256; i++) { 
     array[i] = i; 
    } 

    setenv("badenv", array, 1); 

    system("/bin/sh"); 

    return 0; 
} 

J'exécute ce programme, puis quand je fais echo $ badenv> test; test hexdump je vois:

0000000 0101 0302 0504 0706 2008 0c0b 0e0d 100f 
0000010 1211 1413 1615 1817 1a19 1c1b 1e1d 201f 
0000020 2221 2423 2625 2827 2a29 2c2b 2e2d 302f 
0000030 3231 3433 3635 3837 3a39 3c3b 3e3d 403f 

Il semble que 0x9 est converti en 0x20, et que 0xa est converti en 0xB, entre autres. Est-ce que j'abuse de setenv(), ou peut-être même que j'abuse des variables d'environnement en général? J'ai regardé dans la page de manuel et cherché autour de certains pour voir si les variables d'environnement devraient être capables de gérer les valeurs binaires ou non, mais je ne suis pas sûr.

Quelle est la cause de ce comportement, existe-t-il un moyen de contourner ce problème, tout en continuant à utiliser des variables d'environnement?

+0

Il semble y avoir une restriction silencieuse sur ce qui peut entrer dans la variable d'environnement. 'exporter a =' echo -e "\ t" 'donne la même chose en remplaçant la tabulation par l'espace. – elmo

+0

Puisque 'setenv' attend une chaîne terminée par 0 (une chaîne de style C par exemple) comme variable, la valeur ne peut évidemment pas être une donnée binaire arbitraire, car elle ne gérera pas bien 0 octet. Je ne sais pas pourquoi il convertit les caractères de contrôle comme '0x9' en espaces, cependant. Probablement une mesure de sécurité. – shakurov

Répondre

3

La variable d'environnement est divisée en "mots" selon la valeur de $IFS, et les "mots" sont joints avec un seul séparateur - dans ce cas un espace ordinaire. Ainsi, la séquence "\x09\x0a" ou "\t\n", est réduite à un espace ('\x20') lors de l'interprétation du contenu de array. IFS - Séparateur de champ interne utilisé pour la division de mots après expansion et pour diviser des lignes en mots avec la commande interne de lecture. La valeur par défaut est '' nouvel onglet espace ''. Vous pouvez éviter le remplacement en changeant (temporairement) $IFS

Notez cependant que

  • array[0] a une valeur indéterminée
  • array est de 0 TERMINAISON

dans votre programme. Vous devriez corriger cela.

+0

Merci, que dois-je faire pour $ IFS afin d'obtenir ce comportement? Actuellement $ IFS n'est pas défini, j'ai essayé de le déclarer sans contenu. – csstudent2233

+0

Vous pouvez définir 'IFS =" "', puis une séquence (non vide) d'espaces est réduite à un seul espace, mais puisqu'il n'y a qu'un seul espace, il ne sera pas modifié. Mais je suis sûr que 'IFS' est réglé,' echo -n "$ IFS" | xxd' devrait vous dire à quoi (probablement espace, tab, nouvelle ligne, donc xxd rapportera '2009 0a'). –

+0

Oui, vous avez raison. Merci encore, cela semble fonctionner dans mon programme original. Le programme que j'ai collé ici était juste quelque chose pour démontrer le "problème" en général. – csstudent2233