freem a écrit 5019 commentaires

  • [^] # Re: Programmation objet ?

    Posté par  . En réponse au journal Apprentissage de la programmation : comment moderniser les exercices. Évalué à 8.

    En parlant de Basic, enfin, dans mon cas, QBasic, je me souviens d'une interface (au sens API) capable de générer des images (et du son) à partir de chaînes de caractères. Mais bon, c'est nettement plus récent: c'était il y a 18 ans, et le logiciel lui-même était déjà obsolète. N'empêche, il était accompagné d'une doc de qualité qui permettait d'apprendre sans accès au Web, et ne cachait pas (trop) le fonctionnement réel sous-jacent.

    Pour le coup, moi, c'est bien l'intro faite à ma classe par un prof dans ma 1ère années de seconds que je ne portais pourtant pas dans mon coeur qui m'a filé le virus de l'informatique… 1 an plus tard, j'étudiais par moi-même l'assembleur, le C, et le fonctionnement de windows (je n'avais jamais entendu parler de systèmes autres que DOS ou windows).
    Ce qu'il nous avait montré était juste du printf/scanf pourtant… enfin, en QB, bien sur. Je ne suis pas le seul a avoir aimé ça, d'ailleurs, mon ami de l'époque (qui m'a appris à utiliser google et hotmail, à l'époque) et moi avons ensuite passé énormément de temps au CDI, notamment sur un site nommé de mémoire "qbworld", fait par un type du nom (pardon pour l'écorchage) d'achraf cherti, ou un truc du genre. J'y ai découvert les effets plasma, tunnel, raytracing, entres autres.

    Autre souvenir, de terminale STI électronique, je codais déjà depuis quelques années du coup (bon, ok, 3 ans et des bananes) et les profs d'élec voulaient nous apprendre le C. Je m'ennuyais forcément (j'avais commencé à étudier le C++ a ce moment, avec le bouquin nul à chier "C++ pour les nuls" blindé d'idiomes et de culture ricains traduit mot-à-mot, de fautes, et assommant comme un célèbre livre de Zola), alors je codouillais d'abord un truc qui rebondissait en mode curses… enfin, conio, puisque c'était un vieil IDE borland, puis j'y ajoutais une raquette, puis un système de scores, puis de la couleur en fonction des positions, et enfin de la musique elle-aussi en fonction des position: que du procédural, avec un bel effet années 80…

    Ce truc (le son) a hypnotisé mes camarades de classes, je sais pas pourquoi (j'avais fait ça par désoeuvrement), et les profs ont transformé les TPs pour qu'ils tournent autour de ça.
    À l'époque, plus personne n'utilisait DOS depuis longtemps, sauf moi, pour le code. Les téléphones portables étaient déjà dans toutes les mains, même si moins beaux et intrusifs que de nos jours.
    Du coup, je me demande si vraiment, c'est un problème d'esthétique que d'intéresser les jeunes au code.

  • [^] # Re: cybersécurité

    Posté par  . En réponse à la dépêche Un concours pour donner une nouvelle image de la cybersécurité ?. Évalué à 3.

    Je me permets, parce que je suppose ne pas être le seul a ne pas connaître tous les grands noms…

    Des fois c'est pire : ils ont la tronche de Jérémie Zimmermann

  • [^] # Re: Piste

    Posté par  . En réponse au message Problème BusyBox. Évalué à 2.

    Ce paramètre ne semble pas être un paramètre noyau en lui même

    Nope, le paramètre single était utilisé pour sélectionner un runlevel du temps de sysVinit, et sous runit il permets de ne lancer que le minimum de services.

    Mon intuition est que, dans les services complets, sous systemd, un truc vide et ne repeuple pas bien /dev/disk/by-uuid. Et j'entend bien au niveau de l'initrd, ce qui empêcherait les scripts de boot de passer au montage proprement dit.

    Bon, ça reste de l'intuition, je maîtrise pas initrd et je ne connais pas systemd, donc je peux me tromper complètement de cible.
    M'enfin, si l'initrd marche avec certains paramètres de boot et pas d'autres, y'a un truc quand même: déjà le boot loader trouve le noyau, donc il trouve la partition racine. Dans les 2 cas (sinon l'initrd ne serait pas chargé après tout…).
    Un paramètre présent ou absent fait que l'initrd ne trouve plus la partition racine après que le noyau ait été chargé…
    Ça pourrait aussi être un module qui est juste chargé dans le mode sans échec? L'initrd contiendrais plus de module en mode sans échec que normal? Pas logique.

    Désolé, je réfléchis en même temps…

  • [^] # Re: Piste

    Posté par  . En réponse au message Problème BusyBox. Évalué à 2. Dernière modification le 07 août 2019 à 19:13.

    Peux tu me donner la marche à suivre freem ? Je ne vois pas trop quels scripts tu veux :)

    Vais essayer, mais je n'utilise pas spécialement grub…

    Dans le menu ou tu peux changer de système d'exploitation ou passer en "mode sans échec", la touche "e" (de mémoire) permets d'éditer le script de démarrage lié à une entrée.
    Avoir les scripts liés à l'entrée par défaut et à celle qui fonctionne permettrait de savoir ce qui se passe au démarrage dans le cas qui marche et dans l'autre.

    [edit]
    en fait, c'est la même chose que ce qui est utilisé pour modifier les entrées de démarrage. On peut aussi s'en servir pour bypasser login et donc reset un password root perdu.

  • [^] # Re: Piste

    Posté par  . En réponse au message Problème BusyBox. Évalué à 2. Dernière modification le 07 août 2019 à 14:36.

    Un démarrage "sans échec" c'est un démarrage dans les options avancées avec : […]

    Ok. Donc, soit l'initrd utilisé pour le sans échec est différent de l'initrd normal, ce dont je doute, soit grub lui passe des paramètres différents, ce qui me paraît plus probable, et je vais partir sur cette piste.

    Dans grub, il est possible (comme dit plus haut) de modifier le script de démarrage, de mémoire en allant dans ce menu avancé et en utilisant la touche 'e' sur l'entrée voulue.

    Pourrais-tu nous lister le scripts de l'entrée de démarrage normal et celui de l'entrée du démarrage sans échecs s'il te plaît?

  • [^] # Re: derniere chose

    Posté par  . En réponse au message question sur la structure du code que fait le compilateur (.text, .bss, .heap ...). Évalué à 2.

    Merci beaucoup pour les infos.

  • # pas de shell...

    Posté par  . En réponse au message grep et recherche approximative. Évalué à 4.

    Désolé, mais je doute fortement que les outils UNIX traditionnels permettent de faire ça… surtout vue la longueur des séquences dont tu parles, ça risque d'être très lent.

    Par contre, depuis que je connais Debian, j'ai toujours été sidéré par le nombre d'outils qui, justement, semblent traiter des séquences ADN. Les debtags, qui sont incomplets, mentionnent une centaine de paquets pour la biologie. Je trouve le nombre étonnamment faible, mais bon: les debtags sont incomplets.

    Je ne connais bien entendu rien à ce domaine, mais par exemple, le paquet "acedb-other" est ainsi décrit par aptitude:

    Description-fr: Récupération d'ADN ou de séquences de protéines
     Ce paquet rassemble toutes les petites applications qu'acedb regroupe sous
     la cible « other » de son Makefile.
     .
     efetch: vraisemblablement le raccourci pour « entry fetch » (collecteur
     d'entrées en base de données), assemble les informations de séquence des
     principales bases de données d'ADN et de protéines.
    

    Si ta distro est dérivée de Debian, tu peux par exemple utiliser la commande suivante pour avoir un aperçu des paquets liés à l'ADN:

    grep '^[^ ].*ADN' /var/lib/apt/lists/deb.debian.org_debian_dists_stable_main_i18n_Translation-fr -B2 | grep Package | cut -f2 -d:
    

    Probable qu'il existe de meilleures solutions pour chercher un paquet dont la description ou le nom contiens le terme ADN, mais le but ici est de demander surtout: as-tu vérifié si dans ces paquets l'un ne fait pas déjà le boulot? Si la seule différence est une question de format, on peut peut-être t'aider à réaliser un outil de conversion.

  • [^] # Re: Piste

    Posté par  . En réponse au message Problème BusyBox. Évalué à 2.

    Exact. À ma connaissance, cela requiert la connaissance de la disposition qwerty us par contre, sauf si certaines distros ont le bon boût de changer ça a l'installe, mais j'en serais surpris.

  • [^] # Re: derniere chose

    Posté par  . En réponse au message question sur la structure du code que fait le compilateur (.text, .bss, .heap ...). Évalué à 2.

    Ce n'étais pas le sujet, je pense, de connaître la gestion de mémoire d'un point de vue physique.

    l'OP m'avais l'air de vouloir en comprendre un maximum… et vue l'image qu'il a montrée, je pensais que pour sa compréhension,la notion de page devait être abordée. Mais, je me suis peut-être trompé. Une Nième fois :)

    Cela dépend des architectures, mais majoritairement, oui.

    Pourrais-tu, pour ma culture, citer des archis pour lesquelles ce n'est pas le cas?

    En fait, toutes sont virtuelles ou logiques.

    Je n'étais pas sûr que cela concernait l'ensemble des zones, j'ai préféré prendre des gants, le tas me semblant la zone la moins dangereuse pour laquelle affirmer ça…

    Le terme est «flat».

    Oh, ça va, j'ai juste essayé d'utiliser un maximum de mots français… :)

    Arf, j'ai essayé de demander "linux stack overflow" à Google ;)

    Mais quelle idée, en effet :D

    Plus sérieusement, merci de ces précisions.

  • [^] # Re: derniere chose

    Posté par  . En réponse au message question sur la structure du code que fait le compilateur (.text, .bss, .heap ...). Évalué à 3.

    Pre-scriptum: en lisant en diagonale certains liens que je cite, il est clair que mes souvenirs sont flous et blindés d'erreurs, mais pas le temps de tout lire (p'tet ce soir, ça me fera pas de mal), je prend juste une petite pause au taf… mea culpa.

    J'attendais de voir un peu les réponses, en espérant que quelqu'un aborde la notion de page… pas de bol. Pour le coup, je risque de dire des choses assez fausses… N'hésites pas a vérifier ce que je raconte, ou mieux, a me corriger…

    Or à un moment le tas va arriver vers la mémoire de la pile

    Oui, ce genre de choses peut arriver. Enfin, pouvais arriver. Si je ne dis pas d'âneries (cf plus haut), les noyaux gèrent de nos jours la mémoire par pages. Ce que tu vois quand tu regardes les adresses mémoire de ton processus, ce sont de fausses adresses, au moins pour le tas.

    Quand tu fais un appel a malloc (ou calloc, ou realloc, peu importe…), celui-ci va demander une page au noyau, qui la lui accordera (ou pas: renvoi de NULL/nullptr). Ensuite, il te fileras de petits morceaux de cette page, à la demande. Ce sont ces morceaux de pages qui, ensemble, vont constituer ton tas.
    Le programmeur voit la mémoire comme linéaire grâce au noyau, et, je crois, de la MMU.

    C'est ici l'intérêt d'avoir agrandit la taille des espaces d'adressage: en 16 bits, la mémoire virtuelle n'aurait jamais pu dépasser les 64Kio par processus. En 32 bits, les 4Gio par processus, et en 64 bits… euh… 264 -1 octets :)
    Notes bien le "par processus", parce qu'il existe un mythe selon lequel les machine avec archi 32 bits ne peuvent pas gérer plus de 4Gio de RAM. C'est faux(bon, ok, dans certains cas, certes).

  • [^] # Re: Piste

    Posté par  . En réponse au message Problème BusyBox. Évalué à 3.

    Ce problème peut aussi se produire suite à une mise à jour (kernel, udev).

    Ce cas est "simple" à vérifier rapidement: utiliser les vraies partitions /dev/sdXY au lieu des liens symboliques /dev/disk/by-uuid.
    Si tout boote normalement alors que le système est divisé en plusieurs partitions, alors il est probable que ce soit l'initrd qui merde, et pas un problème d'UUID qui aurait changé.
    Ou voir s'il peut démarrer une autre version du noyau (ça doit être dans le menu avancé de grub2, je suppose, je n'utilise pas ce bootloader).

    Il faudrait aussi voir exactement ce que l'OP appelle "mode sans échecs". Pour moi, ce qui s'en rapproche le plus, c'est le "veuillez entrer le mot de passe root ou CTRL+D pour continuer", voir l'option "single" au démarrage.

  • # awk

    Posté par  . En réponse au message Formater fichier de sortie vers colonnes CSV. Évalué à 2.

    Pour moi, le meilleur outil dans ton cas serais awk, puisqu'il te faut travailler sur plusieurs lignes.

    À l'arrache et sans tests, je dirais que le script devrais ressembler à un truc de ce goût là:

    /^\*/ {
    printf "\n"
    }
    /^[^*]/ {
    printf "%s\t", substr( $1, 0, index( $1, ':' ) )
    }
    END {
    printf "\n"
    }

    Je doute que ça juste marche, mais en bidouillant un peu et en t'aidant de ce lien tu devrais t'en sortir.
    Bon, la sortie n'affiche pas les noms des colonnes, mais ça ne devrais pas être trop compliqué à faire.

  • [^] # Re: sans noyau, pas de framebuffer...

    Posté par  . En réponse au message server X et frame buffer.. Évalué à 3.

    J'ai oublié…

    /dev/fb0 n'existe pas par défaut avec mes vieux pilotes nvidia, il me faut utiliser "modprobe uvesafb" pour que ça marche. Et le résultat reste moche. Par contre, ça marche avec nouveau sans modprobe, mais les performances de nouveau sur mon vieux hardware (GeForce 8400, mais pourquoi jeter: ça marche et me suffit) sont a chier, limite pire qu'un rendu logiciel.

    Je n'ai pas encore testé DRM.

    Les framebuffer n'ont aucune documentation sur les *BSD, et l'on m'a dit qu'ils ne sont pas supportés, donc, ce truc super simple a utiliser (vraiment, c'est trivial) n'est utilisable que sous linux a ma connaissance.

    Je pense avoir fait le tour de toutes les infos que j'ai glanées sur ce sujet, donc bonne chance.

    Petit outil complémentaire: libpng est une p****n d'usine à gaz. Freetype aussi. J'ai préféré implémenter un support rudimentaire des formats psf1 et psf2 pour le texte, et utiliser libspng pour les images. Comme tout ça est pour le taf, je peux pas partager de code. Enfin, s'pas comme si l'implémentation avait été le plus difficile (enfin, si, je galère, mais pour des raisons autres que libinput, fb.h, kd.h, psf1/2 ou spng…).

  • # sans noyau, pas de framebuffer...

    Posté par  . En réponse au message server X et frame buffer.. Évalué à 5. Dernière modification le 29 juillet 2019 à 23:10.

    Plusieurs choses: le framebuffer est une interface mise à disposition par le noyau, et relativement simple à utiliser. Donc, sans noyau, pas de framebuffer, juste du VESA ou autres joyeusetés bas niveau.

    Le nom du fichier de framebuffer est /dev/fb0 sur mon linux. Il est probablement possible d'en avoir plusieurs, pour gérer du multi-écran, mais j'ignore comment.

    Il faut faire partie du groupe video, et pour gérer les entrées, du groupe input, sous Debian.

    Pour aider plus sur la question réelle, voici un lien qui explique comment utiliser les framebuffer de linux, entres autres, et sans bibliothèque.
    Pour info, la SDL gère de manière expérimentale et super foireuse le framebuffer, et ce, en s'appuyant sur le bloatware non maintenu qu'est directfb. Pour avoir essayé, je déconseille fortement.

    Tu trouveras aussi des informations (en plus du lien que j'ai passé plus haut) dans le fichier /usr/include/linux/fb.h. Pour les entrées, je te conseilles l'usage de libinput, un peu galère a utiliser, et l'usage sans udev est pas franchement bien documenté, mais ça juste marche pour moi jusqu'à présent. Restera le problème du curseur texte qui reste affiché, pour ça, /usr/include/linux/kd.h te sera utile: il faut passer le TTY en KD_GRAPHICS si ma mémoire est bonne. Le problème étant que cet appel de ioctl nécessite d'être root, je n'ai pas trouvé comment résoudre ça autrement, peut-être avec les capabilities, mais vu comment c'est documenté… bonne chance. Il doit y avoir moyen de faire autrement, c'est sûr, mais j'ai pas encore cherché. Une piste serait d'analyser le code de logiciels de ngetty ou fgetty.

    Bonne chance.

  • [^] # Re: Jamstack ?

    Posté par  . En réponse au journal Générateur de site web statique. Évalué à 2.

    pre-postum: il est tard, j'ai la flemme de tout relire pour vérifier la cohérence une nième fois. Bref, attendez-vous à un contenu mal écrit et redondant.

    TL;DR:

    Et imaginons qu'on veuille avoir un lien sur tous les titres ? Pourquoi devoir les faire à la main quand on pourrait les générer à la main ? Idem, si on avoir un bête index.

    En shell POSIX standard, à ma connaissance, c'est impossible. Alors j'ai écris un outil en C++ "light" destiné à remplir la fonctionnalité manquante.
    L'outil est pas packagé, le code est publié ici pour la 1ère fois, à la base je voulais le faire sur le blog que je compte monter, mais le CSS m'écoeure alors je galère…

    Le code source suit (amis codeurs, ne regardez pas: c'est sale):

    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <assert.h>
    #include <stdint.h>
    #include <ctype.h>
    
    #include <algorithm>
    
    #include <vector>
    
    /**
     * This program reads stdin and when consecutive lines have specific fields all
     * containing the same value, prints them replacing the newline character by
     * the 1st character in FIELD_SEP.
     * Fields are delimited by the FIELD_SEP environment variable. If not defined,
     * " \\t" is used instead (see isblank(3)).
     * Fields to use are defined by the environment variable FIELDS, which only
     * use unsigned decimal integers separated by commas, other characters makes the
     * value invalid.
     * If FIELDS is not defined or invalid, exits with an error.
     * Empty field indexes ("1,,3") are ignored (will resolve in "1,3").
     * Do not work if input is not in line mode.
     * Line separator is defined by ENTRY_SEP, or "\\n" if not defined.
     *
     * TODO:
     * * check that ENTRY_SEP works as expected;
     * * fix the fact input needs a "\\n" at end of last line for it to be merged;
     * * UTF-8 support (field separators);
     * * providing FIELDS variable as command-line option;
     * * -v/--version option;
     * * -h/--help    option;
     * * remove bloated STL containers;
     * * allow to customize the memory allocation scheme at runtime;
     * * allow to not print twice merged fields;
     * * allow to set verbosity on stderr;
     * * remove hard-coded limit of UINT16_MAX - 1 for fields start/stop positions;
     * * print as many lines as there where duplicates?
     *
     * Coding rules:
     * * const affect what is before it, so it must follow the type;
     **/
    
    class field_marker
    {
        uint16_t m_start = UINT16_MAX, m_end = UINT16_MAX;
    
    public:
        bool ignore( void ) const
        {
            return m_start == m_end && m_start == UINT16_MAX;
        }
    
        void define( uint16_t start, uint16_t end )
        {
            assert( end >= start && start != UINT8_MAX && end != UINT8_MAX );
            m_start = start; m_end = end;
        }
    
        uint16_t start( void ) const
        {
            assert( !ignore() );
            return m_start;
        }
    
        uint16_t end( void ) const
        {
            assert( !ignore() );
            return m_end;
        }
    };
    
    bool allocate_markers(
            char const * const FIELDS,
            std::vector<field_marker>& field_cache
    );
    
    int main( void )
    {
        char const * const DEFAULT_FIELD_SEP = " \t";
        char const * const DEFAULT_ENTRY_SEP = "\n";
    
        char const * SEP_START = getenv( "FIELD_SEP" );
        if( !SEP_START )
        {
            SEP_START = DEFAULT_FIELD_SEP;
        }
        char const * SEP_ENTRY = getenv( "ENTRY_SEP" );
        if( !SEP_ENTRY )
        {
            SEP_ENTRY = DEFAULT_ENTRY_SEP;
        }
    
        char const * const FIELDS = getenv( "FIELDS" );
        if( !FIELDS )
        {
            fputs( "ERROR: FIELDS is not defined\n", stderr );
            return EXIT_FAILURE;
        }
    
        if( strlen( FIELDS ) == 0 )
        {
            fputs( "ERROR: FIELDS is empty\n", stderr );
            return EXIT_FAILURE;
        }
    
        std::vector<field_marker> field_cache;
        if( allocate_markers( FIELDS, field_cache ) )
        {
            return EXIT_FAILURE;
        }
    
        size_t buf_sz = 2048;
        char* buf = nullptr;
    
        // I don't see how merging lines smaller than 16 bytes can be useful
        // also, not even enough mem for that would indicate bigger problems...
        while( !buf && buf_sz >= 32 )
        {
            buf_sz /= 2;
            buf = static_cast<char*>( malloc( buf_sz ) );
        }
    
        if( !buf )
        {
            fprintf( stderr, "ERROR: malloc %s(%d)\n", strerror( errno ), errno );
            return EXIT_FAILURE;
        }
    
        bool fetch = true;
        typedef std::vector<char> line_cache;
        line_cache last_line;
        char const * const SEP_END = SEP_START + strlen( SEP_START );
        while( !feof( stdin ) )
        {
            if( !fgets( buf, static_cast<int>( buf_sz ), stdin ) )
            {
                free( buf );
                buf = nullptr;
                buf_sz = 0;
                if( !feof( stdin ) )
                {
                    fprintf( stderr, "ERROR: fgets %s(%d)\n", strerror( errno ), errno );
                    return EXIT_FAILURE;
                }
                break;
            }
    
            size_t str_sz = strlen( buf );
            if( str_sz == buf_sz - 1 && buf[str_sz] != '\n' && !feof( stdin ) )
            {
                fprintf( stderr, "ERROR: buffer too small for some lines\n" );
                return EXIT_FAILURE;
            }
    
            if( !fetch )
            {
                char const* dst_ptr = buf;
                for( size_t i = 0; i < field_cache.size(); ++i )
                {
                    field_marker const& src = field_cache[i];
                    if( src.ignore() )
                    {
                        char const *sep = SEP_END;
                        while( sep == SEP_END )
                        {
                            ++dst_ptr;
                            sep = SEP_START;
                            for( ; sep != SEP_END && *dst_ptr && *dst_ptr != *sep; ++sep ){}
                        }
                        ++dst_ptr;
                        continue;
                    }
                    char const * src_ptr = last_line.data() + src.start();
                    size_t len = src.end() - src.start();
                    if( len > buf_sz - static_cast<size_t>( dst_ptr - buf ) )
                    {
                        fetch = true;
                        break;
                    }
    
                    if( 0 != memcmp( dst_ptr, src_ptr, len ) )
                    {
                        fetch = true;
                        break;
                    }
    
                    char last = dst_ptr[len];
                    char const * sep_ = SEP_START;
                    assert( sep_ != nullptr );
                    while( 0 != *sep_ && *sep_ != last && *SEP_ENTRY != last )
                    {
                        ++sep_;
                    }
                    if( 0 == *sep_ )
                    {
                        fetch = true;
                        break;
                    }
                    dst_ptr += len;
                    assert( dst_ptr >= buf );
                }
    
                fputc( fetch ? *SEP_ENTRY : * SEP_START, stdout );
            }
    
            last_line.assign( buf, buf + str_sz );
            if( last_line.back() == *SEP_ENTRY )
            {
                last_line.back() = 0;
            }
    
            if( fetch )
            {
                line_cache::iterator start     = last_line.begin();
                line_cache::iterator cache_end = last_line.end();
                size_t field_index = 0;
                while( start != cache_end && field_index < field_cache.size() )
                {
                    auto end = last_line.end();
                    if( last_line.back() == 0 )
                    {
                        --end;
                    }
                    line_cache::iterator it = std::find_first_of
                        (
                         start, end,
                         SEP_START, SEP_END
                        );
                    if( !field_cache[field_index].ignore() )
                    {
                        field_cache[field_index].define(
                                static_cast<uint16_t>( start - last_line.begin() ),
                                static_cast<uint16_t>( it - last_line.begin() )
                                );
                    }
                    start = it + 1;
                    ++field_index;
                }
                fetch = false;
            }
            fputs( last_line.data(), stdout );
        }
        fputc( *SEP_ENTRY, stdout );
        return EXIT_SUCCESS;
    }
    
    bool allocate_markers(
            char const * const FIELDS,
            std::vector<field_marker>& field_cache
    )
    {
        field_cache.reserve( UINT8_MAX ); //255 fields should fit most cases
        size_t last_field = 0;
    
        char const * fields = FIELDS - 1;
        do
        {
            ++fields;
            if( isdigit( *fields ) )
            {
                last_field = last_field * 10 + static_cast<size_t>( *fields - '0' );
            }
            else if( *fields == ',' || *fields == 0 )
            {
                size_t max = std::max( field_cache.size(), last_field );
                field_cache.resize( max );
                field_cache[last_field - 1].define( 0, 0 );
                last_field = 0;
            }
            else
            {
                fputs( "ERROR: FIELDS contains illegal characters\n", stderr );
                return true;
            }
        }while( *fields );
        field_cache.shrink_to_fit();
        return false;
    }

    C'est pas génial, je l'ai pas mis sur une forge, et pour la licence, bah… CC-0, BSD-2, WTFPL ou toute autre compatible, au choix. De toute façon ce code est tellement simple que je vois pas comment on pourrait y coller une licence en étant honnête…
    Les lecteurs y trouverons des opinions techniques douteuses. Sincèrement: elles sont miennes, je veux bien en discuter, mais je souhaite généralement prouver que C++ peut être aussi léger que le C, avec des avantages nets en terme de code. Ce qui explique mon manque d'appréciation pour, notamment, la STL. Mais bref. Ce code est sale de toute façon, je le sais.

    De base, mon idée était de faire un générateur de blog en shell, mais j'ai trouvé aucun outil permettant de merger des lignes en fonction d'une clé, d'où le code précédent.
    Bref, j'ai codé cette fonction, elle marche avec mes scripts, et permets bien plus que faire un vulgaire blog: vu qu'elle fait quasi rien, des gens lui trouverons peut-être d'autres usages. Grand bien leur en fasse.

    Mon idée était d'utiliser les outils UNIX classiques: sed, awk, cat… afin de passer un fichier source au travers d'une moulinette (par exemple /usr/bin/markdown du paquet discount.deb) et de concaténer ces fichiers avec un header, un footer, etc… mais, ça ne permets pas de générer des index, sommaires ou autres, alors j'ai sorti mon clang++.
    Du coup, cet outil est quasiment un pré-compilateur: si ma mémoire est bonne, je récupère une liste de noms de champs de la 1ère ligne, considère que ces champs seront présents à la suite, et les utilise pour générer un texte greppable.

    Une fois le texte greppable, je peux revenir au shell. La principale raison pour laquelle je n'ai rien publié est que… bah, je suis une merde en CSS, au point que je meurs d'envie de faire un <table><line><bla><bla/><line/><table/> dans l'idée… bref, le code est pas assez testé, il est sale, il est largement améliorable, et je le mentionne juste parce que, je me dis que p'tet, quelqu'un le trouveras utile…

  • [^] # Re: hibernation

    Posté par  . En réponse au journal Installation de Linux Mageia 7 sur un Dell 14 5000. Évalué à 3.

    Donc,le kernel en sortie de veille profonde ne passe pas par l'initramfs? Je suis réellement curieux, il n'est pas simple de trouver des infos au sujet du boot sans image, en mode brut. Ou, je ne suis pas doué, l'un n'excluant pas l'autre (mais le fait de pas être doué rends l'autre plus probable dans mon cas personnel, bien sûr).

  • # une autre alternative...

    Posté par  . En réponse au journal Générateur de site web statique. Évalué à 2.

    Je me suis intéressé un peu à ça, il y a quelques mois, sans rien trouver qui satisfasse mon égocentrisme, mais une connaissance m'a parlé de Wswsh qui est un générateur de blog écrit en ksh pur.

    Il n'est pas référencé sur staticgen, et j'ai trouvé l'idée intéressante, parce qu'après tout, j'ai du mal a voir pourquoi ce genre d'outils ne seraient pas écrits en shell: une bonne partie du taf, c'est parser un format pour générer du html, qui a vocation a se faire concaténer avec un header, un footer, et d'autres éléments (index, sommaire, menu, etc). Transformer, par exemple, du markown en html se fait très bien avec, par exemple, discount et le reste, de la concaténation de fichier, rechercher un truc, ce genre de chose, le shell sait faire.
    Jusqu'ici, à part perl, je ne suis pas sûr d'ailleurs de connaître un language qui gère mieux ce genre de tâches spécifiques, mais bon, je connais pas go.

  • [^] # Re: hibernation

    Posté par  . En réponse au journal Installation de Linux Mageia 7 sur un Dell 14 5000. Évalué à 3.

    Quitte a utiliser le swap pour hiberner, pourquoi ne pas assumer et lui allouer la bonne taille, avec les capacités modernes? Pour ne pas user le SSD? Mais dans le cas d'un SSD, vue la vitesse de boot, est-il pertinent d'hiberner, sachant qu'une hibernation conserve aussi les fuites mémoire et augmente le risque de se retrouver avec un secret non chiffré sur le disque?

  • [^] # Re: hibernation

    Posté par  . En réponse au journal Installation de Linux Mageia 7 sur un Dell 14 5000. Évalué à 0.

    Euh… hein? Pas compris ton histoire, mais… soit. Dans ce cas:

    dd if=/dev/zero of=/foo/bar bs=1024
    mkswap /foo/bar
    swapon /foo/bar
    

    Et fichier de swap d'1Kio, un. Et le code qui est le même que pour gérer une partition de swap, puisque du coup, c'est une partition. Il y a certes l'overhead lors de l'ouverture, mais bon, je pense que le noyal, il mmap ça, voir un mécanisme plus performant dont il peut avoir le secret puisqu'il a tous les secrets du temple.

  • [^] # Re: pas compris

    Posté par  . En réponse à la dépêche « Internet est cassé » ou plutôt : comment tester du TCP ou de l’UDP. Évalué à 6.

    C'est toujours le cas devant une langue étrangère si tu ne parles pas la langue en question.

    M'enfin, c'est principalement du shell… pas une langue étrangère… en tout cas, pas pour moi.

    Quelles sont tes questions ?

    Si je prend juste le 1er exemple (mais à vue de nez, ils sont tous du même acabit):

    $ telnet 127.0.0.1 60001
        (durée d'exécution 00:00)
    Trying 127.0.0.1...telnet: Unable to connect to remote host: Connection refused
        (code de retour 1)
    
    $ nc -t -v 127.0.0.1 60001
        (durée d'exécution 00:00)
    nc: connect to 127.0.0.1 port 60001 (tcp) failed: Connection refused
        (code de retour 1)
    
    $ bash -c exec 3<>/dev/tcp/127.0.0.1/60001
        (durée d'exécution 00:00)
    bash: connect: Connexion refusée
    bash: /dev/tcp/127.0.0.1/60001: Connexion refusée
        (code de retour 1)
    
    $ zsh -c autoload -U tcp_open;tcp_open 127.0.0.1 60001
        (durée d'exécution 00:00)
    tcp_open:ztcp:174: connection failed: connexion refusée
        (code de retour 1)
    
    $ nmap -v -sT -p 60001 127.0.0.1
        (durée d'exécution 00:00)
    Starting Nmap 7.70 ( https://nmap.org ) at 2019-06-30 19:06 CEST
    Initiating Ping Scan at 19:06
    Scanning 127.0.0.1 [2 ports]
    Completed Ping Scan at 19:06, 0.00s elapsed (1 total hosts)
    Initiating Connect Scan at 19:06
    Scanning localhost (127.0.0.1) [1 port]
    Completed Connect Scan at 19:06, 0.00s elapsed (1 total ports)
    Nmap scan report for localhost (127.0.0.1)
    Host is up (0.00011s latency).
    
    PORT      STATE  SERVICE
    60001/tcp closed unknown
    
    Read data files from: /usr/bin/../share/nmap
    Nmap done: 1 IP address (1 host up) scanned in 0.06 seconds
        (code de retour 0)
    
    $ sudo traceroute -T -N 1 -m 1 -q 1 -p 60001 127.0.0.1 -O info
        (durée d'exécution 00:00)
    traceroute to 127.0.0.1 (127.0.0.1), 1 hops max, 60 byte packets
     1  localhost (127.0.0.1) <rst,ack>  0.033 ms
        (code de retour 0)
    
    $ openssl s_client -connect 127.0.0.1:60001
        (durée d'exécution 00:00)
    140595570463872:error:0200206F:system library:connect:Connection refused:../crypto/bio/b_sock2.c:110:
    140595570463872:error:2008A067:BIO routines:BIO_connect:connect error:../crypto/bio/b_sock2.c:111:
    connect:errno=111
        (code de retour 1)
    
    $ ssh -p 60001 127.0.0.1
        (durée d'exécution 00:00)
    Pseudo-terminal will not be allocated because stdin is not a terminal.
    ssh: connect to host 127.0.0.1 port 60001: Connection refused
        (code de retour 255)
    
    $ perl -e use IO::Socket::INET;new IO::Socket::INET ( PeerHost => "127.0.0.1", PeerPort => "60001", Proto => "tcp",) or die "ERROR in Socket Creation : $!\n";
        (durée d'exécution 00:00)
    ERROR in Socket Creation : Connection refused
        (code de retour 111)
    
    $ python3 -c import socket;socket.socket().connect(("127.0.0.1",60001))
        (durée d'exécution 00:00)
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    ConnectionRefusedError: [Errno 111] Connection refused
        (code de retour 1)
    
    $ ruby -e require "socket";s = TCPSocket.open("127.0.0.1", 60001)
        (durée d'exécution 00:00)
    -e:1:in `initialize': Connection refused - connect(2) for "127.0.0.1" port 60001 (Errno::ECONNREFUSED)
        from -e:1:in `open'
        from -e:1:in `<main>'
        (code de retour 1)
    
    $ curl -v -s --max-time 60 http://127.0.0.1:60001
        (durée d'exécution 00:00)
    * Expire in 0 ms for 6 (transfer 0x55bf2d3fec40)
    * Expire in 60000 ms for 8 (transfer 0x55bf2d3fec40)
    *   Trying 127.0.0.1...
    * TCP_NODELAY set
    * Expire in 200 ms for 4 (transfer 0x55bf2d3fec40)
    * connect to 127.0.0.1 port 60001 failed: Connexion refusée
    * Failed to connect to 127.0.0.1 port 60001: Connexion refusée
    * Closing connection 0
        (code de retour 7)
    
    $ wget --timeout=60 --tries=1 http://127.0.0.1:60001
        (durée d'exécution 00:00)
    --2019-06-30 19:06:05--  http://127.0.0.1:60001/
    Connexion à 127.0.0.1:60001… échec : Connexion refusée.
        (code de retour 4)
    
    $ links -dump http://127.0.0.1:60001
        (durée d'exécution 00:00)
    Connection refused
        (code de retour 1)
    
    $ chromium http://127.0.0.1:60001
       (Ce site est inaccessible. 127.0.0.1 n'autorise pas la connexion.  ERR_CONNECTION_REFUSED)
    $ firefox http://127.0.0.1:60001
       (Unable to connect Firefox can’t establish a connection to the server at 127.0.0.1:60001)
    

    Pour l'anecdote, ce pavé est tellement long qu'il semblerait que le select/paste d'X11 a besoin de s'y reprendre à 2 fois.

    Pour l'explication de ce qui me plaît pas, perso, je pense que séparer les commandes entres elles aurait rendu la chose nettement plus lisible: ici, on ne peux même pas aisément voir où s'arrête ou se finit une commande.
    De plus, scinder aurait permis d'éventuels commentaires sur les options ou la sortie du programme, voire, soyons fous, un commentaire sur la raison de choisir telle ou telle alternative.

    Que te manque-t-il dans les explications qui manquent selon toi ?

    Je pense avoir donné quelques indices plus haut dans ce post: pourquoi utiliser telle ou telle alternative, quelles sont les avantages et inconvénients, ce genre de trucs.
    Je suis désolé pour ceux qui n'apprécient pas de lire ça, mais même si je reconnais le travail qu'il y a du y avoir pour lister tout ça, je ne suis pas convaincu que la forme lui rende justice, bien au contraire.

    Tu peux mettre une autre IPv4 que 127.0.0.1 si tu veux, ça change rien à la question des flux TCP / UDP.

    Ben si, déjà pas besoin de DNS, qui est un des composants les plus fragiles selon mon vécu propre et me semble bien que localhost est traité de manière spécifique par le noyal, bien que j'aie aucune certitude sur ce point.
    Accessoirement, le titre du journal dit bien "internet est cassé", et désolé, mais je ping pas perdu.com sur localhost moi.

  • [^] # Re: Paquets

    Posté par  . En réponse à la dépêche Bienvenue Mageia 7. Évalué à 6.

    Pas faux, c'est une mauvaise idée en théorie.

    En pratique, le faire ne me dérange pas trop dans certaines conditions. Typiquement, si le paquet ne stocke pas de binaire, mais des ressources ou du code scripté (genre, un programme perl, python ou bash).
    La raison est tout simplement que les paquets contenant un binaire compilé vont souvent dépendre de libs extérieures, dont l'ABI peut changer. Si ce n'est pas le cas, et que le paquet contiens un binaire lié statiquement, ici aussi, je n'aurais pas trop d'hésitations à jouer.
    J'ai déjà eu a le faire une fois ou deux, en pratique (import de paquet buntu vers debian). C'est rare, mais avec les précautions qui vont bien et assez de maîtrise de son système, ce n'est pas trop dangereux.

    Par contre, je ne le conseillerais pas, de manière générale (il y a d'autres risques en dehors du truc qui marche pas) et… ben, franchement, surtout avec un fichier au format RPM, parce que mon opinion de ce format est peu sympa, opinion principalement basée sur la lecture de cet article.
    Pour résumer cet article que j'ai lu il y a plusieurs mois: deb? cpio d'un fichier qui décrit le format, d'une tarball qui décrit le paquet via des fichiers texte, et d'une tarball qui contiens les vraies données. Arch? Tarball. RPM? Format binaire victime d'over-engineering, mal documenté.

  • [^] # Re: hibernation

    Posté par  . En réponse au journal Installation de Linux Mageia 7 sur un Dell 14 5000. Évalué à 2.

    Ouah, tu t'es pris la tête… pourquoi tu ne t'es pas contenté de créer un fichier de swap?

    Il paraît que c'est moins performant, mais je soupçonne cette notion d'être surtout valide sur les disques mécaniques. Enfin, je t'avoues que perso, je n'utilise plus ni swap ni mise en veille depuis longtemps: mon système démarre plus vite en cold boot de toute façon. La seule chose que je «perd», ce sont mes workspace, mais bon… ça me prend à peu près 5s pour en recréer un, et ça change à chaque fois en fonction de mon usage du moment.

    Toujours est-il que, n'utilisant pas ces choses (swap, hibernation longue) je me trompe peut-être sur le coup du fichier.

  • # pas compris

    Posté par  . En réponse à la dépêche « Internet est cassé » ou plutôt : comment tester du TCP ou de l’UDP. Évalué à 9.

    En fait, c'est quoi le message de cette dépêche?

    Je ne sais pas pour vous, mais moi je vois surtout un pâté de commandes illisibles et sans explications. Cela dis, ça semble assumé:

    cet article est généré via une commande du type ansible-playbook InternetEstCassé.yml pour tester réellement les commandes.

    En plus, j'aurais tendance, vu le titre et l'intro, à croire que c'est à destination de l'utilisateur d'un réseau, mais rien sur le DNS, rien sur le routeur… Perso, pour savoir ce qui se passe quand «internet est cassé», je bosse pas sur localhost, je commence par ping la cible, ensuite je ping perdu.com, puis je ping 8.8.8.8, puis je ping mon routeur, et en général à ce moment la, je sais ou est le maillon qui merde.

    Du coup, je pense que j'ai rien compris. J'en viens même à me demander s'il y a quoique ce soit à comprendre, alors je voudrais bien quelques explications?

  • [^] # Re: telnet

    Posté par  . En réponse à la dépêche « Internet est cassé » ou plutôt : comment tester du TCP ou de l’UDP. Évalué à 5.

    Si on omets le fait que tu confondes serveur et client, je suis quasi sûr que tu as un client telnet installé par défaut. Je pense ici à busybox, qui entres autres inclues une implémentation de telnet, ping, netcat, traceroute et bien d'autres.

  • # me semble important

    Posté par  . En réponse au lien Hansen: SKS Keyserver Network Under Attack. Évalué à 4.

    Ça me semblait important, vous me pardonnerez le gratuit, j'espère.